import { state } from '../core/state'; import { openHwModal } from '../components/Modal/HWModal'; import { ASSET_SCHEMA } from '../core/schema'; import { LOCATION_DATA, IMAGE_LOCATIONS } from '../components/Modal/SharedData'; /** * 위치 중심 자산 현황 뷰 (Refined) */ export async function renderLocationView(container: HTMLElement) { if (!container) return; // 로컬 상태 (UI 제어용) let currentLoc = '기술개발센터'; let currentDetail = '서버실'; let currentPage = 0; let mapConfig: any = {}; try { const res = await fetch('/api/maps'); mapConfig = await res.json(); } catch (err) { console.error('Failed to load map config', err); } const render = () => { const locImages = (IMAGE_LOCATIONS[currentLoc] && IMAGE_LOCATIONS[currentLoc][currentDetail]) ? IMAGE_LOCATIONS[currentLoc][currentDetail] : []; const mapPath = locImages[currentPage] || ''; // 자산이 등록된(좌표가 일치하는) 구역만 필터링하여 표시 const allBoxes = mapConfig[mapPath] || []; const boxes = allBoxes.filter((box: any) => state.masterData.hw.some(a => a.location === currentLoc && a.location_detail === currentDetail && String(a.loc_x) === String(box.x) && String(a.loc_y) === String(box.y) ) ); container.innerHTML = `
${locImages.length > 1 ? `
(${currentPage + 1} / ${locImages.length})
` : ''}
${mapPath ? `
${boxes.map((box: any, idx: number) => { const name = box.name || `#${idx+1}`; return `
`}).join('')}
` : '
해당 위치의 도면이 등록되지 않았습니다.
'}

📍 구역을 선택하세요

지도에서 자산 위치를 클릭하세요.

* 지도 위의 구역을 클릭하면 자산 상세 정보가 표시됩니다.

`; // 이미지 로드 및 윈도우 리사이즈 시 오버레이 크기와 위치를 이미지에 정확히 맞춤 const syncOverlaySize = () => { const img = container.querySelector('#main-map-img') as HTMLImageElement; const overlay = container.querySelector('#box-overlay') as HTMLElement; if (img && overlay && img.complete) { overlay.style.width = img.clientWidth + 'px'; overlay.style.height = img.clientHeight + 'px'; overlay.style.left = img.offsetLeft + 'px'; overlay.style.top = img.offsetTop + 'px'; } }; const img = container.querySelector('#main-map-img') as HTMLImageElement; if (img) { if (img.complete) { syncOverlaySize(); setTimeout(syncOverlaySize, 50); // 레이아웃 안정화 대기 } else { img.onload = syncOverlaySize; } } window.removeEventListener('resize', syncOverlaySize); window.addEventListener('resize', syncOverlaySize); // 이벤트 바인딩 const selMain = container.querySelector('#sel-loc-main') as HTMLSelectElement; selMain?.addEventListener('change', () => { currentLoc = selMain.value; currentDetail = LOCATION_DATA[currentLoc][0]; currentPage = 0; render(); }); const selDetail = container.querySelector('#sel-loc-detail') as HTMLSelectElement; selDetail?.addEventListener('change', () => { currentDetail = selDetail.value; currentPage = 0; render(); }); container.querySelector('#btn-prev-page')?.addEventListener('click', () => { currentPage--; render(); }); container.querySelector('#btn-next-page')?.addEventListener('click', () => { currentPage++; render(); }); container.querySelectorAll('.location-box-point').forEach(box => { box.addEventListener('click', () => { const x = box.getAttribute('data-x'); const y = box.getAttribute('data-y'); const targetAsset = state.masterData.hw.find(a => a.location === currentLoc && a.location_detail === currentDetail && String(a.loc_x) === String(x) && String(a.loc_y) === String(y) ); if (targetAsset) { renderAssetDetail(targetAsset); } container.querySelectorAll('.location-box-point').forEach(b => (b as HTMLElement).style.background = 'rgba(30, 81, 73, 0.1)'); (box as HTMLElement).style.background = 'rgba(30, 81, 73, 0.4)'; }); }); }; const renderAssetDetail = (asset: any) => { const title = container.querySelector('#loc-list-title')!; const tableContainer = container.querySelector('#loc-asset-table-container')!; title.innerHTML = `
📍 자산 상세 정보
`; const renderSection = (title: string, fields: { label: string; value: any }[]) => `
${title}
${fields.map(f => `
${f.label}
${f.value || '-'}
`).join('')}
`; const sectionsHTML = [ renderSection('기본 관리 정보', [ { label: ASSET_SCHEMA.ASSET_CODE.ui, value: asset.asset_code }, { label: ASSET_SCHEMA.PURCHASE_CORP.ui, value: asset.purchase_corp }, { label: ASSET_SCHEMA.CATEGORY.ui, value: asset.category }, { label: ASSET_SCHEMA.ASSET_TYPE.ui, value: asset.asset_type }, { label: ASSET_SCHEMA.HW_STATUS.ui, value: asset.hw_status } ]), renderSection('시스템 사양', [ { label: ASSET_SCHEMA.MODEL_NAME.ui, value: asset.model_name }, { label: ASSET_SCHEMA.OS.ui, value: asset.os }, { label: ASSET_SCHEMA.CPU.ui, value: asset.cpu }, { label: ASSET_SCHEMA.RAM.ui, value: asset.ram }, { label: ASSET_SCHEMA.GPU.ui, value: asset.gpu } ]), renderSection('네트워크 정보', [ { label: ASSET_SCHEMA.IP_ADDR.ui, value: asset.ip_address }, { label: ASSET_SCHEMA.MAC_ADDR.ui, value: asset.mac_address }, { label: ASSET_SCHEMA.REMOTE_TOOL.ui, value: asset.remote_tool } ]), renderSection('구매 및 기타', [ { label: ASSET_SCHEMA.PURCHASE_DATE.ui, value: asset.purchase_date }, { label: ASSET_SCHEMA.PURCHASE_AMOUNT.ui, value: asset.purchase_amount ? `${Number(asset.purchase_amount).toLocaleString()}원` : '-' }, { label: ASSET_SCHEMA.MEMO.ui, value: asset.memo } ]) ].join(''); tableContainer.innerHTML = `
${sectionsHTML}
`; container.querySelector('#btn-back-to-list')?.addEventListener('click', () => { title.textContent = `📍 구역을 선택하세요`; tableContainer.innerHTML = `
지도에서 자산 위치를 클릭하세요.
`; }); container.querySelector('#btn-edit-from-loc')?.addEventListener('click', () => { openHwModal(asset, 'edit'); }); }; render(); }