tracreport/src/reports/reports.ts

103 lines
2.8 KiB
TypeScript

interface BaseReport {
unitNumber: string;
reported: string;
comments?: string;
utcTimestamp: Date;
faults: Fault[];
}
interface Fault {
coach: string;
zone: string;
}
export interface GroupedUnitReport {
unitNumber: string;
vehicles: VehicleReport[];
comments: string[];
}
export interface VehicleReport {
vehicleNumber: string;
cabReports: number;
saloonReports: number;
hasCabZone: boolean;
}
async function fetchReports(): Promise<BaseReport[]> {
try {
const res = await fetch('https://rep.fjla.uk/fetch');
if (!res.ok) throw new Error(`Fetch failed: ${res.status} ${res.statusText}`);
const rawData = await res.json();
const reports: BaseReport[] = rawData.map((item: any) => ({
unitNumber: item.unitNumber,
reported: item.reported,
comments: item.comments && item.comments.trim().toLowerCase() !== 'none'
? item.comments
: undefined,
utcTimestamp: new Date(item.utcTimestamp),
faults: item.faults,
}));
return reports;
} catch (err) {
console.error('Error fetching reports:', err);
throw err;
}
}
async function fetchUnitLayout(): Promise<Record<string, { id: string; zones: string[] }[]>> {
const res = await fetch('https://rep.fjla.uk/units.converted.json');
if (!res.ok) throw new Error(`Failed to fetch unit layout: ${res.statusText}`);
return await res.json();
}
function buildInitialReportStructure(
unitLayout: Record<string, { id: string; zones: string[] }[]>
): GroupedUnitReport[] {
return Object.entries(unitLayout).map(([unitNumber, vehicles]) => ({
unitNumber,
comments: [],
vehicles: vehicles.map(v => ({
vehicleNumber: v.id,
saloonReports: 0,
cabReports: 0,
hasCabZone: v.zones.includes('cab'),
}))
}));
};
function populateFaultReports(
grouped: GroupedUnitReport[],
reports: BaseReport[]
): GroupedUnitReport[] {
const unitMap = new Map(grouped.map(u => [u.unitNumber, u]));
for (const report of reports) {
const unit = unitMap.get(report.unitNumber);
if (!unit) continue;
if (report.comments) unit.comments.push(report.comments);
for (const fault of report.faults) {
const vehicle = unit.vehicles.find(v => v.vehicleNumber === fault.coach);
if (!vehicle) continue;
const zone = fault.zone.toLowerCase();
if (zone === 'cab') vehicle.cabReports++;
else vehicle.saloonReports++;
}
}
return grouped;
}
/* USAGE:
const unitLayout = await fetchUnitLayout();
const reports = await fetchReports();
const grouped = buildInitialReportStructure(unitLayout);
const finalReport = populateFaultReports(grouped, reports);
*/