feat(ticket): scope issue preview to selected assignment lot
This commit is contained in:
@@ -6,14 +6,17 @@ import { useRouter } from 'next/navigation';
|
|||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { PERMISSIONS } from '@/constants/permissions';
|
import { PERMISSIONS } from '@/constants/permissions';
|
||||||
import { PermissionGuard } from '@/guards';
|
import { PermissionGuard } from '@/guards';
|
||||||
import type { TicketOverviewDetail } from '@/types';
|
import type { TicketDetail, TicketOverviewDetail } from '@/types';
|
||||||
|
|
||||||
import { AssignTicketAction } from './actions/AssignTicketAction';
|
import { AssignTicketAction } from './actions/AssignTicketAction';
|
||||||
|
import { OpenRepairReviewAction } from './actions/OpenRepairReviewAction';
|
||||||
|
|
||||||
export function TicketDetailHeader({
|
export function TicketDetailHeader({
|
||||||
ticket,
|
ticket,
|
||||||
|
classDetail,
|
||||||
}: {
|
}: {
|
||||||
ticket: TicketOverviewDetail;
|
ticket: TicketOverviewDetail;
|
||||||
|
classDetail?: TicketDetail;
|
||||||
}) {
|
}) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const ticketLabel = ticket.ticket_name || ticket.id;
|
const ticketLabel = ticket.ticket_name || ticket.id;
|
||||||
@@ -26,6 +29,11 @@ export function TicketDetailHeader({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex shrink-0 items-center gap-2">
|
<div className="flex shrink-0 items-center gap-2">
|
||||||
|
{classDetail?.assignment_status === 'under_review' ? (
|
||||||
|
<PermissionGuard permissions={PERMISSIONS.TICKET.REVIEW}>
|
||||||
|
<OpenRepairReviewAction ticket={classDetail} />
|
||||||
|
</PermissionGuard>
|
||||||
|
) : null}
|
||||||
<PermissionGuard permissions={PERMISSIONS.TICKET.ASSIGN}>
|
<PermissionGuard permissions={PERMISSIONS.TICKET.ASSIGN}>
|
||||||
<AssignTicketAction ticketId={ticket.id} />
|
<AssignTicketAction ticketId={ticket.id} />
|
||||||
</PermissionGuard>
|
</PermissionGuard>
|
||||||
|
|||||||
@@ -2,25 +2,24 @@
|
|||||||
|
|
||||||
import { PERMISSIONS } from '@/constants/permissions';
|
import { PERMISSIONS } from '@/constants/permissions';
|
||||||
import { PermissionGuard } from '@/guards';
|
import { PermissionGuard } from '@/guards';
|
||||||
import type { TicketDetail } from '@/types';
|
import type { TicketAssignmentSummary, TicketDetail } from '@/types';
|
||||||
|
|
||||||
import { AssignedContractorAction } from './actions/AssignedContractorAction';
|
import { AssignedContractorAction } from './actions/AssignedContractorAction';
|
||||||
import { ClosedTicketAction } from './actions/ClosedTicketAction';
|
import { ClosedTicketAction } from './actions/ClosedTicketAction';
|
||||||
import { NoTicketAction } from './actions/NoTicketAction';
|
import { NoTicketAction } from './actions/NoTicketAction';
|
||||||
import { OpenRepairReviewAction } from './actions/OpenRepairReviewAction';
|
|
||||||
import { RequestExtensionAction } from './actions/RequestExtensionAction';
|
import { RequestExtensionAction } from './actions/RequestExtensionAction';
|
||||||
import { ReviewExtensionRequestAction } from './actions/ReviewExtensionRequestAction';
|
import { ReviewExtensionRequestAction } from './actions/ReviewExtensionRequestAction';
|
||||||
|
|
||||||
interface TicketStatusActionsProps {
|
interface TicketStatusActionsProps {
|
||||||
ticket: TicketDetail;
|
ticket: TicketDetail;
|
||||||
|
assignment?: TicketAssignmentSummary;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTicketAction(ticket: TicketDetail) {
|
function getTicketAction(
|
||||||
if (ticket.assignment_status === 'unassigned') {
|
ticket: TicketDetail,
|
||||||
return null;
|
assignment?: TicketAssignmentSummary,
|
||||||
}
|
) {
|
||||||
|
if (assignment && !assignment.is_complete) {
|
||||||
if (ticket.assignment_status === 'assigned') {
|
|
||||||
return (
|
return (
|
||||||
<PermissionGuard
|
<PermissionGuard
|
||||||
permissions={PERMISSIONS.TICKET.ASSIGN}
|
permissions={PERMISSIONS.TICKET.ASSIGN}
|
||||||
@@ -29,29 +28,46 @@ function getTicketAction(ticket: TicketDetail) {
|
|||||||
permissions={PERMISSIONS.TICKET.WORK}
|
permissions={PERMISSIONS.TICKET.WORK}
|
||||||
fallback={<NoTicketAction />}
|
fallback={<NoTicketAction />}
|
||||||
>
|
>
|
||||||
<RequestExtensionAction ticket={ticket} />
|
<RequestExtensionAction
|
||||||
|
ticket={ticket}
|
||||||
|
assignmentId={assignment.id}
|
||||||
|
dueAt={assignment.due_at}
|
||||||
|
/>
|
||||||
</PermissionGuard>
|
</PermissionGuard>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
<AssignedContractorAction ticket={ticket} />
|
{ticket.assignment_status === 'assigned' ? (
|
||||||
<ReviewExtensionRequestAction ticket={ticket} />
|
<AssignedContractorAction ticket={ticket} />
|
||||||
|
) : null}
|
||||||
|
<ReviewExtensionRequestAction
|
||||||
|
ticket={ticket}
|
||||||
|
assignmentId={assignment.id}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
</PermissionGuard>
|
</PermissionGuard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ticket.assignment_status === 'under_review') {
|
if (ticket.assignment_status === 'unassigned') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ticket.assignment_status === 'assigned') {
|
||||||
return (
|
return (
|
||||||
<PermissionGuard
|
<PermissionGuard
|
||||||
permissions={PERMISSIONS.TICKET.REVIEW}
|
permissions={PERMISSIONS.TICKET.ASSIGN}
|
||||||
fallback={<NoTicketAction />}
|
fallback={<NoTicketAction />}
|
||||||
>
|
>
|
||||||
<OpenRepairReviewAction ticket={ticket} />
|
<AssignedContractorAction ticket={ticket} />
|
||||||
</PermissionGuard>
|
</PermissionGuard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ticket.assignment_status === 'under_review') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
ticket.assignment_status === 'approved' ||
|
ticket.assignment_status === 'approved' ||
|
||||||
ticket.assignment_status === 'rejected'
|
ticket.assignment_status === 'rejected'
|
||||||
@@ -62,8 +78,11 @@ function getTicketAction(ticket: TicketDetail) {
|
|||||||
return <NoTicketAction />;
|
return <NoTicketAction />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TicketStatusActions({ ticket }: TicketStatusActionsProps) {
|
export function TicketStatusActions({
|
||||||
const action = getTicketAction(ticket);
|
ticket,
|
||||||
|
assignment,
|
||||||
|
}: TicketStatusActionsProps) {
|
||||||
|
const action = getTicketAction(ticket, assignment);
|
||||||
|
|
||||||
return action ? <div className="space-y-3">{action}</div> : null;
|
return action ? <div className="space-y-3">{action}</div> : null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,24 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { ArrowRight, ClipboardCheck } from 'lucide-react';
|
import { ClipboardCheck } from 'lucide-react';
|
||||||
|
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import type { TicketDetail } from '@/types';
|
import type { TicketDetail } from '@/types';
|
||||||
import { ROUTES } from '@/utils/routes';
|
import { ROUTES } from '@/utils/routes';
|
||||||
|
|
||||||
import { TicketActionCard } from './TicketActionCard';
|
|
||||||
|
|
||||||
export function OpenRepairReviewAction({ ticket }: { ticket: TicketDetail }) {
|
export function OpenRepairReviewAction({ ticket }: { ticket: TicketDetail }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TicketActionCard icon={ClipboardCheck} title="Review Submitted Repairs">
|
<Button
|
||||||
<div className="space-y-4">
|
type="button"
|
||||||
<p className="text-sm leading-relaxed text-muted-foreground">
|
onClick={() =>
|
||||||
Review every submitted repair separately using its detection image,
|
router.push(ROUTES.TICKET_CLASS_REVIEW(ticket.id, ticket.defect_class))
|
||||||
location, and repair proof.
|
}
|
||||||
</p>
|
>
|
||||||
<Button
|
<ClipboardCheck />
|
||||||
type="button"
|
Review Repairs
|
||||||
className="w-full"
|
</Button>
|
||||||
onClick={() =>
|
|
||||||
router.push(
|
|
||||||
ROUTES.TICKET_CLASS_REVIEW(ticket.id, ticket.defect_class),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Open Issue Review
|
|
||||||
<ArrowRight />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</TicketActionCard>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,22 @@ import type { TicketDetail } from '@/types';
|
|||||||
import { TicketActionCard } from './TicketActionCard';
|
import { TicketActionCard } from './TicketActionCard';
|
||||||
import { TicketExtensionRequestPanel } from './TicketExtensionRequestPanel';
|
import { TicketExtensionRequestPanel } from './TicketExtensionRequestPanel';
|
||||||
|
|
||||||
export function RequestExtensionAction({ ticket }: { ticket: TicketDetail }) {
|
export function RequestExtensionAction({
|
||||||
|
ticket,
|
||||||
|
assignmentId,
|
||||||
|
dueAt,
|
||||||
|
}: {
|
||||||
|
ticket: TicketDetail;
|
||||||
|
assignmentId: number;
|
||||||
|
dueAt: string | null;
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<TicketActionCard icon={Clock3} title="Request Extension">
|
<TicketActionCard icon={Clock3} title="Request Extension">
|
||||||
<TicketExtensionRequestPanel ticket={ticket} />
|
<TicketExtensionRequestPanel
|
||||||
|
ticket={ticket}
|
||||||
|
assignmentId={assignmentId}
|
||||||
|
dueAt={dueAt}
|
||||||
|
/>
|
||||||
</TicketActionCard>
|
</TicketActionCard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,15 @@ const MAX_REASON_LENGTH = 300;
|
|||||||
|
|
||||||
interface RequestExtensionFormProps {
|
interface RequestExtensionFormProps {
|
||||||
ticket: TicketDetail;
|
ticket: TicketDetail;
|
||||||
|
assignmentId: number;
|
||||||
|
currentDueAt: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RequestExtensionForm({ ticket }: RequestExtensionFormProps) {
|
export function RequestExtensionForm({
|
||||||
const currentDueAt = ticket.worker?.due_at;
|
ticket,
|
||||||
|
assignmentId,
|
||||||
|
currentDueAt,
|
||||||
|
}: RequestExtensionFormProps) {
|
||||||
const currentDueDate = useMemo(
|
const currentDueDate = useMemo(
|
||||||
() => (currentDueAt ? new Date(currentDueAt) : undefined),
|
() => (currentDueAt ? new Date(currentDueAt) : undefined),
|
||||||
[currentDueAt],
|
[currentDueAt],
|
||||||
@@ -36,7 +41,6 @@ export function RequestExtensionForm({ ticket }: RequestExtensionFormProps) {
|
|||||||
);
|
);
|
||||||
const [requestedDueDate, setRequestedDueDate] = useState<Date>();
|
const [requestedDueDate, setRequestedDueDate] = useState<Date>();
|
||||||
const [reason, setReason] = useState('');
|
const [reason, setReason] = useState('');
|
||||||
const assignmentId = ticket.worker?.assignment_id;
|
|
||||||
const requestExtensionMutation = useRequestTicketExtensionMutation(
|
const requestExtensionMutation = useRequestTicketExtensionMutation(
|
||||||
ticket.id,
|
ticket.id,
|
||||||
assignmentId,
|
assignmentId,
|
||||||
@@ -48,10 +52,7 @@ export function RequestExtensionForm({ ticket }: RequestExtensionFormProps) {
|
|||||||
(!currentDueDate || requestedDueDate.getTime() > currentDueDate.getTime()),
|
(!currentDueDate || requestedDueDate.getTime() > currentDueDate.getTime()),
|
||||||
);
|
);
|
||||||
const canSubmit =
|
const canSubmit =
|
||||||
Boolean(assignmentId) &&
|
isRequestedDateValid && Boolean(reason.trim()) && !isPending;
|
||||||
isRequestedDateValid &&
|
|
||||||
Boolean(reason.trim()) &&
|
|
||||||
!isPending;
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
if (!requestedDueDate || !canSubmit) return;
|
if (!requestedDueDate || !canSubmit) return;
|
||||||
|
|||||||
@@ -77,16 +77,17 @@ function Requester({ request }: { request: TicketExtensionRequest }) {
|
|||||||
|
|
||||||
function ExtensionReviewForm({
|
function ExtensionReviewForm({
|
||||||
ticket,
|
ticket,
|
||||||
|
assignmentId,
|
||||||
request,
|
request,
|
||||||
}: {
|
}: {
|
||||||
ticket: TicketDetail;
|
ticket: TicketDetail;
|
||||||
|
assignmentId: number;
|
||||||
request: TicketExtensionRequest;
|
request: TicketExtensionRequest;
|
||||||
}) {
|
}) {
|
||||||
const [note, setNote] = useState('');
|
const [note, setNote] = useState('');
|
||||||
const [selectedAction, setSelectedAction] = useState<
|
const [selectedAction, setSelectedAction] = useState<
|
||||||
'approve' | 'reject' | null
|
'approve' | 'reject' | null
|
||||||
>(null);
|
>(null);
|
||||||
const assignmentId = ticket.worker?.assignment_id as number;
|
|
||||||
const reviewMutation = useReviewTicketExtensionMutation(
|
const reviewMutation = useReviewTicketExtensionMutation(
|
||||||
ticket.id,
|
ticket.id,
|
||||||
assignmentId,
|
assignmentId,
|
||||||
@@ -197,16 +198,17 @@ function ExtensionReviewForm({
|
|||||||
|
|
||||||
export function ReviewExtensionRequestAction({
|
export function ReviewExtensionRequestAction({
|
||||||
ticket,
|
ticket,
|
||||||
|
assignmentId,
|
||||||
}: {
|
}: {
|
||||||
ticket: TicketDetail;
|
ticket: TicketDetail;
|
||||||
|
assignmentId: number;
|
||||||
}) {
|
}) {
|
||||||
const assignmentId = ticket.worker?.assignment_id;
|
|
||||||
const extensionRequestQuery = useTicketExtensionRequestQuery(
|
const extensionRequestQuery = useTicketExtensionRequestQuery(
|
||||||
ticket.id,
|
ticket.id,
|
||||||
assignmentId,
|
assignmentId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!assignmentId || extensionRequestQuery.isError) {
|
if (extensionRequestQuery.isError) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,5 +229,11 @@ export function ReviewExtensionRequestAction({
|
|||||||
|
|
||||||
if (!pendingRequest) return null;
|
if (!pendingRequest) return null;
|
||||||
|
|
||||||
return <ExtensionReviewForm ticket={ticket} request={pendingRequest} />;
|
return (
|
||||||
|
<ExtensionReviewForm
|
||||||
|
ticket={ticket}
|
||||||
|
assignmentId={assignmentId}
|
||||||
|
request={pendingRequest}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,23 +187,18 @@ function ExtensionRequestDetails({
|
|||||||
|
|
||||||
export function TicketExtensionRequestPanel({
|
export function TicketExtensionRequestPanel({
|
||||||
ticket,
|
ticket,
|
||||||
|
assignmentId,
|
||||||
|
dueAt,
|
||||||
}: {
|
}: {
|
||||||
ticket: TicketDetail;
|
ticket: TicketDetail;
|
||||||
|
assignmentId: number;
|
||||||
|
dueAt: string | null;
|
||||||
}) {
|
}) {
|
||||||
const assignmentId = ticket.worker?.assignment_id;
|
|
||||||
const extensionRequestQuery = useTicketExtensionRequestQuery(
|
const extensionRequestQuery = useTicketExtensionRequestQuery(
|
||||||
ticket.id,
|
ticket.id,
|
||||||
assignmentId,
|
assignmentId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!assignmentId) {
|
|
||||||
return (
|
|
||||||
<div className="rounded-lg border border-dashed p-4 text-sm text-muted-foreground">
|
|
||||||
No active assignment is available for this ticket.
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extensionRequestQuery.isLoading) {
|
if (extensionRequestQuery.isLoading) {
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-40 items-center justify-center text-muted-foreground">
|
<div className="flex min-h-40 items-center justify-center text-muted-foreground">
|
||||||
@@ -237,7 +232,13 @@ export function TicketExtensionRequestPanel({
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (!latestRequest) {
|
if (!latestRequest) {
|
||||||
return <RequestExtensionForm ticket={ticket} />;
|
return (
|
||||||
|
<RequestExtensionForm
|
||||||
|
ticket={ticket}
|
||||||
|
assignmentId={assignmentId}
|
||||||
|
currentDueAt={dueAt}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <ExtensionRequestDetails request={latestRequest} />;
|
return <ExtensionRequestDetails request={latestRequest} />;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import { TicketStatusActions } from './components/TicketStatusActions';
|
|||||||
import { TicketDefectClassTabs } from './components/TicketDefectClassTabs';
|
import { TicketDefectClassTabs } from './components/TicketDefectClassTabs';
|
||||||
import { useTicketDetailEvents } from '../hooks/useTicketDetailEvents';
|
import { useTicketDetailEvents } from '../hooks/useTicketDetailEvents';
|
||||||
import {
|
import {
|
||||||
|
useTicketAssignmentsQuery,
|
||||||
useTicketClassDetailQuery,
|
useTicketClassDetailQuery,
|
||||||
useTicketOverviewQuery,
|
useTicketOverviewQuery,
|
||||||
} from '../hooks/useTicketQueries';
|
} from '../hooks/useTicketQueries';
|
||||||
@@ -35,11 +36,18 @@ export default function TicketDetailPage() {
|
|||||||
const [selectedAssignmentId, setSelectedAssignmentId] = useState<number>();
|
const [selectedAssignmentId, setSelectedAssignmentId] = useState<number>();
|
||||||
|
|
||||||
const overviewQuery = useTicketOverviewQuery(ticketId);
|
const overviewQuery = useTicketOverviewQuery(ticketId);
|
||||||
const classDetailQuery = useTicketClassDetailQuery(ticketId, defectClass);
|
|
||||||
const overview = overviewQuery.data;
|
const overview = overviewQuery.data;
|
||||||
|
const assignmentsQuery = useTicketAssignmentsQuery(
|
||||||
|
ticketId,
|
||||||
|
overview?.assignments,
|
||||||
|
);
|
||||||
|
const classDetailQuery = useTicketClassDetailQuery(ticketId, defectClass);
|
||||||
const classDetail = classDetailQuery.data;
|
const classDetail = classDetailQuery.data;
|
||||||
const activeAssignmentId =
|
const assignments = assignmentsQuery.data?.items ?? [];
|
||||||
selectedAssignmentId ?? overview?.assignments?.[0]?.id;
|
const activeAssignmentId = selectedAssignmentId ?? assignments[0]?.id;
|
||||||
|
const activeAssignment = assignments.find(
|
||||||
|
(assignment) => assignment.id === activeAssignmentId,
|
||||||
|
);
|
||||||
const isClassDetailLoading = Boolean(
|
const isClassDetailLoading = Boolean(
|
||||||
defectClass && classDetailQuery.isLoading,
|
defectClass && classDetailQuery.isLoading,
|
||||||
);
|
);
|
||||||
@@ -66,7 +74,7 @@ export default function TicketDetailPage() {
|
|||||||
<main className="relative z-10 min-w-0 max-w-full space-y-5 xl:flex xl:h-[calc(100vh-6.5rem)] xl:min-h-0 xl:flex-col xl:gap-5 xl:space-y-0 xl:overflow-hidden">
|
<main className="relative z-10 min-w-0 max-w-full space-y-5 xl:flex xl:h-[calc(100vh-6.5rem)] xl:min-h-0 xl:flex-col xl:gap-5 xl:space-y-0 xl:overflow-hidden">
|
||||||
<div className="xl:shrink-0">
|
<div className="xl:shrink-0">
|
||||||
{overview ? (
|
{overview ? (
|
||||||
<TicketDetailHeader ticket={overview} />
|
<TicketDetailHeader ticket={overview} classDetail={classDetail} />
|
||||||
) : (
|
) : (
|
||||||
<TicketOverviewHeaderSkeleton />
|
<TicketOverviewHeaderSkeleton />
|
||||||
)}
|
)}
|
||||||
@@ -101,7 +109,10 @@ export default function TicketDetailPage() {
|
|||||||
<div className="min-w-0 space-y-3 self-start xl:min-h-0 xl:self-stretch xl:overflow-y-auto xl:overscroll-contain xl:pr-2">
|
<div className="min-w-0 space-y-3 self-start xl:min-h-0 xl:self-stretch xl:overflow-y-auto xl:overscroll-contain xl:pr-2">
|
||||||
{isClassDetailLoading ? <TicketClassActionsSkeleton /> : null}
|
{isClassDetailLoading ? <TicketClassActionsSkeleton /> : null}
|
||||||
{!isClassDetailLoading && classDetail ? (
|
{!isClassDetailLoading && classDetail ? (
|
||||||
<TicketStatusActions ticket={classDetail} />
|
<TicketStatusActions
|
||||||
|
ticket={classDetail}
|
||||||
|
assignment={activeAssignment}
|
||||||
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -405,6 +405,9 @@ export function useRequestTicketExtensionMutation(
|
|||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: ticketKeys.classDetail(ticketId, defectClass),
|
queryKey: ticketKeys.classDetail(ticketId, defectClass),
|
||||||
});
|
});
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: ticketKeys.assignments(ticketId),
|
||||||
|
});
|
||||||
queryClient.invalidateQueries({ queryKey: ticketKeys.lists() });
|
queryClient.invalidateQueries({ queryKey: ticketKeys.lists() });
|
||||||
},
|
},
|
||||||
onError: () => toast.error('Failed to request an extension'),
|
onError: () => toast.error('Failed to request an extension'),
|
||||||
@@ -432,6 +435,9 @@ export function useReviewTicketExtensionMutation(
|
|||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: ticketKeys.classDetail(ticketId, defectClass),
|
queryKey: ticketKeys.classDetail(ticketId, defectClass),
|
||||||
});
|
});
|
||||||
|
queryClient.invalidateQueries({
|
||||||
|
queryKey: ticketKeys.assignments(ticketId),
|
||||||
|
});
|
||||||
queryClient.invalidateQueries({ queryKey: ticketKeys.lists() });
|
queryClient.invalidateQueries({ queryKey: ticketKeys.lists() });
|
||||||
},
|
},
|
||||||
onError: () => toast.error('Failed to review extension request'),
|
onError: () => toast.error('Failed to review extension request'),
|
||||||
|
|||||||
Reference in New Issue
Block a user