mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 16:35:42 +00:00
feat: enhance contract clearance process with linked booking details
- Added and to for better visibility of GL-created shipment bookings. - Implemented method in to fetch the latest clearance phase for contracts, improving list responses. - Introduced property in the entity to store the latest clearance cycle's phase. - Updated to surface linked booking information in the clearance view. - Created component to display detailed container information in booking details. - Refactored booking actions to remove contract-related actions from the booking request page. - Enhanced the component to reflect the current phase of clearance actions. - Updated UI components to provide clearer messaging regarding the status of clearance and linked bookings. - Adjusted action handling in to include duty payment actions. - Improved the to show hints for each phase of the clearance process.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { useMemo } from "react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { Button, Modal, Text, type ButtonProps } from "@mantine/core";
|
||||
import { AlertCircle, Upload } from "lucide-react";
|
||||
import { AlertCircle, Upload, type LucideIcon } from "lucide-react";
|
||||
|
||||
import { api } from "@/services/api";
|
||||
import { ContractClearancePanel } from "@/pages/contracts/ContractClearancePanel";
|
||||
@@ -13,6 +13,10 @@ interface ContractClearanceActionProps {
|
||||
label?: string;
|
||||
size?: ButtonProps["size"];
|
||||
urgent?: boolean;
|
||||
/** GL's turn — render as a calm status button, not a call to action. */
|
||||
waiting?: boolean;
|
||||
/** Icon override from the phase-aware action derivation. */
|
||||
icon?: LucideIcon;
|
||||
}
|
||||
|
||||
export function ContractClearanceAction({
|
||||
@@ -20,6 +24,8 @@ export function ContractClearanceAction({
|
||||
label: labelProp,
|
||||
size = "xs",
|
||||
urgent = false,
|
||||
waiting = false,
|
||||
icon: iconProp,
|
||||
}: ContractClearanceActionProps) {
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
|
||||
@@ -38,7 +44,13 @@ export function ContractClearanceAction({
|
||||
return urgent ? "Upload clearance" : "Manage clearance";
|
||||
}, [labelProp, clearance, urgent]);
|
||||
|
||||
const Icon = urgent || label.includes("Update") ? AlertCircle : Upload;
|
||||
const Icon =
|
||||
iconProp ?? (urgent || label.includes("Update") ? AlertCircle : Upload);
|
||||
|
||||
// Urgent (customer's turn) = filled orange so it stands out among the green
|
||||
// actions; waiting (GL's turn) = calm subtle gray; default = brand green.
|
||||
const color = urgent ? "orange" : waiting ? "gray" : "edr-green";
|
||||
const variant = waiting ? "light" : "filled";
|
||||
|
||||
return (
|
||||
<ModalSafeWrapper>
|
||||
@@ -47,7 +59,8 @@ export function ContractClearanceAction({
|
||||
radius="md"
|
||||
fw={700}
|
||||
fz={13}
|
||||
color="edr-green"
|
||||
color={color}
|
||||
variant={variant}
|
||||
leftSection={<Icon size={14} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -46,6 +46,8 @@ export function ContractCustomerAction({
|
||||
label={action.label}
|
||||
size={size}
|
||||
urgent={action.urgent}
|
||||
waiting={action.waiting}
|
||||
icon={action.icon}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import {
|
||||
CreditCard,
|
||||
Eye,
|
||||
FileSignature,
|
||||
Hourglass,
|
||||
PackagePlus,
|
||||
PencilLine,
|
||||
Receipt,
|
||||
RotateCcw,
|
||||
Upload,
|
||||
} from "lucide-react";
|
||||
@@ -61,6 +63,8 @@ export type ContractCustomerAction =
|
||||
primary: boolean;
|
||||
icon: LucideIcon;
|
||||
urgent: boolean;
|
||||
/** True when it's GL's turn — render calm/informational, not a call to action. */
|
||||
waiting?: boolean;
|
||||
}
|
||||
| {
|
||||
type: "pay";
|
||||
@@ -126,14 +130,56 @@ export function deriveContractCustomerAction(
|
||||
|
||||
const clr = contractNeedsClearanceAction(contract);
|
||||
if (clr.show) {
|
||||
return {
|
||||
type: "clearance",
|
||||
contractId: id,
|
||||
label: clr.urgent ? "Upload clearance" : "Update clearance",
|
||||
primary: true,
|
||||
icon: Upload,
|
||||
urgent: clr.urgent,
|
||||
};
|
||||
// Refine the generic clearance action by the persisted clearance phase so
|
||||
// the button says what the customer actually has to do right now (e.g.
|
||||
// "Pay duty & upload slip" during CUSTOMER_DUTY, not "Update clearance").
|
||||
const phase = contract.clearancePhase ?? null;
|
||||
switch (phase) {
|
||||
case "CUSTOMER_INTAKE":
|
||||
return {
|
||||
type: "clearance",
|
||||
contractId: id,
|
||||
label: "Upload clearance documents",
|
||||
primary: true,
|
||||
icon: Upload,
|
||||
urgent: true,
|
||||
};
|
||||
case "CUSTOMER_DUTY":
|
||||
return {
|
||||
type: "clearance",
|
||||
contractId: id,
|
||||
label: "Pay duty & upload slip",
|
||||
primary: true,
|
||||
icon: Receipt,
|
||||
urgent: true,
|
||||
};
|
||||
case "GL_ET_REVIEW":
|
||||
case "GL_DJ_COLLECTION":
|
||||
case "GL_ET_OUTPUT":
|
||||
case "GL_ET_POST_CLEARANCE":
|
||||
case "GL_DJ_LOADING":
|
||||
case "POST_TRANSIT":
|
||||
// GL's turn — nothing for the customer to do; show a calm status.
|
||||
return {
|
||||
type: "clearance",
|
||||
contractId: id,
|
||||
label: "Clearance in progress",
|
||||
primary: false,
|
||||
icon: Hourglass,
|
||||
urgent: false,
|
||||
waiting: true,
|
||||
};
|
||||
default:
|
||||
// No persisted phase (legacy / early cycles) — keep the status-derived label.
|
||||
return {
|
||||
type: "clearance",
|
||||
contractId: id,
|
||||
label: clr.urgent ? "Upload clearance" : "Update clearance",
|
||||
primary: true,
|
||||
icon: Upload,
|
||||
urgent: clr.urgent,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
|
||||
Reference in New Issue
Block a user