feat(ticket): show assigned contractor details on in-progress tickets

This commit is contained in:
2026-07-10 18:27:26 +05:30
parent 0026824f84
commit 9d7f956c3b
3 changed files with 68 additions and 4 deletions

View File

@@ -0,0 +1,61 @@
'use client';
import { CalendarClock, UserCheck } from 'lucide-react';
import { PersonInfo } from '@/components/person-avatar';
import { Badge } from '@/components/ui/badge';
import type { TicketDetail } from '@/types';
import { formatDate } from '@/utils/date';
import { TicketActionCard } from './TicketActionCard';
function AssignmentField({ label, value }: { label: string; value: string }) {
return (
<div className="min-w-0 space-y-1">
<p className="text-xs text-muted-foreground">{label}</p>
<p className="truncate text-sm font-medium text-foreground">{value}</p>
</div>
);
}
export function AssignedContractorAction({ ticket }: { ticket: TicketDetail }) {
const worker = ticket.worker;
return (
<TicketActionCard icon={UserCheck} title="Assigned Contractor">
{worker ? (
<div className="space-y-5">
<div className="flex items-center justify-between gap-3">
<PersonInfo person={worker} size="lg" />
<Badge>
Assigned
</Badge>
</div>
<div className="grid grid-cols-2 gap-x-4 gap-y-5 border-t pt-4">
<AssignmentField label="Role" value={worker.role?.name ?? '-'} />
<AssignmentField
label="Assigned By"
value={worker.assigned_by_name ?? '-'}
/>
<AssignmentField
label="Assigned On"
value={formatDate(worker.assigned_at)}
/>
<div className="min-w-0 space-y-1">
<p className="text-xs text-muted-foreground">Due Date</p>
<p className="flex items-center gap-1.5 text-sm font-medium text-foreground">
<CalendarClock className="size-4 shrink-0 text-muted-foreground" />
<span className="truncate">{formatDate(worker.due_at)}</span>
</p>
</div>
</div>
</div>
) : (
<p className="text-sm text-muted-foreground">
Assignment details are not available.
</p>
)}
</TicketActionCard>
);
}

View File

@@ -24,7 +24,6 @@ import {
useReviewTicketExtensionMutation,
useTicketExtensionRequestQuery,
} from '../../../hooks/useTicketQueries';
import { NoTicketAction } from './NoTicketAction';
import { TicketActionCard } from './TicketActionCard';
const MAX_NOTE_LENGTH = 300;
@@ -208,7 +207,7 @@ export function ReviewExtensionRequestAction({
);
if (!assignmentId || extensionRequestQuery.isError) {
return <NoTicketAction />;
return null;
}
if (extensionRequestQuery.isLoading) {
@@ -226,7 +225,7 @@ export function ReviewExtensionRequestAction({
? getPendingRequest(extensionRequestQuery.data)
: null;
if (!pendingRequest) return <NoTicketAction />;
if (!pendingRequest) return null;
return <ExtensionReviewForm ticket={ticket} request={pendingRequest} />;
}