mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-03 15:03:22 +00:00
- Gate the Revoke action on the approved queue row and the detail modal to admin users; non-admins get a disabled button with a plain 'Only admins can revoke uplifts' tooltip and the dialog cannot open. - Stop nesting an h2 inside DialogTitle in the uplift detail modal (hydration error) by rendering the title text as a non-heading. - Handle work-order detail/uplift query 403s quietly in the detail modal: sections fall back to 'Unavailable' and the queries suppress the global error toast (QueryCache now honors suppressErrorToast). - Extract UpliftDecisionDialogs and openUpliftEvidence from the page to meet the changed-file maintainability gate (complexity 23 -> pass).
89 lines
2.9 KiB
TypeScript
89 lines
2.9 KiB
TypeScript
import {
|
|
useMutation,
|
|
useQuery,
|
|
useQueryClient,
|
|
type UseMutationResult,
|
|
type UseQueryResult,
|
|
} from "@tanstack/react-query";
|
|
import { toast } from "react-toastify";
|
|
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";
|
|
|
|
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(error.message || "Failed to create uplift");
|
|
},
|
|
});
|
|
}
|
|
|
|
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");
|
|
},
|
|
});
|
|
}
|