import { state, saveAsset, deleteAsset } from '../../core/state'; import { openModal, closeModals } from './BaseModal'; import { openSwUserModal } from './SWUserModal'; import { createIcons, History, Plus, X, Save, Edit2, RotateCcw, Calendar } from 'lucide'; import { CORP_LIST } from './SharedData'; import { ASSET_SCHEMA, UI_TEXT } from '../../core/schema'; import { API_BASE_URL } from '../../core/utils'; import { generateOptionsHTML, setFieldValue, getFieldValue, setEditLock, applyDateMask } from './ModalUtils'; let currentSwAsset: any | null = null; let isEditMode = false; const SW_MODAL_HTML = ` `; function applySwTypeUI(type: string) { const cloudFields = document.querySelectorAll('.cloud-only'); const swFields = document.querySelectorAll('.sw-standard-field'); const userSection = document.getElementById('sw-user-section'); const expiryGroup = document.getElementById('sw-expiry-group'); const userTracking = document.querySelectorAll('.sw-user-tracking'); if (type === '클라우드') { cloudFields.forEach(el => (el as HTMLElement).style.display = 'flex'); swFields.forEach(el => (el as HTMLElement).style.display = 'none'); if (userSection) userSection.style.display = 'none'; userTracking.forEach(el => (el as HTMLElement).style.display = 'none'); } else { cloudFields.forEach(el => (el as HTMLElement).style.display = 'none'); swFields.forEach(el => (el as HTMLElement).style.display = 'flex'); if (userSection) userSection.style.display = 'block'; if (type === '외부SW' || type === '내부SW') { if (expiryGroup) expiryGroup.style.display = 'flex'; // 외부SW에만 현 사용자/직전 사용자 표시 (내부SW는 user tracking 제외 요청됨) userTracking.forEach(el => (el as HTMLElement).style.display = (type === '외부SW') ? 'flex' : 'none'); } } } function fillSwFormData(asset: any) { setFieldValue('sw-asset-id', asset.id); setFieldValue('sw-asset-type', asset.asset_type || asset.type); setFieldValue('sw-분야', asset.sw_field || ''); setFieldValue('sw-법인', asset.purchase_corp || ''); setFieldValue('sw-부서', asset.current_dept || ''); setFieldValue('sw-user-current', asset.user_current || ''); setFieldValue('sw-previous-user', asset.previous_user || ''); setFieldValue('sw-previous_dept', asset.previous_dept || ''); setFieldValue('sw-제품명', asset.product_name || ''); setFieldValue('sw-수량', asset.asset_count || ''); setFieldValue('sw-금액', asset.purchase_amount || ''); setFieldValue('sw-구매일', asset.purchase_date || ''); setFieldValue('sw-시작일', asset.start_date || ''); setFieldValue('sw-납품업체', asset.purchase_vendor || ''); setFieldValue('sw-개발담당자', asset.dev_manager || ''); setFieldValue('sw-기획담당자', asset.planning_manager || ''); setFieldValue('sw-영업담당자', asset.sales_manager || ''); setFieldValue('sw-비고', asset.memo || ''); if (asset.type === '클라우드' || asset.asset_type === '클라우드') { setFieldValue('sw-플랫폼명', asset.dev_objective || ''); setFieldValue('sw-계정명', asset.email_account || ''); setFieldValue('sw-결제수단', asset.purchase_method || ''); } else { setFieldValue('sw-만료일', asset.expiry_date || ''); } renderSwHistory(asset.id); } function renderSwHistory(swId: string) { const container = document.getElementById('sw-history-list'); if (!container) return; const logs = (state.masterData.logs || []).filter(l => l.assetId === swId); if (logs.length === 0) { container.innerHTML = '
수정 이력이 없습니다.
'; return; } container.innerHTML = logs.map(l => `
${l.date}
${l.user}
${l.details}
`).join(''); } export function openSwModal(asset: any, mode: 'view' | 'add' | 'edit' = 'view') { currentSwAsset = asset; const modal = document.getElementById('sw-asset-modal')!; setEditLock('sw-asset-form', mode, { saveBtnId: 'btn-save-sw-asset', revertBtnId: 'btn-revert-sw-edit' }); isEditMode = (mode === 'add' || mode === 'edit'); fillSwFormData(asset); applySwTypeUI(asset.asset_type || asset.type); modal.classList.remove('hidden'); createIcons({ icons: { X, History, Plus } }); } export function initSwModal(onSave: () => void, closeModals: () => void) { if (!document.getElementById('sw-asset-modal')) { document.body.insertAdjacentHTML('beforeend', SW_MODAL_HTML); } const form = document.getElementById('sw-asset-form') as HTMLFormElement; const saveBtn = document.getElementById('btn-save-sw-asset')!; const revertBtn = document.getElementById('btn-revert-sw-edit')!; const deleteBtn = document.getElementById('btn-delete-sw-asset')!; const userAssignBtn = document.getElementById('btn-open-sw-user')!; const btnOpenUpdate = document.getElementById('btn-open-sw-update')!; const typeSelect = document.getElementById('sw-asset-type') as HTMLSelectElement; typeSelect?.addEventListener('change', () => { applySwTypeUI(typeSelect.value); }); ['sw-구매일', 'sw-시작일', 'sw-만료일', 'sw-update-start', 'sw-update-end'].forEach(id => { applyDateMask(document.getElementById(id) as HTMLInputElement); }); createIcons({ icons: { Calendar } }); const closeModalAction = () => { closeModals(); isEditMode = false; }; document.getElementById('btn-close-sw-modal')?.addEventListener('click', closeModalAction); document.getElementById('btn-cancel-sw-modal')?.addEventListener('click', closeModalAction); revertBtn.addEventListener('click', () => { setEditLock('sw-asset-form', 'view', { saveBtnId: 'btn-save-sw-asset', revertBtnId: 'btn-revert-sw-edit' }); isEditMode = false; if (currentSwAsset) fillSwFormData(currentSwAsset); }); saveBtn.addEventListener('click', async () => { if (!currentSwAsset) return; if (!isEditMode) { setEditLock('sw-asset-form', 'edit', { saveBtnId: 'btn-save-sw-asset', revertBtnId: 'btn-revert-sw-edit' }); isEditMode = true; return; } const type = getFieldValue('sw-asset-type'); const formData = new FormData(form); const updated: any = { ...currentSwAsset }; formData.forEach((value, key) => { updated[key] = value; }); // Mapping for generic saveAsset let categoryKey = 'swExternal'; if (type === '내부SW') categoryKey = 'swInternal'; else if (type === '클라우드') categoryKey = 'cloud'; const success = await saveAsset(categoryKey, updated); if (success) { onSave(); closeModalAction(); } }); deleteBtn.addEventListener('click', async () => { if (!currentSwAsset) return; if (!confirm(UI_TEXT.MESSAGES.CONFIRM_DELETE)) return; const type = currentSwAsset.asset_type || currentSwAsset.type; let categoryKey = 'swExternal'; if (type === '내부SW') categoryKey = 'swInternal'; else if (type === '클라우드') categoryKey = 'cloud'; const success = await deleteAsset(categoryKey, currentSwAsset.id); if (success) { alert('성공적으로 삭제되었습니다.'); onSave(); // Refresh list closeModalAction(); } }); userAssignBtn.addEventListener('click', () => { if (currentSwAsset) openSwUserModal(currentSwAsset); }); // 자산 업데이트(계약 갱신) 모달 로직 const subModal = document.getElementById('sw-update-modal')!; 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(); if (!isEditMode) { alert('자산을 수정 모드로 변경한 후 업데이트를 진행해주세요.'); return; } subModal.classList.remove('hidden'); }); btnSaveUpdate?.addEventListener('click', async (e) => { e.preventDefault(); 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 cost = (document.getElementById('sw-update-cost') as HTMLInputElement).value; const note = (document.getElementById('sw-update-note') as HTMLInputElement).value; if (start) setFieldValue('sw-시작일', start); if (end) setFieldValue('sw-만료일', end); if (cost) setFieldValue('sw-금액', cost); // Save as log const log = { assetId: currentSwAsset.id, date, details: `[계약갱신] ${note} (${start} ~ ${end}, 비용: ${cost})`, user: '관리자' }; // Call generic API for logs (could be added to state.ts) await fetch(`${API_BASE_URL}/api/asset/history/batch`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify([...state.masterData.logs, log]) }); closeUpdateModal(); onSave(); }); }