All files / blong-browser/src/hooks useSubmit.ts

0% Statements 0/53
0% Branches 0/1
0% Functions 0/1
0% Lines 0/53

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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                                                                                                           
/**
 * useSubmit — form submission wrapper with toast feedback.
 */
import {useCallback, useState} from 'react';
import type {IBlongError} from '../types/action.js';
import {useToast} from './useToast.js';

export interface IUseSubmitOptions {
    successMessage?: string;
    errorMessage?: string;
    /** Called on successful submission */
    onSuccess?: (result: unknown) => void;
    /** Called on error */
    onError?: (error: IBlongError | Error) => void;
}

export interface IUseSubmitResult<T extends Record<string, unknown>> {
    submitting: boolean;
    submit: (values: T) => Promise<unknown>;
}

export function useSubmit<T extends Record<string, unknown>>(
    fn: (values: T) => Promise<unknown>,
    options: IUseSubmitOptions = {},
): IUseSubmitResult<T> {
    const {successMessage = 'Saved successfully', errorMessage = 'An error occurred'} = options;
    const [submitting, setSubmitting] = useState(false);
    const toast = useToast();

    const submit = useCallback(
        async (values: T) => {
            setSubmitting(true);
            try {
                const result = await fn(values);
                toast.success(successMessage);
                options.onSuccess?.(result);
                return result;
            } catch (err) {
                const error = err as IBlongError | Error;
                toast.error(
                    'type' in error ? ((error as IBlongError).print ?? errorMessage) : errorMessage,
                );
                options.onError?.(error);
                throw err;
            } finally {
                setSubmitting(false);
            }
        },
        [fn, successMessage, errorMessage, toast, options],
    );

    return {submitting, submit};
}