import React, { useEffect, useRef, useState } from "react";
import { useBlocker, useBeforeUnload } from "react-router-dom";
import { Alert, Box, Button, Checkbox, FormControlLabel, Stack, Typography } from "@mui/material";
import { arrangeDashboardWidgets, DashboardLayout, defaultDashboardLayout, WIDGETS } from "../dashboardLayout";
import { useI18n } from "../i18n/I18nProvider";
import { useConfirm } from "../confirm";
import { PageSection } from "../layout/PageLayout";
export function DashboardNavigationGuard({ dirty, saving }: { dirty: boolean; saving: boolean }) {
const { t } = useI18n();
const { confirm } = useConfirm();
const blocker = useBlocker(dirty || saving);
const [waiting, setWaiting] = useState(false);
const pending = useRef(false);
useBeforeUnload(React.useCallback(event => {
if (!dirty) return;
event.preventDefault(); event.returnValue = "";
}, [dirty]));
useEffect(() => {
if (blocker.state !== "blocked") { pending.current = false; return; }
if (saving) { setWaiting(true); blocker.reset(); return; }
if (pending.current) return;
pending.current = true;
void confirm({ title: t("dashboardDiscardTitle"), message: t("dashboardDiscardBody"), confirmLabel: t("dashboardDiscard"), cancelLabel: t("workspaceKeepEditing"), destructive: true })
.then(approved => { if (approved) blocker.proceed(); else blocker.reset(); });
}, [blocker, confirm, saving, t]);
return waiting && saving ? {t("dashboardWaitForSave")} : null;
}
type Props = {
draft: DashboardLayout;
dirty: boolean;
saving: boolean;
saveError: string | null;
conflict: boolean;
onChange: (next: DashboardLayout) => void;
onSave: () => void;
onCancel: () => void;
onReload: () => void;
};
export default function DashboardLayoutEditor({ draft, dirty, saving, saveError, conflict, onChange, onSave, onCancel, onReload }: Props) {
const { t } = useI18n();
const { confirm } = useConfirm();
const panel = useRef(null);
useEffect(() => {
panel.current?.focus({ preventScroll: true });
panel.current?.scrollIntoView?.({ block: "start" });
}, []);
const cancel = async () => {
if (!dirty || await confirm({ title: t("dashboardDiscardTitle"), message: t("dashboardDiscardBody"), confirmLabel: t("dashboardDiscard"), destructive: true })) onCancel();
};
const reset = async () => {
if (await confirm({ title: t("dashboardReset"), message: t("dashboardResetBody"), confirmLabel: t("dashboardReset") })) onChange({ ...defaultDashboardLayout(), revision: draft.revision });
};
const reload = async () => {
if (await confirm({ title: t("dashboardReload"), message: t("dashboardReloadBody"), confirmLabel: t("dashboardReload"), destructive: true })) onReload();
};
return {
if (event.key === "Escape" && !saving && !event.defaultPrevented) { event.preventDefault(); void cancel(); }
}}>
{saveError ? {t(conflict ? "dashboardConflict" : "dashboardSaveFailed")}
{conflict ? : null}
: null}
{t(dirty ? "assetsUnsavedChanges" : "dashboardDraftSaved")}
{t("dashboardManageWidgets")}
{draft.widgets.map(widget => {
const entry = WIDGETS.find(item => item.id === widget.id)!;
const name = t(entry.titleKey);
return onChange({ ...draft,
widgets: arrangeDashboardWidgets(draft.widgets.map(item => item.id === widget.id ? { ...item, visible: event.target.checked } : item)) })} />} />;
})}
;
}