feat(ticket): show assigned contractor details on in-progress tickets
This commit is contained in:
@@ -4,6 +4,7 @@ import { PERMISSIONS } from '@/constants/permissions';
|
|||||||
import { PermissionGuard } from '@/guards';
|
import { PermissionGuard } from '@/guards';
|
||||||
import type { TicketDetail } from '@/types';
|
import type { TicketDetail } from '@/types';
|
||||||
|
|
||||||
|
import { AssignedContractorAction } from './actions/AssignedContractorAction';
|
||||||
import { AssignTicketAction } from './actions/AssignTicketAction';
|
import { AssignTicketAction } from './actions/AssignTicketAction';
|
||||||
import { ClosedTicketAction } from './actions/ClosedTicketAction';
|
import { ClosedTicketAction } from './actions/ClosedTicketAction';
|
||||||
import { NoTicketAction } from './actions/NoTicketAction';
|
import { NoTicketAction } from './actions/NoTicketAction';
|
||||||
@@ -41,7 +42,10 @@ function getTicketAction(ticket: TicketDetail) {
|
|||||||
</PermissionGuard>
|
</PermissionGuard>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ReviewExtensionRequestAction ticket={ticket} />
|
<>
|
||||||
|
<AssignedContractorAction ticket={ticket} />
|
||||||
|
<ReviewExtensionRequestAction ticket={ticket} />
|
||||||
|
</>
|
||||||
</PermissionGuard>
|
</PermissionGuard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -24,7 +24,6 @@ import {
|
|||||||
useReviewTicketExtensionMutation,
|
useReviewTicketExtensionMutation,
|
||||||
useTicketExtensionRequestQuery,
|
useTicketExtensionRequestQuery,
|
||||||
} from '../../../hooks/useTicketQueries';
|
} from '../../../hooks/useTicketQueries';
|
||||||
import { NoTicketAction } from './NoTicketAction';
|
|
||||||
import { TicketActionCard } from './TicketActionCard';
|
import { TicketActionCard } from './TicketActionCard';
|
||||||
|
|
||||||
const MAX_NOTE_LENGTH = 300;
|
const MAX_NOTE_LENGTH = 300;
|
||||||
@@ -208,7 +207,7 @@ export function ReviewExtensionRequestAction({
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!assignmentId || extensionRequestQuery.isError) {
|
if (!assignmentId || extensionRequestQuery.isError) {
|
||||||
return <NoTicketAction />;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extensionRequestQuery.isLoading) {
|
if (extensionRequestQuery.isLoading) {
|
||||||
@@ -226,7 +225,7 @@ export function ReviewExtensionRequestAction({
|
|||||||
? getPendingRequest(extensionRequestQuery.data)
|
? getPendingRequest(extensionRequestQuery.data)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (!pendingRequest) return <NoTicketAction />;
|
if (!pendingRequest) return null;
|
||||||
|
|
||||||
return <ExtensionReviewForm ticket={ticket} request={pendingRequest} />;
|
return <ExtensionReviewForm ticket={ticket} request={pendingRequest} />;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user