feat: 자산 카테고리별 6개 전용 테이블 분리 및 백엔드 API, 프론트엔드 상태 관리 전면 개편 (개인PC, 서버, 스토리지, 전산비품, 구독SW, 영구SW)

This commit is contained in:
2026-04-17 17:25:52 +09:00
parent 6904925146
commit 415727a866
11 changed files with 409 additions and 593 deletions

View File

@@ -1,96 +1,64 @@
import { MasterAssetData, HardwareAsset } from './excelHandler';
import { generateDummyData } from './dummyDataGenerator';
import { realServerData } from './realServerData';
import { HardwareAsset, SoftwareAsset, SWUser, HardwareLog } from './excelHandler';
// --- State Definitions ---
export interface AppState {
masterData: MasterAssetData;
activeCategory: 'hw' | 'sw' | 'ops';
activeSubTab: string;
activeCharts: any[];
export interface MasterAssetData {
pc: HardwareAsset[];
server: HardwareAsset[];
storage: HardwareAsset[];
equip: HardwareAsset[];
subSw: SoftwareAsset[];
permSw: SoftwareAsset[];
swUsers: SWUser[];
logs: HardwareLog[];
}
const dummy = generateDummyData();
// 서버 데이터만 실제 데이터로 교체
const mergedHw: HardwareAsset[] = [
...dummy.hw.filter(a => a.type !== '서버'),
...realServerData.map((serverData: any) => {
const s = serverData;
return {
id: s.id || Math.random().toString(36).substring(2, 9),
type: '서버',
법인: s.법인,
자산코드: s.자산코드,
명칭: s.용도 || '',
위치: s.위치,
관리자: s.담당자_정 || '홍길동',
담당자_정: s.담당자_정 || '홍길동',
담당자_부: s.담당자_부 || '김철수',
IP주소: s.IP주소,
IP2: s.IP2 || '',
MACaddress: s.MACaddress || '',
HW사양: s.HW사양 || '',
OS: s.OS,
CPU: s.CPU,
RAM: s.RAM,
SSD1: s.SSD1,
SSD2: s.SSD2,
HDD1: s.HDD1,
storage유형: s.storage유형,
모델명: s.모델명,
구매일: s.구매일 || '',
금액: s.금액 || '',
납품업체: s.납품업체 || '',
품의서명: s.품의서명 || '',
용도: s.용도,
상세: s.상세,
원격접속: s.원격접속 || '',
서버ID: s.서버ID || '',
서버PW: s.서버PW || '',
모니터링: s.모니터링 || '',
비고: s.비고 || ''
}})
];
export interface AppState {
activeCategory: 'dashboard' | 'hw' | 'sw';
activeSubTab: string; // '대시보드', '개인PC', '서버', '스토리지', '전산비품', '구독SW', '영구SW'
masterData: MasterAssetData;
}
// --- Initial State ---
// 초기 상태
export const state: AppState = {
masterData: {
...dummy,
hw: mergedHw, // 기본적으로 하드코딩된 데이터를 가지고 시작
logs: []
},
activeCategory: 'hw',
activeCategory: 'dashboard',
activeSubTab: '대시보드',
activeCharts: []
masterData: {
pc: [],
server: [],
storage: [],
equip: [],
subSw: [],
permSw: [],
swUsers: [],
logs: []
}
};
/**
* DB에서 데이터 로드
* 전용 API 엔드포인트들로부터 데이터 로드
*/
export async function loadMasterDataFromDB() {
try {
const [hwRes, swRes, swUserRes] = await Promise.all([
fetch('http://localhost:3000/api/hw'),
fetch('http://localhost:3000/api/sw'),
fetch('http://localhost:3000/api/sw-users')
]);
const endpoints = [
{ key: 'pc', url: 'http://localhost:3000/api/pc' },
{ key: 'server', url: 'http://localhost:3000/api/server' },
{ key: 'storage', url: 'http://localhost:3000/api/storage' },
{ key: 'equip', url: 'http://localhost:3000/api/equip' },
{ key: 'subSw', url: 'http://localhost:3000/api/sw/sub' },
{ key: 'permSw', url: 'http://localhost:3000/api/sw/perm' },
{ key: 'swUsers', url: 'http://localhost:3000/api/sw-users' }
];
if (hwRes.ok) {
const hwData = await hwRes.json();
if (hwData && hwData.length > 0) state.masterData.hw = hwData;
const results = await Promise.all(endpoints.map(e => fetch(e.url)));
for (let i = 0; i < endpoints.length; i++) {
if (results[i].ok) {
const data = await results[i].json();
(state.masterData as any)[endpoints[i].key] = data || [];
}
}
if (swRes.ok) {
const swData = await swRes.json();
if (swData && swData.length > 0) state.masterData.sw = swData;
}
if (swUserRes.ok) {
const swUserData = await swUserRes.json();
if (swUserData && swUserData.length > 0) state.masterData.swUsers = swUserData;
}
console.log('✅ DB 데이터 로드 완료');
console.log('✅ 6개 테이블 데이터 로드 완료');
return true;
} catch (err) {
console.warn('⚠️ 백엔드 서버 연결 실패. 로컬 데이터를 유지합니다.');