mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 13:28:11 +00:00
113 lines
3.6 KiB
TypeScript
113 lines
3.6 KiB
TypeScript
import { Check } from "lucide-react";
|
|
import { Box, Group, Stack, Text } from "@mantine/core";
|
|
import type { Freight } from "@edr/types";
|
|
|
|
const BRAND_GREEN = "var(--freight-brand, #0A6F4D)";
|
|
|
|
const IMPORT_PHASES = [
|
|
"CUSTOMER_INTAKE",
|
|
"GL_ET_REVIEW",
|
|
"GL_ET_OUTPUT",
|
|
"CUSTOMER_DUTY",
|
|
"GL_ET_POST_CLEARANCE",
|
|
"GL_DJ_COLLECTION",
|
|
] as const;
|
|
|
|
const PHASE_LABELS: Record<string, string> = {
|
|
CUSTOMER_INTAKE: "Customer docs",
|
|
GL_ET_REVIEW: "GL ET review",
|
|
GL_DJ_COLLECTION: "GL Djibouti DO",
|
|
GL_ET_OUTPUT: "Declaration",
|
|
CUSTOMER_DUTY: "Duty / customer pays",
|
|
GL_ET_POST_CLEARANCE: "Transit & finalize",
|
|
GL_DJ_LOADING: "Loading",
|
|
POST_TRANSIT: "Transit",
|
|
};
|
|
|
|
const EXPORT_PHASES = [
|
|
"CUSTOMER_INTAKE",
|
|
"GL_ET_REVIEW",
|
|
"GL_DJ_COLLECTION",
|
|
"GL_ET_OUTPUT",
|
|
"GL_ET_POST_CLEARANCE",
|
|
] as const;
|
|
|
|
function phaseIndex(phases: readonly string[], current?: string | null): number {
|
|
if (!current) return 0;
|
|
const idx = phases.indexOf(current);
|
|
return idx >= 0 ? idx : 0;
|
|
}
|
|
|
|
export function ClearancePhaseStepper({
|
|
clearance,
|
|
tradeDirection,
|
|
compact = false,
|
|
}: {
|
|
clearance?: Freight.ContractClearanceView | Freight.ClearanceView | null;
|
|
tradeDirection?: string;
|
|
compact?: boolean;
|
|
}) {
|
|
const phases = tradeDirection === "EXPORT" ? EXPORT_PHASES : IMPORT_PHASES;
|
|
const current = clearance?.phase ?? phases[0];
|
|
const activeIdx = phaseIndex(phases, current);
|
|
|
|
return (
|
|
<Group gap={0} wrap="nowrap" align="flex-start" style={{ overflowX: "auto" }}>
|
|
{phases.map((phase, index) => {
|
|
const isComplete = index < activeIdx;
|
|
const isActive = index === activeIdx;
|
|
const isLast = index === phases.length - 1;
|
|
|
|
return (
|
|
<Box key={phase} style={{ flex: isLast ? "0 0 auto" : 1, minWidth: compact ? 72 : 88 }}>
|
|
<Group gap={0} wrap="nowrap" align="center">
|
|
<Stack gap={4} align="center" style={{ flexShrink: 0 }}>
|
|
<Box
|
|
style={{
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
width: compact ? 28 : 34,
|
|
height: compact ? 28 : 34,
|
|
borderRadius: "50%",
|
|
background: isComplete ? BRAND_GREEN : isActive ? "white" : "var(--mantine-color-gray-1)",
|
|
border: isActive
|
|
? `2px solid ${BRAND_GREEN}`
|
|
: isComplete
|
|
? "2px solid transparent"
|
|
: "2px solid var(--mantine-color-gray-3)",
|
|
color: isComplete ? "white" : isActive ? BRAND_GREEN : "var(--mantine-color-gray-5)",
|
|
}}
|
|
>
|
|
{isComplete ? <Check size={compact ? 14 : 16} strokeWidth={3} /> : null}
|
|
</Box>
|
|
<Text
|
|
size={compact ? "10px" : "xs"}
|
|
fw={isActive ? 600 : 500}
|
|
c={isActive ? "edr-green.7" : isComplete ? "dark" : "dimmed"}
|
|
ta="center"
|
|
style={{ whiteSpace: "nowrap" }}
|
|
>
|
|
{PHASE_LABELS[phase] ?? phase}
|
|
</Text>
|
|
</Stack>
|
|
{!isLast && (
|
|
<Box
|
|
style={{
|
|
flex: 1,
|
|
height: 2,
|
|
marginInline: 6,
|
|
marginBottom: compact ? 16 : 20,
|
|
borderRadius: 2,
|
|
background: isComplete ? BRAND_GREEN : "var(--mantine-color-gray-2)",
|
|
}}
|
|
/>
|
|
)}
|
|
</Group>
|
|
</Box>
|
|
);
|
|
})}
|
|
</Group>
|
|
);
|
|
}
|