mirror of
https://github.com/Sea-Haven-Industries/seahaven-ap.git
synced 2026-10-07 16:18:53 +00:00
fix(frontend): sync approvals; fix invoice not-found query (AP-6)
Keep approvals inbox rows aligned when detail stubs transition status, and return null from useInvoice so missing ids hit the not-found UI instead of a query error.
This commit is contained in:
parent
532c0f7f85
commit
b00a3311f5
6 changed files with 44 additions and 3 deletions
|
|
@ -43,4 +43,10 @@ test.describe("invoice detail 3-pane shell", () => {
|
||||||
await expect(page).toHaveURL(/\/invoices\/inv-/);
|
await expect(page).toHaveURL(/\/invoices\/inv-/);
|
||||||
await expect(page.getByTestId("invoice-document-viewer")).toBeVisible();
|
await expect(page.getByTestId("invoice-document-viewer")).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("unknown invoice id shows not-found warning", async ({ page }) => {
|
||||||
|
await page.goto("/invoices/missing-invoice");
|
||||||
|
await expect(page.getByTestId("invoice-not-found")).toBeVisible();
|
||||||
|
await expect(page.getByTestId("invoice-document-viewer")).toHaveCount(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import {
|
||||||
type MockInvoiceLine,
|
type MockInvoiceLine,
|
||||||
type MockInvoiceStatus,
|
type MockInvoiceStatus,
|
||||||
} from "@/mocks";
|
} from "@/mocks";
|
||||||
|
import { approvalQueryKeys } from "@/domain/approvals/query-keys";
|
||||||
import { invoiceQueryKeys } from "@/domain/invoices/query-keys";
|
import { invoiceQueryKeys } from "@/domain/invoices/query-keys";
|
||||||
|
|
||||||
async function invalidateInvoiceQueries(
|
async function invalidateInvoiceQueries(
|
||||||
|
|
@ -37,9 +38,9 @@ export function useInvoice(id: string | undefined) {
|
||||||
queryKey: invoiceQueryKeys.detail(id ?? ""),
|
queryKey: invoiceQueryKeys.detail(id ?? ""),
|
||||||
queryFn: () => {
|
queryFn: () => {
|
||||||
if (!id) {
|
if (!id) {
|
||||||
return undefined;
|
return null;
|
||||||
}
|
}
|
||||||
return getMockInvoice(id);
|
return getMockInvoice(id) ?? null;
|
||||||
},
|
},
|
||||||
enabled: Boolean(id),
|
enabled: Boolean(id),
|
||||||
});
|
});
|
||||||
|
|
@ -117,6 +118,7 @@ export function useTransitionInvoiceStatus() {
|
||||||
}) => Promise.resolve(transitionMockInvoiceStatus(id, status, activity)),
|
}) => Promise.resolve(transitionMockInvoiceStatus(id, status, activity)),
|
||||||
onSuccess: async (_data, variables) => {
|
onSuccess: async (_data, variables) => {
|
||||||
await invalidateInvoiceQueries(queryClient, variables.id);
|
await invalidateInvoiceQueries(queryClient, variables.id);
|
||||||
|
await queryClient.invalidateQueries({ queryKey: approvalQueryKeys.all });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,23 @@ export function updateMockApprovalStatus(
|
||||||
return { ...updated };
|
return { ...updated };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Keep inbox rows aligned when invoice detail stubs transition status. */
|
||||||
|
export function syncMockApprovalsForInvoice(
|
||||||
|
invoiceId: string,
|
||||||
|
status: MockApprovalStatus,
|
||||||
|
): MockApprovalItem[] {
|
||||||
|
const updated: MockApprovalItem[] = [];
|
||||||
|
approvalStore = approvalStore.map((item) => {
|
||||||
|
if (item.invoiceId !== invoiceId) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
const next = { ...item, status };
|
||||||
|
updated.push({ ...next });
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
export function resetMockApprovals(): void {
|
export function resetMockApprovals(): void {
|
||||||
approvalStore = seedApprovals.map((item) => ({ ...item }));
|
approvalStore = seedApprovals.map((item) => ({ ...item }));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,12 @@ describe("mocks module", () => {
|
||||||
});
|
});
|
||||||
expect(approved.status).toBe("approved");
|
expect(approved.status).toBe("approved");
|
||||||
expect(approved.activity.some((entry) => entry.message === "Approved")).toBe(true);
|
expect(approved.activity.some((entry) => entry.message === "Approved")).toBe(true);
|
||||||
|
expect(getMockPendingApprovals().some((item) => item.invoiceId === "inv-2")).toBe(false);
|
||||||
|
expect(getMockApprovals().find((item) => item.invoiceId === "inv-2")?.status).toBe("approved");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns undefined for unknown invoice ids", () => {
|
||||||
|
expect(getMockInvoice("missing-invoice")).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("switches mock session user", () => {
|
it("switches mock session user", () => {
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ export {
|
||||||
getMockApprovals,
|
getMockApprovals,
|
||||||
getMockPendingApprovals,
|
getMockPendingApprovals,
|
||||||
resetMockApprovals,
|
resetMockApprovals,
|
||||||
|
syncMockApprovalsForInvoice,
|
||||||
updateMockApprovalStatus,
|
updateMockApprovalStatus,
|
||||||
type MockApprovalItem,
|
type MockApprovalItem,
|
||||||
type MockApprovalStatus,
|
type MockApprovalStatus,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { syncMockApprovalsForInvoice } from "@/mocks/approvals";
|
||||||
import { areMocksEnabled } from "@/mocks/env";
|
import { areMocksEnabled } from "@/mocks/env";
|
||||||
|
|
||||||
export type MockInvoiceStatus = "pending_approval" | "approved" | "scheduled" | "paid" | "rejected";
|
export type MockInvoiceStatus = "pending_approval" | "approved" | "scheduled" | "paid" | "rejected";
|
||||||
|
|
@ -515,11 +516,19 @@ export function transitionMockInvoiceStatus(
|
||||||
createdAt: activity.createdAt ?? new Date().toISOString(),
|
createdAt: activity.createdAt ?? new Date().toISOString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return replaceInvoice(index, {
|
const updated = replaceInvoice(index, {
|
||||||
...current,
|
...current,
|
||||||
status,
|
status,
|
||||||
activity: [...current.activity, nextActivity],
|
activity: [...current.activity, nextActivity],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (status === "approved" || status === "rejected") {
|
||||||
|
syncMockApprovalsForInvoice(id, status);
|
||||||
|
} else if (status === "pending_approval") {
|
||||||
|
syncMockApprovalsForInvoice(id, "pending");
|
||||||
|
}
|
||||||
|
|
||||||
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Test helper to restore seed data between unit tests. */
|
/** Test helper to restore seed data between unit tests. */
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue