236 lines
6.4 KiB
TypeScript
236 lines
6.4 KiB
TypeScript
import { HardwareAsset, SoftwareAsset, SWUser, HardwareLog, MasterAssetData, SystemUser } from './types';
|
|
import { API_BASE_URL } from './utils';
|
|
import { dummyPCs, dummyServers, dummyStorages, dummyEquips, dummySubSw, dummyPermSw, dummyCloud, dummyDomain, dummySwUsers, dummyLogs } from './dummyData';
|
|
|
|
// --- State Definitions ---
|
|
export interface AppState {
|
|
activeCategory: 'dashboard' | 'hw' | 'sw' | 'ops' | 'vip' | 'fac' | 'users' | 'etc';
|
|
activeSubTab: string;
|
|
viewMode: 'location' | 'legacy' | 'list';
|
|
masterData: MasterAssetData;
|
|
activeCharts: any[];
|
|
currentUserRole: 'admin' | 'user';
|
|
listFilters?: Record<string, any>;
|
|
}
|
|
|
|
// 초기 상태
|
|
export const state: AppState = {
|
|
activeCategory: 'hw',
|
|
activeSubTab: '대시보드',
|
|
viewMode: 'location',
|
|
activeCharts: [],
|
|
currentUserRole: 'user',
|
|
listFilters: {},
|
|
masterData: {
|
|
users: [],
|
|
pc: [], server: [], storage: [], network: [],
|
|
survey: [], pcParts: [], partsMaster: [], equipment: [], officeSupplies: [],
|
|
swInternal: [], swExternal: [], cloud: [], domain: [],
|
|
cost: [], vip: [],
|
|
hw: [], sw: [],
|
|
swUsers: [], logs: [],
|
|
jobSpecs: [],
|
|
mobile: []
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 통합 V2 스키마에 맞춘 데이터 로드
|
|
*/
|
|
export async function loadMasterDataFromDB() {
|
|
try {
|
|
const response = await fetch(`${API_BASE_URL}/api/assets/master`);
|
|
if (!response.ok) throw new Error('Failed to fetch master data');
|
|
|
|
const data = await response.json();
|
|
|
|
// 전역 상태 업데이트
|
|
state.masterData = {
|
|
...state.masterData,
|
|
...data,
|
|
jobSpecs: data.jobSpecs || [],
|
|
logs: (data.logs || []).map((l: any) => ({
|
|
...l,
|
|
assetId: l.asset_id || l.assetId,
|
|
date: l.log_date || l.date,
|
|
user: l.log_user || l.user,
|
|
log_date: l.log_date || l.date,
|
|
log_user: l.log_user || l.user
|
|
}))
|
|
};
|
|
|
|
// Mapping for backward compatibility
|
|
(state.masterData as any).equip = state.masterData.equipment;
|
|
(state.masterData as any).subSw = state.masterData.swExternal;
|
|
(state.masterData as any).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('✅ V2 Normalized data loaded successfully');
|
|
return true;
|
|
} catch (err) {
|
|
console.warn('⚠️ Dummy 로드 실패:', err);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export function updateState(newState: Partial<AppState>) {
|
|
Object.assign(state, newState);
|
|
}
|
|
|
|
/**
|
|
* 자산 저장 (V2 Normalized API)
|
|
*/
|
|
export async function saveAsset(category: string, asset: any) {
|
|
try {
|
|
const url = `${API_BASE_URL}/api/asset/${category}/save`;
|
|
const response = await fetch(url, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(asset)
|
|
});
|
|
|
|
if (response.ok) {
|
|
await loadMasterDataFromDB(); // 전역 상태 갱신
|
|
return true;
|
|
}
|
|
} catch (err) {
|
|
console.error('자산 저장 실패:', err);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 자산 삭제 (V2 API)
|
|
*/
|
|
export async function deleteAsset(category: string, assetId: string) {
|
|
try {
|
|
const url = `${API_BASE_URL}/api/asset/${category}/${assetId}`;
|
|
const response = await fetch(url, { method: 'DELETE' });
|
|
|
|
if (response.ok) {
|
|
await loadMasterDataFromDB(); // 전역 상태 갱신
|
|
return true;
|
|
}
|
|
} catch (err) {
|
|
console.error('자산 삭제 실패:', err);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export async function savePartsMaster(component: any) {
|
|
try {
|
|
const url = `${API_BASE_URL}/api/hardware-components/save`;
|
|
const response = await fetch(url, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(component)
|
|
});
|
|
|
|
if (response.ok) {
|
|
await loadMasterDataFromDB(); // 전역 상태 갱신
|
|
return true;
|
|
}
|
|
} catch (err) {
|
|
console.error('부품 마스터 저장 실패:', err);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export async function deletePartsMaster(id: number) {
|
|
try {
|
|
const url = `${API_BASE_URL}/api/hardware-components/${id}`;
|
|
const response = await fetch(url, { method: 'DELETE' });
|
|
|
|
if (response.ok) {
|
|
await loadMasterDataFromDB(); // 전역 상태 갱신
|
|
return true;
|
|
}
|
|
} catch (err) {
|
|
console.error('부품 마스터 삭제 실패:', err);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export async function saveSystemUser(user: any) {
|
|
try {
|
|
const url = `${API_BASE_URL}/api/system-users/save`;
|
|
const response = await fetch(url, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(user)
|
|
});
|
|
if (response.ok) {
|
|
await loadMasterDataFromDB(); // 전역 상태 갱신
|
|
return true;
|
|
}
|
|
} catch (err) {
|
|
console.error('사용자 정보 저장 실패:', err);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export async function deleteSystemUser(id: string) {
|
|
try {
|
|
const url = `${API_BASE_URL}/api/system-users/${id}`;
|
|
const response = await fetch(url, { method: 'DELETE' });
|
|
if (response.ok) {
|
|
await loadMasterDataFromDB(); // 전역 상태 갱신
|
|
return true;
|
|
}
|
|
} catch (err) {
|
|
console.error('사용자 정보 삭제 실패:', err);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export async function saveJobSpec(spec: any) {
|
|
try {
|
|
const url = `${API_BASE_URL}/api/job-specs/save`;
|
|
const response = await fetch(url, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(spec)
|
|
});
|
|
|
|
if (response.ok) {
|
|
await loadMasterDataFromDB(); // 전역 상태 갱신
|
|
return true;
|
|
}
|
|
} catch (err) {
|
|
console.error('직무별 기준 사양 저장 실패:', err);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export async function deleteJobSpec(id: number) {
|
|
try {
|
|
const url = `${API_BASE_URL}/api/job-specs/${id}`;
|
|
const response = await fetch(url, { method: 'DELETE' });
|
|
|
|
if (response.ok) {
|
|
await loadMasterDataFromDB(); // 전역 상태 갱신
|
|
return true;
|
|
}
|
|
} catch (err) {
|
|
console.error('직무별 기준 사양 삭제 실패:', err);
|
|
}
|
|
return false;
|
|
}
|