Skip to content

Commit

Permalink
added logic for preventing navigation on dirty form
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacobjeevan committed Jan 8, 2025
1 parent adac786 commit 22da20d
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/components/Questionnaire/QuestionnaireForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { Button } from "@/components/ui/button";

import Loading from "@/components/Common/Loading";

import { usePreventNavigation } from "@/hooks/usePreventNavigation";

import routes from "@/Utils/request/api";
import useMutation from "@/Utils/request/useMutation";
import useQuery from "@/Utils/request/useQuery";
Expand Down Expand Up @@ -61,6 +63,7 @@ export function QuestionnaireForm({
onCancel,
facilityId,
}: QuestionnaireFormProps) {
const [isDirty, setIsDirty] = useState(false);
const [questionnaireForms, setQuestionnaireForms] = useState<
QuestionnaireFormState[]
>([]);
Expand All @@ -82,6 +85,8 @@ export function QuestionnaireForm({
{ silent: true },
);

usePreventNavigation({ isDirty });

useEffect(() => {
if (!isInitialized && questionnaireSlug) {
const questionnaire =
Expand All @@ -100,6 +105,19 @@ export function QuestionnaireForm({
}
}, [questionnaireData, isInitialized, questionnaireSlug]);

useEffect(() => {
const hasEdits = questionnaireForms.some((form) =>
form.responses.some(
(response) =>
response.values.length > 0 ||
response.note ||
response.body_site ||
response.method,
),
);
setIsDirty(hasEdits);
}, [questionnaireForms]);

if (isQuestionnaireLoading) {
return <Loading />;
}
Expand Down
54 changes: 54 additions & 0 deletions src/hooks/usePreventNavigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { useEffect } from "react";

interface UsePreventNavigationOptions {
isDirty: boolean;
message?: string;
}

export function usePreventNavigation({
isDirty,
message = "You have unsaved changes. Are you sure you want to leave?",
}: UsePreventNavigationOptions) {
useEffect(() => {
if (!isDirty) return;

const handleBeforeUnload = (e: BeforeUnloadEvent) => {
e.preventDefault();
e.returnValue = "";
return "";
};

const preventNavigation = (e: Event) => {
const confirmLeave = window.confirm(message);

if (!confirmLeave) {
e.preventDefault();
e.stopPropagation();
window.history.replaceState(null, "", window.location.pathname);
return false;
}
};

const handleLinkClick = (e: MouseEvent) => {
const link = (e.target as HTMLElement).closest("a");
if (link) preventNavigation(e);
};

// Common options for event listeners
const listenerOptions = { capture: true };

window.addEventListener("beforeunload", handleBeforeUnload);
window.addEventListener("popstate", preventNavigation, listenerOptions);
document.addEventListener("click", handleLinkClick, listenerOptions);

return () => {
window.removeEventListener("beforeunload", handleBeforeUnload);
window.removeEventListener(
"popstate",
preventNavigation,
listenerOptions,
);
document.removeEventListener("click", handleLinkClick, listenerOptions);
};
}, [isDirty, message]);
}

0 comments on commit 22da20d

Please sign in to comment.