import type { ReactNode } from "react"; import { Box, Group, Paper, Stack, Text } from "@mantine/core"; import type { LucideIcon } from "lucide-react"; import { MapPin } from "lucide-react"; import { freightBrand } from "@/theme/freight-brand"; /** * Shared visual building blocks for the Train Scheduling V2 surfaces. * Everything keys off the freight brand green so the list + detail pages * read as one cohesive, premium product. */ export const scheduleBrand = { /** Deep green → emerald hero wash used across scheduling surfaces. */ heroGradient: `linear-gradient(135deg, ${freightBrand.primaryDark} 0%, ${freightBrand.primary} 48%, ${freightBrand.primaryLight} 120%)`, /** Soft tinted surface for cards on white backgrounds. */ softSurface: `linear-gradient(135deg, ${freightBrand.mutedBg} 0%, #ffffff 60%, var(--mantine-color-gray-0) 100%)`, ring: freightBrand.ring, shadow: freightBrand.shadow, shadowSm: freightBrand.shadowSm, mutedBorder: freightBrand.mutedBorder, } as const; const STATUS_META: Record< string, { color: string; dot: string; label?: string } > = { DRAFT: { color: "gray", dot: "var(--mantine-color-gray-5)" }, SCHEDULED: { color: "green", dot: freightBrand.primary }, DISPATCHED: { color: "teal", dot: "var(--mantine-color-teal-6)" }, ARRIVED: { color: "blue", dot: "var(--mantine-color-blue-6)" }, CANCELLED: { color: "red", dot: "var(--mantine-color-red-6)" }, }; export function statusMeta(status: string) { return STATUS_META[status] ?? STATUS_META.DRAFT; } /** * Status pill with a leading status dot — clearer at a glance than a plain * badge and consistent everywhere a schedule status appears. */ export function StatusPill({ status, size = "sm", }: { status: string; size?: "sm" | "md"; }) { const meta = statusMeta(status); const isMd = size === "md"; return ( {meta.label ?? status} ); } /** * Compact metric tile used in hero strips. `onDark` flips colors for use on * the green hero gradient. */ export function StatTile({ icon: Icon, label, value, hint, onDark = false, accent = freightBrand.primary, }: { icon?: LucideIcon; label: string; value: ReactNode; hint?: ReactNode; onDark?: boolean; accent?: string; }) { return ( {Icon ? ( ) : null} {label} {value} {hint ? ( {hint} ) : null} ); } /** * Origin → destination corridor visual: two anchored stops joined by a rail * line. `variant="compact"` is for dense table rows; `default` for cards. */ export function RouteCorridor({ origin, destination, variant = "default", onDark = false, }: { origin?: string | null; destination?: string | null; variant?: "default" | "compact"; onDark?: boolean; }) { const compact = variant === "compact"; const dim = onDark ? "rgba(255,255,255,0.7)" : "var(--mantine-color-gray-5)"; const strong = onDark ? "white" : "var(--mantine-color-gray-8)"; const lineColor = onDark ? "rgba(255,255,255,0.4)" : "var(--mantine-color-gray-3)"; const accent = onDark ? "white" : freightBrand.primary; return ( {origin ?? "—"} {destination ?? "—"} ); }