backstory/frontend/src/components/DeleteConfirmation.tsx

149 lines
4.0 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import {
IconButton,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Button,
useMediaQuery,
Tooltip,
SxProps,
} from '@mui/material';
import { useTheme } from '@mui/material/styles';
import ResetIcon from '@mui/icons-material/History';
interface DeleteConfirmationProps {
// Legacy props for backward compatibility (uncontrolled mode)
onDelete?: () => void;
disabled?: boolean;
label?: string;
action?: "delete" | "reset";
color?: "inherit" | "default" | "primary" | "secondary" | "error" | "info" | "success" | "warning" | undefined;
sx?: SxProps;
// New props for controlled mode
open?: boolean;
onClose?: () => void;
onConfirm?: () => void;
title?: string;
message?: string;
// Optional props for button customization in controlled mode
hideButton?: boolean;
confirmButtonText?: string;
cancelButtonText?: string;
}
function capitalizeFirstLetter(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
const DeleteConfirmation = (props: DeleteConfirmationProps) => {
const {
// Legacy props
onDelete,
disabled,
label,
color,
action = "delete",
// New props
open: controlledOpen,
onClose: controlledOnClose,
onConfirm,
title,
message,
hideButton = false,
confirmButtonText,
cancelButtonText = "Cancel",
sx
} = props;
// Internal state for uncontrolled mode
const [internalOpen, setInternalOpen] = useState(false);
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down('md'));
// Determine if we're in controlled or uncontrolled mode
const isControlled = controlledOpen !== undefined;
const isOpen = isControlled ? controlledOpen : internalOpen;
const handleClickOpen = () => {
if (!isControlled) {
setInternalOpen(true);
}
};
const handleClose = () => {
if (isControlled) {
controlledOnClose?.();
} else {
setInternalOpen(false);
}
};
const handleConfirm = () => {
if (isControlled) {
onConfirm?.();
} else {
onDelete?.();
setInternalOpen(false);
}
};
// Determine dialog content based on mode
const dialogTitle = title || "Confirm Reset";
const dialogMessage = message || `This action will permanently ${capitalizeFirstLetter(action)} ${label ? label.toLowerCase() : "all data"} without the ability to recover it. Are you sure you want to continue?`;
const confirmText = confirmButtonText || `${capitalizeFirstLetter(action)} ${label || "Everything"}`;
return (
<>
{/* Only show button if not hidden (for controlled mode) */}
{!hideButton && (
<Tooltip title={label ? `${capitalizeFirstLetter(action)} ${label}` : "Reset"}>
<span style={{ display: "flex" }}> {/* This span is used to wrap the IconButton to ensure Tooltip works even when disabled */}
<IconButton
aria-label={action}
onClick={handleClickOpen}
color={color || "inherit"}
sx={{ display: "flex", margin: 'auto 0px', ...sx }}
size="large"
edge="start"
disabled={disabled}
>
<ResetIcon />
</IconButton>
</span>
</Tooltip>
)}
<Dialog
fullScreen={fullScreen}
open={isOpen}
onClose={handleClose}
aria-labelledby="responsive-dialog-title"
>
<DialogTitle id="responsive-dialog-title">
{dialogTitle}
</DialogTitle>
<DialogContent>
<DialogContentText>
{dialogMessage}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button autoFocus onClick={handleClose}>
{cancelButtonText}
</Button>
<Button onClick={handleConfirm} color="error" variant="contained">
{confirmText}
</Button>
</DialogActions>
</Dialog>
</>
);
}
export {
DeleteConfirmation
};