Files
edr-platform/apps/edr-freight-web/backoffice/src/pages/fleet/FuelStatsPage.tsx
natib21 ea8198f8a8 style: reduce horizontal padding on fleet dashboards
Add px="lg" (24px) to all Container components:
- FleetDashboard
- FuelPurchasePage
- FuelStatsPage
- MaintenancePage
- FinancialReportsPage
- TrackingPage

Reduces left/right padding from default to 24px,
making better use of horizontal screen space.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-30 14:13:58 +00:00

201 lines
6.7 KiB
TypeScript

import { useQuery } from "@tanstack/react-query";
import { Box, Card, Container, Grid, Group, Select, Stack, Table, Text, Title, Badge } from "@mantine/core";
import Breadcrumbs from "@/components/ui/Breadcrumbs";
import { api } from "@/auth/http";
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
import { vehiclesService, type Vehicle as VehicleType } from "@/services/vehicles.service";
import { useState } from "react";
interface FuelStats {
vehicleId: string;
totalPurchases: number;
totalLiters: number;
totalCost: number;
averagePricePerLiter: number;
dateRange: { startDate: string; endDate: string };
}
export default function FuelStatsPage() {
const [selectedVehicleId, setSelectedVehicleId] = useState<string>("");
const [monthsBack, setMonthsBack] = useState<string>("12");
// Fetch vehicles
const { data: vehiclesData } = useQuery({
queryKey: QUERY_KEYS.VEHICLES.list(),
queryFn: async () => {
const res = await vehiclesService.getAll({ limit: 1000 });
return res.data || [];
},
});
// Fetch fuel stats
const { data: statsData } = useQuery({
queryKey: ["fuel-stats", selectedVehicleId, monthsBack],
queryFn: async () => {
if (!selectedVehicleId) return null;
const res = await api.get(`/fuel/stats/${selectedVehicleId}?months=${monthsBack}`);
return res.data;
},
enabled: !!selectedVehicleId,
});
const vehicleOptions =
vehiclesData?.map((v: VehicleType) => ({
value: v.id,
label: `${v.plateNumber} - ${v.manufacturer} ${v.model}`,
})) || [];
const selectedVehicle = vehiclesData?.find((v: VehicleType) => v.id === selectedVehicleId);
const costPerKm =
statsData && selectedVehicle?.actualDistanceKm
? (statsData.totalCost / selectedVehicle.actualDistanceKm).toFixed(2)
: "—";
const efficiency = statsData
? (statsData.totalLiters > 0 ? (selectedVehicle?.actualDistanceKm || 0) / statsData.totalLiters : 0).toFixed(2)
: "—";
return (
<Container size="xl" py="xl" px="lg">
<Breadcrumbs items={[{ label: "Fleet" }, { label: "Fuel Management" }, { label: "Statistics" }]} />
<Group justify="space-between" mb="lg">
<Title order={1}>Fuel Consumption Analysis</Title>
</Group>
{/* Filters */}
<Card withBorder mb="lg" padding="md">
<Grid>
<Grid.Col span={{ base: 12, sm: 6 }}>
<Select
label="Vehicle"
placeholder="Select vehicle to analyze"
data={vehicleOptions}
value={selectedVehicleId}
onChange={(val) => setSelectedVehicleId(val || "")}
searchable
/>
</Grid.Col>
<Grid.Col span={{ base: 12, sm: 6 }}>
<Select
label="Period"
data={[
{ value: "3", label: "Last 3 months" },
{ value: "6", label: "Last 6 months" },
{ value: "12", label: "Last 12 months" },
]}
value={monthsBack}
onChange={(val) => setMonthsBack(val || "12")}
/>
</Grid.Col>
</Grid>
</Card>
{selectedVehicleId && statsData ? (
<>
{/* Stats Cards */}
<Grid mb="lg">
<Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
<Card withBorder padding="lg">
<Text size="sm" c="dimmed" fw={500}>
Total Purchases
</Text>
<Text fw={700} size="lg">
{statsData.totalPurchases}
</Text>
</Card>
</Grid.Col>
<Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
<Card withBorder padding="lg">
<Text size="sm" c="dimmed" fw={500}>
Total Fuel
</Text>
<Text fw={700} size="lg">
{statsData.totalLiters.toFixed(2)} L
</Text>
</Card>
</Grid.Col>
<Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
<Card withBorder padding="lg">
<Text size="sm" c="dimmed" fw={500}>
Total Cost
</Text>
<Text fw={700} size="lg">
ETB {statsData.totalCost.toLocaleString("en-US", { maximumFractionDigits: 2 })}
</Text>
</Card>
</Grid.Col>
<Grid.Col span={{ base: 12, sm: 6, md: 3 }}>
<Card withBorder padding="lg">
<Text size="sm" c="dimmed" fw={500}>
Avg Price/L
</Text>
<Text fw={700} size="lg">
ETB {statsData.averagePricePerLiter.toFixed(2)}
</Text>
</Card>
</Grid.Col>
</Grid>
{/* Efficiency Metrics */}
<Grid mb="lg">
<Grid.Col span={{ base: 12, sm: 6 }}>
<Card withBorder padding="lg">
<Text size="sm" c="dimmed" fw={500}>
Fuel Efficiency
</Text>
<Text fw={700} size="lg">
{efficiency} km/L
</Text>
</Card>
</Grid.Col>
<Grid.Col span={{ base: 12, sm: 6 }}>
<Card withBorder padding="lg">
<Text size="sm" c="dimmed" fw={500}>
Cost per KM
</Text>
<Text fw={700} size="lg">
ETB {costPerKm}
</Text>
</Card>
</Grid.Col>
</Grid>
{/* Summary */}
<Card withBorder padding="lg">
<Stack gap="md">
<div>
<Text fw={600} mb="xs">
Summary
</Text>
<Text size="sm">
{selectedVehicle?.plateNumber} consumed{" "}
<Text fw={700} span>
{statsData.totalLiters.toFixed(2)} liters
</Text>{" "}
over the last {monthsBack} months, costing{" "}
<Text fw={700} span>
ETB {statsData.totalCost.toLocaleString("en-US", { maximumFractionDigits: 2 })}
</Text>
. Average fuel price was{" "}
<Text fw={700} span>
ETB {statsData.averagePricePerLiter.toFixed(2)} per liter
</Text>
.
</Text>
</div>
</Stack>
</Card>
</>
) : (
<Card withBorder padding="lg">
<Text c="dimmed" ta="center">
Select a vehicle to view fuel consumption statistics
</Text>
</Card>
)}
</Container>
);
}