import { LOCATION_DATA } from './SharedData'; /** * 모달 조작 및 UI 생성을 위한 공통 유틸리티 */ // 1. Select 박스의 Option HTML 생성 export function generateOptionsHTML(list: string[], defaultValue: string = '', includeSelectHint: boolean = true): string { let html = includeSelectHint ? '' : ''; html += list.map(item => ``).join(''); return html; } // 2. 안전하게 폼 필드 값 설정 (Null 에러 방지) export function setFieldValue(id: string, value: any) { const el = document.getElementById(id) as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement; if (el) { el.value = value || ''; } } // 3. 안전하게 폼 필드 값 읽기 export function getFieldValue(id: string): string { const el = document.getElementById(id) as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement; return el ? el.value : ''; } // 4. 위치 정보 파싱 및 UI 세팅 export function parseAndSetLocation(locationStr: string, bldgId: string, detailId: string, etcGroupId: string, etcInputId: string) { const bldgSelect = document.getElementById(bldgId) as HTMLSelectElement; const detailSelect = document.getElementById(detailId) as HTMLSelectElement; const etcGroup = document.getElementById(etcGroupId); const etcInput = document.getElementById(etcInputId) as HTMLInputElement; if (!bldgSelect || !detailSelect) return; // 초기화 bldgSelect.value = ''; detailSelect.innerHTML = ''; if (etcGroup) etcGroup.style.display = 'none'; if (!locationStr) return; const parts = locationStr.split(' '); const bldg = parts[0]; if (LOCATION_DATA[bldg]) { bldgSelect.value = bldg; // 상세 목록 갱신 detailSelect.innerHTML = generateOptionsHTML(LOCATION_DATA[bldg]); const detail = parts[1]; if (detail) { detailSelect.value = detail; if (detail === '기타' && etcGroup && etcInput) { etcGroup.style.display = 'flex'; etcInput.value = parts.slice(2).join(' '); } } } } // 5. 위치 종속성(Cascade) 이벤트 바인딩 export function bindLocationEvents(bldgId: string, detailId: string, etcGroupId: string, etcInputId: string) { const bldgSelect = document.getElementById(bldgId) as HTMLSelectElement; const detailSelect = document.getElementById(detailId) as HTMLSelectElement; const etcGroup = document.getElementById(etcGroupId); const etcInput = document.getElementById(etcInputId) as HTMLInputElement; if (!bldgSelect || !detailSelect) return; bldgSelect.addEventListener('change', () => { const bldg = bldgSelect.value; detailSelect.innerHTML = generateOptionsHTML(LOCATION_DATA[bldg] || []); if (etcGroup) etcGroup.style.display = 'none'; if (etcInput) etcInput.value = ''; }); detailSelect.addEventListener('change', () => { if (etcGroup) { etcGroup.style.display = detailSelect.value === '기타' ? 'flex' : 'none'; } }); } // 6. 위치 문자열 조합 (저장용) export function getCombinedLocation(bldgId: string, detailId: string, etcInputId: string): string { const bldg = getFieldValue(bldgId); const detail = getFieldValue(detailId); const etc = getFieldValue(etcInputId); let combined = bldg; if (detail) combined += ` ${detail}`; if (detail === '기타' && etc) combined += ` ${etc}`; return combined.trim(); } // 7. 조회/수정 모드 UI 통합 제어 export function setEditLock( formId: string, mode: 'view' | 'add' | 'edit', options: { saveBtnId: string, revertBtnId: string, generateBtnId?: string, addLogBtnId?: string } ) { const form = document.getElementById(formId) as HTMLFormElement; const saveBtn = document.getElementById(options.saveBtnId); const revertBtn = document.getElementById(options.revertBtnId); const generateBtn = options.generateBtnId ? document.getElementById(options.generateBtnId) : null; const addLogBtn = options.addLogBtnId ? document.getElementById(options.addLogBtnId) : null; if (!form || !saveBtn || !revertBtn) return; if (mode === 'add' || mode === 'edit') { // 편집 모드 활성화 form.classList.remove('is-view-mode'); form.classList.add('is-edit-mode'); saveBtn.textContent = '저장'; revertBtn.classList.toggle('hidden', mode === 'add'); // 신규 추가 시에는 취소 버튼 숨김 // 번호 생성 버튼은 '추가(add)' 시에만 노출 if (generateBtn) { generateBtn.style.display = mode === 'add' ? 'flex' : 'none'; } // 내역 추가 버튼 노출 if (addLogBtn) addLogBtn.style.display = 'flex'; } else { // 조회 모드 (잠금) form.classList.remove('is-edit-mode'); form.classList.add('is-view-mode'); saveBtn.textContent = '수정'; revertBtn.classList.add('hidden'); // 조회 모드에서는 버튼들 숨김 if (generateBtn) generateBtn.style.display = 'none'; if (addLogBtn) addLogBtn.style.display = 'none'; } } /** * 8. 공통 모달 프레임 템플릿 생성 * @param idPrefix 필드 ID의 접두사 (예: 'hw', 'sw', 'pc') * @param title 모달 제목 * @param formContent 각 모달마다 다른 폼 본문 HTML * @param options 설정 (이력 영역 제목 등) */ export function createModalFrameHTML( idPrefix: string, title: string, formContent: string, options: { historyTitle: string, addLogBtnId: string } ): string { return ` `; } /** * 9. 데이터 ↔ 폼 자동 매핑 (유지보수 핵심) */ export function autoFillForm(idPrefix: string, data: any, fieldMap: Record) { Object.entries(fieldMap).forEach(([fieldId, dataKey]) => { setFieldValue(`${idPrefix}-${fieldId}`, data[dataKey]); }); } export function autoExtractForm(idPrefix: string, fieldMap: Record): any { const result: any = {}; Object.entries(fieldMap).forEach(([fieldId, dataKey]) => { result[dataKey] = getFieldValue(`${idPrefix}-${fieldId}`); }); return result; } /** * 10. 날짜 자동 마스킹 및 포커스 제어 (Auto-jump) */ export function applyDateMask(el: HTMLInputElement) { if (!el) return; el.placeholder = 'YYYY-MM-DD'; el.maxLength = 10; el.addEventListener('input', (e) => { let value = el.value.replace(/[^0-9]/g, ''); // 숫자만 남김 let result = ''; if (value.length <= 4) { result = value; } else if (value.length <= 6) { result = value.substring(0, 4) + '-' + value.substring(4); } else { result = value.substring(0, 4) + '-' + value.substring(4, 6) + '-' + value.substring(6, 10); } el.value = result; }); // 엔터 키나 입력 완료 시 유효성 검사 (선택 사항) el.addEventListener('blur', () => { const val = el.value; if (val && !/^\d{4}-\d{2}-\d{2}$/.test(val)) { // 형식이 맞지 않으면 경고 효과 등을 줄 수 있음 } }); }