feat(ticket): add issue-by-issue repair review page
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
'use client';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import {
|
||||
useInfiniteQuery,
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
} from '@tanstack/react-query';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
import { detectionService, ticketService, videoService } from '@/services/api';
|
||||
@@ -10,12 +15,13 @@ import type {
|
||||
CloseTicketPayload,
|
||||
DiscardDetectionPayload,
|
||||
RequestTicketExtensionPayload,
|
||||
ReviewDetectionRepairProofPayload,
|
||||
ReviewTicketExtensionPayload,
|
||||
ReviewRepairPayload,
|
||||
SubmitRepairPayload,
|
||||
SubmitRepairUploadPayload,
|
||||
TicketDetail,
|
||||
TicketListParams,
|
||||
DetectionProofStatus,
|
||||
VideoDetectionsParams,
|
||||
} from '@/types';
|
||||
|
||||
@@ -118,6 +124,36 @@ export function useTicketClassDetectionsQuery(
|
||||
});
|
||||
}
|
||||
|
||||
export function useTicketClassReviewDetectionsQuery(
|
||||
videoId: string | undefined,
|
||||
defectClass: string | undefined,
|
||||
proofStatus?: DetectionProofStatus,
|
||||
) {
|
||||
const pageSize = 20;
|
||||
|
||||
return useInfiniteQuery({
|
||||
queryKey: ticketKeys.classReviewDetections(
|
||||
videoId ?? '',
|
||||
defectClass ?? '',
|
||||
proofStatus,
|
||||
),
|
||||
queryFn: ({ pageParam }) =>
|
||||
videoService.getVideoDetections(videoId as string, {
|
||||
class_name: defectClass,
|
||||
proof_status: proofStatus,
|
||||
sort: 'timestamp_asc',
|
||||
skip: pageParam,
|
||||
limit: pageSize,
|
||||
}),
|
||||
initialPageParam: 0,
|
||||
getNextPageParam: (lastPage) => {
|
||||
const nextSkip = lastPage.skip + lastPage.items.length;
|
||||
return nextSkip < lastPage.total ? nextSkip : undefined;
|
||||
},
|
||||
enabled: Boolean(videoId && defectClass),
|
||||
});
|
||||
}
|
||||
|
||||
export function useDiscardDetectionMutation(
|
||||
ticketId: string,
|
||||
videoId: string | undefined,
|
||||
@@ -158,6 +194,54 @@ export function useDiscardDetectionMutation(
|
||||
});
|
||||
}
|
||||
|
||||
export function useReviewDetectionRepairProofMutation({
|
||||
ticketId,
|
||||
videoId,
|
||||
defectClass,
|
||||
}: {
|
||||
ticketId: string;
|
||||
videoId: string | undefined;
|
||||
defectClass: string;
|
||||
}) {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({
|
||||
detectionId,
|
||||
payload,
|
||||
}: {
|
||||
detectionId: number;
|
||||
payload: ReviewDetectionRepairProofPayload;
|
||||
}) => detectionService.reviewRepairProof(ticketId, detectionId, payload),
|
||||
onSuccess: async (_repairProof, variables) => {
|
||||
toast.success(
|
||||
variables.payload.action === 'approve'
|
||||
? 'Repair proof approved'
|
||||
: 'Repair proof rejected',
|
||||
);
|
||||
|
||||
await Promise.all([
|
||||
videoId
|
||||
? queryClient.invalidateQueries({
|
||||
queryKey: ticketKeys.classDetectionLists(videoId),
|
||||
})
|
||||
: Promise.resolve(),
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ticketKeys.classDetail(ticketId, defectClass),
|
||||
}),
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ticketKeys.defectClasses(ticketId),
|
||||
}),
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ticketKeys.overview(ticketId),
|
||||
}),
|
||||
queryClient.invalidateQueries({ queryKey: ticketKeys.lists() }),
|
||||
]);
|
||||
},
|
||||
onError: () => toast.error('Failed to review repair proof'),
|
||||
});
|
||||
}
|
||||
|
||||
export function useTicketExtensionRequestQuery(
|
||||
ticketId: string | undefined,
|
||||
assignmentId: number | undefined,
|
||||
@@ -306,26 +390,6 @@ export function useReviewTicketExtensionMutation(
|
||||
onError: () => toast.error('Failed to review extension request'),
|
||||
});
|
||||
}
|
||||
export function useReviewRepairMutation(ticketId: string) {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (payload: ReviewRepairPayload) =>
|
||||
ticketService.reviewRepair(ticketId, payload),
|
||||
onSuccess: (ticket, payload) => {
|
||||
toast.success(
|
||||
payload.action === 'approve' ? 'Repair approved' : 'Repair rejected',
|
||||
);
|
||||
queryClient.setQueryData<TicketDetail>(
|
||||
ticketKeys.classDetail(ticketId, payload.defect_class),
|
||||
(current) => mergeTicketDetailResponse(current, ticket),
|
||||
);
|
||||
queryClient.invalidateQueries({ queryKey: ticketKeys.lists() });
|
||||
},
|
||||
onError: () => toast.error('Failed to review repair'),
|
||||
});
|
||||
}
|
||||
|
||||
export function useCloseTicketMutation(ticketId: string) {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user