import { useCallback, useEffect, useRef } from "react"; /** * Dirty-form guard shared by the document detail pages (extracted from * OfferDetail). Serializes `snapshot` (typically `{ form, items, sections }`) * every render, captures a baseline on the first `ready` render — or * explicitly via `markClean` — and registers a `beforeunload` warning while * the current snapshot differs from the baseline. * * `markClean(value?)`: * - with a value: baseline = that value (use from a hydration effect, where * the freshly-mapped objects are ahead of the not-yet-rendered state); * - without: baseline = the last RENDERED snapshot (use after a successful * save, where the handler's closure state equals the rendered state). */ export function useUnsavedChangesGuard(snapshot: unknown, ready: boolean) { const serialized = JSON.stringify(snapshot); const serializedRef = useRef(serialized); serializedRef.current = serialized; const baselineRef = useRef(null); if (ready && baselineRef.current === null) baselineRef.current = serialized; const isDirty = baselineRef.current !== null && serialized !== baselineRef.current; useEffect(() => { if (!isDirty) return; const handler = (e: BeforeUnloadEvent) => { e.preventDefault(); e.returnValue = ""; }; window.addEventListener("beforeunload", handler); return () => window.removeEventListener("beforeunload", handler); }, [isDirty]); const markClean = useCallback((value?: unknown) => { baselineRef.current = value !== undefined ? JSON.stringify(value) : serializedRef.current; }, []); return { isDirty, markClean }; }