All checks were successful
Deploy to Production / deploy (push) Successful in 1m37s
Add import, sync, and push capabilities between factoryOps and the digital-twin (BaSyx AAS) backend. Includes: - Equipment sync service with field mapping and LWW conflict resolution - Import preview modal with already-imported detection - Bidirectional sync (pull updates + push local changes) - Sync history tracking via equipment_sync_history table - Machine detail page shows sync status and change history - Docker networking for container-to-container communication - UI fixes: responsive layout (375px), touch targets, section spacing - 30 test cases for sync service
215 lines
5.5 KiB
TypeScript
215 lines
5.5 KiB
TypeScript
import useSWR from 'swr';
|
|
import { fetcher, getTenantUrl } from './api';
|
|
import type { Tenant, Machine, MachineDetail, EquipmentPart, InspectionTemplate, InspectionSession, PartReplacementLog, Alarm, AlarmSummary, ChangeHistoryItem } from './types';
|
|
|
|
export function useTenants() {
|
|
const { data, error, isLoading, mutate } = useSWR<{ tenants: Tenant[] }>(
|
|
'/api/tenants',
|
|
fetcher,
|
|
);
|
|
|
|
return {
|
|
tenants: data?.tenants || [],
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|
|
|
|
export function useTenantData<T>(path: string, tenantId?: string) {
|
|
const url = tenantId ? getTenantUrl(path, tenantId) : null;
|
|
const { data, error, isLoading, mutate } = useSWR<T>(url, fetcher);
|
|
|
|
return {
|
|
data: data ?? null,
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|
|
|
|
export function useMachines(tenantId?: string) {
|
|
const url = tenantId ? `/api/${tenantId}/machines` : null;
|
|
const { data, error, isLoading, mutate } = useSWR<{ machines: Machine[] }>(
|
|
url,
|
|
fetcher,
|
|
{ refreshInterval: 30000, dedupingInterval: 2000 },
|
|
);
|
|
|
|
return {
|
|
machines: data?.machines || [],
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|
|
|
|
export function useMachine(tenantId?: string, machineId?: string) {
|
|
const url = tenantId && machineId ? `/api/${tenantId}/machines/${machineId}` : null;
|
|
const { data, error, isLoading, mutate } = useSWR<MachineDetail>(
|
|
url,
|
|
fetcher,
|
|
{ refreshInterval: 30000, dedupingInterval: 2000 },
|
|
);
|
|
|
|
return {
|
|
machine: data ?? null,
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|
|
|
|
export function useEquipmentParts(tenantId?: string, machineId?: string) {
|
|
const url = tenantId && machineId ? `/api/${tenantId}/machines/${machineId}/parts` : null;
|
|
const { data, error, isLoading, mutate } = useSWR<{ parts: EquipmentPart[] }>(
|
|
url,
|
|
fetcher,
|
|
{ refreshInterval: 30000, dedupingInterval: 2000 },
|
|
);
|
|
|
|
return {
|
|
parts: data?.parts || [],
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|
|
|
|
export function useTemplates(tenantId?: string, subjectType?: string) {
|
|
const params = subjectType ? `?subject_type=${subjectType}` : '';
|
|
const url = tenantId ? `/api/${tenantId}/templates${params}` : null;
|
|
const { data, error, isLoading, mutate } = useSWR<{ templates: InspectionTemplate[] }>(
|
|
url,
|
|
fetcher,
|
|
{ refreshInterval: 30000, dedupingInterval: 2000 },
|
|
);
|
|
|
|
return {
|
|
templates: data?.templates || [],
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|
|
|
|
export function useTemplate(tenantId?: string, templateId?: string) {
|
|
const url = tenantId && templateId ? `/api/${tenantId}/templates/${templateId}` : null;
|
|
const { data, error, isLoading, mutate } = useSWR<InspectionTemplate>(
|
|
url,
|
|
fetcher,
|
|
{ refreshInterval: 30000, dedupingInterval: 2000 },
|
|
);
|
|
|
|
return {
|
|
template: data ?? null,
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|
|
|
|
export function useReplacements(tenantId?: string, partId?: string) {
|
|
const url = tenantId && partId ? `/api/${tenantId}/parts/${partId}/replacements` : null;
|
|
const { data, error, isLoading, mutate } = useSWR<{ replacements: PartReplacementLog[] }>(
|
|
url,
|
|
fetcher,
|
|
{ dedupingInterval: 2000 },
|
|
);
|
|
|
|
return {
|
|
replacements: data?.replacements || [],
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|
|
|
|
export function useAlarms(tenantId?: string, isAcknowledged?: boolean) {
|
|
const params = new URLSearchParams();
|
|
if (isAcknowledged !== undefined) params.set('is_acknowledged', String(isAcknowledged));
|
|
const qs = params.toString();
|
|
const url = tenantId ? `/api/${tenantId}/alarms${qs ? `?${qs}` : ''}` : null;
|
|
const { data, error, isLoading, mutate } = useSWR<{ alarms: Alarm[] }>(
|
|
url,
|
|
fetcher,
|
|
{ refreshInterval: 10000, dedupingInterval: 2000 },
|
|
);
|
|
|
|
return {
|
|
alarms: data?.alarms || [],
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|
|
|
|
export function useAlarmSummary(tenantId?: string) {
|
|
const url = tenantId ? `/api/${tenantId}/alarms/summary` : null;
|
|
const { data, error, isLoading, mutate } = useSWR<AlarmSummary>(
|
|
url,
|
|
fetcher,
|
|
{ refreshInterval: 10000, dedupingInterval: 2000 },
|
|
);
|
|
|
|
return {
|
|
summary: data ?? null,
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|
|
|
|
export function useInspections(tenantId?: string, status?: string, templateId?: string) {
|
|
const params = new URLSearchParams();
|
|
if (status) params.set('status', status);
|
|
if (templateId) params.set('template_id', templateId);
|
|
const qs = params.toString();
|
|
const url = tenantId ? `/api/${tenantId}/inspections${qs ? `?${qs}` : ''}` : null;
|
|
const { data, error, isLoading, mutate } = useSWR<{ inspections: InspectionSession[] }>(
|
|
url,
|
|
fetcher,
|
|
{ refreshInterval: 10000, dedupingInterval: 2000 },
|
|
);
|
|
|
|
return {
|
|
inspections: data?.inspections || [],
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|
|
|
|
export function useMachineHistory(tenantId?: string, machineId?: string) {
|
|
const url = tenantId && machineId ? `/api/${tenantId}/machines/${machineId}/history` : null;
|
|
const { data, error, isLoading, mutate } = useSWR<{ history: ChangeHistoryItem[]; total: number }>(
|
|
url,
|
|
fetcher,
|
|
{ dedupingInterval: 2000 },
|
|
);
|
|
|
|
return {
|
|
history: data?.history || [],
|
|
total: data?.total || 0,
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|
|
|
|
export function useInspection(tenantId?: string, inspectionId?: string) {
|
|
const url = tenantId && inspectionId ? `/api/${tenantId}/inspections/${inspectionId}` : null;
|
|
const { data, error, isLoading, mutate } = useSWR<InspectionSession>(
|
|
url,
|
|
fetcher,
|
|
{ refreshInterval: 5000, dedupingInterval: 2000 },
|
|
);
|
|
|
|
return {
|
|
inspection: data ?? null,
|
|
error,
|
|
isLoading,
|
|
mutate,
|
|
};
|
|
}
|