feat: overhaul admin user management and desktop UX

This commit is contained in:
Esdras Renan 2025-10-13 10:36:38 -03:00
parent 7d6f3bea01
commit ecad81b0ea
16 changed files with 1546 additions and 395 deletions

View file

@ -133,37 +133,38 @@ export function TicketsTable({ tickets = ticketsMock }: TicketsTableProps) {
return (
<Card className="gap-0 rounded-3xl border border-slate-200 bg-white py-0 shadow-sm">
<CardContent className="p-0">
<Table className="min-w-full overflow-hidden rounded-3xl table-fixed">
<TableHeader className="bg-slate-100/80">
<TableRow className="bg-transparent text-[11px] uppercase tracking-wide text-neutral-600">
<TableHead className="w-[120px] px-4 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6">
<div className="w-full overflow-x-auto">
<Table className="w-full min-w-[920px] overflow-hidden rounded-3xl">
<TableHeader className="bg-slate-100/80">
<TableRow className="bg-transparent text-[11px] uppercase tracking-wide text-neutral-600">
<TableHead className="w-[110px] px-4 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 sm:w-[120px]">
Ticket
</TableHead>
<TableHead className="w-[40%] px-4 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6">
<TableHead className="w-[38%] px-4 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 sm:w-[40%]">
Assunto
</TableHead>
<TableHead className="hidden w-[120px] pl-8 pr-3 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 lg:table-cell">
<TableHead className="hidden w-[120px] pl-6 pr-3 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 lg:table-cell">
Fila
</TableHead>
<TableHead className="hidden w-[80px] pl-8 pr-3 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 md:table-cell">
<TableHead className="hidden w-[70px] pl-6 pr-3 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 md:table-cell sm:w-[80px]">
Canal
</TableHead>
<TableHead className="hidden w-[180px] pl-8 pr-3 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 lg:table-cell">
<TableHead className="hidden w-[150px] pl-6 pr-3 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 lg:table-cell xl:w-[180px]">
Empresa
</TableHead>
<TableHead className="hidden w-[100px] pl-1 pr-3 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 md:table-cell">
<TableHead className="hidden w-[90px] pl-1 pr-3 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 md:table-cell lg:w-[100px]">
Prioridade
</TableHead>
<TableHead className="w-[230px] pl-14 pr-3 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6">
<TableHead className="w-[160px] pl-6 pr-3 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 sm:w-[200px] lg:pl-10 xl:w-[230px] xl:pl-14">
Status
</TableHead>
<TableHead className="hidden w-[110px] px-4 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 lg:table-cell">
<TableHead className="hidden w-[110px] px-4 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 lg:table-cell">
Tempo
</TableHead>
<TableHead className="hidden w-[200px] px-4 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 xl:table-cell">
<TableHead className="hidden w-[180px] px-4 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 xl:table-cell xl:w-[200px]">
Responsável
</TableHead>
<TableHead className="w-[140px] px-4 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6">
<TableHead className="w-[130px] px-4 py-3 text-left text-[11px] font-semibold uppercase tracking-wide text-neutral-600 first:pl-6 last:pr-6 sm:w-[140px]">
Atualizado
</TableHead>
</TableRow>
@ -217,12 +218,12 @@ export function TicketsTable({ tickets = ticketsMock }: TicketsTableProps) {
</div>
</div>
</TableCell>
<TableCell className={`${cellClass} hidden lg:table-cell pl-8`}>
<TableCell className={`${cellClass} hidden lg:table-cell pl-6`}>
<span className="text-sm font-semibold text-neutral-800">
{ticket.queue ?? "Sem fila"}
</span>
</TableCell>
<TableCell className={`${cellClass} hidden md:table-cell pl-8`}>
<TableCell className={`${cellClass} hidden md:table-cell pl-6`}>
<div className="flex items-center">
<span className="sr-only">Canal {channelLabel[ticket.channel]}</span>
<span
@ -234,12 +235,12 @@ export function TicketsTable({ tickets = ticketsMock }: TicketsTableProps) {
</span>
</div>
</TableCell>
<TableCell className={`${cellClass} hidden lg:table-cell pl-8`}>
<TableCell className={`${cellClass} hidden lg:table-cell pl-6`}>
<span className="max-w-[160px] truncate text-sm text-neutral-800" title={((ticket.company ?? null) as { name?: string } | null)?.name ?? "—"}>
{((ticket.company ?? null) as { name?: string } | null)?.name ?? "—"}
</span>
</TableCell>
<TableCell className={`${cellClass} hidden md:table-cell pl-1 pr-8`}>
<TableCell className={`${cellClass} hidden md:table-cell pl-1 pr-6 lg:pr-8`}>
<div
className="inline-flex"
onClick={(event) => event.stopPropagation()}
@ -248,9 +249,9 @@ export function TicketsTable({ tickets = ticketsMock }: TicketsTableProps) {
<PrioritySelect ticketId={ticket.id} value={ticket.priority} />
</div>
</TableCell>
<TableCell className={`${cellClass} pl-14`}>
<TableCell className={`${cellClass} pl-6 sm:pl-10 xl:pl-14`}>
<div className="flex flex-col gap-1">
<span className={cn("text-sm font-semibold break-words leading-tight max-w-[140px] sm:max-w-[180px]", statusTone[ticket.status])}>
<span className={cn("text-sm font-semibold break-words leading-tight max-w-[140px] sm:max-w-[180px] lg:max-w-[210px]", statusTone[ticket.status])}>
{statusLabel[ticket.status]}
</span>
{ticket.metrics?.timeWaitingMinutes ? (
@ -285,7 +286,8 @@ export function TicketsTable({ tickets = ticketsMock }: TicketsTableProps) {
)
})}
</TableBody>
</Table>
</Table>
</div>
{tickets.length === 0 && (
<Empty className="my-6">
<EmptyHeader>