Files
edr-platform/apps/edr-freight-web/backoffice/src/components/overview/OverviewKpiSection.tsx

168 lines
3.7 KiB
TypeScript

import {
AlertCircle,
Banknote,
Box,
Clock,
Container,
CreditCard,
FileText,
Train,
Truck,
UserCheck,
Users,
Wallet,
} from "lucide-react";
import { Group, Paper, Stack, Text } from "@mantine/core";
import type { IOverviewKpis } from "@/types/overview";
import { OverviewKpiCard } from "./OverviewKpiCard";
function formatCurrency(amount: number, currency: "ETB" | "USD") {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency,
maximumFractionDigits: 0,
}).format(amount);
}
export function OverviewKpiSection({ kpis }: { kpis: IOverviewKpis }) {
const bookingItems = [
{
label: "Active bookings",
value: kpis.bookings.totalActive,
icon: FileText,
accent: "emerald" as const,
},
{
label: "Needs action",
value: kpis.bookings.needsAction,
icon: AlertCircle,
accent: "amber" as const,
},
{
label: "Urgent",
value: kpis.bookings.urgent,
icon: Clock,
accent: "rose" as const,
},
{
label: "In approval",
value: kpis.bookings.inApproval,
icon: UserCheck,
accent: "sky" as const,
},
{
label: "Submitted today",
value: kpis.bookings.submittedToday,
icon: FileText,
},
];
const operationsItems = [
{
label: "Active trains",
value: kpis.operations.trainsActive,
icon: Train,
accent: "emerald" as const,
},
{
label: "Wagons available",
value: kpis.operations.wagonsAvailable,
icon: Truck,
},
{
label: "Containers in transit",
value: kpis.operations.containersInTransit,
icon: Container,
},
{
label: "Cargoes loaded",
value: kpis.operations.cargoesLoaded,
icon: Box,
},
];
const billingItems = [
{
label: "Revenue MTD (ETB)",
value: formatCurrency(kpis.billing.revenueMtdEtb, "ETB"),
icon: Banknote,
accent: "emerald" as const,
},
{
label: "Revenue MTD (USD)",
value: formatCurrency(kpis.billing.revenueMtdUsd, "USD"),
icon: Wallet,
},
{
label: "Pending payments",
value: kpis.billing.pendingPayments,
icon: CreditCard,
accent: "amber" as const,
},
{
label: "Successful MTD",
value: kpis.billing.successfulPaymentsMtd,
icon: Banknote,
},
];
const peopleItems = [
{
label: "Total customers",
value: kpis.customers.totalCustomers,
icon: Users,
},
{
label: "New this month",
value: kpis.customers.newCustomersThisMonth,
icon: Users,
accent: "emerald" as const,
},
{
label: "Active employees",
value: kpis.staff.activeEmployees,
icon: UserCheck,
},
{
label: "Active users",
value: kpis.staff.activeUsers,
icon: Users,
},
];
const sections = [
{ title: "Bookings", items: bookingItems },
{ title: "Operations", items: operationsItems },
{ title: "Billing", items: billingItems },
{ title: "Customers & staff", items: peopleItems },
];
return (
<Stack gap="md">
{sections.map((section) => (
<Paper
key={section.title}
p="md"
radius="lg"
withBorder
style={{
background: "white",
border: "1px solid var(--mantine-color-gray-2)",
overflowX: "auto",
}}
>
<Text size="sm" fw={600} mb="sm" c="dimmed">
{section.title}
</Text>
<Group gap="md" style={{ flexWrap: "nowrap", minWidth: "min-content" }}>
{section.items.map((item) => (
<OverviewKpiCard key={item.label} item={item} />
))}
</Group>
</Paper>
))}
</Stack>
);
}