The Správa kategorií modal footer had two buttons that both just close it (Zrušit + Zavřít). Added an opt-in hideCancel prop to the kit Modal (default false → every other modal unchanged) and set it on PlanCategoriesModal, leaving only 'Zavřít'. Verified: footer shows only Zavřít; close/Escape/backdrop intact. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
95 lines
3.0 KiB
TypeScript
95 lines
3.0 KiB
TypeScript
import { useState, type ReactNode } from "react";
|
|
import Dialog from "@mui/material/Dialog";
|
|
import DialogTitle from "@mui/material/DialogTitle";
|
|
import DialogContent from "@mui/material/DialogContent";
|
|
import DialogActions from "@mui/material/DialogActions";
|
|
import Typography from "@mui/material/Typography";
|
|
import MuiButton from "@mui/material/Button";
|
|
import useDialogScrollLock from "./useDialogScrollLock";
|
|
|
|
export interface ModalProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
onSubmit: () => void;
|
|
title: string;
|
|
subtitle?: string;
|
|
children: ReactNode;
|
|
loading?: boolean;
|
|
submitDisabled?: boolean;
|
|
submitText?: string;
|
|
cancelText?: string;
|
|
/** Hide the secondary cancel button (e.g. modals whose only action closes). */
|
|
hideCancel?: boolean;
|
|
maxWidth?: "xs" | "sm" | "md" | "lg";
|
|
}
|
|
|
|
/** Form modal over MUI Dialog. Preserves the legacy FormModal prop shape. */
|
|
export default function Modal({
|
|
isOpen,
|
|
onClose,
|
|
onSubmit,
|
|
title,
|
|
subtitle,
|
|
children,
|
|
loading = false,
|
|
submitDisabled = false,
|
|
submitText = "Uložit",
|
|
cancelText = "Zrušit",
|
|
hideCancel = false,
|
|
maxWidth = "sm",
|
|
}: ModalProps) {
|
|
useDialogScrollLock(isOpen);
|
|
// Freeze the shown title/subtitle/submitText while closing, so the fade-out
|
|
// never flashes the "create" variant when the caller clears `editingUser` on
|
|
// close (React derive-state-from-props: update only while open).
|
|
// Freeze label-affecting props (incl. `loading`) while open, so neither the
|
|
// title/submitText NOR the loading state flips during the close fade-out
|
|
// (e.g. on save, `loading` goes false a beat before the dialog finishes
|
|
// closing — without this the button would flash back to "Uložit změny").
|
|
const [shown, setShown] = useState({ title, subtitle, submitText, loading });
|
|
if (
|
|
isOpen &&
|
|
(shown.title !== title ||
|
|
shown.subtitle !== subtitle ||
|
|
shown.submitText !== submitText ||
|
|
shown.loading !== loading)
|
|
) {
|
|
setShown({ title, subtitle, submitText, loading });
|
|
}
|
|
|
|
return (
|
|
<Dialog
|
|
open={isOpen}
|
|
onClose={shown.loading ? undefined : onClose}
|
|
fullWidth
|
|
maxWidth={maxWidth}
|
|
disableScrollLock
|
|
slotProps={{ paper: { sx: { borderRadius: 3 } } }}
|
|
>
|
|
<DialogTitle sx={{ pb: shown.subtitle ? 0.5 : 1.5 }}>
|
|
{shown.title}
|
|
{shown.subtitle && (
|
|
<Typography variant="body2" color="text.secondary">
|
|
{shown.subtitle}
|
|
</Typography>
|
|
)}
|
|
</DialogTitle>
|
|
<DialogContent>{children}</DialogContent>
|
|
<DialogActions sx={{ px: 3, pb: 2 }}>
|
|
{!hideCancel && (
|
|
<MuiButton onClick={onClose} color="inherit" disabled={shown.loading}>
|
|
{cancelText}
|
|
</MuiButton>
|
|
)}
|
|
<MuiButton
|
|
onClick={onSubmit}
|
|
variant="contained"
|
|
disabled={shown.loading || submitDisabled}
|
|
>
|
|
{shown.loading ? "Ukládám…" : shown.submitText}
|
|
</MuiButton>
|
|
</DialogActions>
|
|
</Dialog>
|
|
);
|
|
}
|