dashpresshq/dashpress

View on GitHub
src/frontend/lib/data/useMutate/useWaitForResponseMutationOptions.ts

Summary

Maintainability
A
2 hrs
Test Coverage
C
75%
import { msg } from "@lingui/macro";
import { useMutation, useQueryClient } from "@tanstack/react-query";

import { useToast } from "@/components/app/toast/use-toast";
import { fakeMessageDescriptor } from "@/translations/fake";

import { getQueryCachekey } from "../constants/getQueryCacheKey";
import type { ToastMessageInput } from "./types";

export interface IWaitForResponseMutationOptions<V, R> {
  endpoints: string[];
  redirect?: string;
  mutationFn: (formData: V) => Promise<R>;
  onSuccessActionWithFormData?: (response: R) => void;
  successMessage?: ToastMessageInput;
  smartSuccessMessage?: (formData: R) => ToastMessageInput;
}

const PASS_DATA_FROM_HANDLER_ERROR_MESSAGE =
  "Please return in the mutation what data you want to pass to the success handlers";

export function useWaitForResponseMutationOptions<V, R = void>(
  options: IWaitForResponseMutationOptions<V, R>
) {
  const queryClient = useQueryClient();
  const { toast } = useToast();

  return useMutation({
    mutationFn: options.mutationFn,
    onSuccess: async (formData: R | undefined) => {
      options.endpoints.forEach((queryKey) => {
        queryClient.invalidateQueries({ queryKey: getQueryCachekey(queryKey) });
      });

      if (options.smartSuccessMessage) {
        if (formData === undefined) {
          throw new Error(PASS_DATA_FROM_HANDLER_ERROR_MESSAGE);
        }
        toast({ variant: "green", ...options.smartSuccessMessage(formData) });
      } else if (options.successMessage) {
        toast({ variant: "green", ...options.successMessage });
      }

      if (options.onSuccessActionWithFormData) {
        if (formData === undefined) {
          throw new Error(PASS_DATA_FROM_HANDLER_ERROR_MESSAGE);
        }
        options.onSuccessActionWithFormData(formData);
      }
    },
    onError: (error: { message: string }) => {
      toast({
        variant: "red",
        title: msg`Request Failed`,
        description: fakeMessageDescriptor(
          error.message ||
            "Something went wrong. Please try again or contact your adminstrator."
        ),
      });
    },
  });
}