mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-09-30 06:53:12 +00:00
fix(sites): block delete until the open work-order check succeeds
This commit is contained in:
parent
3ab9c9a65b
commit
9bb0416346
2 changed files with 43 additions and 3 deletions
|
|
@ -21,6 +21,9 @@ interface SiteDeleteDialogProps {
|
|||
onDeleted: () => void;
|
||||
}
|
||||
|
||||
const CHECK_FAILED_MESSAGE =
|
||||
"Couldn't check this site for open work orders. Try again before deleting it.";
|
||||
|
||||
function describeDeletion(siteCode: string, openCount: number): string {
|
||||
if (openCount === 0) {
|
||||
return `This will permanently remove ${siteCode} from Sites. This cannot be undone.`;
|
||||
|
|
@ -39,8 +42,16 @@ export function SiteDeleteDialog({
|
|||
}: SiteDeleteDialogProps) {
|
||||
const navigate = useNavigate();
|
||||
const deleteLocation = useDeleteLocation();
|
||||
const { data: openWorkOrders, isLoading } = useSiteOpenWorkOrders(siteId, open);
|
||||
const {
|
||||
data: openWorkOrders,
|
||||
isLoading,
|
||||
isError,
|
||||
isFetching,
|
||||
refetch,
|
||||
} = useSiteOpenWorkOrders(siteId, open);
|
||||
const openCount = openWorkOrders?.count ?? 0;
|
||||
// Without the count the warning cannot be shown, so Delete waits for a successful check.
|
||||
const countUnknown = isLoading || isError;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
|
|
@ -56,7 +67,8 @@ export function SiteDeleteDialog({
|
|||
<DialogTitle id="site-delete-title">Delete this site?</DialogTitle>
|
||||
<DialogContent>
|
||||
{isLoading && <CircularProgress size={20} aria-label="Checking open work orders" />}
|
||||
{!isLoading && (
|
||||
{isError && <DialogContentText role="alert">{CHECK_FAILED_MESSAGE}</DialogContentText>}
|
||||
{!countUnknown && (
|
||||
<DialogContentText>{describeDeletion(siteCode, openCount)}</DialogContentText>
|
||||
)}
|
||||
</DialogContent>
|
||||
|
|
@ -64,6 +76,11 @@ export function SiteDeleteDialog({
|
|||
<Button variant="text" onClick={onClose} disabled={deleteLocation.isPending}>
|
||||
Cancel
|
||||
</Button>
|
||||
{isError && (
|
||||
<Button variant="outlined" disabled={isFetching} onClick={() => void refetch()}>
|
||||
Try again
|
||||
</Button>
|
||||
)}
|
||||
{openCount > 0 && (
|
||||
<Button
|
||||
variant="outlined"
|
||||
|
|
@ -75,7 +92,7 @@ export function SiteDeleteDialog({
|
|||
<Button
|
||||
variant="contained"
|
||||
color="error"
|
||||
disabled={isLoading || deleteLocation.isPending}
|
||||
disabled={countUnknown || deleteLocation.isPending}
|
||||
onClick={() => deleteLocation.mutate(siteId, { onSuccess: onDeleted })}
|
||||
>
|
||||
{deleteLocation.isPending ? "Deleting..." : "Delete"}
|
||||
|
|
|
|||
|
|
@ -173,6 +173,29 @@ describe("Delete a site from the detail panel", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("blocks Delete when the open work-order check fails, until a retry succeeds", async () => {
|
||||
getOpenWorkOrders.mockRejectedValueOnce(new Error("Server error"));
|
||||
getOpenWorkOrders.mockResolvedValueOnce({ count: 2, workOrderIds: [101, 205] });
|
||||
renderAs("Admin");
|
||||
const panel = await openPanel();
|
||||
|
||||
fireEvent.click(within(panel).getByRole("button", { name: "Delete" }));
|
||||
const dialog = await screen.findByRole("dialog", { name: "Delete this site?" });
|
||||
|
||||
expect(await within(dialog).findByRole("alert")).toHaveTextContent(
|
||||
"Couldn't check this site for open work orders. Try again before deleting it.",
|
||||
);
|
||||
expect(within(dialog).getByRole("button", { name: "Delete" })).toBeDisabled();
|
||||
expect(within(dialog).queryByText(/This cannot be undone/)).not.toBeInTheDocument();
|
||||
|
||||
fireEvent.click(within(dialog).getByRole("button", { name: "Try again" }));
|
||||
|
||||
expect(await within(dialog).findByText(/It still has 2 open work orders/)).toBeInTheDocument();
|
||||
expect(within(dialog).getByRole("button", { name: "Delete" })).toBeEnabled();
|
||||
expect(within(dialog).getByRole("button", { name: "View open work orders" })).toBeEnabled();
|
||||
expect(deleteSite).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("keeps the site and shows the server's refusal when the API answers 403", async () => {
|
||||
getOpenWorkOrders.mockResolvedValue({ count: 0, workOrderIds: [] });
|
||||
deleteSite.mockRejectedValue(forbidden());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue