feat: preview de imagens com modal, download com nome correto; cartões (Conversa/Detalhes/Timeline) com sombra e padding; alias '@/convex/_generated/api'; payloads legíveis (nome de fila/responsável, label de status) e timeline amigável; Dropzone no 'Novo ticket' com comentário inicial; microtipografia refinada

This commit is contained in:
esdrasrenan 2025-10-04 01:23:34 -03:00
parent 90c3c8e4d6
commit 44c98fec4a
24 changed files with 1409 additions and 301 deletions

View file

@ -25,16 +25,17 @@ const timelineLabels: Record<string, string> = {
STATUS_CHANGED: "Status alterado",
ASSIGNEE_CHANGED: "Responsável alterado",
COMMENT_ADDED: "Comentário adicionado",
QUEUE_CHANGED: "Fila alterada",
}
interface TicketTimelineProps {
ticket: TicketWithDetails
}
export function TicketTimeline({ ticket }: TicketTimelineProps) {
return (
<Card className="border-none shadow-none">
<CardContent className="space-y-6">
export function TicketTimeline({ ticket }: TicketTimelineProps) {
return (
<Card className="rounded-xl border bg-card shadow-sm">
<CardContent className="space-y-6 px-4 pb-6">
{ticket.timeline.map((entry, index) => {
const Icon = timelineIcons[entry.type] ?? IconClockHour4
const isLast = index === ticket.timeline.length - 1
@ -55,13 +56,19 @@ export function TicketTimeline({ ticket }: TicketTimelineProps) {
{format(entry.createdAt, "dd MMM yyyy HH:mm", { locale: ptBR })}
</span>
</div>
{entry.payload ? (
<div className="rounded-lg border border-dashed bg-card px-3 py-2 text-sm text-muted-foreground">
<pre className="whitespace-pre-wrap leading-relaxed">
{JSON.stringify(entry.payload, null, 2)}
</pre>
</div>
) : null}
{(() => {
const p: any = entry.payload || {}
let message: string | null = null
if (entry.type === "STATUS_CHANGED" && (p.toLabel || p.to)) message = `Status alterado para ${p.toLabel || p.to}`
if (entry.type === "ASSIGNEE_CHANGED" && (p.assigneeName || p.assigneeId)) message = `Responsável alterado${p.assigneeName ? ` para ${p.assigneeName}` : ""}`
if (entry.type === "QUEUE_CHANGED" && (p.queueName || p.queueId)) message = `Fila alterada${p.queueName ? ` para ${p.queueName}` : ""}`
if (!message) return null
return (
<div className="rounded-lg border border-dashed bg-card px-3 py-2 text-sm text-muted-foreground">
{message}
</div>
)
})()}
</div>
</div>
)