mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-04 18:22:05 +00:00
fix(work-orders): preserve staged vendor selection
This commit is contained in:
parent
747515870e
commit
3bb7acde2d
6 changed files with 60 additions and 7 deletions
|
|
@ -146,9 +146,9 @@ export function useVendorDialogForm({
|
||||||
handleCompanyPick: (nextCompany: string) => {
|
handleCompanyPick: (nextCompany: string) => {
|
||||||
const selectedOption = technicianOptions.find((option) => option.key === selectedKey);
|
const selectedOption = technicianOptions.find((option) => option.key === selectedKey);
|
||||||
setSelectedCompany(nextCompany);
|
setSelectedCompany(nextCompany);
|
||||||
setAddedVendors([]);
|
|
||||||
setPendingCreates({});
|
|
||||||
if (selectedOption?.company !== nextCompany) {
|
if (selectedOption?.company !== nextCompany) {
|
||||||
|
setAddedVendors([]);
|
||||||
|
setPendingCreates({});
|
||||||
setSelectedKey("");
|
setSelectedKey("");
|
||||||
setT("");
|
setT("");
|
||||||
setPhone("");
|
setPhone("");
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ export function computeVendorDialogCanSubmit({
|
||||||
current.company !== baseline.company ||
|
current.company !== baseline.company ||
|
||||||
current.selectedKey !== baseline.selectedKey ||
|
current.selectedKey !== baseline.selectedKey ||
|
||||||
current.phone !== baseline.phone ||
|
current.phone !== baseline.phone ||
|
||||||
current.notes !== baseline.notes ||
|
|
||||||
current.pendingCreateCount !== baseline.pendingCreateCount;
|
current.pendingCreateCount !== baseline.pendingCreateCount;
|
||||||
return valid && (dirty || hasNewTechs);
|
return valid && (dirty || hasNewTechs);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ export function VendorDialogFooter({
|
||||||
<Button
|
<Button
|
||||||
className="min-h-0 px-3 py-1 text-[12px]"
|
className="min-h-0 px-3 py-1 text-[12px]"
|
||||||
disabled={isPending}
|
disabled={isPending}
|
||||||
|
aria-disabled={!canSubmit && !isPending}
|
||||||
// why: AAP Save stays clickable; native disabled would change the no-op look-disabled gate.
|
// why: AAP Save stays clickable; native disabled would change the no-op look-disabled gate.
|
||||||
sx={canSubmit || isPending ? undefined : lookDisabledSx}
|
sx={canSubmit || isPending ? undefined : lookDisabledSx}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
||||||
|
|
@ -57,13 +57,13 @@ describe("computeVendorDialogCanSubmit", () => {
|
||||||
).toBe(true);
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("allows save when notes change on a valid company", () => {
|
it("rejects notes-only changes because notes are not persisted", () => {
|
||||||
expect(
|
expect(
|
||||||
computeVendorDialogCanSubmit({
|
computeVendorDialogCanSubmit({
|
||||||
current: { ...assigned, notes: "Call before arrival" },
|
current: { ...assigned, notes: "Call before arrival" },
|
||||||
baseline: assigned,
|
baseline: assigned,
|
||||||
}),
|
}),
|
||||||
).toBe(true);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not allow notes-only save without a company or technician", () => {
|
it("does not allow notes-only save without a company or technician", () => {
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ describe("VendorDialog save gate", () => {
|
||||||
expect(screen.getByRole("button", { name: /pick a company first/i })).toBeDisabled();
|
expect(screen.getByRole("button", { name: /pick a company first/i })).toBeDisabled();
|
||||||
const save = screen.getByRole("button", { name: /^save$/i });
|
const save = screen.getByRole("button", { name: /^save$/i });
|
||||||
expect(save).not.toBeDisabled();
|
expect(save).not.toBeDisabled();
|
||||||
|
expect(save).toHaveAttribute("aria-disabled", "true");
|
||||||
expect(save).toHaveStyle({ opacity: "0.5", cursor: "not-allowed" });
|
expect(save).toHaveStyle({ opacity: "0.5", cursor: "not-allowed" });
|
||||||
fireEvent.click(save);
|
fireEvent.click(save);
|
||||||
expect(onSave).not.toHaveBeenCalled();
|
expect(onSave).not.toHaveBeenCalled();
|
||||||
|
|
@ -147,12 +148,12 @@ describe("VendorDialog save gate", () => {
|
||||||
expect(screen.queryByRole("button", { name: "Casey New" })).not.toBeInTheDocument();
|
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();
|
const onSave = renderAssigned();
|
||||||
fireEvent.change(screen.getByPlaceholderText("Contact preferences, availability, etc."), {
|
fireEvent.change(screen.getByPlaceholderText("Contact preferences, availability, etc."), {
|
||||||
target: { value: "Gate code 12" },
|
target: { value: "Gate code 12" },
|
||||||
});
|
});
|
||||||
fireEvent.click(screen.getByRole("button", { name: /^save$/i }));
|
fireEvent.click(screen.getByRole("button", { name: /^save$/i }));
|
||||||
expect(onSave).toHaveBeenCalledTimes(1);
|
expect(onSave).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue