import type { ReactNode } from "react";
import { Box, Button, Group, Paper, Stack, Text, ThemeIcon, Title } from "@mantine/core";
import type { LucideIcon } from "lucide-react";
import {
AlertTriangle,
CheckCircle2,
Clock,
Inbox,
LayoutList,
Plus,
RefreshCw,
} from "lucide-react";
import { freightBrand } from "@/theme/freight-brand";
import type {
BookingListSummaryMetrics,
BookingListSummaryTabs,
} from "@/services/bookings.service";
const HERO_GRADIENT = `linear-gradient(135deg, ${freightBrand.primaryDark} 0%, ${freightBrand.primary} 48%, ${freightBrand.primaryLight} 120%)`;
/** Lifecycle stages for the pipeline distribution bar (in flow order). */
const PIPELINE_STAGES: Array<{
key: keyof BookingListSummaryTabs;
label: string;
color: string;
}> = [
{ key: "intake", label: "Intake", color: "#38bdf8" },
{ key: "in_approval", label: "Approval", color: "#fbbf24" },
{ key: "approved_contract", label: "Contract", color: "#a78bfa" },
{ key: "payment", label: "Payment", color: "#fb923c" },
{ key: "operations", label: "Operations", color: "#2dd4bf" },
{ key: "completed", label: "Completed", color: "#86efac" },
];
export interface BookingRequestsHeaderProps {
metrics?: BookingListSummaryMetrics;
tabs?: BookingListSummaryTabs;
loading?: boolean;
isFetching?: boolean;
onCreate: () => void;
onRefresh: () => void;
}
export function BookingRequestsHeader({
metrics,
tabs,
loading,
isFetching,
onCreate,
onRefresh,
}: BookingRequestsHeaderProps) {
const val = (n?: number) => (loading ? "—" : (n ?? 0));
return (
{/* decorative glows */}
Operations
Booking Requests
Track every booking from submission through approval, payment, and
dispatch — prioritize what needs action.
}
onClick={onCreate}
>
Create booking
}
loading={isFetching}
onClick={onRefresh}
style={{ background: "rgba(255,255,255,0.15)" }}
>
Refresh
{tabs ? : null}
);
}
/** Compact ring gauge with the stat icon at its center. */
function MiniDonut({
pct,
color = "white",
children,
size = 52,
stroke = 5,
}: {
pct?: number | null;
color?: string;
children: ReactNode;
size?: number;
stroke?: number;
}) {
const radius = (size - stroke) / 2;
const circumference = 2 * Math.PI * radius;
const clamped =
pct != null ? Math.min(100, Math.max(0, Math.round(pct))) : null;
const dash = clamped != null ? (clamped / 100) * circumference : 0;
return (
{children}
);
}
function HeroStat({
icon: Icon,
label,
value,
hint,
ratio,
ratioColor = "white",
}: {
icon: LucideIcon;
label: string;
value: ReactNode;
hint?: string;
ratio?: number;
ratioColor?: string;
}) {
const pct = ratio != null ? Math.round(Math.min(1, Math.max(0, ratio)) * 100) : null;
return (
{label}
{value}
{pct != null ? `${pct}% of queue` : hint}
);
}
function PipelineBar({ tabs }: { tabs: BookingListSummaryTabs }) {
const segments = PIPELINE_STAGES.map((s) => ({ ...s, count: tabs[s.key] ?? 0 }));
const total = segments.reduce((sum, s) => sum + s.count, 0);
return (
Booking pipeline
{total} active
{total > 0 ? (
segments.map((s) =>
s.count > 0 ? (
) : null,
)
) : (
)}
{segments.map((s) => (
{s.label}
{s.count}
))}
);
}