sistema-de-chamados/web/src/lib/mappers/ticket.ts

103 lines
3.1 KiB
TypeScript

import { z } from "zod";
import {
ticketSchema,
ticketWithDetailsSchema,
ticketEventSchema,
ticketCommentSchema,
userSummarySchema,
} from "@/lib/schemas/ticket";
// Server shapes: datas como number (epoch ms) e alguns nullables
const serverUserSchema = userSummarySchema;
const serverTicketSchema = z.object({
id: z.string(),
reference: z.number(),
tenantId: z.string(),
subject: z.string(),
summary: z.string().optional().nullable(),
status: z.string(),
priority: z.string(),
channel: z.string(),
queue: z.string().nullable(),
requester: serverUserSchema,
assignee: serverUserSchema.nullable(),
slaPolicy: z.any().nullable().optional(),
dueAt: z.number().nullable().optional(),
firstResponseAt: z.number().nullable().optional(),
resolvedAt: z.number().nullable().optional(),
updatedAt: z.number(),
createdAt: z.number(),
tags: z.array(z.string()).default([]).optional(),
lastTimelineEntry: z.string().nullable().optional(),
metrics: z.any().nullable().optional(),
});
const serverAttachmentSchema = z.object({
id: z.any(),
name: z.string(),
size: z.number().optional(),
url: z.string().url().optional(),
});
const serverCommentSchema = z.object({
id: z.string(),
author: serverUserSchema,
visibility: z.string(),
body: z.string(),
attachments: z.array(serverAttachmentSchema).default([]).optional(),
createdAt: z.number(),
updatedAt: z.number(),
});
const serverEventSchema = z.object({
id: z.string(),
type: z.string(),
payload: z.any().optional(),
createdAt: z.number(),
});
const serverTicketWithDetailsSchema = serverTicketSchema.extend({
description: z.string().optional().nullable(),
customFields: z.record(z.any()).default({}).optional(),
timeline: z.array(serverEventSchema),
comments: z.array(serverCommentSchema),
});
export function mapTicketFromServer(input: unknown) {
const s = serverTicketSchema.parse(input);
const ui = {
...s,
lastTimelineEntry: s.lastTimelineEntry ?? undefined,
updatedAt: new Date(s.updatedAt),
createdAt: new Date(s.createdAt),
dueAt: s.dueAt ? new Date(s.dueAt) : null,
firstResponseAt: s.firstResponseAt ? new Date(s.firstResponseAt) : null,
resolvedAt: s.resolvedAt ? new Date(s.resolvedAt) : null,
};
return ticketSchema.parse(ui);
}
export function mapTicketsFromServerList(arr: unknown[]) {
return arr.map(mapTicketFromServer);
}
export function mapTicketWithDetailsFromServer(input: unknown) {
const s = serverTicketWithDetailsSchema.parse(input);
const ui = {
...s,
lastTimelineEntry: s.lastTimelineEntry ?? undefined,
updatedAt: new Date(s.updatedAt),
createdAt: new Date(s.createdAt),
dueAt: s.dueAt ? new Date(s.dueAt) : null,
firstResponseAt: s.firstResponseAt ? new Date(s.firstResponseAt) : null,
resolvedAt: s.resolvedAt ? new Date(s.resolvedAt) : null,
timeline: s.timeline.map((e) => ({ ...e, createdAt: new Date(e.createdAt) })),
comments: s.comments.map((c) => ({
...c,
createdAt: new Date(c.createdAt),
updatedAt: new Date(c.updatedAt),
})),
};
return ticketWithDetailsSchema.parse(ui);
}