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); const tableWrapper = document.createElement('div'); tableWrapper.className = 'table-container'; if (state.activeSubTab === '개인PC') { table.innerHTML = `No구매법인자산코드사용자위치CPUGPURAMSSD1SSD2HDD1HDD2구매일금액납품업체품의서관리`; tableWrapper.appendChild(table); container.appendChild(tableWrapper); mainContent.appendChild(container); const tbody = document.getElementById('dynamic-tbody')!; if (fullList.length === 0) { tbody.innerHTML = `등록된 자산이 없습니다.`; return; } fullList.forEach((asset, idx) => { const tr = document.createElement('tr'); tr.style.cursor = 'pointer'; tr.innerHTML = `${idx+1}${asset.법인}${asset.자산코드}${asset.사용자||''}${asset.위치||''}${asset.CPU||''}${asset.GPU||''}${asset.RAM||''}${asset.SSD1||'-'}${asset.SSD2||'-'}${asset.HDD1||'-'}${asset.HDD2||'-'}${asset.구매일||''}${asset.금액||''}${asset.납품업체||''}${asset.품의서명 ? '' : '-'}`; tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openPcModal(asset); }); tbody.appendChild(tr); }); } else if (state.activeSubTab === '스토리지') { table.innerHTML = `No구매법인유형자산코드명칭위치모델명용량담당자(정)IP주소구매일금액관리`; tableWrapper.appendChild(table); container.appendChild(tableWrapper); mainContent.appendChild(container); const tbody = document.getElementById('dynamic-tbody')!; if (fullList.length === 0) { tbody.innerHTML = `등록된 자산이 없습니다.`; return; } fullList.forEach((asset, idx) => { const tr = document.createElement('tr'); tr.style.cursor = 'pointer'; tr.innerHTML = `${idx+1}${asset.법인}${asset.storage유형||''}${asset.자산코드}${asset.명칭}${asset.위치||''}${asset.모델명||''}${asset.용량||''}${asset.담당자_정||''}${asset.IP주소||''}${asset.구매일||''}${asset.금액||''}`; tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openStorageModal(asset); }); tbody.appendChild(tr); }); } else if (state.activeSubTab === '서버') { // --- 서버 전용 필터 및 검색 기능 --- 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(); const types = Array.from(new Set(fullList.map(a => a.storage유형))).filter(Boolean).sort(); const locations = Array.from(new Set(fullList.map(a => { const loc = String(a.위치 || ''); if (loc.startsWith('서관') || loc.startsWith('동관')) return 'IDC'; return loc.split(' ')[0]; // 첫 단어 기준 (본사, 지사, 마천사무실 등) }))).filter(Boolean).sort(); filterBar.innerHTML = `
`; container.appendChild(filterBar); table.innerHTML = `No구매법인현 사용조직자산번호유형용도상세설치위치담당자모델명OSCPURAMStorage`; 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 type = (document.getElementById('filter-type') as HTMLSelectElement).value; const location = (document.getElementById('filter-location') as HTMLSelectElement).value; const filtered = fullList.filter(asset => { const formatAsset = (v: any) => String(v || '').toLowerCase(); const matchKeyword = !keyword || formatAsset(asset.자산코드).includes(keyword) || formatAsset(asset.용도).includes(keyword) || formatAsset(asset.상세).includes(keyword) || formatAsset(asset.모델명).includes(keyword) || formatAsset(asset.담당자_정).includes(keyword) || formatAsset(asset.현사용조직).includes(keyword) || formatAsset(asset.담당자_부).includes(keyword); const matchCorp = !corp || asset.법인 === corp; const matchOrgUnit = !orgUnit || asset.현사용조직 === orgUnit; const matchType = !type || asset.storage유형 === type; let matchLocation = true; if (location) { const loc = String(asset.위치 || ''); if (location === 'IDC') { matchLocation = loc.startsWith('서관') || loc.startsWith('동관'); } else { matchLocation = loc.includes(location); } } return matchKeyword && matchCorp && matchOrgUnit && matchType && matchLocation; }); tbody.innerHTML = ''; if (filtered.length === 0) { 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(); const getBadge = (text: string, bgColor: string) => `${text}`; const mainManager = asset.담당자_정 || ''; const subManager = asset.담당자_부 || ''; const managerHtml = [mainManager ? `${getBadge('정', '#1E5149')} ${mainManager}` : '', subManager ? `${getBadge('부', '#9CA3AF')} ${subManager}` : ''].filter(v => v !== '').join(' / '); const storageInfo = [asset.SSD1, asset.SSD2].filter(v => v && v !== '').join(' / '); let locationHtml = formatInline(asset.위치); if (locationHtml.startsWith('서관') || locationHtml.startsWith('동관')) { locationHtml = `IDC(${locationHtml})`; } tr.innerHTML = ` ${idx+1} ${formatInline(asset.법인)} ${formatInline(asset.현사용조직)} ${formatInline(asset.자산코드)} ${formatInline(asset.storage유형)} ${formatInline(asset.용도)} ${formatInline(asset.상세)} ${locationHtml} ${managerHtml} ${formatInline(asset.모델명)} ${formatInline(asset.OS)} ${formatInline(asset.CPU)} ${formatInline(asset.RAM)} ${formatInline(storageInfo)} `; tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openHwModal(asset); }); tbody.appendChild(tr); }); createIcons({ icons: { RefreshCcw, Paperclip } }); }; const keywordInput = document.getElementById('filter-keyword') as HTMLInputElement; const corpSelect = document.getElementById('filter-corp') as HTMLSelectElement; const typeSelect = document.getElementById('filter-type') as HTMLSelectElement; const locationSelect = document.getElementById('filter-location') as HTMLSelectElement; const resetBtn = document.getElementById('btn-reset-filters') as HTMLButtonElement; keywordInput.addEventListener('input', updateTable); corpSelect.addEventListener('change', updateTable); typeSelect.addEventListener('change', updateTable); locationSelect.addEventListener('change', updateTable); resetBtn.addEventListener('click', () => { keywordInput.value = ''; corpSelect.value = ''; typeSelect.value = ''; locationSelect.value = ''; updateTable(); }); updateTable(); } else { // 전산비품 table.innerHTML = `No구매법인${state.activeSubTab === '전산비품' ? '유형' : ''}자산코드명칭위치관리자구매일금액관리`; tableWrapper.appendChild(table); container.appendChild(tableWrapper); mainContent.appendChild(container); const tbody = document.getElementById('dynamic-tbody')!; const colCount = state.activeSubTab === '전산비품' ? 11 : 10; if (fullList.length === 0) { tbody.innerHTML = `등록된 자산이 없습니다.`; return; } fullList.forEach((asset, idx) => { const tr = document.createElement('tr'); tr.style.cursor = 'pointer'; tr.innerHTML = `${idx+1}${asset.법인}${state.activeSubTab === '전산비품' ? `${asset.비품유형||'-'}` : ''}${asset.자산코드}${asset.명칭}${asset.위치}${asset.관리자}${asset.구매일||''}${asset.금액||''}`; tr.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('button')) openHwModal(asset); }); tbody.appendChild(tr); }); } } 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(); }