import React, { createContext, useCallback, useContext, useId, useMemo, useRef, useState } from "react"; import { Alert, Button, Dialog, DialogActions, DialogContent, DialogTitle, Typography } from "@mui/material"; import { useOptionalI18n } from "./i18n/I18nProvider"; type ConfirmOptions = { title?: string; message: string; confirmLabel?: string; cancelLabel?: string; destructive?: boolean; }; type ConfirmContextValue = { confirm: (options: ConfirmOptions) => Promise; }; type ConfirmState = ConfirmOptions & { open: boolean; }; const ConfirmContext = createContext(null); export function ConfirmProvider({ children }: { children: React.ReactNode }) { const i18n = useOptionalI18n(); const messageId = useId(); const resolverRef = useRef<((value: boolean) => void) | null>(null); const cancelButtonRef = useRef(null); const [state, setState] = useState({ open: false, message: "", title: "Confirm action", confirmLabel: "Confirm", cancelLabel: "Cancel", destructive: false, }); const closeWith = useCallback((value: boolean) => { const resolve = resolverRef.current; resolverRef.current = null; setState((prev) => ({ ...prev, open: false })); resolve?.(value); }, []); const confirm = useCallback((options: ConfirmOptions) => { return new Promise((resolve) => { resolverRef.current = resolve; setState({ open: true, title: options.title ?? i18n?.t("confirmAction") ?? "Confirm action", message: options.message, confirmLabel: options.confirmLabel ?? i18n?.t("confirm") ?? "Confirm", cancelLabel: options.cancelLabel ?? i18n?.t("cancel") ?? "Cancel", destructive: options.destructive ?? false, }); }); }, [i18n]); const value = useMemo(() => ({ confirm }), [confirm]); return ( {children} closeWith(false)} aria-describedby={messageId} fullWidth maxWidth="xs" slotProps={{ paper: { sx: { borderRadius: 3, border: 1, borderColor: "divider", backgroundImage: "none" } }, transition: { onEntered: () => cancelButtonRef.current?.focus() }, }}> {state.title} {state.destructive ? i18n?.t("confirmDestructiveHint") ?? "This action may be hard to undo." : i18n?.t("confirmStandardHint") ?? "Please confirm this action."} {state.message} ); } export function useConfirm() { const ctx = useContext(ConfirmContext); if (!ctx) throw new Error("useConfirm must be used within ConfirmProvider"); return ctx; }