This commit is contained in:
Marshal
2026-06-12 14:21:07 +00:00
parent 6b79348074
commit d3a479c142
25 changed files with 656 additions and 373 deletions

View File

@@ -58,10 +58,10 @@ const fmtScheduleDate = (iso: string | null) =>
}).format(new Date(iso)) + " EAT"
: "No date";
/** Capacity ring color: gold normally, red once over capacity. */
function ringColor(pct: number) {
if (pct >= 100) return "red";
if (pct >= 85) return "orange";
return "green";
if (pct >= 100) return "#fa5252";
return "#F2A516";
}
/** Capacity ring that keeps the explicit allocated/max numbers underneath. */
@@ -88,7 +88,7 @@ function CapacityRing({
rootColor="var(--mantine-color-gray-1)"
label={
<Stack gap={0} align="center">
<Text ta="center" size="lg" fw={800} c={`${color}.7`} lh={1}>
<Text ta="center" size="lg" fw={800} lh={1} style={{ color }}>
{Math.round(pct)}%
</Text>
<Text ta="center" size="9px" c="dimmed" fw={600}>
@@ -141,19 +141,11 @@ function ScheduleCard({ schedule }: { schedule: BatchBoardSchedule }) {
navigate(`/dashboard/operations/batch-board/${schedule.scheduleId}`)
}
>
{/* thin brand accent line */}
<Box
style={{
height: 4,
background: `linear-gradient(90deg, ${FREIGHT_BRAND}, var(--mantine-color-teal-6))`,
}}
/>
<Stack gap="md" p="lg" style={{ flex: 1 }}>
{/* header */}
<Group justify="space-between" align="flex-start" wrap="nowrap">
<Group gap="sm" wrap="nowrap" style={{ minWidth: 0 }}>
<ThemeIcon size={44} radius="md" variant="light" color="green">
<ThemeIcon size={44} radius="md" variant="light" color="#F2A516">
<Train size={22} />
</ThemeIcon>
<Box style={{ minWidth: 0 }}>
@@ -224,7 +216,7 @@ function ScheduleCard({ schedule }: { schedule: BatchBoardSchedule }) {
) : null}
<Stack gap={0} align="center" style={{ flex: 1 }}>
<ThemeIcon size={34} radius="md" variant="light" color="green">
<ThemeIcon size={34} radius="md" variant="light" color="gray">
<Package size={17} />
</ThemeIcon>
<Text fw={800} size="26px" c="dark.5" lh={1.1} mt={6}>
@@ -289,7 +281,6 @@ function ScheduleCard({ schedule }: { schedule: BatchBoardSchedule }) {
function CardSkeleton() {
return (
<Paper radius="lg" withBorder style={{ overflow: "hidden" }}>
<Skeleton height={4} radius={0} />
<Stack gap="md" p="lg">
<Group justify="space-between">
<Group gap="sm">
@@ -339,18 +330,32 @@ export default function BatchBoardPage() {
label="Active schedules"
value={isLoading ? "…" : schedules.length}
hint="on the board right now"
accent="#F2A516"
graph="area"
graphAccent="gold"
/>
<StatTile
icon={CalendarDays}
label="Open windows"
value={isLoading ? "…" : summary.openWindows}
hint="accepting bookings"
accent="#FB8C2E"
graph="line"
graphAccent="orange"
/>
<StatTile
icon={Package}
label="Bookings in play"
value={isLoading ? "…" : summary.totalBookings}
hint={`${summary.totalWagons} wagons allocated`}
accent="#F2A516"
graph="ring"
graphAccent="gold"
graphPct={
schedules.length
? Math.min(100, Math.round((summary.openWindows / schedules.length) * 100))
: 0
}
/>
</SimpleGrid>