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}
/>
{
dirtyAll();
if (validate(values)) {
onConfirm();
}
}}
>
{c("operationDialog.confirm")}
);
} 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 (
);
}
export default OperationDialog;