Files
probo/apps/console/src/hooks/useMutationWithToasts.ts
Émile Ré c168be6de0 Add import order sorting rules
Signed-off-by: Émile Ré <emile@getprobo.com>
2026-01-22 20:38:37 +04:00

76 lines
2.5 KiB
TypeScript

import { formatError, type GraphQLError } from "@probo/helpers";
import { useTranslate } from "@probo/i18n";
import { useToast } from "@probo/ui";
import { useCallback } from "react";
import { useMutation, type UseMutationConfig } from "react-relay";
import type { GraphQLTaggedNode, MutationParameters } from "relay-runtime";
/**
* A decorated useMutation hook that emits toast notifications on success or error.
*/
export function useMutationWithToasts<T extends MutationParameters>(
query: GraphQLTaggedNode,
baseOptions?: {
successMessage?: string | ((response: T["response"]) => string);
errorMessage?: string;
},
) {
const [mutate, isLoading] = useMutation<T>(query);
const { toast } = useToast();
const { __ } = useTranslate();
const mutateWithToast = useCallback(
(
queryOptions: UseMutationConfig<T> & {
onSuccess?: () => void;
successMessage?: string | ((response: T["response"]) => string);
errorMessage?: string;
},
) => {
const options = { ...baseOptions, ...queryOptions };
return new Promise<void>((resolve, reject) =>
mutate({
...queryOptions,
onCompleted: (response, error) => {
options.onCompleted?.(response, error);
if (error) {
const errorTitle = options.errorMessage ?? __("Failed to commit this operation");
toast({
title: __("Error"),
description: formatError(errorTitle, error as GraphQLError[]),
variant: "error",
});
reject(new Error(errorTitle));
return;
}
const successMessage = typeof options.successMessage === "function"
? options.successMessage(response)
: options.successMessage;
toast({
title: __("Success"),
description:
successMessage
?? __("Operation completed successfully"),
variant: "success",
});
options.onSuccess?.();
resolve();
},
onError: (error) => {
const errorTitle = options.errorMessage ?? __("Failed to commit this operation");
toast({
title: __("Error"),
description: formatError(errorTitle, error as GraphQLError),
variant: "error",
});
reject(error);
},
}),
);
},
[mutate, toast, __, baseOptions],
);
return [mutateWithToast, isLoading] as const;
}