fix(work-orders): preserve staged vendor selection

This commit is contained in:
Arthur Bassi 2026-09-09 17:09:26 -03:00
parent 747515870e
commit 3bb7acde2d
6 changed files with 60 additions and 7 deletions

View file

@ -146,9 +146,9 @@ export function useVendorDialogForm({
handleCompanyPick: (nextCompany: string) => {
const selectedOption = technicianOptions.find((option) => option.key === selectedKey);
setSelectedCompany(nextCompany);
setAddedVendors([]);
setPendingCreates({});
if (selectedOption?.company !== nextCompany) {
setAddedVendors([]);
setPendingCreates({});
setSelectedKey("");
setT("");
setPhone("");

View file

@ -21,7 +21,6 @@ export function computeVendorDialogCanSubmit({
current.company !== baseline.company ||
current.selectedKey !== baseline.selectedKey ||
current.phone !== baseline.phone ||
current.notes !== baseline.notes ||
current.pendingCreateCount !== baseline.pendingCreateCount;
return valid && (dirty || hasNewTechs);
}

View file

@ -44,6 +44,7 @@ export function VendorDialogFooter({
<Button
className="min-h-0 px-3 py-1 text-[12px]"
disabled={isPending}
aria-disabled={!canSubmit && !isPending}
// why: AAP Save stays clickable; native disabled would change the no-op look-disabled gate.
sx={canSubmit || isPending ? undefined : lookDisabledSx}
onClick={() => {

View file

@ -57,13 +57,13 @@ describe("computeVendorDialogCanSubmit", () => {
).toBe(true);
});
it("allows save when notes change on a valid company", () => {
it("rejects notes-only changes because notes are not persisted", () => {
expect(
computeVendorDialogCanSubmit({
current: { ...assigned, notes: "Call before arrival" },
baseline: assigned,
}),
).toBe(true);
).toBe(false);
});
it("does not allow notes-only save without a company or technician", () => {

View file

@ -69,6 +69,7 @@ describe("VendorDialog save gate", () => {
expect(screen.getByRole("button", { name: /pick a company first/i })).toBeDisabled();
const save = screen.getByRole("button", { name: /^save$/i });
expect(save).not.toBeDisabled();
expect(save).toHaveAttribute("aria-disabled", "true");
expect(save).toHaveStyle({ opacity: "0.5", cursor: "not-allowed" });
fireEvent.click(save);
expect(onSave).not.toHaveBeenCalled();
@ -147,12 +148,12 @@ describe("VendorDialog save gate", () => {
expect(screen.queryByRole("button", { name: "Casey New" })).not.toBeInTheDocument();
});
it("persists after notes change on an existing assignment", () => {
it("does not persist after a notes-only change", () => {
const onSave = renderAssigned();
fireEvent.change(screen.getByPlaceholderText("Contact preferences, availability, etc."), {
target: { value: "Gate code 12" },
});
fireEvent.click(screen.getByRole("button", { name: /^save$/i }));
expect(onSave).toHaveBeenCalledTimes(1);
expect(onSave).not.toHaveBeenCalled();
});
});

View file

@ -175,4 +175,56 @@ describe("VendorDialog stable technician identity", () => {
);
});
});
it("keeps a staged draft when the same company is picked again", async () => {
const onSave = vi.fn();
mutateAsync.mockResolvedValue({
...createdVendor,
id: 88,
contactName: "Casey New",
phone: "3145550188",
});
renderWithProviders(
<VendorDialog
open={true}
onOpenChange={vi.fn()}
vendorId={10}
company="Gateway Plumbing"
tech="Jordan Lee"
techPhone="(314) 555-0100"
vendors={[existingVendor]}
onSave={onSave}
/>,
);
fireEvent.click(screen.getByRole("button", { name: /\+ add technician/i }));
fireEvent.change(screen.getByPlaceholderText("Full name"), {
target: { value: "Casey New" },
});
fireEvent.change(screen.getByPlaceholderText("(000) 000-0000"), {
target: { value: "3145550188" },
});
fireEvent.click(screen.getByRole("button", { name: /^add$/i }));
fireEvent.click(screen.getByRole("button", { name: "Gateway Plumbing" }));
const companyButtons = await screen.findAllByRole("button", { name: "Gateway Plumbing" });
fireEvent.click(companyButtons[companyButtons.length - 1]!);
fireEvent.click(screen.getByRole("button", { name: /^save$/i }));
await waitFor(() => {
expect(mutateAsync).toHaveBeenCalledWith(
expect.objectContaining({
contactName: "Casey New",
phone: "3145550188",
}),
);
});
expect(onSave).toHaveBeenCalledWith(
expect.objectContaining({
vendorId: "88",
tech: "Casey New",
}),
);
});
});