-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.tsx
More file actions
91 lines (81 loc) · 2.76 KB
/
index.tsx
File metadata and controls
91 lines (81 loc) · 2.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { useLayoutEffect, useState } from 'react';
import { Form, notification, Spin } from 'antd';
import { PropsWithChildren } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { clsx } from 'clsx';
import { checkIsFormFieldsError, FormFieldError, getErrorMessage } from '@shared/config';
import { useTranslation } from 'react-i18next';
import * as classes from './styles.module.less';
import { ManagedFormProps } from './types';
import { cleanErrors, revalidateErrorFields, showErrorsInFields } from './utils';
/** Form component to manage the request and results of a form request */
export const ManagedForm = <T extends object, R>({
children,
mutationFunction,
onSuccess,
successMessage,
keysInvalidateQueries = [],
isHiddenLoadingOnSuccess = false,
onError = () => undefined,
prepareFormErrors,
...props
}: PropsWithChildren<ManagedFormProps<T, R>>) => {
const { t, i18n } = useTranslation('error');
const [form] = Form.useForm<T>();
const [isLoading, setLoading] = useState(false);
const queryClient = useQueryClient();
const { mutate } = useMutation<R, unknown, T>({ mutationFn: mutationFunction });
const onFinish = (values: T) => {
setLoading(true);
mutate(values, {
onSuccess: async (response) => {
await Promise.all(keysInvalidateQueries.map((params) => queryClient.invalidateQueries(...params)));
onSuccess(response);
if (isHiddenLoadingOnSuccess) {
setLoading(false);
}
if (successMessage) {
notification.success({
message: successMessage,
});
}
},
onError: (error) => {
onError(error);
setLoading(false);
let message = getErrorMessage(error, t);
if (checkIsFormFieldsError(error) && error.response) {
message = t('formErrorHasOccurred');
const errors: FormFieldError[] = error.response.data.error.details;
const preparedErrors = prepareFormErrors ? prepareFormErrors(errors) : errors;
showErrorsInFields(form, preparedErrors);
}
notification.error({
message,
});
},
});
};
const onValuesChange = (values: T) => {
cleanErrors(form, values);
};
// revalidate form when language change to translate current errors
useLayoutEffect(() => {
revalidateErrorFields(form);
}, [i18n.language, form]);
return (
<div className={classes.wrapper} data-loading={isLoading}>
<Spin className={classes.loader} size="default" />
<Form
onValuesChange={onValuesChange}
layout="vertical"
className={clsx(classes.form, props.className)}
form={form}
onFinish={onFinish}
{...props}
>
{children}
</Form>
</div>
);
};