diff --git a/src/components/portal/portal-ticket-card.tsx b/src/components/portal/portal-ticket-card.tsx index c019c7a..5d89968 100644 --- a/src/components/portal/portal-ticket-card.tsx +++ b/src/components/portal/portal-ticket-card.tsx @@ -11,20 +11,7 @@ import { useAuth } from "@/lib/auth-client" import { Badge } from "@/components/ui/badge" import { Card, CardContent, CardHeader } from "@/components/ui/card" import { cn } from "@/lib/utils" - -const statusLabel: Record = { - PENDING: "Pendente", - AWAITING_ATTENDANCE: "Em andamento", - PAUSED: "Pausado", - RESOLVED: "Resolvido", -} - -const statusTone: Record = { - PENDING: "border border-slate-200 bg-slate-100 text-slate-700", - AWAITING_ATTENDANCE: "border border-sky-200 bg-sky-100 text-sky-700", - PAUSED: "border border-amber-200 bg-[#fff3c4] text-[#7a5901]", - RESOLVED: "border border-emerald-200 bg-emerald-100 text-emerald-700", -} +import { getTicketStatusBadgeClass, getTicketStatusLabel } from "@/lib/ticket-status-style" const priorityLabel: Record = { LOW: "Baixa", @@ -67,8 +54,8 @@ export function PortalTicketCard({ ticket }: PortalTicketCardProps) { ) : null}
- - {statusLabel[ticket.status]} + + {getTicketStatusLabel(ticket.status)} {!isCustomer ? ( @@ -86,7 +73,7 @@ export function PortalTicketCard({ ticket }: PortalTicketCardProps) { ) : null}
Status - {statusLabel[ticket.status]} + {getTicketStatusLabel(ticket.status)}
{ticket.assignee ? (
diff --git a/src/components/tickets/ticket-details-panel.tsx b/src/components/tickets/ticket-details-panel.tsx index 0c6128e..1239a3b 100644 --- a/src/components/tickets/ticket-details-panel.tsx +++ b/src/components/tickets/ticket-details-panel.tsx @@ -6,6 +6,7 @@ import type { TicketWithDetails } from "@/lib/schemas/ticket" import { Badge } from "@/components/ui/badge" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { cn } from "@/lib/utils" +import { getTicketStatusLabel, getTicketStatusSummaryTone } from "@/lib/ticket-status-style" interface TicketDetailsPanelProps { ticket: TicketWithDetails @@ -13,20 +14,6 @@ interface TicketDetailsPanelProps { type SummaryTone = "default" | "info" | "warning" | "success" | "muted" | "danger" -const statusLabel: Record = { - PENDING: "Pendente", - AWAITING_ATTENDANCE: "Em andamento", - PAUSED: "Pausado", - RESOLVED: "Resolvido", -} - -const statusTone: Record = { - PENDING: "muted", - AWAITING_ATTENDANCE: "info", - PAUSED: "warning", - RESOLVED: "success", -} - const priorityLabel: Record = { LOW: "Baixa", MEDIUM: "Média", @@ -82,8 +69,8 @@ export function TicketDetailsPanel({ ticket }: TicketDetailsPanelProps) { { key: "status", label: "Status", - value: statusLabel[ticket.status] ?? ticket.status, - tone: statusTone[ticket.status] ?? "default", + value: getTicketStatusLabel(ticket.status) ?? ticket.status, + tone: getTicketStatusSummaryTone(ticket.status) as SummaryTone, }, { key: "priority", diff --git a/src/components/tickets/tickets-board.tsx b/src/components/tickets/tickets-board.tsx index d6d9ee4..1164f41 100644 --- a/src/components/tickets/tickets-board.tsx +++ b/src/components/tickets/tickets-board.tsx @@ -5,30 +5,17 @@ import { formatDistanceToNowStrict } from "date-fns" import { ptBR } from "date-fns/locale" import { LayoutGrid } from "lucide-react" -import type { Ticket, TicketStatus } from "@/lib/schemas/ticket" +import type { Ticket } from "@/lib/schemas/ticket" import { Badge } from "@/components/ui/badge" import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyTitle } from "@/components/ui/empty" import { cn } from "@/lib/utils" import { TicketPriorityPill } from "@/components/tickets/priority-pill" +import { getTicketStatusChipClass, getTicketStatusLabel } from "@/lib/ticket-status-style" type TicketsBoardProps = { tickets: Ticket[] } -const statusLabel: Record = { - PENDING: "Pendente", - AWAITING_ATTENDANCE: "Em andamento", - PAUSED: "Pausado", - RESOLVED: "Resolvido", -} - -const statusChipClass: Record = { - PENDING: "bg-amber-100 text-amber-800 ring-1 ring-amber-200", - AWAITING_ATTENDANCE: "bg-sky-100 text-sky-700 ring-1 ring-sky-200", - PAUSED: "bg-violet-100 text-violet-700 ring-1 ring-violet-200", - RESOLVED: "bg-emerald-100 text-emerald-700 ring-1 ring-emerald-200", -} - function formatUpdated(date: Date) { return formatDistanceToNowStrict(date, { addSuffix: true, locale: ptBR }) } @@ -71,10 +58,10 @@ export function TicketsBoard({ tickets }: TicketsBoardProps) { - {statusLabel[ticket.status]} + {getTicketStatusLabel(ticket.status)}
diff --git a/src/components/tickets/tickets-table.tsx b/src/components/tickets/tickets-table.tsx index 468794b..b6c7bf4 100644 --- a/src/components/tickets/tickets-table.tsx +++ b/src/components/tickets/tickets-table.tsx @@ -6,7 +6,7 @@ import { format, formatDistanceToNowStrict } from "date-fns" import { ptBR } from "date-fns/locale" import { type LucideIcon, Code, FileText, Mail, MessageCircle, MessageSquare, Phone } from "lucide-react" -import type { Ticket, TicketChannel, TicketStatus } from "@/lib/schemas/ticket" +import type { Ticket, TicketChannel } from "@/lib/schemas/ticket" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" import { Badge } from "@/components/ui/badge" import { Card, CardContent } from "@/components/ui/card" @@ -23,6 +23,7 @@ import { import { PrioritySelect } from "@/components/tickets/priority-select" import { cn } from "@/lib/utils" import { deriveServerOffset, toServerTimestamp } from "@/components/tickets/ticket-timer.utils" +import { getTicketStatusLabel, getTicketStatusTextClass } from "@/lib/ticket-status-style" const channelLabel: Record = { EMAIL: "E-mail", @@ -48,20 +49,6 @@ const categoryChipClass = "inline-flex items-center gap-1 rounded-full bg-slate- const tableRowClass = "group border-b border-slate-100 text-sm transition-colors hover:bg-slate-100/70 last:border-none" -const statusLabel: Record = { - PENDING: "Pendente", - AWAITING_ATTENDANCE: "Em andamento", - PAUSED: "Pausado", - RESOLVED: "Resolvido", -} - -const statusTone: Record = { - PENDING: "text-slate-700", - AWAITING_ATTENDANCE: "text-sky-700", - PAUSED: "text-violet-700", - RESOLVED: "text-emerald-700", -} - function formatDuration(ms?: number) { if (!ms || ms <= 0) return "—" const totalSeconds = Math.floor(ms / 1000) @@ -267,8 +254,11 @@ export function TicketsTable({ tickets }: TicketsTableProps) {
- - {statusLabel[ticket.status]} + + {getTicketStatusLabel(ticket.status)} {ticket.metrics?.timeWaitingMinutes ? ( diff --git a/src/components/ui/rich-text-editor.tsx b/src/components/ui/rich-text-editor.tsx index 1ec8516..b276386 100644 --- a/src/components/ui/rich-text-editor.tsx +++ b/src/components/ui/rich-text-editor.tsx @@ -25,6 +25,7 @@ import { Button } from "@/components/ui/button" import { Separator } from "@/components/ui/separator" import { Input } from "@/components/ui/input" import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" +import { getTicketStatusDotClass, getTicketStatusLabel } from "@/lib/ticket-status-style" import { Bold, Italic, @@ -115,20 +116,6 @@ type TicketMentionAttributes = Record const TICKET_MENTION_FALLBACK_STATUS = "PENDING" const TICKET_MENTION_FALLBACK_PRIORITY = "MEDIUM" -const statusLabels: Record = { - PENDING: "Pendente", - AWAITING_ATTENDANCE: "Em andamento", - PAUSED: "Pausado", - RESOLVED: "Resolvido", -} - -const statusTone: Record = { - PENDING: "bg-amber-400", - AWAITING_ATTENDANCE: "bg-sky-500", - PAUSED: "bg-violet-500", - RESOLVED: "bg-emerald-500", -} - function toPlainString(value: unknown): string { if (value === null || value === undefined) return "" return String(value) @@ -162,11 +149,11 @@ function updateTicketMentionNodeElements(elements: TicketMentionNodeElements, at const displayedReference = referenceLabel ? `#${referenceLabel}` : "#" const formattedSubject = normalized.subject ? formatMentionSubject(normalized.subject) : "" const additionalClass = toPlainString(attrs.class ?? attrs.className) - const statusToneClass = statusTone[normalized.status] ?? "bg-slate-400" + const dotClass = getTicketStatusDotClass(normalized.status) root.className = cn(TICKET_MENTION_BASE_CLASSES, additionalClass) root.dataset.ticketMention = "true" - dotEl.className = cn(TICKET_MENTION_DOT_BASE_CLASSES, statusToneClass) + dotEl.className = cn(TICKET_MENTION_DOT_BASE_CLASSES, dotClass) referenceEl.className = TICKET_MENTION_REF_CLASSES subjectEl.className = TICKET_MENTION_SUBJECT_CLASSES separatorEl.className = TICKET_MENTION_SEP_CLASSES @@ -244,8 +231,7 @@ function buildTicketMentionAnchorHtml(attrs: { const url = attrs.url ?? "" const displayedReference = reference || id const formattedSubject = subject ? formatMentionSubject(subject) : "" - const dotToneClass = statusTone[status] ?? "bg-slate-400" - const dotClass = `${TICKET_MENTION_DOT_BASE_CLASSES} ${dotToneClass}` + const dotClass = `${TICKET_MENTION_DOT_BASE_CLASSES} ${getTicketStatusDotClass(status)}` const title = formattedSubject ? `#${displayedReference} • ${formattedSubject}` : `#${displayedReference}` return `#${escapeHtml(displayedReference)}${escapeHtml(formattedSubject)}` @@ -424,8 +410,8 @@ function TicketMentionList({ items, command, onRegister }: TicketMentionSuggesti
{items.map((item, index) => { const isActive = index === selectedIndex - const status = statusLabels[item.status] ?? item.status - const statusDot = statusTone[item.status] ?? "bg-slate-400" + const status = getTicketStatusLabel(item.status) + const statusDot = getTicketStatusDotClass(item.status) const priority = priorityLabels[item.priority] ?? item.priority return (