Files
flxn-app/src/lib/tanstack-query/hooks/use-server-mutation.ts
2025-09-24 08:04:09 -05:00

66 lines
2.0 KiB
TypeScript

import { useMutation, UseMutationOptions } from "@tanstack/react-query";
import { ServerResult } from "../types";
import toast from '@/lib/sonner'
export function useServerMutation<TData, TVariables = unknown>(
options: Omit<UseMutationOptions<TData, Error, TVariables>, 'mutationFn'> & {
mutationFn: (variables: TVariables) => Promise<ServerResult<TData>>;
successMessage?: string;
showErrorToast?: boolean;
showSuccessToast?: boolean;
}
) {
const {
mutationFn,
successMessage,
showErrorToast = true,
showSuccessToast = true,
onSuccess,
onError,
...mutationOptions
} = options;
return useMutation({
...mutationOptions,
mutationFn: async (variables: TVariables) => {
try {
const result = await mutationFn(variables);
if (!result.success) {
if (showErrorToast) {
toast.error(result.error.userMessage);
}
throw new Error(result.error.userMessage);
}
return result.data;
} catch (error: any) {
if (error?.response?.status === 401) {
try {
const errorData = typeof error.response.data === 'string'
? JSON.parse(error.response.data)
: error.response.data;
if (errorData?.error === "SESSION_REFRESH_REQUIRED") {
const currentUrl = window.location.pathname + window.location.search;
window.location.href = `/refresh-session?redirect=${encodeURIComponent(currentUrl)}`;
throw new Error("SESSION_REFRESH_REQUIRED");
}
} catch (parseError) {}
}
throw error;
}
},
onSuccess: (data, variables, onMutateResult, context) => {
if (showSuccessToast && successMessage) {
toast.success(successMessage);
}
onSuccess?.(data, variables, onMutateResult, context);
},
onError: (error, variables, onMutateResult, context) => {
onError?.(error, variables, onMutateResult, context);
}
});
}