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 { 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> { 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 ): 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); */