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

60.37% Statements 32/53
100% Branches 1/1
0% Functions 0/1
60.37% Lines 32/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 541x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                           1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x  
/**
 * 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};
}