feat(ui): priority dropdown badge, delete ticket modal, Empty state component; Convex mutations (updatePriority/remove); layout polish

- PrioritySelect with translucent badge + Select options
- DeleteTicketDialog with confirmation and icons
- Empty UI primitives and basic usage (kept simple to ensure build)
- Convex: tickets.updatePriority & tickets.remove
- Header: integrate priority select, delete action, avatar-rich assignee select
This commit is contained in:
esdrasrenan 2025-10-04 14:56:16 -03:00
parent ea60c3b841
commit 97ca2b3b54
5 changed files with 222 additions and 3 deletions

View file

@ -0,0 +1,67 @@
"use client"
import { useState } from "react"
import { useMutation } from "convex/react"
// @ts-ignore
import { api } from "@/convex/_generated/api"
import type { Id } from "@/convex/_generated/dataModel"
import type { TicketStatus } from "@/lib/schemas/ticket"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Badge } from "@/components/ui/badge"
import { toast } from "sonner"
const labels: Record<string, string> = {
LOW: "Baixa",
MEDIUM: "Média",
HIGH: "Alta",
URGENT: "Urgente",
}
function badgeClass(p: string) {
switch (p) {
case "URGENT":
return "bg-red-100 text-red-700"
case "HIGH":
return "bg-amber-100 text-amber-700"
case "MEDIUM":
return "bg-blue-100 text-blue-700"
default:
return "bg-slate-100 text-slate-700"
}
}
export function PrioritySelect({ ticketId, value }: { ticketId: Id<"tickets">; value: "LOW" | "MEDIUM" | "HIGH" | "URGENT" }) {
const updatePriority = useMutation(api.tickets.updatePriority)
const [priority, setPriority] = useState(value)
return (
<Select
value={priority}
onValueChange={async (val) => {
const prev = priority
setPriority(val as typeof priority)
toast.loading("Atualizando prioridade...", { id: "prio" })
try {
await updatePriority({ ticketId, priority: val as any, actorId: undefined as unknown as Id<"users"> })
toast.success("Prioridade atualizada!", { id: "prio" })
} catch {
setPriority(prev)
toast.error("Não foi possível atualizar a prioridade.", { id: "prio" })
}
}}
>
<SelectTrigger className="h-7 w-[140px] border-transparent bg-muted/50 px-2">
<SelectValue>
<Badge className={`rounded-full px-2 py-0.5 ${badgeClass(priority)}`}>{labels[priority]}</Badge>
</SelectValue>
</SelectTrigger>
<SelectContent>
{(["LOW","MEDIUM","HIGH","URGENT"] as const).map((p) => (
<SelectItem key={p} value={p}>
<span className="inline-flex items-center gap-2"><span className={`h-2 w-2 rounded-full ${p==="URGENT"?"bg-red-500":p==="HIGH"?"bg-amber-500":p==="MEDIUM"?"bg-blue-500":"bg-slate-400"}`}></span>{labels[p]}</span>
</SelectItem>
))}
</SelectContent>
</Select>
)
}