import { state } from '../core/state'; import { createIcons, Download, Upload, FileSpreadsheet, Plus, X, LayoutDashboard, Monitor, Server, Database, Laptop, CalendarClock, Key, Cpu, Layers, Users, Paperclip, Edit2, RefreshCcw } from 'lucide'; import { openPcModal } from '../components/Modal/PCModal'; import { openHwModal } from '../components/Modal/HWModal'; import { openStorageModal } from '../components/Modal/StorageModal'; import { openSwModal } from '../components/Modal/SWModal'; import { openSwUserModal } from '../components/Modal/SWUserModal'; /** * 자산 목록 테이블 렌더링 메인 함수 */ export function renderTable(mainContent: HTMLElement) { mainContent.innerHTML = ''; const container = document.createElement('div'); container.className = 'view-container'; const table = document.createElement('table'); if (state.activeCategory === 'hw') { renderHwTable(table, container, mainContent); } else { renderSwTable(table, container, mainContent); } createIcons({ icons: { Download, Upload, FileSpreadsheet, Plus, X, LayoutDashboard, Monitor, Server, Database, Laptop, CalendarClock, Key, Cpu, Layers, Users, Paperclip, Edit2 } }); } function renderHwTable(table: HTMLTableElement, container: HTMLElement, mainContent: HTMLElement) { const fullList = state.masterData.hw.filter(a => a.type === state.activeSubTab); container.innerHTML = ''; // --- 1. Search Bar (Unified Style) --- const filterBar = document.createElement('div'); filterBar.className = 'search-bar'; const corps = Array.from(new Set(fullList.map(a => a.법인))).filter(Boolean).sort(); const orgUnits = Array.from(new Set(fullList.map(a => a.현사용조직))).filter(Boolean).sort(); filterBar.innerHTML = `
${state.activeSubTab === '서버' ? `
` : ''} `; container.appendChild(filterBar); // --- 2. Table Structure (Unified Style) --- const tableWrapper = document.createElement('div'); tableWrapper.className = 'table-container'; if (state.activeSubTab === '개인PC') { table.innerHTML = `No법인자산코드사용자위치CPURAMStorage구매일금액품의서관리`; } else if (state.activeSubTab === '서버') { table.innerHTML = `No법인현 사용조직자산번호용도상세설치위치담당자IP주소모델명OSCPU/RAMStorage관리`; } else if (state.activeSubTab === '스토리지') { table.innerHTML = `No법인유형자산코드명칭위치모델명용량IP주소구매일관리`; } else { table.innerHTML = `No법인자산코드명칭위치관리자구매일금액관리`; } tableWrapper.appendChild(table); container.appendChild(tableWrapper); mainContent.appendChild(container); const tbody = document.getElementById('dynamic-tbody')!; const updateTable = () => { const keyword = (document.getElementById('filter-keyword') as HTMLInputElement).value.toLowerCase().trim(); const corp = (document.getElementById('filter-corp') as HTMLSelectElement).value; const orgUnit = (document.getElementById('filter-org-unit') as HTMLSelectElement)?.value || ''; const filtered = fullList.filter(asset => { const matchKeyword = !keyword || String(asset.자산코드||'').toLowerCase().includes(keyword) || String(asset.현사용조직||'').toLowerCase().includes(keyword) || String(asset.모델명||'').toLowerCase().includes(keyword); const matchCorp = !corp || asset.법인 === corp; const matchOrg = !orgUnit || asset.현사용조직 === orgUnit; return matchKeyword && matchCorp && matchOrg; }); tbody.innerHTML = ''; if (filtered.length === 0) { const colSpan = table.querySelectorAll('th').length; tbody.innerHTML = `검색 결과가 없습니다.`; return; } filtered.forEach((asset, idx) => { const tr = document.createElement('tr'); tr.style.cursor = 'pointer'; const formatInline = (v: any) => String(v || '').replace(/\n/g, ' / ').trim(); if (state.activeSubTab === '개인PC') { const storage = [asset.SSD1, asset.SSD2, asset.HDD1].filter(v => v).join(' / '); tr.innerHTML = `${idx+1}${asset.법인}${asset.자산코드}${asset.사용자||''}${asset.위치||''}${asset.CPU||''}${asset.RAM||''}${formatInline(storage)}${asset.구매일||''}${asset.금액||''}${asset.품의서명 ? '' : '-'}`; tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openPcModal(asset); }); } else if (state.activeSubTab === '서버') { const cpuRam = [asset.CPU, asset.RAM].filter(v => v).join(' / '); const storage = [asset.SSD1, asset.SSD2].filter(v => v).join(' / '); const ipInfo = [asset.IP주소, asset.IP2].filter(v => v).join(' / '); tr.innerHTML = `${idx+1}${asset.법인}${asset.현사용조직||''}${asset.자산코드}${formatInline(asset.용도)}${formatInline(asset.상세)}${formatInline(asset.위치)}${asset.담당자_정||''}${formatInline(ipInfo)}${asset.모델명||''}${asset.OS||''}${formatInline(cpuRam)}${formatInline(storage)}`; tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openHwModal(asset); }); } else if (state.activeSubTab === '스토리지') { tr.innerHTML = `${idx+1}${asset.법인}${asset.storage유형||''}${asset.자산코드}${asset.명칭}${asset.위치||''}${asset.모델명||''}${asset.용량||''}${asset.IP주소||''}${asset.구매일||''}`; tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openStorageModal(asset); }); } else { tr.innerHTML = `${idx+1}${asset.법인}${asset.자산코드}${asset.명칭}${asset.위치}${asset.관리자}${asset.구매일||''}${asset.금액||''}`; tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openHwModal(asset); }); } tbody.appendChild(tr); }); createIcons({ icons: { Paperclip, Edit2, RefreshCcw } }); }; const keywordInput = document.getElementById('filter-keyword') as HTMLInputElement; const corpSelect = document.getElementById('filter-corp') as HTMLSelectElement; const orgSelect = document.getElementById('filter-org-unit') as HTMLSelectElement; const resetBtn = document.getElementById('btn-reset-filters') as HTMLButtonElement; keywordInput.addEventListener('input', updateTable); corpSelect.addEventListener('change', updateTable); orgSelect?.addEventListener('change', updateTable); resetBtn.addEventListener('click', () => { keywordInput.value = ''; corpSelect.value = ''; if(orgSelect) orgSelect.value = ''; updateTable(); }); updateTable(); } function renderSwTable(table: HTMLTableElement, container: HTMLElement, mainContent: HTMLElement) { const fullList = state.masterData.sw.filter(a => a.type === state.activeSubTab); const isSub = state.activeSubTab === '구독SW'; container.innerHTML = ''; const filterBar = document.createElement('div'); filterBar.className = 'search-bar'; filterBar.innerHTML = `
`; container.appendChild(filterBar); const tableWrapper = document.createElement('div'); tableWrapper.className = 'table-container'; table.classList.add('sw-table'); table.innerHTML = `No.분야법인부서제품명구매일${isSub ? '구독일' : ''}금액수량사용가능관리`; tableWrapper.appendChild(table); container.appendChild(tableWrapper); mainContent.appendChild(container); const tbody = document.getElementById('dynamic-tbody')!; const updateTable = () => { const keyword = (document.getElementById('filter-keyword') as HTMLInputElement).value.toLowerCase().trim(); const field = (document.getElementById('filter-field') as HTMLSelectElement).value; const corp = (document.getElementById('filter-corp') as HTMLSelectElement).value; const filtered = fullList.filter(asset => { const matchKeyword = !keyword || (asset.제품명 || '').toLowerCase().includes(keyword) || (asset.부서 || '').toLowerCase().includes(keyword); const matchField = !field || asset.분야 === field; const matchCorp = !corp || asset.법인 === corp; return matchKeyword && matchField && matchCorp; }); tbody.innerHTML = ''; if (filtered.length === 0) { tbody.innerHTML = `검색 결과가 없습니다.`; return; } filtered.forEach((asset, idx) => { 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; const tr = document.createElement('tr'); tr.style.cursor = 'pointer'; tr.innerHTML = `${idx+1}${asset.분야||''}${asset.법인}${asset.부서||''}${asset.제품명}${asset.구매일||''}${isSub ? `${asset.구독일||''}` : ''}${asset.금액||'0'}${qty}${avail}`; tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openSwModal(asset); }); tr.querySelector('.btn-edit')?.addEventListener('click', () => openSwModal(asset)); tr.querySelector('.btn-users')?.addEventListener('click', () => openSwUserModal(asset)); tbody.appendChild(tr); }); createIcons({ icons: { Edit2, Users, RefreshCcw } }); }; const keywordInput = document.getElementById('filter-keyword') as HTMLInputElement; const fieldSelect = document.getElementById('filter-field') as HTMLSelectElement; const corpSelect = document.getElementById('filter-corp') as HTMLSelectElement; const resetBtn = document.getElementById('btn-reset-filters') as HTMLButtonElement; keywordInput.addEventListener('input', updateTable); fieldSelect.addEventListener('change', updateTable); corpSelect.addEventListener('change', updateTable); resetBtn.addEventListener('click', () => { keywordInput.value = ''; fieldSelect.value = ''; corpSelect.value = ''; updateTable(); }); updateTable(); }