chore: reorganize project structure and ensure default queues
This commit is contained in:
parent
854887f499
commit
1cccb852a5
201 changed files with 417 additions and 838 deletions
|
|
@ -1,84 +0,0 @@
|
|||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { useMutation } from "convex/react"
|
||||
// @ts-expect-error Convex runtime API lacks TypeScript declarations
|
||||
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, ChevronDown } from "lucide-react"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
export const priorityStyles: Record<TicketPriority, { label: string; badgeClass: string }> = {
|
||||
LOW: { label: "Baixa", badgeClass: "bg-slate-100 text-slate-700" },
|
||||
MEDIUM: { label: "Média", badgeClass: "bg-[#dff1fb] text-[#0a4760]" },
|
||||
HIGH: { label: "Alta", badgeClass: "bg-[#fde8d1] text-[#7d3b05]" },
|
||||
URGENT: { label: "Urgente", badgeClass: "bg-[#fbd9dd] text-[#8b0f1c]" },
|
||||
}
|
||||
|
||||
export const priorityTriggerClass =
|
||||
"h-8 w-[160px] 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]"
|
||||
export const priorityItemClass = "flex items-center gap-2 rounded-md px-2 py-2 text-sm text-neutral-800 transition data-[state=checked]:bg-[#00e8ff]/15 data-[state=checked]:text-neutral-900 focus:bg-[#00e8ff]/10"
|
||||
const iconClass = "size-4 text-neutral-700"
|
||||
export const priorityBadgeClass =
|
||||
"inline-flex h-9 items-center gap-2 rounded-full border border-slate-200 px-3 text-sm font-semibold transition hover:border-slate-300"
|
||||
|
||||
const headerTriggerClass =
|
||||
"group inline-flex h-auto w-auto items-center justify-center rounded-full border border-transparent bg-transparent p-0 shadow-none ring-0 ring-offset-0 ring-offset-transparent focus-visible:outline-none focus-visible:border-transparent focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:shadow-none hover:bg-transparent data-[state=open]:bg-transparent data-[state=open]:border-transparent data-[state=open]:shadow-none data-[state=open]:ring-0 data-[state=open]:ring-offset-0 data-[state=open]:ring-offset-transparent [&>*:last-child]:hidden"
|
||||
|
||||
export function PriorityIcon({ value }: { value: TicketPriority }) {
|
||||
if (value === "LOW") return <ArrowDown className={iconClass} />
|
||||
if (value === "MEDIUM") return <ArrowRight className={iconClass} />
|
||||
if (value === "HIGH") return <ArrowUp className={iconClass} />
|
||||
return <ChevronsUp className={iconClass} />
|
||||
}
|
||||
|
||||
export function PrioritySelect({ ticketId, value }: { ticketId: string; value: TicketPriority }) {
|
||||
const updatePriority = useMutation(api.tickets.updatePriority)
|
||||
const [priority, setPriority] = useState<TicketPriority>(value)
|
||||
const { convexUserId } = useAuth()
|
||||
|
||||
return (
|
||||
<Select
|
||||
value={priority}
|
||||
onValueChange={async (selected) => {
|
||||
const previous = priority
|
||||
const next = selected as TicketPriority
|
||||
setPriority(next)
|
||||
toast.loading("Atualizando prioridade...", { id: "priority" })
|
||||
try {
|
||||
if (!convexUserId) throw new Error("missing user")
|
||||
await updatePriority({ ticketId: ticketId as unknown as Id<"tickets">, priority: next, actorId: convexUserId as Id<"users"> })
|
||||
toast.success("Prioridade atualizada!", { id: "priority" })
|
||||
} catch {
|
||||
setPriority(previous)
|
||||
toast.error("Não foi possível atualizar a prioridade.", { id: "priority" })
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className={headerTriggerClass} aria-label="Atualizar prioridade">
|
||||
<SelectValue asChild>
|
||||
<Badge className={cn(priorityBadgeClass, priorityStyles[priority]?.badgeClass)}>
|
||||
<PriorityIcon value={priority} />
|
||||
{priorityStyles[priority]?.label ?? priority}
|
||||
<ChevronDown className="size-3 text-current transition group-data-[state=open]:rotate-180" />
|
||||
</Badge>
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent className="rounded-lg border border-slate-200 bg-white text-neutral-800 shadow-sm">
|
||||
{(["LOW", "MEDIUM", "HIGH", "URGENT"] as const).map((option) => (
|
||||
<SelectItem key={option} value={option} className={priorityItemClass}>
|
||||
<span className="inline-flex items-center gap-2">
|
||||
<PriorityIcon value={option} />
|
||||
{priorityStyles[option].label}
|
||||
</span>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue