import { useState, ReactNode } from "react"; import classNames from "classnames"; import { useC, Text, ThemeColor } from "../common"; import Button from "../button/Button"; import { useInputs, InputGroup, Initializer as InputInitializer, InputValueDict, InputErrorDict, } from "../input/InputGroup"; import LoadingButton from "../button/LoadingButton"; import Dialog from "./Dialog"; import "./OperationDialog.css"; export type { InputInitializer, InputValueDict, InputErrorDict }; interface OperationDialogPromptProps { message?: Text; customMessage?: ReactNode; className?: string; } function OperationDialogPrompt(props: OperationDialogPromptProps) { const { message, customMessage, className } = props; const c = useC(); return (
{message &&

{c(message)}

} {customMessage}
); } export interface OperationDialogProps { open: boolean; onClose: () => void; color?: ThemeColor; inputColor?: ThemeColor; title: Text; inputPrompt?: Text; successPrompt?: (data: TData) => ReactNode; failurePrompt?: (error: unknown) => ReactNode; inputs: InputInitializer; onProcess: (inputs: InputValueDict) => Promise; onSuccessAndClose?: (data: TData) => void; } function OperationDialog(props: OperationDialogProps) { const { open, onClose, color, inputColor, title, inputPrompt, successPrompt, failurePrompt, inputs, onProcess, onSuccessAndClose, } = props; const c = useC(); type Step = | { type: "input" } | { type: "process" } | { type: "success"; data: TData; } | { type: "failure"; data: unknown; }; const [step, setStep] = useState({ type: "input" }); const { inputGroupProps, hasErrorAndDirty, setAllDisabled, confirm } = useInputs({ init: inputs, }); function close() { if (step.type !== "process") { onClose(); if (step.type === "success" && onSuccessAndClose) { onSuccessAndClose?.(step.data); } } else { console.log("Attempt to close modal dialog when processing."); } } function onConfirm() { const result = confirm(); if (result.type === "ok") { setStep({ type: "process" }); setAllDisabled(true); onProcess(result.values).then( (d) => { setStep({ type: "success", data: d, }); }, (e: unknown) => { setStep({ type: "failure", data: e, }); }, ); } } let body: ReactNode; if (step.type === "input" || step.type === "process") { const isProcessing = step.type === "process"; body = (

); } else { const result = step; const promptProps: OperationDialogPromptProps = result.type === "success" ? { message: "operationDialog.success", customMessage: successPrompt?.(result.data), } : { message: "operationDialog.error", customMessage: failurePrompt?.(result.data), }; body = (

); } return (
{c(title)}

{body}
); } export default OperationDialog;