feat(ui,tickets): aplicar visual Rever (badges revertidas), header com play/pause, edição inline com cancelar, empty states e toasts centralizados; novas mutations Convex (updateSubject/updateSummary/toggleWork)
This commit is contained in:
parent
881bb7bfdd
commit
6c57c691f3
14 changed files with 512 additions and 307 deletions
|
|
@ -5,19 +5,21 @@ import { useMutation } from "convex/react"
|
|||
// @ts-ignore
|
||||
import { api } from "@/convex/_generated/api"
|
||||
import type { Id } from "@/convex/_generated/dataModel"
|
||||
import type { TicketPriority } from "@/lib/schemas/ticket"
|
||||
import { useAuth } from "@/lib/auth-client"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { toast } from "sonner"
|
||||
import { ArrowDown, ArrowRight, ArrowUp, ChevronsUp } from "lucide-react"
|
||||
|
||||
const labels: Record<string, string> = {
|
||||
const labels: Record<TicketPriority, string> = {
|
||||
LOW: "Baixa",
|
||||
MEDIUM: "Média",
|
||||
HIGH: "Alta",
|
||||
URGENT: "Urgente",
|
||||
}
|
||||
|
||||
function badgeClass(p: string) {
|
||||
function badgeClass(p: TicketPriority) {
|
||||
switch (p) {
|
||||
case "URGENT":
|
||||
return "bg-red-100 text-red-700"
|
||||
|
|
@ -30,20 +32,29 @@ function badgeClass(p: string) {
|
|||
}
|
||||
}
|
||||
|
||||
export function PrioritySelect({ ticketId, value }: { ticketId: Id<"tickets">; value: "LOW" | "MEDIUM" | "HIGH" | "URGENT" }) {
|
||||
function PriorityIcon({ p }: { p: TicketPriority }) {
|
||||
const cls = "size-3.5 text-cyan-600"
|
||||
if (p === "LOW") return <ArrowDown className={cls} />
|
||||
if (p === "MEDIUM") return <ArrowRight className={cls} />
|
||||
if (p === "HIGH") return <ArrowUp className={cls} />
|
||||
return <ChevronsUp className={cls} />
|
||||
}
|
||||
|
||||
export function PrioritySelect({ ticketId, value }: { ticketId: string; value: TicketPriority }) {
|
||||
const updatePriority = useMutation(api.tickets.updatePriority)
|
||||
const [priority, setPriority] = useState(value)
|
||||
const [priority, setPriority] = useState<TicketPriority>(value)
|
||||
const { userId } = useAuth()
|
||||
return (
|
||||
<Select
|
||||
value={priority}
|
||||
onValueChange={async (val) => {
|
||||
const prev = priority
|
||||
setPriority(val as typeof priority)
|
||||
const next = val as TicketPriority
|
||||
setPriority(next)
|
||||
toast.loading("Atualizando prioridade...", { id: "prio" })
|
||||
try {
|
||||
if (!userId) throw new Error("No user")
|
||||
await updatePriority({ ticketId, priority: val as any, actorId: userId as Id<"users"> })
|
||||
await updatePriority({ ticketId: ticketId as unknown as Id<"tickets">, priority: next, actorId: userId as Id<"users"> })
|
||||
toast.success("Prioridade atualizada!", { id: "prio" })
|
||||
} catch {
|
||||
setPriority(prev)
|
||||
|
|
@ -53,16 +64,19 @@ export function PrioritySelect({ ticketId, value }: { ticketId: Id<"tickets">; v
|
|||
>
|
||||
<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>
|
||||
<Badge className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 ${badgeClass(priority)}`}>
|
||||
<PriorityIcon p={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>
|
||||
<span className="inline-flex items-center gap-2"><PriorityIcon p={p} />{labels[p]}</span>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue