import { useState, ReactNode } from "react"; import classNames from "classnames"; import { useC, Text, ThemeColor } from "../common"; import Button from "../button/Button"; import { default as InputGroup, InputErrors, InputList, Validator, Values, useDirties, } from "../input/InputGroup"; import LoadingButton from "../button/LoadingButton"; import Dialog from "./Dialog"; import "./OperationDialog.css"; 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; title: Text; inputPrompt?: Text; processPrompt?: Text; successPrompt?: (data: TData) => ReactNode; failurePrompt?: (error: unknown) => ReactNode; inputs: Inputs; validator?: Validator; onProcess: (inputs: Values) => Promise; onSuccessAndClose?: (data: TData) => void; } function OperationDialog( props: OperationDialogProps, ) { const { open, onClose, color, title, inputPrompt, processPrompt, successPrompt, failurePrompt, inputs, validator, 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 [values, setValues] = useState>(); const [errors, setErrors] = useState(); const [dirties, setDirties, dirtyAll] = useDirties(); function close() { if (step.type !== "process") { props.onClose(); if (step.type === "success" && props.onSuccessAndClose) { props.onSuccessAndClose(step.data); } } else { console.log("Attempt to close modal dialog when processing."); } } function onConfirm() { setStep({ type: "process" }); props .onProcess( values.map((value, index) => finalValueMapperMap[inputScheme[index].type](value as never), ) as 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"; const hasError = errors.length > 0; body = (
{ setValues(values); setErrors(errors); }} dirties={dirties} onDirty={setDirties} />

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

); } return (
{c(props.title)}

{body}
); } export default OperationDialog;