import React, { createContext, useContext, useState, useCallback, ReactNode } from 'react'; import { Modal, Text, Button, Group, Stack } from '@mantine/core'; import { useTranslation } from 'react-i18next'; interface UnsavedChangesContextType { isDirty: boolean; setIsDirty: (dirty: boolean) => void; /** * Call this before navigating away or closing. * Returns a promise that resolves to true if safe to proceed, false if blocked. */ confirmIfDirty: () => Promise; /** * Reset dirty state (call after successful save) */ markClean: () => void; } const UnsavedChangesContext = createContext(undefined); interface UnsavedChangesProviderProps { children: ReactNode; } export function UnsavedChangesProvider({ children }: UnsavedChangesProviderProps) { const { t } = useTranslation(); const [isDirty, setIsDirty] = useState(false); const [modalOpen, setModalOpen] = useState(false); const [resolvePromise, setResolvePromise] = useState<((value: boolean) => void) | null>(null); const confirmIfDirty = useCallback((): Promise => { if (!isDirty) { return Promise.resolve(true); } return new Promise((resolve) => { setResolvePromise(() => resolve); setModalOpen(true); }); }, [isDirty]); const markClean = useCallback(() => { setIsDirty(false); }, []); const handleDiscard = () => { setModalOpen(false); setIsDirty(false); resolvePromise?.(true); setResolvePromise(null); }; const handleCancel = () => { setModalOpen(false); resolvePromise?.(false); setResolvePromise(null); }; return ( {children} {t('admin.settings.unsavedChanges.message', 'You have unsaved changes. Do you want to discard them?')} ); } export function useUnsavedChanges(): UnsavedChangesContextType { const context = useContext(UnsavedChangesContext); if (!context) { throw new Error('useUnsavedChanges must be used within an UnsavedChangesProvider'); } return context; }