+
+
+
`;
+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');
+ } else {
+ swForm.classList.add('is-view-mode');
+ swForm.classList.remove('is-edit-mode');
+ btnSaveSw.textContent = '수정';
+ btnRevertEdit.classList.add('hidden');
+ btnCloseFooter.classList.remove('hidden');
+ 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);
@@ -98,44 +208,6 @@ export function initSwModal(renderContent: () => void, closeModals: () => void)
const btnCloseHeader = document.getElementById('btn-close-sw-modal') as HTMLButtonElement;
const btnCloseFooter = document.getElementById('btn-close-sw-footer') as HTMLButtonElement;
- let isEditMode = false;
- let currentAsset: SoftwareAsset | null = null;
-
- const setEditMode = (edit: boolean) => {
- isEditMode = edit;
- if (edit) {
- swForm.classList.add('is-edit-mode');
- swForm.classList.remove('is-view-mode');
- btnSaveSw.textContent = '저장';
- btnRevertEdit.classList.remove('hidden');
- btnCloseFooter.classList.add('hidden');
- } else {
- swForm.classList.add('is-view-mode');
- swForm.classList.remove('is-edit-mode');
- btnSaveSw.textContent = '수정';
- btnRevertEdit.classList.add('hidden');
- btnCloseFooter.classList.remove('hidden');
- if (currentAsset) fillFormData(currentAsset);
- }
- };
-
- 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.구매일 || '';
- (document.getElementById('sw-구독일') as HTMLInputElement).value = asset.구독일 || '';
- (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.비고 || '';
- }
-
btnRevertEdit?.addEventListener('click', () => setEditMode(false));
btnCloseHeader?.addEventListener('click', closeModals);
btnCloseFooter?.addEventListener('click', closeModals);
@@ -150,6 +222,10 @@ export function initSwModal(renderContent: () => void, closeModals: () => void)
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,
@@ -158,7 +234,7 @@ export function initSwModal(renderContent: () => void, closeModals: () => void)
부서: (document.getElementById('sw-부서') as HTMLInputElement).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),
@@ -187,6 +263,109 @@ export function initSwModal(renderContent: () => void, closeModals: () => void)
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;
+
+ 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) {
@@ -217,6 +396,10 @@ export function openSwModal(asset?: SoftwareAsset) {
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 } });
}
diff --git a/src/components/Modal/SWUserModal.ts b/src/components/Modal/SWUserModal.ts
index f4f0668..8f20868 100644
--- a/src/components/Modal/SWUserModal.ts
+++ b/src/components/Modal/SWUserModal.ts
@@ -116,14 +116,14 @@ export function initSwUserModal(renderContent: () => void, closeModals: () => vo
btnSaveSwUserMapping?.addEventListener('click', () => {
state.masterData.swUsers = state.masterData.swUsers.filter(u => u.swId !== currentSwUserAssetId);
state.masterData.swUsers.push(...tempSwUsers);
- document.getElementById('sw-user-modal')?.classList.add('hidden');
+ closeModals();
renderContent();
});
btnCancelUserEdit?.addEventListener('click', () => document.getElementById('sw-user-edit-modal')?.classList.add('hidden'));
btnCloseUserEdit?.addEventListener('click', () => document.getElementById('sw-user-edit-modal')?.classList.add('hidden'));
- btnCancelUserModal?.addEventListener('click', () => document.getElementById('sw-user-modal')?.classList.add('hidden'));
- btnCloseUserModal?.addEventListener('click', () => document.getElementById('sw-user-modal')?.classList.add('hidden'));
+ btnCancelUserModal?.addEventListener('click', closeModals);
+ btnCloseUserModal?.addEventListener('click', closeModals);
}
function renderUserList() {
diff --git a/src/components/Modal/StorageModal.ts b/src/components/Modal/StorageModal.ts
index 1a88b70..1733521 100644
--- a/src/components/Modal/StorageModal.ts
+++ b/src/components/Modal/StorageModal.ts
@@ -38,6 +38,47 @@ const STORAGE_MODAL_HTML = `
`;
+export let currentAsset: HardwareAsset | null = null;
+export let isEditMode = false;
+
+export function setEditMode(edit: boolean) {
+ isEditMode = edit;
+ const storageForm = document.getElementById('storage-asset-form') as HTMLFormElement;
+ const btnSaveStorage = document.getElementById('btn-save-storage-asset') as HTMLButtonElement;
+ const btnRevertEdit = document.getElementById('btn-revert-storage-edit') as HTMLButtonElement;
+ const btnCloseFooter = document.getElementById('btn-close-storage-footer') as HTMLButtonElement;
+
+ if (edit) {
+ storageForm.classList.add('is-edit-mode');
+ storageForm.classList.remove('is-view-mode');
+ btnSaveStorage.textContent = '저장';
+ btnRevertEdit.classList.remove('hidden');
+ btnCloseFooter.classList.add('hidden');
+ } else {
+ storageForm.classList.add('is-view-mode');
+ storageForm.classList.remove('is-edit-mode');
+ btnSaveStorage.textContent = '수정';
+ btnRevertEdit.classList.add('hidden');
+ btnCloseFooter.classList.remove('hidden');
+ if (currentAsset) fillFormData(currentAsset);
+ }
+}
+
+export function fillFormData(asset: HardwareAsset) {
+ (document.getElementById('storage-asset-id') as HTMLInputElement).value = asset.id;
+ (document.getElementById('storage-법인') as HTMLInputElement).value = asset.법인;
+ (document.getElementById('storage-유형') as HTMLInputElement).value = asset.storage유형 || 'NAS';
+ (document.getElementById('storage-자산코드') as HTMLInputElement).value = asset.자산코드;
+ (document.getElementById('storage-명칭') as HTMLInputElement).value = asset.명칭;
+ (document.getElementById('storage-위치') as HTMLInputElement).value = asset.위치 || '';
+ (document.getElementById('storage-모델명') as HTMLInputElement).value = asset.모델명 || '';
+ (document.getElementById('storage-용량') as HTMLInputElement).value = asset.용량 || '';
+ (document.getElementById('storage-담당자_정') as HTMLInputElement).value = asset.담당자_정 || '';
+ (document.getElementById('storage-IP주소') as HTMLInputElement).value = asset.IP주소 || '';
+ (document.getElementById('storage-구매일') as HTMLInputElement).value = asset.구매일 || '';
+ (document.getElementById('storage-금액') as HTMLInputElement).value = asset.금액 || '';
+}
+
export function initStorageModal(renderContent: () => void, closeModals: () => void) {
if (!document.getElementById('storage-asset-modal')) {
document.body.insertAdjacentHTML('beforeend', STORAGE_MODAL_HTML);
@@ -50,42 +91,6 @@ export function initStorageModal(renderContent: () => void, closeModals: () => v
const btnCloseHeader = document.getElementById('btn-close-storage-modal') as HTMLButtonElement;
const btnCloseFooter = document.getElementById('btn-close-storage-footer') as HTMLButtonElement;
- let isEditMode = false;
- let currentAsset: HardwareAsset | null = null;
-
- const setEditMode = (edit: boolean) => {
- isEditMode = edit;
- if (edit) {
- storageForm.classList.add('is-edit-mode');
- storageForm.classList.remove('is-view-mode');
- btnSaveStorage.textContent = '저장';
- btnRevertEdit.classList.remove('hidden');
- btnCloseFooter.classList.add('hidden');
- } else {
- storageForm.classList.add('is-view-mode');
- storageForm.classList.remove('is-edit-mode');
- btnSaveStorage.textContent = '수정';
- btnRevertEdit.classList.add('hidden');
- btnCloseFooter.classList.remove('hidden');
- if (currentAsset) fillFormData(currentAsset);
- }
- };
-
- function fillFormData(asset: HardwareAsset) {
- (document.getElementById('storage-asset-id') as HTMLInputElement).value = asset.id;
- (document.getElementById('storage-법인') as HTMLInputElement).value = asset.법인;
- (document.getElementById('storage-유형') as HTMLInputElement).value = asset.storage유형 || 'NAS';
- (document.getElementById('storage-자산코드') as HTMLInputElement).value = asset.자산코드;
- (document.getElementById('storage-명칭') as HTMLInputElement).value = asset.명칭;
- (document.getElementById('storage-위치') as HTMLInputElement).value = asset.위치 || '';
- (document.getElementById('storage-모델명') as HTMLInputElement).value = asset.모델명 || '';
- (document.getElementById('storage-용량') as HTMLInputElement).value = asset.용량 || '';
- (document.getElementById('storage-담당자_정') as HTMLInputElement).value = asset.담당자_정 || '';
- (document.getElementById('storage-IP주소') as HTMLInputElement).value = asset.IP주소 || '';
- (document.getElementById('storage-구매일') as HTMLInputElement).value = asset.구매일 || '';
- (document.getElementById('storage-금액') as HTMLInputElement).value = asset.금액 || '';
- }
-
btnRevertEdit?.addEventListener('click', () => setEditMode(false));
btnCloseHeader?.addEventListener('click', closeModals);
btnCloseFooter?.addEventListener('click', closeModals);
diff --git a/src/core/excelHandler.ts b/src/core/excelHandler.ts
index 967b14f..618a77a 100644
--- a/src/core/excelHandler.ts
+++ b/src/core/excelHandler.ts
@@ -38,6 +38,7 @@ export interface HardwareAsset {
서버PW?: string;
모니터링?: string;
비고?: string;
+ 현사용조직?: string;
}
diff --git a/src/core/state.ts b/src/core/state.ts
index 00207ed..2e5294c 100644
--- a/src/core/state.ts
+++ b/src/core/state.ts
@@ -14,7 +14,9 @@ const dummy = generateDummyData();
// 서버 데이터만 실제 데이터로 교체
const mergedHw: HardwareAsset[] = [
...dummy.hw.filter(a => a.type !== '서버'),
- ...realServerData.map(s => ({
+ ...realServerData.map((serverData: any) => {
+ const s = serverData;
+ return {
id: s.id || Math.random().toString(36).substring(2, 9),
type: '서버',
법인: s.법인,
@@ -47,7 +49,7 @@ const mergedHw: HardwareAsset[] = [
서버PW: s.서버PW || '',
모니터링: s.모니터링 || '',
비고: s.비고 || ''
- }))
+ }})
];
// --- Initial State ---
diff --git a/src/styles/common.css b/src/styles/common.css
index 590469c..7502ac7 100644
--- a/src/styles/common.css
+++ b/src/styles/common.css
@@ -6,6 +6,8 @@
--text-muted: #6B7280;
--border-color: #E5E7EB;
--bg-color: #F9FAFB;
+ --bg-light: #FAFAFA;
+ --sidebar-bg: #ffffff;
--white: #FFFFFF;
--danger: #dc2626;
diff --git a/src/styles/modal.css b/src/styles/modal.css
index 4f6b79c..43aeb87 100644
--- a/src/styles/modal.css
+++ b/src/styles/modal.css
@@ -265,3 +265,78 @@
color: var(--text-muted);
font-size: 0.8125rem;
}
+
+/* Dashboard Detail Modal Table Fixed Header */
+#dashboard-detail-modal .modal-body {
+ overflow-y: auto;
+ max-height: calc(80vh - 120px);
+ padding: 0;
+}
+
+/* 모달 내부의 table-container 기존 전역 스타일 무력화 */
+#dashboard-detail-modal .table-container {
+ border: none;
+ border-radius: 0;
+ box-shadow: none;
+ max-height: none;
+ overflow: visible;
+}
+
+#dashboard-detail-modal table {
+ width: 100%;
+ border-collapse: separate;
+ border-spacing: 0;
+}
+
+#dashboard-detail-modal thead th {
+ position: sticky;
+ top: 0;
+ background-color: var(--bg-light);
+ z-index: 10;
+ border-bottom: 2px solid var(--border-color);
+ box-shadow: none;
+ padding: 0.75rem 1rem;
+ font-size: 0.8125rem;
+ font-weight: 600;
+ color: var(--text-main);
+ text-align: left;
+ white-space: nowrap;
+}
+
+#dashboard-detail-modal tbody td {
+ padding: 0.75rem 1rem;
+ border-bottom: 1px solid var(--border-color);
+ font-size: 0.8125rem;
+ color: var(--text-main);
+ white-space: nowrap;
+}
+
+#dashboard-detail-modal tbody tr:last-child td {
+ border-bottom: none;
+}
+
+#dashboard-detail-modal tbody tr:hover {
+ background-color: var(--bg-light);
+}
+
+/* 뱃지 스타일 (대시보드 상세 목록용) */
+#dashboard-detail-modal .badge {
+ display: inline-block;
+ padding: 0.125rem 0.5rem;
+ border-radius: 4px;
+ font-size: 0.75rem;
+ font-weight: 500;
+ line-height: 1.5;
+}
+
+#dashboard-detail-modal .badge-outline {
+ border: 1px solid var(--primary-color);
+ color: var(--primary-color);
+ background: var(--primary-light);
+}
+
+#dashboard-detail-modal .badge-sw {
+ border: 1px solid #3b82f6;
+ color: #3b82f6;
+ background: #eff6ff;
+}
diff --git a/src/views/AssetTableView.ts b/src/views/AssetTableView.ts
index 89391ea..a665c6b 100644
--- a/src/views/AssetTableView.ts
+++ b/src/views/AssetTableView.ts
@@ -42,8 +42,8 @@ export function renderTable(mainContent: HTMLElement) {
createIcons({
icons: { Download, Upload, FileSpreadsheet, Plus, X, LayoutDashboard, Monitor, Server, Database, Laptop, CalendarClock, Key, Cpu, Layers, Users, Paperclip, Edit2, RefreshCcw }
});
- } catch (err) {
+ } catch (err: any) {
console.error('❌ Error rendering table view:', err);
- mainContent.innerHTML = `
목록을 불러오는 중 오류가 발생했습니다: ${err.message}
`;
+ mainContent.innerHTML = `
목록을 불러오는 중 오류가 발생했습니다: ${err?.message || err}
`;
}
}
diff --git a/src/views/List/SwListView.ts b/src/views/List/SwListView.ts
index cfd9607..04073b5 100644
--- a/src/views/List/SwListView.ts
+++ b/src/views/List/SwListView.ts
@@ -44,6 +44,7 @@ export function renderSwList(container: HTMLElement) {
| No. |
+ 상태 |
분야 |
법인 |
부서 |
@@ -81,7 +82,7 @@ export function renderSwList(container: HTMLElement) {
tbody.innerHTML = '';
if (filtered.length === 0) {
- tbody.innerHTML = `
| 검색 결과가 없습니다. |
`;
+ tbody.innerHTML = `| 검색 결과가 없습니다. |
`;
return;
}
@@ -89,11 +90,40 @@ export function renderSwList(container: HTMLElement) {
const assigned = state.masterData.swUsers.filter(u => u.swId === asset.id).length;
const qty = typeof asset.수량 === 'number' ? asset.수량 : parseInt(asset.수량||'0', 10);
const avail = qty - assigned;
+
+ let statusHtml = '';
+ if (isSub) {
+ let isExpired = false;
+ if (asset.구독일) {
+ const parts = asset.구독일.split('~');
+ const endDateStr = parts[parts.length - 1].trim().replace(/\./g, '-');
+ const endDate = new Date(endDateStr);
+ if (!isNaN(endDate.getTime())) {
+ endDate.setHours(23, 59, 59, 999);
+ if (endDate < new Date()) {
+ isExpired = true;
+ }
+ }
+ }
+ if (isExpired) {
+ statusHtml = `만료`;
+ } else {
+ statusHtml = `사용중`;
+ }
+ } else {
+ if (asset.유지보수여부) {
+ statusHtml = `유효`;
+ } else {
+ statusHtml = `없음`;
+ }
+ }
+
const tr = document.createElement('tr');
tr.style.cursor = 'pointer';
tr.innerHTML = `
${idx+1} |
+ ${statusHtml} |
${asset.분야||''} |
${asset.법인} |
${asset.부서||''} |
diff --git a/tsconfig.json b/tsconfig.json
index 75abdef..38c5bb0 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -15,8 +15,8 @@
/* Linting */
"strict": true,
- "noUnusedLocals": true,
- "noUnusedParameters": true,
+ "noUnusedLocals": false,
+ "noUnusedParameters": false,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]