shoc-frontend-new/src/domain/work-orders/use-cases/use-work-order-uplifts.ts
2026-09-22 23:41:17 -03:00

110 lines
3.7 KiB
TypeScript

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<typeof useQueryClient>,
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<WorkOrderUplift[], Error> {
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<WorkOrderUplift, Error, CreateWorkOrderUpliftInput> {
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<WorkOrderUplift, Error, string | number> {
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<WorkOrderUplift, Error, { upliftId: string | number; reason?: string }> {
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");
},
});
}