From 1fa9f6ec02971cc9b1c53d31ba8dcae44b47c2b9 Mon Sep 17 00:00:00 2001 From: Codex Review Integration Date: Wed, 16 Sep 2026 19:29:29 -0300 Subject: [PATCH] fix(work-orders): close wizard before saving vendor notes on create The create mutation's onSuccess awaited saveCompanyNotes before calling onOpenChange(false). Because isCreating is createMutation.isPending || isCheckingDuplicate, and isPending drops to false the moment the work-order create resolves, the dialog stayed open with Create re-enabled and pointer events unlocked for the length of the roster GET plus notes PATCH. A second Create click ran handleCreate again; with a blank provisional WO number the duplicate lookup short-circuits without an API call, so createMutation.mutate fired a second time and created a duplicate work order. Close the dialog first, then fire saveCompanyNotes unawaited. The save does not need the dialog open: fetchCurrentBaseline reads the roster when the baseline is missing, and the failure toast is raised from the mutation's option-level onError, so it still surfaces after the dialog unmounts. --- .../_components/wizard/use-new-wo-wizard-controller.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-controller.ts b/src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-controller.ts index 9e0476d3..cb988a51 100644 --- a/src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-controller.ts +++ b/src/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-controller.ts @@ -65,9 +65,13 @@ export function useNewWoWizardController({ }; const createMutation = useCreateWorkOrderFromWizard((createdDraft) => { - // Close only after the company-notes save attempt settles; its failures are surfaced - // as note-save warnings and must never report the work-order creation as failed. - void saveCompanyNotes(createdDraft).finally(() => onOpenChange(false)); + // Close the dialog first: the work-order create's isPending has already dropped, so + // holding the dialog open through the notes save would re-enable Create and unlock + // pointer events, and a second click would create a second work order. The save runs + // independently of the dialog — fetchCurrentBaseline covers a missing baseline and the + // note-save failure toast is surfaced from the mutation itself, not the dialog. + onOpenChange(false); + void saveCompanyNotes(createdDraft); }); const { duplicateRow, setDuplicateRow, handleDuplicateFound, handleCreate, isCreating } = useWizardDuplicateActions({