feat(ticket): add due date picker and contractor details to assign flow
This commit is contained in:
@@ -1,56 +1,93 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Send, UserPlus } from 'lucide-react';
|
||||
import { Users, Mail, Phone, Send, ShieldCheck } from 'lucide-react';
|
||||
|
||||
import { DatePicker } from '@/components/form/DatePicker';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { AssignableWorkerSelect } from '@/components/lookups/AssignableWorkerSelect';
|
||||
import type { TicketDetail } from '@/types';
|
||||
import type { AssignableTicketUser, TicketDetail } from '@/types';
|
||||
|
||||
import { useAssignTicketMutation } from '../../../hooks/useTicketQueries';
|
||||
import { TicketActionCard } from './TicketActionCard';
|
||||
|
||||
export function AssignTicketAction({ ticket }: { ticket: TicketDetail }) {
|
||||
const [selectedUserId, setSelectedUserId] = useState('');
|
||||
const [selectedContractor, setSelectedContractor] =
|
||||
useState<AssignableTicketUser | null>(null);
|
||||
const [dueDate, setDueDate] = useState<Date>();
|
||||
const [assignNote, setAssignNote] = useState('');
|
||||
|
||||
const assignMutation = useAssignTicketMutation(ticket.id);
|
||||
|
||||
return (
|
||||
<TicketActionCard icon={UserPlus} title="Assign Ticket">
|
||||
<TicketActionCard icon={Users} title="Assign to Contractor">
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label>Contractor</Label>
|
||||
<Label>Contractor *</Label>
|
||||
<AssignableWorkerSelect
|
||||
value={selectedUserId}
|
||||
onValueChange={setSelectedUserId}
|
||||
onValueChange={(userId, user) => {
|
||||
setSelectedUserId(userId);
|
||||
setSelectedContractor(user);
|
||||
}}
|
||||
disabled={assignMutation.isPending}
|
||||
/>
|
||||
</div>
|
||||
{selectedContractor ? (
|
||||
<div className="space-y-2 rounded-lg border bg-muted/30 p-3">
|
||||
<p className="text-sm font-medium">Contractor Details</p>
|
||||
{selectedContractor.phone_number ? (
|
||||
<p className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Phone className="size-4 shrink-0" />
|
||||
{selectedContractor.phone_number}
|
||||
</p>
|
||||
) : null}
|
||||
<p className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Mail className="size-4 shrink-0" />
|
||||
<span className="truncate">{selectedContractor.email}</span>
|
||||
</p>
|
||||
<p className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<ShieldCheck className="size-4 shrink-0" />
|
||||
{selectedContractor.role.name}
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="space-y-2">
|
||||
<Label>Note</Label>
|
||||
<Label>Due Date *</Label>
|
||||
<DatePicker
|
||||
value={dueDate}
|
||||
onChange={setDueDate}
|
||||
showTimeZone={false}
|
||||
disabled={assignMutation.isPending}
|
||||
className="w-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label>Assignment Note (Optional)</Label>
|
||||
<Textarea
|
||||
value={assignNote}
|
||||
onChange={(event) => setAssignNote(event.target.value)}
|
||||
placeholder="Please inspect and repair"
|
||||
placeholder="Add any instructions or notes for the contractor..."
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
disabled={!selectedUserId || assignMutation.isPending}
|
||||
disabled={!selectedUserId || !dueDate || assignMutation.isPending}
|
||||
onClick={() => {
|
||||
if (!selectedUserId) return;
|
||||
if (!selectedUserId || !dueDate) return;
|
||||
assignMutation.mutate({
|
||||
assigned_to_user_id: Number(selectedUserId),
|
||||
defect_class: ticket.defect_class,
|
||||
due_at: dueDate.toISOString(),
|
||||
note: assignNote || undefined,
|
||||
});
|
||||
}}
|
||||
className="w-full"
|
||||
>
|
||||
<Send />
|
||||
Assign
|
||||
Assign Ticket
|
||||
</Button>
|
||||
</div>
|
||||
</TicketActionCard>
|
||||
|
||||
Reference in New Issue
Block a user