Files
clean-architecture-frontend…/src/presentation/forms/use-dirty-navigation-guard.tsx
T

57 lines
1.4 KiB
TypeScript

import { useCallback } from "react";
import { useBeforeUnload, useBlocker } from "react-router-dom";
import { Button } from "../components/ui/button.jsx";
import { Dialog } from "../components/ui/dialog.jsx";
import { useLocale } from "../i18n/index.js";
export function useDirtyNavigationGuard(when: boolean) {
const blocker = useBlocker(when);
useBeforeUnload(
useCallback(
(event) => {
if (!when) return;
event.preventDefault();
event.returnValue = "";
},
[when],
),
{ capture: true },
);
return Object.freeze({
blocked: blocker.state === "blocked",
stay() {
blocker.reset?.();
},
leave() {
blocker.proceed?.();
},
});
}
export function DirtyNavigationDialog(props: Readonly<{
guard: ReturnType<typeof useDirtyNavigationGuard>;
}>) {
const { message } = useLocale();
return (
<Dialog
open={props.guard.blocked}
onClose={props.guard.stay}
title={message("form.unsaved.title")}
description={message("form.unsaved.description")}
actions={
<>
<Button variant="secondary" onClick={props.guard.stay}>
{message("action.continueEditing")}
</Button>
<Button variant="danger" onClick={props.guard.leave}>
{message("action.discardAndLeave")}
</Button>
</>
}
/>
);
}