fix: add category field to admin tickets page

This commit is contained in:
Tiago Yamamoto 2026-02-23 15:53:17 -06:00
parent 74afffa4a9
commit f061763ae4

View file

@ -41,7 +41,7 @@ export default function AdminTicketsPage() {
const [deleteId, setDeleteId] = useState<string | null>(null) const [deleteId, setDeleteId] = useState<string | null>(null)
const [createOpen, setCreateOpen] = useState(false) const [createOpen, setCreateOpen] = useState(false)
const [creating, setCreating] = useState(false) const [creating, setCreating] = useState(false)
const [newTicket, setNewTicket] = useState({ subject: "", message: "", priority: "medium" }) const [newTicket, setNewTicket] = useState({ subject: "", category: "support", message: "", priority: "medium" })
// Pagination state // Pagination state
const [currentPage, setCurrentPage] = useState(1) const [currentPage, setCurrentPage] = useState(1)
@ -88,10 +88,10 @@ export default function AdminTicketsPage() {
} }
try { try {
setCreating(true) setCreating(true)
await ticketsApi.create({ subject: newTicket.subject, priority: newTicket.priority }) await ticketsApi.create({ subject: newTicket.subject, category: newTicket.category, priority: newTicket.priority, message: newTicket.message })
toast.success(t("ticketsPage.messages.created")) toast.success(t("ticketsPage.messages.created"))
setCreateOpen(false) setCreateOpen(false)
setNewTicket({ subject: "", message: "", priority: "medium" }) setNewTicket({ subject: "", category: "support", message: "", priority: "medium" })
fetchTickets() fetchTickets()
} catch (error) { } catch (error) {
console.error("Failed to create ticket", error) console.error("Failed to create ticket", error)
@ -129,6 +129,17 @@ export default function AdminTicketsPage() {
} }
} }
const getCategoryBadge = (category: string) => {
const colors: Record<string, "default" | "secondary" | "destructive" | "outline"> = {
bug: "destructive",
feature: "default",
support: "secondary",
billing: "default",
other: "outline",
}
return <Badge variant={colors[category] || "outline"}>{category}</Badge>
}
// Skeleton loader component // Skeleton loader component
const SkeletonRow = () => ( const SkeletonRow = () => (
<TableRow> <TableRow>
@ -136,6 +147,7 @@ export default function AdminTicketsPage() {
<TableCell><Skeleton className="h-4 w-48" /></TableCell> <TableCell><Skeleton className="h-4 w-48" /></TableCell>
<TableCell><Skeleton className="h-4 w-24" /></TableCell> <TableCell><Skeleton className="h-4 w-24" /></TableCell>
<TableCell><Skeleton className="h-5 w-16" /></TableCell> <TableCell><Skeleton className="h-5 w-16" /></TableCell>
<TableCell><Skeleton className="h-5 w-16" /></TableCell>
<TableCell><Skeleton className="h-5 w-14" /></TableCell> <TableCell><Skeleton className="h-5 w-14" /></TableCell>
<TableCell><Skeleton className="h-4 w-24" /></TableCell> <TableCell><Skeleton className="h-4 w-24" /></TableCell>
<TableCell className="text-right"><Skeleton className="h-8 w-16 ml-auto" /></TableCell> <TableCell className="text-right"><Skeleton className="h-8 w-16 ml-auto" /></TableCell>
@ -167,6 +179,7 @@ export default function AdminTicketsPage() {
<TableHead>{t("ticketsPage.table.id")}</TableHead> <TableHead>{t("ticketsPage.table.id")}</TableHead>
<TableHead>{t("ticketsPage.table.subject")}</TableHead> <TableHead>{t("ticketsPage.table.subject")}</TableHead>
<TableHead>{t("ticketsPage.table.user")}</TableHead> <TableHead>{t("ticketsPage.table.user")}</TableHead>
<TableHead>Category</TableHead>
<TableHead>{t("ticketsPage.table.status")}</TableHead> <TableHead>{t("ticketsPage.table.status")}</TableHead>
<TableHead>{t("ticketsPage.table.priority")}</TableHead> <TableHead>{t("ticketsPage.table.priority")}</TableHead>
<TableHead>{t("ticketsPage.table.created")}</TableHead> <TableHead>{t("ticketsPage.table.created")}</TableHead>
@ -184,7 +197,7 @@ export default function AdminTicketsPage() {
</> </>
) : paginatedTickets.length === 0 ? ( ) : paginatedTickets.length === 0 ? (
<TableRow> <TableRow>
<TableCell colSpan={7} className="text-center py-8 text-muted-foreground"> <TableCell colSpan={8} className="text-center py-8 text-muted-foreground">
{t("ticketsPage.noTickets")} {t("ticketsPage.noTickets")}
</TableCell> </TableCell>
</TableRow> </TableRow>
@ -200,6 +213,7 @@ export default function AdminTicketsPage() {
<TableCell className="text-sm" title={String(ticket.userId)}> <TableCell className="text-sm" title={String(ticket.userId)}>
{(ticket as any).userFullName || (ticket as any).userName || String(ticket.userId)} {(ticket as any).userFullName || (ticket as any).userName || String(ticket.userId)}
</TableCell> </TableCell>
<TableCell>{getCategoryBadge(ticket.category)}</TableCell>
<TableCell>{getStatusBadge(ticket.status)}</TableCell> <TableCell>{getStatusBadge(ticket.status)}</TableCell>
<TableCell>{getPriorityBadge(ticket.priority)}</TableCell> <TableCell>{getPriorityBadge(ticket.priority)}</TableCell>
<TableCell>{format(new Date(ticket.createdAt), "MMM d, yyyy")}</TableCell> <TableCell>{format(new Date(ticket.createdAt), "MMM d, yyyy")}</TableCell>
@ -298,6 +312,24 @@ export default function AdminTicketsPage() {
placeholder={t("ticketsPage.createDialog.subjectPlaceholder")} placeholder={t("ticketsPage.createDialog.subjectPlaceholder")}
/> />
</div> </div>
<div className="space-y-2">
<Label htmlFor="category">{t("ticketsPage.createDialog.category")}</Label>
<Select
value={newTicket.category}
onValueChange={(value) => setNewTicket(prev => ({ ...prev, category: value }))}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="bug">Bug</SelectItem>
<SelectItem value="feature">Feature Request</SelectItem>
<SelectItem value="support">Support</SelectItem>
<SelectItem value="billing">Billing</SelectItem>
<SelectItem value="other">Other</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="priority">{t("ticketsPage.createDialog.priority")}</Label> <Label htmlFor="priority">{t("ticketsPage.createDialog.priority")}</Label>
<Select <Select