import { state } from '../../core/state'; import { SoftwareAsset } from '../../core/excelHandler'; import { openModal } from './BaseModal'; import { createIcons, X, History, Plus } from 'lucide'; const SW_MODAL_HTML = ` `; export let currentAsset: SoftwareAsset | null = null; export let isEditMode = false; export function setEditMode(edit: boolean) { isEditMode = edit; const swForm = document.getElementById('sw-asset-form') as HTMLFormElement; const btnSaveSw = document.getElementById('btn-save-sw-asset') as HTMLButtonElement; const btnRevertEdit = document.getElementById('btn-revert-sw-edit') as HTMLButtonElement; const btnCloseFooter = document.getElementById('btn-close-sw-footer') as HTMLButtonElement; if (edit) { swForm.classList.add('is-edit-mode'); swForm.classList.remove('is-view-mode'); btnSaveSw.textContent = '저장'; btnRevertEdit.classList.remove('hidden'); btnCloseFooter.classList.add('hidden'); Array.from(swForm.elements).forEach((el: any) => el.disabled = false); } else { swForm.classList.add('is-view-mode'); swForm.classList.remove('is-edit-mode'); btnSaveSw.textContent = '수정'; btnRevertEdit.classList.add('hidden'); btnCloseFooter.classList.remove('hidden'); Array.from(swForm.elements).forEach((el: any) => el.disabled = true); if (currentAsset) fillFormData(currentAsset); } } export function fillFormData(asset: SoftwareAsset) { (document.getElementById('sw-asset-id') as HTMLInputElement).value = asset.id; (document.getElementById('sw-asset-type') as HTMLInputElement).value = asset.type; (document.getElementById('sw-분야') as HTMLSelectElement).value = asset.분야 || '업무공통'; (document.getElementById('sw-법인') as HTMLSelectElement).value = asset.법인; (document.getElementById('sw-부서') as HTMLInputElement).value = asset.부서 || ''; (document.getElementById('sw-제품명') as HTMLInputElement).value = asset.제품명; (document.getElementById('sw-구매일') as HTMLInputElement).value = asset.구매일 || ''; if (asset.구독일) { const parts = asset.구독일.split('~'); (document.getElementById('sw-구독일-시작') as HTMLInputElement).value = parts[0]?.trim() || ''; (document.getElementById('sw-구독일-종료') as HTMLInputElement).value = parts[1]?.trim() || ''; } else { (document.getElementById('sw-구독일-시작') as HTMLInputElement).value = ''; (document.getElementById('sw-구독일-종료') as HTMLInputElement).value = ''; } (document.getElementById('sw-유지보수여부') as HTMLInputElement).checked = !!asset.유지보수여부; (document.getElementById('sw-금액') as HTMLInputElement).value = asset.금액 || ''; (document.getElementById('sw-수량') as HTMLInputElement).value = String(asset.수량); (document.getElementById('sw-계정명') as HTMLInputElement).value = asset.계정명 || ''; (document.getElementById('sw-납품업체') as HTMLInputElement).value = asset.납품업체 || ''; (document.getElementById('sw-비고') as HTMLInputElement).value = asset.비고 || ''; document.getElementById('btn-open-sw-update')!.style.display = 'flex'; renderSwHistory(asset.id); } export function initSwModal(renderContent: () => void, closeModals: () => void) { if (!document.getElementById('sw-asset-modal')) { document.body.insertAdjacentHTML('beforeend', SW_MODAL_HTML); } const swForm = document.getElementById('sw-asset-form') as HTMLFormElement; const btnRevertEdit = document.getElementById('btn-revert-sw-edit') as HTMLButtonElement; const btnSaveSw = document.getElementById('btn-save-sw-asset') as HTMLButtonElement; const btnDeleteSw = document.getElementById('btn-delete-sw-asset') as HTMLButtonElement; const btnCloseHeader = document.getElementById('btn-close-sw-modal') as HTMLButtonElement; const btnCloseFooter = document.getElementById('btn-close-sw-footer') as HTMLButtonElement; btnRevertEdit?.addEventListener('click', () => setEditMode(false)); btnCloseHeader?.addEventListener('click', closeModals); btnCloseFooter?.addEventListener('click', closeModals); btnSaveSw?.addEventListener('click', (e) => { e.preventDefault(); if (!isEditMode) { setEditMode(true); return; } if (!swForm.checkValidity()) { swForm.reportValidity(); return; } const id = (document.getElementById('sw-asset-id') as HTMLInputElement).value; const start = (document.getElementById('sw-구독일-시작') as HTMLInputElement).value; const end = (document.getElementById('sw-구독일-종료') as HTMLInputElement).value; const 구독일Str = (start || end) ? `${start || ''} ~ ${end || ''}` : ''; const newAsset: SoftwareAsset = { id: id || Math.random().toString(36).substring(2, 9), type: (document.getElementById('sw-asset-type') as HTMLInputElement).value, 분야: (document.getElementById('sw-분야') as HTMLSelectElement).value, 법인: (document.getElementById('sw-법인') as HTMLSelectElement).value, 부서: (document.getElementById('sw-부서') as HTMLInputElement).value, 제품명: (document.getElementById('sw-제품명') as HTMLInputElement).value, 구매일: (document.getElementById('sw-구매일') as HTMLInputElement).value, 구독일: 구독일Str, 유지보수여부: (document.getElementById('sw-유지보수여부') as HTMLInputElement).checked, 금액: (document.getElementById('sw-금액') as HTMLInputElement).value, 수량: parseInt((document.getElementById('sw-수량') as HTMLInputElement).value || '1', 10), 계정명: (document.getElementById('sw-계정명') as HTMLInputElement).value, 납품업체: (document.getElementById('sw-납품업체') as HTMLInputElement).value, 비고: (document.getElementById('sw-비고') as HTMLInputElement).value, }; if (id) { const idx = state.masterData.sw.findIndex(a => a.id === id); if(idx !== -1) state.masterData.sw[idx] = newAsset; } else { state.masterData.sw.push(newAsset); const now = new Date(); state.masterData.logs = state.masterData.logs || []; state.masterData.logs.push({ id: Math.random().toString(36).substring(2, 9), assetId: newAsset.id, date: `${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-${String(now.getDate()).padStart(2,'0')}`, user: '관리자', details: '신규 등록' }); } closeModals(); renderContent(); }); btnDeleteSw?.addEventListener('click', (e) => { e.preventDefault(); const id = (document.getElementById('sw-asset-id') as HTMLInputElement).value; if (confirm('삭제하시겠습니까?')) { state.masterData.sw = state.masterData.sw.filter(a => a.id !== id); closeModals(); renderContent(); } }); // Update Sub-modal integration const subModal = document.getElementById('sw-update-modal')!; const btnOpenUpdate = document.getElementById('btn-open-sw-update')!; const btnCloseUpdate = document.getElementById('btn-close-sw-update')!; const btnCancelUpdate = document.getElementById('btn-cancel-sw-update')!; const btnSaveUpdate = document.getElementById('btn-save-sw-update')!; const closeUpdateModal = () => subModal.classList.add('hidden'); btnCloseUpdate?.addEventListener('click', closeUpdateModal); btnCancelUpdate?.addEventListener('click', closeUpdateModal); btnOpenUpdate?.addEventListener('click', (e) => { e.preventDefault(); const isSub = (document.getElementById('sw-asset-type') as HTMLInputElement).value === '구독SW'; subModal.classList.remove('hidden'); // Set default values (document.getElementById('sw-update-date') as HTMLInputElement).value = new Date().toISOString().substring(0, 10); (document.getElementById('sw-update-start') as HTMLInputElement).value = ''; (document.getElementById('sw-update-end') as HTMLInputElement).value = ''; (document.getElementById('sw-update-cost') as HTMLInputElement).value = ''; (document.getElementById('sw-update-note') as HTMLInputElement).value = ''; if (isSub) { document.querySelector('.sub-sw-update')!.setAttribute('style', 'display:flex; flex-direction:column;'); document.querySelector('.perm-sw-update')!.setAttribute('style', 'display:none'); } else { document.querySelector('.sub-sw-update')!.setAttribute('style', 'display:none'); document.querySelector('.perm-sw-update')!.setAttribute('style', 'display:flex; flex-direction:column;'); (document.getElementById('sw-update-maintenance') as HTMLInputElement).checked = (document.getElementById('sw-유지보수여부') as HTMLInputElement).checked; } }); btnSaveUpdate?.addEventListener('click', (e) => { e.preventDefault(); const id = (document.getElementById('sw-asset-id') as HTMLInputElement).value; if (!id) { alert('자산이 저장되지 않았습니다. 메인 폼을 먼저 저장해주세요.'); return; } const isSub = (document.getElementById('sw-asset-type') as HTMLInputElement).value === '구독SW'; const date = (document.getElementById('sw-update-date') as HTMLInputElement).value; const start = (document.getElementById('sw-update-start') as HTMLInputElement).value; const end = (document.getElementById('sw-update-end') as HTMLInputElement).value; const maintenance = (document.getElementById('sw-update-maintenance') as HTMLInputElement).checked; const cost = (document.getElementById('sw-update-cost') as HTMLInputElement).value; const note = (document.getElementById('sw-update-note') as HTMLInputElement).value; const periodStr = (start || end) ? `${start || ''} ~ ${end || ''}` : ''; let details = `[업데이트] ${note || (isSub ? '구독 갱신' : '유지보수 계약')}\n`; if (cost) details += `발생 비용: ${cost}원\n`; if (isSub) { if (periodStr) details += `구독 변경: -> ${periodStr}\n`; // Always update main fields if period is provided if (periodStr) { (document.getElementById('sw-구독일-시작') as HTMLInputElement).value = start; (document.getElementById('sw-구독일-종료') as HTMLInputElement).value = end; } } else { details += `유지보수 상태: -> ${maintenance ? '유효' : '없음'}\n`; (document.getElementById('sw-유지보수여부') as HTMLInputElement).checked = maintenance; } if (cost) (document.getElementById('sw-금액') as HTMLInputElement).value = cost; state.masterData.logs.push({ id: Math.random().toString(36).substring(2, 9), assetId: id, date, details, user: '관리자' }); closeUpdateModal(); renderSwHistory(id); // 메인 테이블 리렌더링도 트리거 (뒤에 보일 수 있게) renderContent(); }); } function renderSwHistory(assetId: string) { const historyList = document.getElementById('sw-history-list'); if (!historyList) return; if (!state.masterData.logs) state.masterData.logs = []; const logs = state.masterData.logs .filter(l => l.assetId === assetId) .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); if (logs.length === 0) { historyList.innerHTML = '
업데이트 내역이 없습니다.
'; return; } historyList.innerHTML = logs.map(log => `
${log.date}
작업자: ${log.user}
${log.details.replace(/\\n/g, '
')}
`).join(''); createIcons({ icons: { X, History, Plus } }); } export function openSwModal(asset?: SoftwareAsset) { currentAsset = asset || null; const swForm = document.getElementById('sw-asset-form') as HTMLFormElement; const deleteBtn = document.getElementById('btn-delete-sw-asset')!; openModal('sw-asset-modal'); swForm.reset(); const subGroup = document.getElementById('sw-구독일-group')!; const permGroup = document.getElementById('sw-유지보수-group')!; if (state.activeSubTab === '구독SW') { subGroup.style.display = 'flex'; permGroup.style.display = 'none'; } else { subGroup.style.display = 'none'; permGroup.style.display = 'flex'; } if (asset) { document.getElementById('sw-modal-title')!.textContent = `${state.activeSubTab} 상세 정보 수정`; deleteBtn.style.display = 'block'; fillFormData(asset); setEditMode(false); } else { document.getElementById('sw-modal-title')!.textContent = `신규 ${state.activeSubTab} 자산 추가`; deleteBtn.style.display = 'none'; (document.getElementById('sw-asset-id') as HTMLInputElement).value = ''; (document.getElementById('sw-asset-type') as HTMLInputElement).value = state.activeSubTab; document.getElementById('btn-open-sw-update')!.style.display = 'none'; renderSwHistory(''); setEditMode(true); } createIcons({ icons: { X, History, Plus } }); }