mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 11:08:12 +00:00
changes
This commit is contained in:
@@ -39,11 +39,9 @@ import {
|
|||||||
import useAuth from "@/hooks/useAuth";
|
import useAuth from "@/hooks/useAuth";
|
||||||
import {
|
import {
|
||||||
CONTRACT_STEPS,
|
CONTRACT_STEPS,
|
||||||
EDIT_CONTRACT_STEPS,
|
|
||||||
ContractFormInputValues,
|
ContractFormInputValues,
|
||||||
contractFormSchema,
|
contractFormSchema,
|
||||||
contractStepFields,
|
contractStepFields,
|
||||||
editContractStepFields,
|
|
||||||
initialContractFormValues,
|
initialContractFormValues,
|
||||||
OPERATION_TYPES,
|
OPERATION_TYPES,
|
||||||
type ContractFormValues,
|
type ContractFormValues,
|
||||||
@@ -55,12 +53,6 @@ import {
|
|||||||
operationToTradeDirection,
|
operationToTradeDirection,
|
||||||
} from "./new-contract-form/helpers";
|
} from "./new-contract-form/helpers";
|
||||||
import { contractToFormValues } from "./new-contract-form/contractToForm";
|
import { contractToFormValues } from "./new-contract-form/contractToForm";
|
||||||
import {
|
|
||||||
ContractDocsEditor,
|
|
||||||
documentSettingCode,
|
|
||||||
missingRequiredDocKeys,
|
|
||||||
useCompanyDocuments,
|
|
||||||
} from "./new-contract-form/ContractDocsEditor";
|
|
||||||
import { PROFILE_TYPE_LABELS } from "@/constants/profileMode";
|
import { PROFILE_TYPE_LABELS } from "@/constants/profileMode";
|
||||||
import type { ProfileTypeValue } from "@/services/companies.service";
|
import type { ProfileTypeValue } from "@/services/companies.service";
|
||||||
import { StepIndicator } from "./new-contract-form/StepIndicator";
|
import { StepIndicator } from "./new-contract-form/StepIndicator";
|
||||||
@@ -84,8 +76,8 @@ type PriceModalMode = "submit" | "draft";
|
|||||||
* The contract wizard, used both to create a new contract and — in `edit` mode —
|
* The contract wizard, used both to create a new contract and — in `edit` mode —
|
||||||
* to continue an unsubmitted DRAFT or edit & resubmit a contract staff returned
|
* to continue an unsubmitted DRAFT or edit & resubmit a contract staff returned
|
||||||
* with CHANGES_REQUESTED. Edit mode hydrates the form from the saved contract,
|
* with CHANGES_REQUESTED. Edit mode hydrates the form from the saved contract,
|
||||||
* lets the customer change any term and replace documents, then runs the same
|
* lets the customer change any term, then runs the same update → price →
|
||||||
* update → price → submit flow.
|
* submit flow. Same 3 steps as create — there is no separate documents step.
|
||||||
*/
|
*/
|
||||||
export default function NewContractPage({
|
export default function NewContractPage({
|
||||||
mode = "create",
|
mode = "create",
|
||||||
@@ -105,22 +97,6 @@ export default function NewContractPage({
|
|||||||
...api.contracts.get.queryOptions({ input: { id: editId ?? "" } }),
|
...api.contracts.get.queryOptions({ input: { id: editId ?? "" } }),
|
||||||
enabled: isEdit,
|
enabled: isEdit,
|
||||||
});
|
});
|
||||||
// Onboarding document requirements — used in edit mode to block resubmit until
|
|
||||||
// every required document is on file (existing or freshly attached).
|
|
||||||
const editDocSettingQuery = useQuery({
|
|
||||||
...api.fileUploadSettings.getByCode.queryOptions({
|
|
||||||
input: {
|
|
||||||
code: documentSettingCode(
|
|
||||||
auth.company?.company?.nationality as string | null | undefined,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
enabled: isEdit,
|
|
||||||
});
|
|
||||||
// Profile documents (TIN, licenses, IDs) satisfy requirements too — the API
|
|
||||||
// carries them onto the contract on save.
|
|
||||||
const companyDocs = useCompanyDocuments();
|
|
||||||
|
|
||||||
// Contract creation is gated on profile approval, same as bookings.
|
// Contract creation is gated on profile approval, same as bookings.
|
||||||
if (!auth.isPending && auth.company && !auth.canBook) {
|
if (!auth.isPending && auth.company && !auth.canBook) {
|
||||||
return <Navigate to="/contracts" replace />;
|
return <Navigate to="/contracts" replace />;
|
||||||
@@ -167,12 +143,6 @@ export default function NewContractPage({
|
|||||||
const [priceContractId, setPriceContractId] = useState<string | null>(
|
const [priceContractId, setPriceContractId] = useState<string | null>(
|
||||||
isEdit ? (editId ?? null) : null,
|
isEdit ? (editId ?? null) : null,
|
||||||
);
|
);
|
||||||
// Documents freshly attached on the review step (edit mode only). Merged into
|
|
||||||
// the form's `documents` map before the contract is updated.
|
|
||||||
const [editDocuments, setEditDocuments] = useState<
|
|
||||||
Record<string, File | File[] | null>
|
|
||||||
>({});
|
|
||||||
const [showDocErrors, setShowDocErrors] = useState(false);
|
|
||||||
const [priceModalMode, setPriceModalMode] = useState<PriceModalMode | null>(
|
const [priceModalMode, setPriceModalMode] = useState<PriceModalMode | null>(
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
@@ -311,10 +281,9 @@ export default function NewContractPage({
|
|||||||
const destinationYard = form.watch("destinationYard");
|
const destinationYard = form.watch("destinationYard");
|
||||||
const operationType = form.watch("operationType");
|
const operationType = form.watch("operationType");
|
||||||
|
|
||||||
const visibleSteps = useMemo(
|
// Create and edit share the same 3 steps — documents come along automatically
|
||||||
() => (isEdit ? EDIT_CONTRACT_STEPS : CONTRACT_STEPS),
|
// (company profile docs are carried onto the contract by the API on save).
|
||||||
[isEdit],
|
const visibleSteps = CONTRACT_STEPS;
|
||||||
);
|
|
||||||
const visibleStepIds = useMemo<number[]>(
|
const visibleStepIds = useMemo<number[]>(
|
||||||
() => visibleSteps.map((s) => s.id),
|
() => visibleSteps.map((s) => s.id),
|
||||||
[visibleSteps],
|
[visibleSteps],
|
||||||
@@ -519,25 +488,11 @@ export default function NewContractPage({
|
|||||||
}, [auth.company, auth.activeCompanyProfileId]);
|
}, [auth.company, auth.activeCompanyProfileId]);
|
||||||
|
|
||||||
async function handleContinue() {
|
async function handleContinue() {
|
||||||
const stepFields = isEdit ? editContractStepFields : contractStepFields;
|
const fields = contractStepFields[step];
|
||||||
const fields = stepFields[step];
|
|
||||||
if (fields.length > 0) {
|
if (fields.length > 0) {
|
||||||
const valid = await form.trigger(fields, { shouldFocus: true });
|
const valid = await form.trigger(fields, { shouldFocus: true });
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
}
|
}
|
||||||
if (isEdit && step === 2 && editContract) {
|
|
||||||
const missing = missingRequiredDocKeys(
|
|
||||||
editDocSettingQuery.data,
|
|
||||||
editContract,
|
|
||||||
editDocuments,
|
|
||||||
companyDocs,
|
|
||||||
);
|
|
||||||
if (missing.length > 0) {
|
|
||||||
setShowDocErrors(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setShowDocErrors(false);
|
|
||||||
}
|
|
||||||
goToStep(1);
|
goToStep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,26 +604,6 @@ export default function NewContractPage({
|
|||||||
|
|
||||||
const handleSubmitContract = form.handleSubmit((data) => {
|
const handleSubmitContract = form.handleSubmit((data) => {
|
||||||
try {
|
try {
|
||||||
// Edit mode: all required documents must be on file (already uploaded or
|
|
||||||
// freshly attached) before resubmitting, and freshly attached files are
|
|
||||||
// merged into the form's documents map so the update sends them.
|
|
||||||
if (isEdit && editContract) {
|
|
||||||
const missing = missingRequiredDocKeys(
|
|
||||||
editDocSettingQuery.data,
|
|
||||||
editContract,
|
|
||||||
editDocuments,
|
|
||||||
companyDocs,
|
|
||||||
);
|
|
||||||
if (missing.length > 0) {
|
|
||||||
setShowDocErrors(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setShowDocErrors(false);
|
|
||||||
form.setValue("documents", {
|
|
||||||
...(form.getValues("documents") ?? {}),
|
|
||||||
...editDocuments,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const apiPayload = buildApiPayload(data);
|
const apiPayload = buildApiPayload(data);
|
||||||
persistAndPriceMutation.mutate({
|
persistAndPriceMutation.mutate({
|
||||||
payload: apiPayload,
|
payload: apiPayload,
|
||||||
@@ -724,8 +659,8 @@ export default function NewContractPage({
|
|||||||
<Text size="sm" c="edr-muted" mt={4}>
|
<Text size="sm" c="edr-muted" mt={4}>
|
||||||
{isEdit
|
{isEdit
|
||||||
? editContract?.status === "CHANGES_REQUESTED"
|
? editContract?.status === "CHANGES_REQUESTED"
|
||||||
? "Update your contract details and documents, then resubmit it for EDR staff review."
|
? "Update your contract details, then resubmit it for EDR staff review."
|
||||||
: "Update your draft contract details and documents, then submit it for EDR staff review."
|
: "Update your draft contract details, then submit it for EDR staff review."
|
||||||
: "Define your freight contract — scope, routes, and unit rates. Book shipments against it after signing."}
|
: "Define your freight contract — scope, routes, and unit rates. Book shipments against it after signing."}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -769,12 +704,12 @@ export default function NewContractPage({
|
|||||||
{editContract.latestChangeRequestNote}
|
{editContract.latestChangeRequestNote}
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="sm" c="dimmed" mt={2}>
|
<Text size="sm" c="dimmed" mt={2}>
|
||||||
Update the details or documents below, then resubmit the
|
Update the details below, then resubmit the contract for
|
||||||
contract for review.
|
review.
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
) : (
|
) : (
|
||||||
"Update any contract detail or document that needs to change, then resubmit the contract for review."
|
"Update any contract detail that needs to change, then resubmit the contract for review."
|
||||||
)}
|
)}
|
||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
@@ -843,35 +778,8 @@ export default function NewContractPage({
|
|||||||
</StepCard>
|
</StepCard>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Step 2 (edit) — Documents. */}
|
{/* Step 2 — Review & Submit. */}
|
||||||
{step === 2 && isEdit && editContract && (
|
{step === 2 && (
|
||||||
<StepCard>
|
|
||||||
<StepHeader
|
|
||||||
title="Contract Documents"
|
|
||||||
description="Upload or replace the documents required for this contract before resubmitting."
|
|
||||||
/>
|
|
||||||
<ContractDocsEditor
|
|
||||||
contract={editContract}
|
|
||||||
value={editDocuments}
|
|
||||||
onChange={setEditDocuments}
|
|
||||||
errors={
|
|
||||||
showDocErrors
|
|
||||||
? Object.fromEntries(
|
|
||||||
missingRequiredDocKeys(
|
|
||||||
editDocSettingQuery.data,
|
|
||||||
editContract,
|
|
||||||
editDocuments,
|
|
||||||
companyDocs,
|
|
||||||
).map((k) => [k, "Required"]),
|
|
||||||
)
|
|
||||||
: {}
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</StepCard>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Step 2 (create) / Step 3 (edit) — Review & Submit. */}
|
|
||||||
{((step === 2 && !isEdit) || (step === 3 && isEdit)) && (
|
|
||||||
<Step8Review
|
<Step8Review
|
||||||
form={form}
|
form={form}
|
||||||
setStep={setStep}
|
setStep={setStep}
|
||||||
|
|||||||
@@ -11,14 +11,6 @@ export const CONTRACT_STEPS = [
|
|||||||
{ id: 2, label: "Review & Submit", short: "Review" },
|
{ id: 2, label: "Review & Submit", short: "Review" },
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
/** Edit flow (CHANGES_REQUESTED): documents on step 2, review on step 3. */
|
|
||||||
export const EDIT_CONTRACT_STEPS = [
|
|
||||||
{ id: 0, label: "Setup", short: "Setup" },
|
|
||||||
{ id: 1, label: "Cargo & Route", short: "Cargo & Route" },
|
|
||||||
{ id: 2, label: "Documents", short: "Documents" },
|
|
||||||
{ id: 3, label: "Review & Submit", short: "Review" },
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export const OPERATION_TYPES = [
|
export const OPERATION_TYPES = [
|
||||||
"import",
|
"import",
|
||||||
"export",
|
"export",
|
||||||
@@ -330,15 +322,3 @@ export const contractStepFields: Record<
|
|||||||
// company profile documents are attached to the contract automatically.)
|
// company profile documents are attached to the contract automatically.)
|
||||||
2: ["notes"],
|
2: ["notes"],
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Field validation per step when editing a CHANGES_REQUESTED contract. */
|
|
||||||
export const editContractStepFields: Record<
|
|
||||||
number,
|
|
||||||
Array<Path<ContractFormValues>>
|
|
||||||
> = {
|
|
||||||
0: contractStepFields[0],
|
|
||||||
1: contractStepFields[1],
|
|
||||||
// Step 2 — Documents: validated via missingRequiredDocKeys in the wizard.
|
|
||||||
2: [],
|
|
||||||
3: ["notes"],
|
|
||||||
};
|
|
||||||
|
|||||||
Reference in New Issue
Block a user