Atualiza dashboards e painel de tickets

This commit is contained in:
Esdras Renan 2025-11-07 00:56:59 -03:00
parent c66ffa6e0b
commit 4655c7570a
9 changed files with 483 additions and 420 deletions

View file

@ -7,13 +7,12 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com
import { getTicketStatusLabel, getTicketStatusSummaryTone } from "@/lib/ticket-status-style"
import { Badge } from "@/components/ui/badge"
import { cn } from "@/lib/utils"
import { TicketCustomFieldsSection } from "@/components/tickets/ticket-custom-fields"
interface TicketDetailsPanelProps {
ticket: TicketWithDetails
}
type SummaryTone = "default" | "info" | "warning" | "success" | "muted" | "danger"
type SummaryTone = "default" | "info" | "warning" | "success" | "muted" | "danger" | "primary"
const priorityLabel: Record<TicketWithDetails["priority"], string> = {
LOW: "Baixa",
@ -49,12 +48,20 @@ function formatMinutes(value?: number | null) {
return `${value} min`
}
type SummaryChipConfig = {
key: string
label: string
value: string
tone: SummaryTone
labelClassName?: string
}
export function TicketDetailsPanel({ ticket }: TicketDetailsPanelProps) {
const isAvulso = Boolean(ticket.company?.isAvulso)
const companyLabel = ticket.company?.name ?? (isAvulso ? "Cliente avulso" : "Sem empresa vinculada")
const summaryChips = useMemo(() => {
const chips: Array<{ key: string; label: string; value: string; tone: SummaryTone }> = [
const chips: SummaryChipConfig[] = [
{
key: "queue",
label: "Fila",
@ -87,11 +94,12 @@ export function TicketDetailsPanel({ ticket }: TicketDetailsPanelProps) {
},
]
if (ticket.formTemplateLabel) {
chips.push({
chips.splice(Math.min(chips.length, 5), 0, {
key: "formTemplate",
label: "Tipo de solicitação",
label: "Fluxo",
value: ticket.formTemplateLabel,
tone: "info",
tone: "primary",
labelClassName: "text-white",
})
}
return chips
@ -117,7 +125,7 @@ export function TicketDetailsPanel({ ticket }: TicketDetailsPanelProps) {
<div className="space-y-1">
<CardTitle className="text-lg font-semibold text-neutral-900">Detalhes</CardTitle>
<CardDescription className="text-sm text-neutral-500">
Resumo do ticket, métricas de SLA e tempo dedicado pela equipe.
Resumo do ticket, métricas de SLA, tempo dedicado e campos personalizados.
</CardDescription>
</div>
{isAvulso ? (
@ -131,8 +139,8 @@ export function TicketDetailsPanel({ ticket }: TicketDetailsPanelProps) {
<section className="space-y-3">
<h3 className="text-sm font-semibold text-neutral-900">Resumo</h3>
<div className="grid gap-3 sm:grid-cols-2">
{summaryChips.map(({ key, label, value, tone }) => (
<SummaryChip key={key} label={label} value={value} tone={tone} />
{summaryChips.map(({ key, label, value, tone, labelClassName }) => (
<SummaryChip key={key} label={label} value={value} tone={tone} labelClassName={labelClassName} />
))}
</div>
</section>
@ -190,8 +198,6 @@ export function TicketDetailsPanel({ ticket }: TicketDetailsPanelProps) {
</div>
</section>
<TicketCustomFieldsSection ticket={ticket} />
<section className="space-y-3">
<h3 className="text-sm font-semibold text-neutral-900">Tempo por agente</h3>
{agentTotals.length > 0 ? (
@ -255,7 +261,17 @@ export function TicketDetailsPanel({ ticket }: TicketDetailsPanelProps) {
)
}
function SummaryChip({ label, value, tone = "default" }: { label: string; value: string; tone?: SummaryTone }) {
function SummaryChip({
label,
value,
tone = "default",
labelClassName,
}: {
label: string
value: string
tone?: SummaryTone
labelClassName?: string
}) {
const toneClasses: Record<SummaryTone, string> = {
default: "border-slate-200 bg-white text-neutral-900",
info: "border-sky-200 bg-sky-50 text-sky-900",
@ -263,11 +279,12 @@ function SummaryChip({ label, value, tone = "default" }: { label: string; value:
success: "border-emerald-200 bg-emerald-50 text-emerald-800",
muted: "border-slate-200 bg-slate-50 text-neutral-600",
danger: "border-rose-200 bg-rose-50 text-rose-700",
primary: "border-black bg-black text-white",
}
return (
<div className={cn("rounded-xl border px-3 py-2 shadow-sm", toneClasses[tone])}>
<p className="text-[11px] font-semibold uppercase tracking-wide text-neutral-500">{label}</p>
<p className={cn("text-[11px] font-semibold uppercase tracking-wide text-neutral-500", labelClassName)}>{label}</p>
<p className="mt-1 truncate text-sm font-semibold text-current">{value}</p>
</div>
)