style: refresh ticket ui components
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
parent
5c16ab75a6
commit
744d5933d4
16 changed files with 718 additions and 650 deletions
|
|
@ -10,63 +10,56 @@ 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 { cn } from "@/lib/utils"
|
||||
|
||||
const labels: Record<TicketStatus, string> = {
|
||||
NEW: "Novo",
|
||||
OPEN: "Aberto",
|
||||
PENDING: "Pendente",
|
||||
ON_HOLD: "Em espera",
|
||||
RESOLVED: "Resolvido",
|
||||
CLOSED: "Fechado",
|
||||
const statusStyles: Record<TicketStatus, { label: string; badgeClass: string }> = {
|
||||
NEW: { label: "Novo", badgeClass: "border border-slate-200 bg-slate-100 text-slate-700" },
|
||||
OPEN: { label: "Aberto", badgeClass: "border border-slate-200 bg-[#dff1fb] text-[#0a4760]" },
|
||||
PENDING: { label: "Pendente", badgeClass: "border border-slate-200 bg-[#fdebd6] text-[#7b4107]" },
|
||||
ON_HOLD: { label: "Em espera", badgeClass: "border border-slate-200 bg-[#ede8ff] text-[#4f2f96]" },
|
||||
RESOLVED: { label: "Resolvido", badgeClass: "border border-slate-200 bg-[#dcf4eb] text-[#1f6a45]" },
|
||||
CLOSED: { label: "Fechado", badgeClass: "border border-slate-200 bg-slate-200 text-slate-700" },
|
||||
}
|
||||
|
||||
function badgeClass(s: TicketStatus) {
|
||||
switch (s) {
|
||||
case "OPEN":
|
||||
return "bg-blue-100 text-blue-700"
|
||||
case "PENDING":
|
||||
return "bg-amber-100 text-amber-700"
|
||||
case "ON_HOLD":
|
||||
return "bg-purple-100 text-purple-700"
|
||||
case "RESOLVED":
|
||||
return "bg-emerald-100 text-emerald-700"
|
||||
case "CLOSED":
|
||||
return "bg-slate-100 text-slate-700"
|
||||
default:
|
||||
return "bg-slate-100 text-slate-700"
|
||||
}
|
||||
}
|
||||
const triggerClass = "h-8 w-[180px] rounded-full border border-slate-300 bg-white px-3 text-left text-sm font-medium text-neutral-800 shadow-sm focus:ring-0 data-[state=open]:border-[#00d6eb]"
|
||||
const itemClass = "rounded-md px-2 py-2 text-sm text-neutral-800 transition hover:bg-slate-100 data-[state=checked]:bg-[#00e8ff]/15 data-[state=checked]:text-neutral-900 focus:bg-[#00e8ff]/10"
|
||||
const baseBadgeClass = "inline-flex items-center rounded-full px-3 py-0.5 text-xs font-semibold"
|
||||
|
||||
export function StatusSelect({ ticketId, value }: { ticketId: string; value: TicketStatus }) {
|
||||
const updateStatus = useMutation(api.tickets.updateStatus)
|
||||
const [status, setStatus] = useState<TicketStatus>(value)
|
||||
const { userId } = useAuth()
|
||||
|
||||
return (
|
||||
<Select
|
||||
value={status}
|
||||
onValueChange={async (val) => {
|
||||
const prev = status
|
||||
const next = val as TicketStatus
|
||||
onValueChange={async (selected) => {
|
||||
const previous = status
|
||||
const next = selected as TicketStatus
|
||||
setStatus(next)
|
||||
toast.loading("Atualizando status...", { id: "status" })
|
||||
try {
|
||||
if (!userId) throw new Error("No user")
|
||||
if (!userId) throw new Error("missing user")
|
||||
await updateStatus({ ticketId: ticketId as unknown as Id<"tickets">, status: next, actorId: userId as Id<"users"> })
|
||||
toast.success(`Status alterado para ${labels[next] ?? next}.`, { id: "status" })
|
||||
toast.success("Status alterado para " + (statusStyles[next]?.label ?? next) + ".", { id: "status" })
|
||||
} catch {
|
||||
setStatus(prev)
|
||||
setStatus(previous)
|
||||
toast.error("Não foi possível atualizar o status.", { id: "status" })
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-7 w-[160px] border-transparent bg-muted/50 px-2">
|
||||
<SelectTrigger className={triggerClass}>
|
||||
<SelectValue>
|
||||
<Badge className={`rounded-full px-2 py-0.5 ${badgeClass(status)}`}>{labels[status]}</Badge>
|
||||
<Badge className={cn(baseBadgeClass, statusStyles[status]?.badgeClass)}>
|
||||
{statusStyles[status]?.label ?? status}
|
||||
</Badge>
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{(["NEW","OPEN","PENDING","ON_HOLD","RESOLVED","CLOSED"] as const).map((s) => (
|
||||
<SelectItem key={s} value={s}>{labels[s as TicketStatus]}</SelectItem>
|
||||
<SelectContent className="rounded-lg border border-slate-200 bg-white text-neutral-800 shadow-sm">
|
||||
{(["NEW", "OPEN", "PENDING", "ON_HOLD", "RESOLVED", "CLOSED"] as const).map((option) => (
|
||||
<SelectItem key={option} value={option} className={itemClass}>
|
||||
{statusStyles[option].label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue