Untitled

 avatar
unknown
plain_text
a year ago
2.3 kB
5
Indexable
import { reactive, ref } from 'vue';
import Joi, { Schema } from 'joi';

interface UseFormOptions<T> {
    initialValues: T;
    validationSchema: Schema;
    onSubmit: (values: T, signal: AbortSignal) => Promise<ResponseType<T>>;
}

export function useForm<T>({ initialValues, validationSchema, onSubmit }: UseFormOptions<T>) {
    const formData = reactive({ ...initialValues });
    const errors = reactive({} as Record<keyof T, string>);
    const isSubmitting = ref(false);
    const isSubmitted = ref(false);
    const serverError = ref<{ message: string; code: number } | null>(null);
    let abortController = new AbortController();

    const validate = () => {
        const { error } = validationSchema.validate(formData, { abortEarly: false });
        if (error) {
            error.details.forEach(err => {
                const path = err.path[0] as keyof T;
                errors[path] = err.message;
            });
            return false;
        }
        return true;
    };

    const handleSubmit = async () => {
        if (!validate()) return;

        isSubmitting.value = true;
        serverError.value = null;
        abortController = new AbortController();

        try {
            const response = await onSubmit(formData, abortController.signal);
            if (response.status === 'error') {
                serverError.value = { message: response.message, code: response.code };
            } else {
                isSubmitted.value = true;
                serverError.value = null;
            }
        } catch (error) {
            console.error(error);
            serverError.value = { message: error.message, code: 500 }; // Or set a more appropriate code
        } finally {
            isSubmitting.value = false;
        }
    };

    const resetErrors = () => {
        Object.keys(errors).forEach(key => {
            errors[key as keyof T] = '';
        });
        serverError.value = null;
    };

    const abortRequest = () => {
        abortController.abort();
    };

    return {
        formData,
        errors,
        isSubmitting,
        isSubmitted,
        serverError,
        validate,
        handleSubmit,
        resetErrors,
        abortRequest,
    };
}
Editor is loading...
Leave a Comment