import { state, saveHardwareAsset, deleteHardwareAsset } from '../../core/state'; import { HardwareAsset, MasterAssetData } from '../../core/excelHandler'; import { openModal, closeModals } from './BaseModal'; import { createIcons, Paperclip } from 'lucide'; import { CORP_LIST, ORG_LIST, HW_TYPE_LIST, LOCATION_DATA, TYPE_PREFIX_MAP } from './SharedData'; import { generateOptionsHTML, setFieldValue, getFieldValue, parseAndSetLocation, bindLocationEvents, getCombinedLocation, setEditLock } from './ModalUtils'; let currentAsset: HardwareAsset | null = null; let isEditMode = false; const HW_MODAL_HTML = ` `; export function openHwModal(asset: HardwareAsset, mode: 'view' | 'add' = 'view') { currentAsset = asset; const modal = document.getElementById('hw-asset-modal')!; // 1. 잠금 상태 통합 제어 (데이터 유무가 아닌 호출 mode에만 의존) setEditLock('hw-asset-form', mode, { saveBtnId: 'btn-save-hw-asset', revertBtnId: 'btn-revert-hw-edit', generateBtnId: 'btn-generate-hw-code' }); isEditMode = (mode === 'add'); // 2. 데이터 바인딩 fillHwFormData(asset); modal.classList.remove('hidden'); applyTypeSpecificUI(asset.type); createIcons({ icons: { Paperclip } }); } function applyTypeSpecificUI(type: string) { const detailPurpose = getFieldValue('hw-상세용도'); const form = document.getElementById('hw-asset-form') as HTMLFormElement; if (!form) return; const serverOnly = document.querySelectorAll('.server-only'); const nonServer = document.querySelectorAll('.non-server'); const locationFields = document.querySelectorAll('.hw-location-field'); const groups: Record = { detailPurpose: document.getElementById('hw-상세용도-group'), model: document.getElementById('hw-model-group'), ip: document.getElementById('hw-ip-group'), ip2: document.getElementById('hw-ip2-group'), remote: document.getElementById('hw-remote-group'), os: document.getElementById('hw-os-group'), cpu: document.getElementById('hw-cpu-group'), ram: document.getElementById('hw-ram-group'), ssd1: document.getElementById('hw-ssd1-group'), ssd2: document.getElementById('hw-ssd2-group'), monitoring: document.getElementById('hw-monitoring-group'), serverId: document.getElementById('hw-server-id-group'), serverPw: document.getElementById('hw-server-pw-group'), hwSpec: document.getElementById('hw-hwspec-group'), ipNonServer: document.getElementById('hw-ip-non-server-group'), type: document.getElementById('hw-유형-group'), networkTitle: document.getElementById('hw-network-title'), specTitle: document.getElementById('hw-spec-title'), opTitle: document.getElementById('hw-op-title') }; // 1. 초기화 serverOnly.forEach(el => (el as HTMLElement).style.display = 'none'); nonServer.forEach(el => (el as HTMLElement).style.display = 'none'); locationFields.forEach(el => (el as HTMLElement).style.display = 'none'); Object.values(groups).forEach(g => { if (g) g.style.display = 'none'; }); if (groups.type) groups.type.style.display = 'flex'; if (groups.opTitle) groups.opTitle.style.display = 'flex'; // 2. PC 유형일 때 상세용도 선택창 노출 (복구 핵심) if (type === 'PC' || type === '개인PC' || type === '노트북') { if (groups.detailPurpose) groups.detailPurpose.style.display = 'flex'; // 상세용도가 '서버'인 경우 서버용 필드 노출, 아니면 일반 PC용 필드 노출 if (detailPurpose === '서버') { serverOnly.forEach(el => (el as HTMLElement).style.display = 'flex'); locationFields.forEach(el => (el as HTMLElement).style.display = 'flex'); if (groups.networkTitle) groups.networkTitle.style.display = 'flex'; ['ip', 'ip2', 'remote', 'serverId', 'serverPw', 'monitoring', 'model', 'os', 'cpu', 'ram', 'ssd1', 'ssd2'].forEach(k => { if (groups[k]) groups[k]!.style.display = 'flex'; }); } else { nonServer.forEach(el => (el as HTMLElement).style.display = 'flex'); if (groups.specTitle) groups.specTitle.style.display = 'flex'; ['model', 'os', 'cpu', 'ram', 'ssd1', 'ssd2', 'hwSpec', 'ipNonServer'].forEach(k => { if (groups[k]) groups[k]!.style.display = 'flex'; }); } } else if (type === '서버') { serverOnly.forEach(el => (el as HTMLElement).style.display = 'flex'); locationFields.forEach(el => (el as HTMLElement).style.display = 'flex'); Object.values(groups).forEach(g => { if (g) g.style.display = 'flex'; }); } else if (['스토리지', 'NAS', 'DAS'].includes(type)) { serverOnly.forEach(el => (el as HTMLElement).style.display = 'flex'); locationFields.forEach(el => (el as HTMLElement).style.display = 'flex'); if (groups.networkTitle) groups.networkTitle.style.display = 'flex'; if (groups.ip) groups.ip.style.display = 'flex'; if (groups.specTitle) groups.specTitle.style.display = 'flex'; if (groups.model) groups.model.style.display = 'flex'; if (groups.ssd1) groups.ssd1.style.display = 'flex'; } else { // 기타 유형 (CPU, RAM, 모바일 등) if (groups.specTitle) groups.specTitle.style.display = 'flex'; if (groups.model) groups.model.style.display = 'flex'; } } function fillHwFormData(asset: HardwareAsset) { setFieldValue('hw-asset-id', asset.id); setFieldValue('hw-asset-type', asset.type); setFieldValue('hw-법인', asset.법인); setFieldValue('hw-자산코드', asset.자산코드); setFieldValue('hw-현사용조직', asset.현사용조직); setFieldValue('hw-이전사용조직', asset.이전사용조직); setFieldValue('hw-상세용도', (asset as any).상세용도); parseAndSetLocation(asset.위치, 'hw-위치-빌딩', 'hw-위치-상세', 'hw-위치-기타-group', 'hw-위치-기타'); setFieldValue('hw-모델명', asset.모델명); setFieldValue('hw-OS', asset.OS); setFieldValue('hw-CPU', asset.CPU); setFieldValue('hw-RAM', asset.RAM); setFieldValue('hw-SSD1', asset.SSD1); setFieldValue('hw-SSD2', asset.SSD2); setFieldValue('hw-담당자_정', asset.담당자_정 || asset.관리자); setFieldValue('hw-담당자_부', asset.담당자_부); const isServerGrade = asset.type === '서버' || (asset as any).상세용도 === '서버' || asset.type === '스토리지' || ['NAS', 'DAS'].includes(asset.type); if (isServerGrade) { setFieldValue('hw-용도', asset.용도 || (asset as any).purpose); setFieldValue('hw-상세', asset.상세 || (asset as any).details); setFieldValue('hw-비고', asset.비고 || (asset as any).remarks); setFieldValue('hw-구매일', asset.구매일 || (asset as any).purchase_date); setFieldValue('hw-유형', asset.storage유형 || asset.type); setFieldValue('hw-IP주소', asset.IP주소 || (asset as any).ip_address); setFieldValue('hw-IP2', (asset as any).IP2 || (asset as any).ip_address_2); setFieldValue('hw-원격접속', asset.원격접속 || (asset as any).remote_tool); setFieldValue('hw-서버ID', (asset as any).서버ID || (asset as any).server_id); setFieldValue('hw-서버PW', (asset as any).서버PW || (asset as any).server_pw); setFieldValue('hw-모니터링', asset.모니터링 || (asset as any).monitoring); } else { setFieldValue('hw-명칭', asset.명칭 || asset.모델명); setFieldValue('hw-구매일', asset.구매일 || (asset as any).purchase_date); setFieldValue('hw-금액', asset.금액 || (asset as any).price); setFieldValue('hw-HW사양', asset.HW사양 || asset.상세 || (asset as any).details); setFieldValue('hw-IP주소-non-server', asset.IP주소 || (asset as any).ip_address); } } export function initHwModal(onSave: () => void, closeModals: () => void) { if (!document.getElementById('hw-asset-modal')) { document.body.insertAdjacentHTML('beforeend', HW_MODAL_HTML); } const form = document.getElementById('hw-asset-form') as HTMLFormElement; const saveBtn = document.getElementById('btn-save-hw-asset')!; const revertBtn = document.getElementById('btn-revert-hw-edit')!; const deleteBtn = document.getElementById('btn-delete-hw-asset')!; const typeSelect = document.getElementById('hw-유형') as HTMLSelectElement; const detailPurposeSelect = document.getElementById('hw-상세용도') as HTMLSelectElement; [typeSelect, detailPurposeSelect].forEach(el => { el?.addEventListener('change', () => applyTypeSpecificUI(typeSelect.value)); }); bindLocationEvents('hw-위치-빌딩', 'hw-위치-상세', 'hw-위치-기타-group', 'hw-위치-기타'); const closeModalAction = () => { closeModals(); isEditMode = false; }; document.getElementById('btn-close-hw-modal')?.addEventListener('click', closeModalAction); document.getElementById('btn-cancel-hw-modal')?.addEventListener('click', closeModalAction); revertBtn.addEventListener('click', () => { setEditLock('hw-asset-form', 'view', { saveBtnId: 'btn-save-hw-asset', revertBtnId: 'btn-revert-hw-edit', generateBtnId: 'btn-generate-hw-code' }); isEditMode = false; if (currentAsset) fillHwFormData(currentAsset); }); document.getElementById('btn-generate-hw-code')?.addEventListener('click', async () => { const typeValue = typeSelect.value; const purchaseDate = getFieldValue('hw-구매일'); const typeCode = TYPE_PREFIX_MAP[typeValue] || 'ETC'; const dateStr = purchaseDate.replace(/[^0-9]/g, ''); if (dateStr.length < 4) { alert('올바른 구매일(연월)을 입력해주세요.'); return; } const prefix = `${typeCode}-${dateStr.substring(2, 6)}-`; try { const res = await fetch(`http://localhost:3000/api/generate-asset-code?prefix=${prefix}`); const data = await res.json(); if (data.nextCode) setFieldValue('hw-자산코드', data.nextCode); } catch (err) { alert('자산번호 생성에 실패했습니다.'); } }); saveBtn.addEventListener('click', () => { if (!currentAsset) return; if (!isEditMode) { setEditLock('hw-asset-form', 'edit', { saveBtnId: 'btn-save-hw-asset', revertBtnId: 'btn-revert-hw-edit' }); isEditMode = true; return; } const type = typeSelect.value; const detailPurpose = detailPurposeSelect.value; const updated: any = { ...currentAsset, 법인: getFieldValue('hw-법인'), 자산코드: getFieldValue('hw-자산코드'), 현사용조직: getFieldValue('hw-현사용조직'), 이전사용조직: getFieldValue('hw-이전사용조직'), 위치: getCombinedLocation('hw-위치-빌딩', 'hw-위치-상세', 'hw-위치-기타'), 모델명: getFieldValue('hw-모델명'), OS: getFieldValue('hw-OS'), CPU: getFieldValue('hw-CPU'), RAM: getFieldValue('hw-RAM'), SSD1: getFieldValue('hw-SSD1'), SSD2: getFieldValue('hw-SSD2'), 담당자_정: getFieldValue('hw-담당자_정'), 관리자: getFieldValue('hw-담당자_정'), 담당자_부: getFieldValue('hw-담당자_부'), type: type, 상세용도: detailPurpose }; if (type === '서버' || (type === 'PC' && detailPurpose === '서버') || ['스토리지', 'NAS', 'DAS'].includes(type)) { updated.용도 = getFieldValue('hw-용도'); updated.상세 = getFieldValue('hw-상세'); updated.비고 = getFieldValue('hw-비고'); updated.storage유형 = type; updated.IP주소 = getFieldValue('hw-IP주소'); updated.IP2 = getFieldValue('hw-IP2'); updated.원격접속 = getFieldValue('hw-원격접속'); updated.서버ID = getFieldValue('hw-서버ID'); updated.서버PW = getFieldValue('hw-서버PW'); updated.모니터링 = getFieldValue('hw-모니터링'); } else { updated.명칭 = getFieldValue('hw-명칭'); updated.구매일 = getFieldValue('hw-구매일'); updated.금액 = getFieldValue('hw-금액'); updated.HW사양 = getFieldValue('hw-HW사양'); updated.IP주소 = getFieldValue('hw-IP주소-non-server'); } saveHardwareAsset(updated); onSave(); setEditLock('hw-asset-form', 'view', { saveBtnId: 'btn-save-hw-asset', revertBtnId: 'btn-revert-hw-edit' }); isEditMode = false; }); deleteBtn.addEventListener('click', () => { if (!currentAsset) return; if (confirm('정말로 이 자산을 삭제하시겠습니까?')) { deleteHardwareAsset(currentAsset.id); onSave(); closeModals(); } }); }