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

100% Statements 16/16
57.14% Branches 4/7
100% Functions 2/2
100% Lines 16/16

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                                                  13x 13x 13x   13x   6x 6x 6x 4x 4x 6x   2x 2x     2x 2x   6x           13x    
/**
 * 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};
}