Files
edr-platform/apps/edr-freight-web/backoffice/src/components/contracts/gl-actions/AssignRiskCard.tsx
2026-07-10 12:10:17 +00:00

93 lines
2.7 KiB
TypeScript

import { useEffect, useState } from "react";
import { Badge, Box, Button, Group, SegmentedControl, Text } from "@mantine/core";
import { ShieldAlert } from "lucide-react";
import type { Freight } from "@edr/types";
import { useAssignRisk } from "@/hooks/contracts/useContracts";
import { ActionShell } from "./ActionShell";
const RISK_COLOR: Record<Freight.CustomsRiskLevel, string> = {
GREEN: "green",
YELLOW: "yellow",
RED: "red",
};
export function AssignRiskCard({
bookingId,
milestone,
locked = false,
}: {
bookingId: string;
milestone: Freight.IClearanceMilestone;
/**
* Duty has already been advised off this risk level, so the decision is now
* final. Until then a mis-assigned level must stay correctable — the server
* accepts reassignment and overwrites the milestone metadata.
*/
locked?: boolean;
}) {
const assign = useAssignRisk(bookingId);
const assigned = milestone.status === "COMPLETED";
const current = milestone.metadata?.riskLevel;
const [level, setLevel] = useState<Freight.CustomsRiskLevel>(
current ?? "GREEN",
);
// The milestone loads (and refetches after a reassignment) after first render,
// so mirror the persisted level onto the control whenever it changes.
useEffect(() => {
if (current) setLevel(current);
}, [current]);
return (
<ActionShell
icon={ShieldAlert}
title="Customs risk"
subtitle={
assigned && !locked
? "Reassign the customs examination risk level."
: "Assign the customs examination risk level."
}
done={assigned}
keepChildrenWhenDone={!locked}
doneLabel={
current ? (
<Badge color={RISK_COLOR[current]} variant="filled" radius="sm">
{current}
</Badge>
) : (
"Assigned"
)
}
>
<Box>
<SegmentedControl
fullWidth
value={level}
onChange={(v) => setLevel(v as Freight.CustomsRiskLevel)}
data={[
{ label: "Green", value: "GREEN" },
{ label: "Yellow", value: "YELLOW" },
{ label: "Red", value: "RED" },
]}
/>
<Group justify="space-between" mt="sm">
<Text size="xs" c="dimmed">
Customer is notified of the assigned risk.
</Text>
<Button
size="compact-sm"
color="edr-green"
loading={assign.isPending}
disabled={assigned && level === current}
onClick={() => assign.mutate({ riskLevel: level })}
>
{assigned ? "Reassign risk" : "Assign risk"}
</Button>
</Group>
</Box>
</ActionShell>
);
}