import { useMutation, useQuery, useQueryClient, type UseMutationResult, type UseQueryResult, } from "@tanstack/react-query"; import { isHTTPError, isNetworkError, isTimeoutError } from "ky"; import { toast } from "react-toastify"; import { mapHttpStatusToMessage, REQUEST_UPLIFTS_ROLE_DENIAL_MESSAGE } from "@/api/api-error"; import { workOrderUpliftsApi } from "@/domain/work-orders/api/work-order-uplifts-api"; import type { CreateWorkOrderUpliftInput, WorkOrderUplift, } from "@/domain/work-orders/types/work-order-uplift"; import { queryKeys } from "@/infra/query-key/query-key"; import { requireQueryParam } from "@/lib/query/require-query-param"; const CREATE_UPLIFT_ERROR_FALLBACK = "Failed to create uplift"; const CREATE_UPLIFT_FIXED_STATUS_COPY = new Set([401, 403, 404, 500]); function createUpliftErrorMessage(error: unknown): string { if (isHTTPError(error)) { const status = error.response.status; if (status === 403 && error.message === REQUEST_UPLIFTS_ROLE_DENIAL_MESSAGE) { return REQUEST_UPLIFTS_ROLE_DENIAL_MESSAGE; } return CREATE_UPLIFT_FIXED_STATUS_COPY.has(status) ? mapHttpStatusToMessage(status) : CREATE_UPLIFT_ERROR_FALLBACK; } if (isNetworkError(error) || isTimeoutError(error)) { return error.message; } return CREATE_UPLIFT_ERROR_FALLBACK; } function invalidateUpliftQueries( queryClient: ReturnType, workOrderId: string | number, ): void { void queryClient.invalidateQueries({ queryKey: queryKeys.workOrders.uplifts(workOrderId) }); void queryClient.invalidateQueries({ queryKey: queryKeys.workOrders.all }); } export function useWorkOrderUplifts( workOrderId: string | number | null | undefined, meta?: { suppressErrorToast?: boolean }, ): UseQueryResult { return useQuery({ queryKey: queryKeys.workOrders.uplifts(workOrderId ?? ""), queryFn: () => workOrderUpliftsApi.list(requireQueryParam(workOrderId ?? undefined, "Work order id")), enabled: workOrderId != null && workOrderId !== "", meta, }); } export function useCreateWorkOrderUplift( workOrderId: string | number, ): UseMutationResult { const queryClient = useQueryClient(); return useMutation({ mutationFn: (input: CreateWorkOrderUpliftInput) => workOrderUpliftsApi.create(workOrderId, input), onSuccess: () => { invalidateUpliftQueries(queryClient, workOrderId); toast.success("Uplift request created"); }, onError: (error) => { toast.error(createUpliftErrorMessage(error)); }, }); } export function useCancelWorkOrderUplift( workOrderId: string | number, ): UseMutationResult { const queryClient = useQueryClient(); return useMutation({ mutationFn: (upliftId: string | number) => workOrderUpliftsApi.cancel(workOrderId, upliftId), onSuccess: () => { invalidateUpliftQueries(queryClient, workOrderId); toast.success("Uplift cancelled"); }, onError: (error) => { toast.error(error.message || "Failed to cancel uplift"); }, }); } export function useRevokeWorkOrderUplift( workOrderId: string | number, ): UseMutationResult { const queryClient = useQueryClient(); return useMutation({ mutationFn: ({ upliftId, reason }: { upliftId: string | number; reason?: string }) => workOrderUpliftsApi.revoke(workOrderId, upliftId, reason), onSuccess: () => { invalidateUpliftQueries(queryClient, workOrderId); toast.success("Uplift revoked"); }, onError: (error) => { toast.error(error.message || "Failed to revoke uplift"); }, }); }