'use client'; import { useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { Card, CardContent } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { Skeleton } from '@/components/ui/skeleton'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { Search, Plus } from 'lucide-react'; import { api } from '@/lib/api'; import { useDebounce } from '@/lib/hooks'; import { format } from 'date-fns'; interface Ticket { id: string; subject: string; type: string; status: string; priority: string; createdAt: string; client?: { firstName: string; lastName: string; accountNumber: string }; assignedTo?: { firstName: string; lastName: string }; } const STATUS_COLORS: Record = { OPEN: 'bg-blue-100 text-blue-700', IN_PROGRESS: 'bg-yellow-100 text-yellow-700', RESOLVED: 'bg-emerald-100 text-emerald-700', CLOSED: 'bg-gray-100 text-gray-500', }; const TYPE_COLORS: Record = { INSTALLATION: 'bg-purple-100 text-purple-700', SUPPORT: 'bg-orange-100 text-orange-700', BILLING: 'bg-cyan-100 text-cyan-700', }; const PRIORITY_COLORS: Record = { NORMAL: 'bg-gray-100 text-gray-600', HIGH: 'bg-red-100 text-red-700', }; const STATUSES = ['', 'OPEN', 'IN_PROGRESS', 'RESOLVED', 'CLOSED']; const TYPES = ['', 'INSTALLATION', 'SUPPORT', 'BILLING']; export default function TicketsPage() { const [search, setSearch] = useState(''); const [status, setStatus] = useState(''); const [type, setType] = useState(''); const [page, setPage] = useState(1); const debouncedSearch = useDebounce(search, 400); const limit = 20; const { data, isLoading } = useQuery({ queryKey: ['tickets', debouncedSearch, status, type, page], queryFn: async () => { const params = new URLSearchParams({ page: String(page), limit: String(limit) }); if (status) params.set('status', status); if (type) params.set('type', type); if (debouncedSearch) params.set('search', debouncedSearch); const res = await api.get(`/api/v1/tickets?${params}`); return res.data; }, }); const tickets: Ticket[] = Array.isArray(data) ? data : (data?.data ?? data?.items ?? []); const total = (data as any)?.meta?.total ?? (data as any)?.total ?? tickets.length; return (

Tickets

Support, installation, and billing issues

{/* Filters */}
{ setSearch(e.target.value); setPage(1); }} />
{STATUSES.map(s => ( ))}
{TYPES.map(t => ( ))}
Subject Type Status Priority Client Assigned To Created {isLoading ? ( Array.from({ length: 8 }).map((_, i) => ( {Array.from({ length: 7 }).map((_, j) => ( ))} )) ) : tickets.length === 0 ? ( No tickets found ) : ( tickets.map((t) => ( {t.subject} {t.type} {t.status.replace('_', ' ')} {t.priority} {t.client ? `${t.client.firstName} ${t.client.lastName}` : '—'} {t.assignedTo ? `${t.assignedTo.firstName} ${t.assignedTo.lastName}` : 'Unassigned'} {format(new Date(t.createdAt), 'MMM d, yyyy')} )) )}
); }