feat: custom fields improvements
This commit is contained in:
parent
9495b54a28
commit
0f0f367b3a
11 changed files with 1290 additions and 12 deletions
89
src/lib/ticket-custom-fields.ts
Normal file
89
src/lib/ticket-custom-fields.ts
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import { format } from "date-fns"
|
||||
import { ptBR } from "date-fns/locale"
|
||||
|
||||
export type TicketCustomFieldRecord = Record<
|
||||
string,
|
||||
{
|
||||
label: string
|
||||
type: string
|
||||
value?: unknown
|
||||
displayValue?: string
|
||||
}
|
||||
>
|
||||
|
||||
export type TicketCustomFieldEntry = {
|
||||
key: string
|
||||
label: string
|
||||
type: string
|
||||
value: unknown
|
||||
displayValue?: string
|
||||
formattedValue: string
|
||||
}
|
||||
|
||||
function formatBoolean(value: unknown): string {
|
||||
if (value === null || value === undefined) return "—"
|
||||
return value === true || String(value).toLowerCase() === "true" ? "Sim" : "Não"
|
||||
}
|
||||
|
||||
function formatDate(value: unknown): string {
|
||||
if (value === null || value === undefined) return "—"
|
||||
const date =
|
||||
typeof value === "number"
|
||||
? Number.isFinite(value)
|
||||
? new Date(value)
|
||||
: null
|
||||
: typeof value === "string" && value.trim().length > 0
|
||||
? new Date(value)
|
||||
: null
|
||||
if (!date || Number.isNaN(date.getTime())) return "—"
|
||||
return format(date, "dd/MM/yyyy", { locale: ptBR })
|
||||
}
|
||||
|
||||
function formatNumber(value: unknown): string {
|
||||
if (value === null || value === undefined || value === "") return "—"
|
||||
const numeric = typeof value === "number" ? value : Number(String(value).replace(",", "."))
|
||||
if (!Number.isFinite(numeric)) return String(value)
|
||||
return new Intl.NumberFormat("pt-BR", { maximumFractionDigits: 2 }).format(numeric)
|
||||
}
|
||||
|
||||
function formatFallback(value: unknown): string {
|
||||
if (value === null || value === undefined) return "—"
|
||||
if (typeof value === "string" && value.trim().length === 0) return "—"
|
||||
return String(value)
|
||||
}
|
||||
|
||||
export function formatTicketCustomFieldValue(entry: {
|
||||
type: string
|
||||
value?: unknown
|
||||
displayValue?: string
|
||||
}): string {
|
||||
if (entry.displayValue && entry.displayValue.trim().length > 0) {
|
||||
return entry.displayValue
|
||||
}
|
||||
switch ((entry.type ?? "").toLowerCase()) {
|
||||
case "boolean":
|
||||
return formatBoolean(entry.value)
|
||||
case "date":
|
||||
return formatDate(entry.value)
|
||||
case "number":
|
||||
return formatNumber(entry.value)
|
||||
default:
|
||||
return formatFallback(entry.value)
|
||||
}
|
||||
}
|
||||
|
||||
export function mapTicketCustomFields(
|
||||
record: TicketCustomFieldRecord | undefined | null
|
||||
): TicketCustomFieldEntry[] {
|
||||
if (!record) return []
|
||||
return Object.entries(record)
|
||||
.map(([key, field]) => ({
|
||||
key,
|
||||
label: field.label,
|
||||
type: field.type,
|
||||
value: field.value ?? null,
|
||||
displayValue: field.displayValue,
|
||||
formattedValue: formatTicketCustomFieldValue(field),
|
||||
}))
|
||||
.sort((a, b) => a.label.localeCompare(b.label, "pt-BR"))
|
||||
}
|
||||
|
|
@ -18,4 +18,5 @@ export const TICKET_TIMELINE_LABELS: Record<string, string> = {
|
|||
CSAT_RECEIVED: "CSAT recebido",
|
||||
CSAT_RATED: "CSAT avaliado",
|
||||
TICKET_LINKED: "Chamado vinculado",
|
||||
CUSTOM_FIELDS_UPDATED: "Campos personalizados atualizados",
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue