feat(ui): Spinner e Dialog shadcn; Novo ticket em Dialog com RHF+Zod; selects de responsável e fila com updates otimistas; spinners e toasts; fix setState durante render nos filtros; loading states\n\nchore(test): Vitest + testes de mapeadores\n

This commit is contained in:
esdrasrenan 2025-10-04 00:52:56 -03:00
parent 27b103cb46
commit 90c3c8e4d6
12 changed files with 415 additions and 50 deletions

View file

@ -9,11 +9,12 @@ import { DEFAULT_TENANT_ID } from "@/lib/constants"
import { mapTicketsFromServerList } from "@/lib/mappers/ticket"
import { TicketsFilters, TicketFiltersState, defaultTicketFilters } from "@/components/tickets/tickets-filters"
import { TicketsTable } from "@/components/tickets/tickets-table"
import { Spinner } from "@/components/ui/spinner"
export function TicketsView() {
const [filters, setFilters] = useState<TicketFiltersState>(defaultTicketFilters)
const queues = useQuery(api.queues.summary, { tenantId: DEFAULT_TENANT_ID }) ?? []
const queues = useQuery(api.queues.summary, { tenantId: DEFAULT_TENANT_ID })
const ticketsRaw = useQuery(api.tickets.list, {
tenantId: DEFAULT_TENANT_ID,
status: filters.status ?? undefined,
@ -21,9 +22,9 @@ export function TicketsView() {
channel: filters.channel ?? undefined,
queueId: undefined, // simplified: filter by queue name on client
search: filters.search || undefined,
}) ?? []
})
const tickets = useMemo(() => mapTicketsFromServerList(ticketsRaw as any[]), [ticketsRaw])
const tickets = useMemo(() => mapTicketsFromServerList((ticketsRaw ?? []) as any[]), [ticketsRaw])
const filteredTickets = useMemo(() => {
if (!filters.queue) return tickets
@ -32,8 +33,12 @@ export function TicketsView() {
return (
<div className="flex flex-col gap-6 px-4 lg:px-6">
<TicketsFilters onChange={setFilters} queues={queues.map((q: any) => q.name)} />
<TicketsTable tickets={filteredTickets as any} />
<TicketsFilters onChange={setFilters} queues={(queues ?? []).map((q: any) => q.name)} />
{ticketsRaw === undefined ? (
<div className="flex items-center gap-2 text-sm text-muted-foreground"><Spinner /> Carregando tickets</div>
) : (
<TicketsTable tickets={filteredTickets as any} />
)}
</div>
)
}