+ >();
const styles = useStyles();
const extensions = useMemo(() => {
@@ -61,12 +67,40 @@ export const Stepper = (props: StepperProps) => {
);
}, [props.extensions]);
+ const validators = useMemo(() => {
+ return Object.fromEntries(
+ props.extensions.map(({ name, validation }) => [name, validation]),
+ );
+ }, [props.extensions]);
+
+ const validation = useMemo(() => {
+ const { mergedSchema } = steps[activeStep];
+ return createAsyncValidators(mergedSchema, validators, {
+ apiHolder,
+ });
+ }, [steps, activeStep, validators, apiHolder]);
+
const handleBack = () => {
setActiveStep(prevActiveStep => prevActiveStep - 1);
};
- const handleNext = ({ formData }: { formData: JsonObject }) => {
- setActiveStep(prevActiveStep => prevActiveStep + 1);
+ const handleNext = async ({ formData }: { formData: JsonObject }) => {
+ // TODO(blam): What do we do about loading states, does each field extension get a chance
+ // to display it's own loading? Or should we grey out the entire form.
+ setErrors(undefined);
+
+ const returnedValidation = await validation(formData);
+
+ const hasErrors = Object.values(returnedValidation).some(i => {
+ return i.__errors.length > 0;
+ });
+
+ if (hasErrors) {
+ setErrors(returnedValidation);
+ } else {
+ setErrors(undefined);
+ setActiveStep(prevActiveStep => prevActiveStep + 1);
+ }
setFormState(current => ({ ...current, ...formData }));
};
@@ -81,6 +115,7 @@ export const Stepper = (props: StepperProps) => {