fix: add category field to admin tickets page
This commit is contained in:
parent
74afffa4a9
commit
f061763ae4
1 changed files with 36 additions and 4 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue