finilize gl

This commit is contained in:
marshal
2026-07-02 12:06:17 +03:00
parent 9c18d086d7
commit 4fefe4f827
50 changed files with 5150 additions and 1793 deletions

View File

@@ -56,9 +56,13 @@ export interface ContractClearanceReviewSectionProps {
readOnly?: boolean;
/**
* Document approvals are locked (e.g. after all docs approved in phased flow)
* but queries remain available until {@link readOnly}.
* but queries remain available until {@link queriesLocked} or {@link readOnly}.
*/
approvalsLocked?: boolean;
/**
* Pre-clearance finalized — block opening new queries on customer documents.
*/
queriesLocked?: boolean;
/**
* ONE_TIME customs contracts use the phased milestone workflow. Hides the
* legacy "Finalize clearance" shortcut; booking readiness follows delivery
@@ -102,6 +106,7 @@ export function ContractClearanceReviewSection({
readOnly = false,
phasedCustoms = false,
approvalsLocked = false,
queriesLocked = false,
}: ContractClearanceReviewSectionProps) {
const [queryNotes, setQueryNotes] = useState<Record<string, string>>({});
const [openQuery, setOpenQuery] = useState<Record<string, boolean>>({});
@@ -150,6 +155,11 @@ export function ContractClearanceReviewSection({
.filter((d) => d.file && d.reviewStatus !== "APPROVED")
.map((d) => d.fileKey);
const hasDocsAwaitingApproval = customerDocs.some(
(d) => d.file && d.reviewStatus !== "APPROVED",
);
const effectiveApprovalsLocked = approvalsLocked && !hasDocsAwaitingApproval;
if (isLoading || !clearance) {
return (
<Group justify="center" py="xl" gap={10}>
@@ -183,7 +193,7 @@ export function ContractClearanceReviewSection({
subtitle={
readOnly
? `Reviewed by the ${reviewerTeam} team.`
: approvalsLocked
: effectiveApprovalsLocked
? "Documents are approved — you can still open a query if something needs fixing."
: "Approve each document, or open a query to tell the customer what to fix."
}
@@ -192,7 +202,7 @@ export function ContractClearanceReviewSection({
<Text size="xs" c="dimmed" fw={600}>
{stats.approved}/{stats.total} approved
</Text>
{!readOnly && !approvalsLocked && approvableKeys.length > 0 && (
{!readOnly && !effectiveApprovalsLocked && approvableKeys.length > 0 && (
<Button
size="compact-sm"
color="edr-green"
@@ -236,7 +246,8 @@ export function ContractClearanceReviewSection({
doc={doc}
reviewerTeam={reviewerTeam}
readOnly={readOnly}
approvalsLocked={approvalsLocked}
approvalsLocked={effectiveApprovalsLocked}
queriesLocked={queriesLocked}
note={queryNotes[doc.fileKey] ?? ""}
queryOpen={openQuery[doc.fileKey] ?? false}
onToggleQuery={(open) =>
@@ -394,7 +405,7 @@ export function ContractClearanceReviewSection({
</Text>
</Group>
</Paper>
) : phasedCustoms && approvalsLocked ? (
) : phasedCustoms && effectiveApprovalsLocked ? (
<Paper withBorder radius="md" p="md">
<Group gap={8} wrap="nowrap" style={{ minWidth: 0 }}>
<ThemeIcon variant="light" color="edr-green" radius="md" size={28}>
@@ -402,7 +413,10 @@ export function ContractClearanceReviewSection({
</ThemeIcon>
<Text fz="12.5px" c="dimmed">
Document review is complete. Use the action panel for declaration, duty, and
transit steps or open a query above if a customer document needs correction.
transit steps
{queriesLocked
? ". Pre-clearance is finalized — customer documents can no longer be queried."
: " — or open a query above if a customer document needs correction."}
</Text>
</Group>
</Paper>
@@ -419,7 +433,7 @@ export function ContractClearanceReviewSection({
</ThemeIcon>
<Text fz="12.5px" c="dimmed">
{clearance.allApproved
? "All required documents are approved. Upload declaration, duty, transit permit, and delivery order in the action panel."
? "All required documents are approved. Continue declaration, duty, and transit in the action panel."
: "Approve every required document to unlock the customs milestone steps."}
</Text>
</Group>
@@ -498,6 +512,7 @@ function DocReviewCard({
reviewerTeam,
readOnly,
approvalsLocked,
queriesLocked,
note,
queryOpen,
onToggleQuery,
@@ -511,6 +526,7 @@ function DocReviewCard({
reviewerTeam: string;
readOnly: boolean;
approvalsLocked: boolean;
queriesLocked: boolean;
note: string;
queryOpen: boolean;
onToggleQuery: (open: boolean) => void;
@@ -636,17 +652,19 @@ function DocReviewCard({
<Box mt="sm">
{!queryOpen ? (
<Group justify="flex-end" gap={8}>
<Button
size="sm"
variant="light"
color="red"
radius="md"
leftSection={<MessageSquareWarning size={15} />}
disabled={busy}
onClick={() => onToggleQuery(true)}
>
Open query
</Button>
{!queriesLocked && (
<Button
size="sm"
variant="light"
color="red"
radius="md"
leftSection={<MessageSquareWarning size={15} />}
disabled={busy}
onClick={() => onToggleQuery(true)}
>
Open query
</Button>
)}
{!isApproved && !approvalsLocked && (
<Button
size="sm"