fix(portal): Table has no size prop in BulkTruckUploadModal

This commit is contained in:
Hagernesh
2026-07-22 13:34:53 +00:00
parent cd3b2b3873
commit 15540f78e2
4 changed files with 159 additions and 1 deletions

View File

@@ -199,6 +199,7 @@ export const QUERY_KEYS = {
MAINTENANCE: {
ROOT: ["maintenance"] as const,
dueBoard: () => ["maintenance", "due-board"] as const,
schedules: (vehicleId?: string) =>
["maintenance", "schedules", vehicleId ?? "all"] as const,
upcoming: (vehicleId?: string) =>

View File

@@ -35,6 +35,21 @@ interface MaintenanceSchedule {
serviceProvider?: string;
}
interface DueBoardRow {
scheduleId: string;
vehicleId: string;
plateNumber: string;
maintenanceType: string;
description: string;
scheduledDate: string;
nextDueDate: string | null;
nextDueKm: number | null;
currentKm: number | null;
kmRemaining: number | null;
daysRemaining: number | null;
overdue: boolean;
}
const emptyForm = {
maintenanceType: 'PREVENTIVE',
description: '',
@@ -51,6 +66,16 @@ export function MaintenancePage() {
const [openScheduleModal, setOpenScheduleModal] = useState(false);
const [formData, setFormData] = useState(emptyForm);
// Maintenance is driven by time AND km, not a picked-then-scheduled action —
// this is the fleet-wide board of what's actually due, by date or mileage.
const { data: dueBoard, isLoading: dueLoading } = useQuery({
queryKey: QUERY_KEYS.MAINTENANCE.dueBoard(),
queryFn: async () => {
const res = await api.get('/maintenance/due-board');
return (res.data || []) as DueBoardRow[];
},
});
const { data: vehiclesData } = useQuery({
queryKey: QUERY_KEYS.VEHICLES.list(),
queryFn: async () => {
@@ -132,6 +157,62 @@ export function MaintenancePage() {
</Group>
<Stack gap="md">
<Card withBorder>
<Card.Section p="md" withBorder>
<Text fw={500}>Due Board by date and driven km</Text>
</Card.Section>
<Card.Section p="md">
{dueLoading ? (
<Text>Loading</Text>
) : dueBoard && dueBoard.length > 0 ? (
<Table striped highlightOnHover>
<Table.Thead>
<Table.Tr>
<Table.Th>Vehicle</Table.Th>
<Table.Th>Type</Table.Th>
<Table.Th>Next Due Date</Table.Th>
<Table.Th>Next Due Km</Table.Th>
<Table.Th>Current Km</Table.Th>
<Table.Th>Remaining</Table.Th>
<Table.Th>Status</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>
{dueBoard.map((row) => (
<Table.Tr
key={row.scheduleId}
onClick={() => setSelectedVehicle(row.vehicleId)}
style={{ cursor: 'pointer' }}
>
<Table.Td>{row.plateNumber}</Table.Td>
<Table.Td>{row.maintenanceType}</Table.Td>
<Table.Td>
{row.nextDueDate ? new Date(row.nextDueDate).toLocaleDateString() : '—'}
</Table.Td>
<Table.Td>{row.nextDueKm ?? '—'}</Table.Td>
<Table.Td>{row.currentKm ?? '—'}</Table.Td>
<Table.Td>
{row.kmRemaining != null
? `${row.kmRemaining} km`
: row.daysRemaining != null
? `${row.daysRemaining} d`
: '—'}
</Table.Td>
<Table.Td>
<Badge color={row.overdue ? 'edr-red' : 'edr-blue'}>
{row.overdue ? 'OVERDUE' : 'SCHEDULED'}
</Badge>
</Table.Td>
</Table.Tr>
))}
</Table.Tbody>
</Table>
) : (
<Text c="dimmed">Nothing scheduled fleet-wide</Text>
)}
</Card.Section>
</Card>
<Card withBorder padding="md">
<Select
label="Select Vehicle"