208 lines
6.8 KiB
TypeScript
208 lines
6.8 KiB
TypeScript
import { apiClient } from './client';
|
|
|
|
// Frontend Interface (CamelCase)
|
|
export interface Asset {
|
|
id: string;
|
|
parentId?: string; // DB: parent_id
|
|
parentName?: string; // Joined
|
|
name: string;
|
|
category: string;
|
|
model: string; // DB: model_name
|
|
serialNumber: string; // DB: serial_number
|
|
manufacturer: string;
|
|
location: string;
|
|
purchaseDate: string; // DB: purchase_date
|
|
manager: string;
|
|
status: 'active' | 'maintain' | 'broken' | 'disposed';
|
|
purchasePrice?: number; // DB: purchase_price
|
|
image?: string; // DB: image_url
|
|
calibrationCycle?: string; // DB: calibration_cycle
|
|
specs?: string;
|
|
quantity?: number;
|
|
children?: Partial<Asset>[]; // List of sub-assets
|
|
}
|
|
|
|
// DB Interface (SnakeCase) - for internal mapping
|
|
interface DBAsset {
|
|
id: string;
|
|
parent_id?: string;
|
|
parent_name?: string; // Joined or added in response
|
|
name: string;
|
|
category: string;
|
|
model_name: string;
|
|
serial_number: string;
|
|
manufacturer: string;
|
|
location: string;
|
|
purchase_date: string;
|
|
manager: string;
|
|
status: 'active' | 'maintain' | 'broken' | 'disposed';
|
|
purchase_price?: number;
|
|
image_url?: string;
|
|
calibration_cycle: string;
|
|
specs: string;
|
|
quantity?: number;
|
|
created_at: string;
|
|
updated_at: string;
|
|
children?: any[];
|
|
}
|
|
|
|
export interface MaintenanceRecord {
|
|
id: number;
|
|
asset_id: string;
|
|
maintenance_date: string;
|
|
type: string;
|
|
content: string;
|
|
image_url?: string; // Legacy
|
|
images?: string[]; // New: Multiple images
|
|
created_at?: string;
|
|
parts?: PartUsage[];
|
|
}
|
|
|
|
export interface PartUsage {
|
|
id?: number; // maintenance_parts id
|
|
part_id: string; // asset id
|
|
part_name?: string; // joined
|
|
model_name?: string; // joined
|
|
quantity: number;
|
|
}
|
|
|
|
// Manual Interface
|
|
export interface Manual {
|
|
id: number;
|
|
asset_id: string;
|
|
file_name: string;
|
|
file_url: string;
|
|
created_at?: string;
|
|
}
|
|
|
|
export const assetApi = {
|
|
getAll: async (): Promise<Asset[]> => {
|
|
try {
|
|
const response = await apiClient.get<DBAsset[]>('/assets');
|
|
if (!response.data || !Array.isArray(response.data)) return [];
|
|
return response.data.map(mapDBToAsset);
|
|
} catch (err) {
|
|
console.error('API Error in getAll:', err);
|
|
throw err;
|
|
}
|
|
},
|
|
|
|
getById: async (id: string): Promise<Asset> => {
|
|
const response = await apiClient.get<DBAsset>(`/assets/${id}`);
|
|
const asset = mapDBToAsset(response.data);
|
|
if (response.data.children) {
|
|
asset.children = response.data.children.map(c => ({
|
|
id: c.id,
|
|
name: c.name,
|
|
category: c.category,
|
|
status: c.status,
|
|
location: c.location
|
|
}));
|
|
}
|
|
if (response.data.parent_name) {
|
|
asset.parentName = response.data.parent_name;
|
|
}
|
|
return asset;
|
|
},
|
|
|
|
create: (data: Partial<Asset>) => {
|
|
const dbData = mapAssetToDB(data);
|
|
return apiClient.post<{ message: string, id: string }>('/assets', dbData);
|
|
},
|
|
|
|
update: (id: string, data: Partial<Asset>) => {
|
|
const dbData = mapAssetToDB(data);
|
|
return apiClient.put(`/assets/${id}`, dbData);
|
|
},
|
|
|
|
uploadImage: (file: File) => {
|
|
const formData = new FormData();
|
|
formData.append('image', file);
|
|
return apiClient.post<{ url: string }>('/upload', formData, {
|
|
headers: { 'Content-Type': 'multipart/form-data' }
|
|
});
|
|
},
|
|
|
|
// Maintenance History
|
|
getMaintenanceHistory: async (assetId: string): Promise<MaintenanceRecord[]> => {
|
|
const response = await apiClient.get<any[]>(`/assets/${assetId}/maintenance`);
|
|
return response.data.map(record => ({
|
|
...record,
|
|
// Ensure images is parsed as array if it comes as string from DB
|
|
images: typeof record.images === 'string' ? JSON.parse(record.images) : (record.images || [])
|
|
}));
|
|
},
|
|
|
|
addMaintenance: async (assetId: string, data: Partial<MaintenanceRecord>) => {
|
|
return apiClient.post(`/assets/${assetId}/maintenance`, data);
|
|
},
|
|
|
|
deleteMaintenance: async (id: number) => {
|
|
return apiClient.delete(`/maintenance/${id}`);
|
|
},
|
|
|
|
updateMaintenance: async (id: number, data: Partial<MaintenanceRecord>) => {
|
|
return apiClient.put(`/maintenance/${id}`, data);
|
|
},
|
|
|
|
// Manuals / Instructions
|
|
getManuals: async (assetId: string): Promise<Manual[]> => {
|
|
const response = await apiClient.get<Manual[]>(`/assets/${assetId}/manuals`);
|
|
return response.data;
|
|
},
|
|
|
|
addManual: async (assetId: string, data: { file_name: string; file_url: string }) => {
|
|
return apiClient.post(`/assets/${assetId}/manuals`, data);
|
|
},
|
|
|
|
deleteManual: async (id: number) => {
|
|
return apiClient.delete(`/manuals/${id}`);
|
|
},
|
|
|
|
// Accessories
|
|
getAccessories: async (assetId: string): Promise<any[]> => {
|
|
const response = await apiClient.get<any[]>(`/assets/${assetId}/accessories`);
|
|
return response.data;
|
|
},
|
|
|
|
addAccessory: async (assetId: string, data: { name: string, spec: string, quantity: number }) => {
|
|
return apiClient.post(`/assets/${assetId}/accessories`, data);
|
|
},
|
|
|
|
deleteAccessory: async (id: number) => {
|
|
return apiClient.delete(`/accessories/${id}`);
|
|
}
|
|
};
|
|
|
|
// Helper Mappers
|
|
const mapDBToAsset = (db: DBAsset): Asset => ({
|
|
id: db.id,
|
|
parentId: db.parent_id,
|
|
name: db.name,
|
|
category: db.category,
|
|
model: db.model_name || '',
|
|
serialNumber: db.serial_number || '',
|
|
manufacturer: db.manufacturer || '',
|
|
location: db.location || '',
|
|
purchaseDate: db.purchase_date ? new Date(db.purchase_date).toISOString().split('T')[0] : '', // Format YYYY-MM-DD
|
|
manager: db.manager || '',
|
|
status: db.status,
|
|
purchasePrice: db.purchase_price,
|
|
image: db.image_url,
|
|
calibrationCycle: db.calibration_cycle || '',
|
|
specs: db.specs || '',
|
|
quantity: db.quantity
|
|
});
|
|
|
|
const mapAssetToDB = (asset: Partial<Asset>): Partial<DBAsset> => {
|
|
const db: any = { ...asset };
|
|
if (asset.parentId !== undefined) { db.parent_id = asset.parentId; delete db.parentId; }
|
|
if (asset.model !== undefined) { db.model_name = asset.model; delete db.model; }
|
|
if (asset.serialNumber !== undefined) { db.serial_number = asset.serialNumber; delete db.serialNumber; }
|
|
if (asset.purchaseDate !== undefined) { db.purchase_date = asset.purchaseDate; delete db.purchaseDate; }
|
|
if (asset.purchasePrice !== undefined) { db.purchase_price = asset.purchasePrice; delete db.purchasePrice; }
|
|
if (asset.image !== undefined) { db.image_url = asset.image; delete db.image; }
|
|
if (asset.calibrationCycle !== undefined) { db.calibration_cycle = asset.calibrationCycle; delete db.calibrationCycle; }
|
|
return db;
|
|
};
|