diff --git a/packages/app/src/components/FormWithSteps/index.jsx b/packages/app/src/components/FormWithSteps/index.jsx new file mode 100644 index 00000000..4c31cfe9 --- /dev/null +++ b/packages/app/src/components/FormWithSteps/index.jsx @@ -0,0 +1,112 @@ +import React from "react" +import { Button, Alert } from "antd" + +import "./index.less" + +const FormWithSteps = (props) => { + const { steps, header, onCancel, onFinish, cancelable } = props + + const [step, setStep] = React.useState(0) + const [values, setValues] = React.useState({}) + const [error, setError] = React.useState(null) + + function updateState(key, value) { + setValues((prevValues) => ({ ...prevValues, [key]: value })) + } + + function previousStep() { + if (step === 0) { + if (!cancelable) { + return false + } + + if (typeof onCancel === "function") { + onCancel() + } + } + + setStep((prev) => { + if (step === 0) { + return prev + } + + return prev - 1 + }) + } + + async function nextStep() { + if (!canNext()) { + return false + } + + if (step === steps.length - 1) { + return await onFinish({ + values, + updateState, + setError, + }) + } + + if (typeof steps[step].onNext === "function") { + const result = await steps[step].onNext({ + values, + updateState, + setError, + }) + + if (result) { + if (result.cancel === true) { + return false + } + } + } + + setStep((prev) => { + if (step === steps.length - 1) { + return prev + } + + return prev + 1 + }) + + setError(null) + } + + function canNext() { + if (typeof steps[step].validate === "function") { + return steps[step].validate(values) + } + + return true + } + + return ( +
+ {typeof header === "function" && + header({ + step: step, + })} + +
+ {steps[step].render({ + updateState: updateState, + values: values, + })} + + {error && } + +
+ + + +
+
+
+ ) +} + +export default FormWithSteps diff --git a/packages/app/src/components/FormWithSteps/index.less b/packages/app/src/components/FormWithSteps/index.less new file mode 100644 index 00000000..16c3bc16 --- /dev/null +++ b/packages/app/src/components/FormWithSteps/index.less @@ -0,0 +1,31 @@ +.steped-form { + display: flex; + flex-direction: column; + + gap: 40px; + + width: 100%; + + .steped-form-header { + display: flex; + flex-direction: column; + width: 100%; + } + + .steped-form-content { + display: flex; + flex-direction: column; + + gap: 10px; + width: 100%; + } + + .steped-form-content-actions { + display: flex; + flex-direction: row; + + justify-content: flex-end; + + gap: 10px; + } +}