mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
feat(fleet): make the dashboard stat cards link to their detail
The four headline cards — total vehicles, drivers, fuel spend, maintenance — were static numbers with no way through to the list behind them. Each now takes an optional href and, when set, wraps in a link to its detail page (vehicles, drivers, fuel purchases, maintenance). A card without an href stays exactly as before. The Card is wrapped rather than turned into a link so Mantine's Card typing stays clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import { useQuery } from '@tanstack/react-query';
|
||||
import { Card, Stack, Group, Grid, Text, ThemeIcon, Progress, Badge, Table, RingProgress, Container, Title, Box, Tabs } from '@mantine/core';
|
||||
import { Truck, Fuel, Wrench, AlertCircle, Users, User, MapPin } from 'lucide-react';
|
||||
import type { LucideIcon } from 'lucide-react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import Breadcrumbs from '@/components/ui/Breadcrumbs';
|
||||
import { QUERY_KEYS } from '@/constants/QUERY_KEYS';
|
||||
import { api } from '@/auth/http';
|
||||
@@ -51,28 +52,46 @@ interface StatCardProps {
|
||||
value: string | number;
|
||||
color?: string;
|
||||
change?: number;
|
||||
/** Detail route the card opens. When set the card is a link; otherwise static. */
|
||||
href?: string;
|
||||
}
|
||||
|
||||
const StatCard = ({ icon: Icon, label, value, color = 'edr-green', change }: StatCardProps) => (
|
||||
<Card withBorder p="lg" style={{ borderTop: `3px solid ${freightBrand.primary}` }}>
|
||||
<Group justify="space-between" mb="sm">
|
||||
<ThemeIcon size="xl" radius="md" color={color} variant="light">
|
||||
<Icon size={28} />
|
||||
</ThemeIcon>
|
||||
</Group>
|
||||
<Stack gap="xs">
|
||||
<Text size="xs" c="dimmed" fw={500} tt="uppercase">
|
||||
{label}
|
||||
</Text>
|
||||
<Group justify="space-between">
|
||||
<Text fw={700} size="xl" c="edr-ink">
|
||||
{value}
|
||||
</Text>
|
||||
{change && <Badge color={change > 0 ? 'edr-green' : 'edr-red'} size="lg">{change > 0 ? '+' : ''}{change}%</Badge>}
|
||||
const StatCard = ({ icon: Icon, label, value, color = 'edr-green', change, href }: StatCardProps) => {
|
||||
const card = (
|
||||
<Card withBorder p="lg" style={{ borderTop: `3px solid ${freightBrand.primary}`, height: '100%' }}>
|
||||
<Group justify="space-between" mb="sm">
|
||||
<ThemeIcon size="xl" radius="md" color={color} variant="light">
|
||||
<Icon size={28} />
|
||||
</ThemeIcon>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
<Stack gap="xs">
|
||||
<Text size="xs" c="dimmed" fw={500} tt="uppercase">
|
||||
{label}
|
||||
</Text>
|
||||
<Group justify="space-between">
|
||||
<Text fw={700} size="xl" c="edr-ink">
|
||||
{value}
|
||||
</Text>
|
||||
{change && <Badge color={change > 0 ? 'edr-green' : 'edr-red'} size="lg">{change > 0 ? '+' : ''}{change}%</Badge>}
|
||||
</Group>
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
|
||||
// Wrap in a link to the detail view rather than morphing the Card itself —
|
||||
// keeps Mantine's Card typing clean. Static when no href.
|
||||
return href ? (
|
||||
<Link
|
||||
to={href}
|
||||
aria-label={`${label} — view detail`}
|
||||
className="block h-full cursor-pointer no-underline transition-opacity hover:opacity-90"
|
||||
>
|
||||
{card}
|
||||
</Link>
|
||||
) : (
|
||||
card
|
||||
);
|
||||
};
|
||||
|
||||
export function FleetDashboard() {
|
||||
const { data: vehicles = [] } = useQuery({
|
||||
@@ -160,16 +179,16 @@ export function FleetDashboard() {
|
||||
{/* Primary Metrics */}
|
||||
<Grid mb="xl">
|
||||
<Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
|
||||
<StatCard icon={Truck} label="Total Vehicles" value={metrics.totalVehicles} color="edr-green" />
|
||||
<StatCard icon={Truck} label="Total Vehicles" value={metrics.totalVehicles} color="edr-green" href="/dashboard/vehicles" />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
|
||||
<StatCard icon={Users} label="Total Drivers" value={metrics.totalDrivers} color="edr-blue" />
|
||||
<StatCard icon={Users} label="Total Drivers" value={metrics.totalDrivers} color="edr-blue" href="/dashboard/drivers" />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
|
||||
<StatCard icon={Fuel} label="Fuel Spend" value={etb(metrics.totalFuelSpend)} color="edr-accent" />
|
||||
<StatCard icon={Fuel} label="Fuel Spend" value={etb(metrics.totalFuelSpend)} color="edr-accent" href="/dashboard/fuel-purchases" />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
|
||||
<StatCard icon={Wrench} label="Maintenance" value={etb(metrics.totalMaintenanceSpend)} color="edr-red" />
|
||||
<StatCard icon={Wrench} label="Maintenance" value={etb(metrics.totalMaintenanceSpend)} color="edr-red" href="/dashboard/maintenance" />
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user