From c9694177d8206c36b8f4983257dbe8bf80e10076 Mon Sep 17 00:00:00 2001 From: Nathnael Date: Wed, 24 Jun 2026 08:55:09 +0000 Subject: [PATCH] style: ui improvement to kpi in portal --- .../pages/MyPortalPage/components/StatKpi.tsx | 88 +++++++++++++++---- .../MyPortalPage/components/StatsSection.tsx | 30 +++++-- 2 files changed, 91 insertions(+), 27 deletions(-) diff --git a/apps/edr-freight-web/portal/src/pages/MyPortalPage/components/StatKpi.tsx b/apps/edr-freight-web/portal/src/pages/MyPortalPage/components/StatKpi.tsx index 413caafc4..a17af733d 100644 --- a/apps/edr-freight-web/portal/src/pages/MyPortalPage/components/StatKpi.tsx +++ b/apps/edr-freight-web/portal/src/pages/MyPortalPage/components/StatKpi.tsx @@ -1,15 +1,30 @@ import { Box, Group, Text } from "@mantine/core"; -import { memo } from "react"; import type { LucideIcon } from "lucide-react"; +import { memo } from "react"; import { cv } from "../constants"; +/** Accent families map a KPI to a soft tile + strong ink pair from the theme. */ +type Accent = "green" | "amber" | "blue" | "slate"; + +const ACCENTS: Record = { + green: { soft: cv("edr-soft"), ink: cv("edr-green.7") }, + amber: { soft: cv("edr-amber-soft"), ink: cv("edr-amber-text") }, + blue: { soft: cv("edr-blue-soft"), ink: cv("edr-blue") }, + slate: { soft: cv("edr-slate-soft"), ink: cv("edr-slate") }, +}; + interface StatKpiProps { icon: LucideIcon; label: string; value: string; delta: string; - deltaColor: string; + /** Color family for the icon chip. */ + accent: Accent; + /** Tint of the delta pill — defaults to the card accent. */ + deltaTone?: Accent | "muted"; + /** Draw a separating border on the left (on wide layouts). */ divider?: boolean; + loading?: boolean; } export const StatKpi = memo(function StatKpi({ @@ -17,30 +32,67 @@ export const StatKpi = memo(function StatKpi({ label, value, delta, - deltaColor, + accent, + deltaTone, divider, + loading, }: StatKpiProps) { + const a = ACCENTS[accent]; + const tone = deltaTone ?? accent; + const pill = + tone === "muted" + ? { bg: cv("edr-slate-soft2"), fg: cv("edr-muted") } + : { bg: ACCENTS[tone].soft, fg: ACCENTS[tone].ink }; + return ( - - - - {label} - - - - - {value} - - - {delta} - + {/* Icon chip + metric label, aligned on one line. */} + + + + + + + + {loading ? "—" : value} + + {delta && !loading && ( + + + {delta} + + + )} + + + {label} + + + + {/* Value + its trend pill, grouped together at the bottom of the cell. */} + ); }); diff --git a/apps/edr-freight-web/portal/src/pages/MyPortalPage/components/StatsSection.tsx b/apps/edr-freight-web/portal/src/pages/MyPortalPage/components/StatsSection.tsx index 8a0545fb7..dbd12546b 100644 --- a/apps/edr-freight-web/portal/src/pages/MyPortalPage/components/StatsSection.tsx +++ b/apps/edr-freight-web/portal/src/pages/MyPortalPage/components/StatsSection.tsx @@ -1,7 +1,7 @@ +import { formatCurrency } from "@/pages/billing/invoices.mock"; import { SimpleGrid } from "@mantine/core"; import { CheckCircle2, Clock3, Truck, Wallet } from "lucide-react"; import { memo } from "react"; -import { formatCurrency } from "@/pages/billing/invoices.mock"; import { formatPct } from "../constants"; import { Card } from "./Card"; import { StatKpi } from "./StatKpi"; @@ -29,39 +29,51 @@ export const StatsSection = memo(function StatsSection({ completionRate, spendYtd, spendYtdChangePct, + dashboardLoading, }: StatsSectionProps) { return ( - - + + 0 ? `+${newActiveThisWeek} this week` : ""} + loading={bookingsLoading} />