import { HardwareAsset, SoftwareAsset, SWUser, HardwareLog } from './excelHandler'; import { API_BASE_URL } from './utils'; // --- State Definitions --- export interface MasterAssetData { users: any[]; pc: any[]; server: any[]; storage: any[]; network: any[]; survey: any[]; pcParts: any[]; equipment: any[]; officeSupplies: any[]; swInternal: any[]; swExternal: any[]; cloud: any[]; domain: any[]; cost: any[]; vip: any[]; mobile?: any[]; // Legacy mobile support equip?: any[]; // Backward compat // Backward compatibility subSw: any[]; permSw: any[]; swUsers: SWUser[]; logs: HardwareLog[]; // 통합 배열 hw: any[]; sw: any[]; } export interface AppState { activeCategory: 'dashboard' | 'hw' | 'sw' | 'ops' | 'vip' | 'fac' | 'users' | 'etc'; activeSubTab: string; masterData: MasterAssetData; activeCharts: any[]; currentUserRole: 'admin' | 'user'; } // 초기 상태 export const state: AppState = { activeCategory: 'hw', activeSubTab: '서버', // 대시보드 제거됨에 따라 기본값 변경 activeCharts: [], currentUserRole: 'user', masterData: { users: [], pc: [], server: [], storage: [], network: [], survey: [], pcParts: [], equipment: [], officeSupplies: [], swInternal: [], swExternal: [], cloud: [], domain: [], cost: [], vip: [], subSw: [], permSw: [], hw: [], sw: [], swUsers: [], logs: [] } }; /** * 신규 14개 테이블 구조에 맞춘 데이터 로드 */ export async function loadMasterDataFromDB() { try { const endpoints = [ { key: 'users', url: '/api/users' }, { key: 'pc', url: '/api/pc' }, { key: 'server', url: '/api/server' }, { key: 'storage', url: '/api/storage' }, { key: 'network', url: '/api/network' }, { key: 'survey', url: '/api/survey' }, { key: 'pcParts', url: '/api/pc-parts' }, { key: 'equipment', url: '/api/equipment' }, { key: 'officeSupplies', url: '/api/office-supplies' }, { key: 'swInternal', url: '/api/sw/internal' }, { key: 'swExternal', url: '/api/sw/external' }, { key: 'cloud', url: '/api/cloud' }, { key: 'domain', url: '/api/domain' }, { key: 'cost', url: '/api/cost' }, { key: 'vip', url: '/api/vip' }, { key: 'swUsers', url: '/api/asset/software/assignment' }, { key: 'logs', url: '/api/asset/history' } ]; const results = await Promise.all(endpoints.map(e => fetch(API_BASE_URL + e.url))); for (let i = 0; i < endpoints.length; i++) { if (results[i].ok) { const data = await results[i].json(); const key = endpoints[i].key; (state.masterData as any)[key] = Array.isArray(data) ? data : []; } } // Mapping for backward compatibility state.masterData.equip = state.masterData.equipment; state.masterData.subSw = state.masterData.swExternal; state.masterData.permSw = state.masterData.swInternal; // 하드웨어 통합 (대시보드 호환용) state.masterData.hw = [ ...state.masterData.pc, ...state.masterData.server, ...state.masterData.storage, ...state.masterData.network, ...state.masterData.survey, ...state.masterData.equipment, ...state.masterData.officeSupplies ]; // 소프트웨어 통합 state.masterData.sw = [ ...state.masterData.swInternal, ...state.masterData.swExternal, ...state.masterData.cloud ]; console.log('✅ All data (including users) loaded and unified'); return true; } catch (err) { console.warn('⚠️ 서버 연결 실패:', err); } return false; } export function updateState(newState: Partial) { Object.assign(state, newState); } /** * 자산 저장 (Generic API) */ export async function saveAsset(category: string, asset: any) { try { const endpointMap: Record = { 'users': '/api/users/batch', 'pc': '/api/pc/batch', 'server': '/api/server/batch', 'storage': '/api/storage/batch', 'network': '/api/network/batch', 'survey': '/api/survey/batch', 'pcParts': '/api/pc-parts/batch', 'equipment': '/api/equipment/batch', 'officeSupplies': '/api/office-supplies/batch', 'swInternal': '/api/sw/internal/batch', 'swExternal': '/api/sw/external/batch', 'cloud': '/api/cloud/batch', 'domain': '/api/domain/batch', 'cost': '/api/cost/batch', 'vip': '/api/vip/batch' }; const url = `${API_BASE_URL}${endpointMap[category]}`; const currentList = [...(state.masterData as any)[category]]; const idx = currentList.findIndex(a => a.id === asset.id); if (idx > -1) currentList[idx] = asset; else currentList.push(asset); const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(currentList) }); if (response.ok) { await loadMasterDataFromDB(); // 전역 상태 갱신 return true; } } catch (err) { console.error('자산 저장 실패:', err); } return false; } /** * 자산 삭제 (Generic API - Batch 방식 활용) */ export async function deleteAsset(category: string, assetId: string) { try { const endpointMap: Record = { 'users': '/api/users/batch', 'pc': '/api/pc/batch', 'server': '/api/server/batch', 'storage': '/api/storage/batch', 'network': '/api/network/batch', 'survey': '/api/survey/batch', 'pcParts': '/api/pc-parts/batch', 'equipment': '/api/equipment/batch', 'officeSupplies': '/api/office-supplies/batch', 'swInternal': '/api/sw/internal/batch', 'swExternal': '/api/sw/external/batch', 'cloud': '/api/cloud/batch', 'domain': '/api/domain/batch', 'cost': '/api/cost/batch', 'vip': '/api/vip/batch' }; const url = `${API_BASE_URL}${endpointMap[category]}`; const currentList = [...(state.masterData as any)[category]]; const filteredList = currentList.filter(a => a.id !== assetId); const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(filteredList) }); if (response.ok) { await loadMasterDataFromDB(); // 전역 상태 갱신 return true; } } catch (err) { console.error('자산 삭제 실패:', err); } return false; }