chore: reorganize project structure and ensure default queues
This commit is contained in:
parent
854887f499
commit
1cccb852a5
201 changed files with 417 additions and 838 deletions
|
|
@ -1,184 +0,0 @@
|
|||
import { z } from "zod";
|
||||
import { ticketSchema, ticketWithDetailsSchema } from "@/lib/schemas/ticket";
|
||||
|
||||
// Server shapes: datas como number (epoch ms) e alguns nullables
|
||||
// Relaxamos email/urls no shape do servidor para evitar que payloads parciais quebrem o app.
|
||||
const serverUserSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
email: z.string().optional(),
|
||||
avatarUrl: z.string().optional(),
|
||||
teams: z.array(z.string()).optional(),
|
||||
});
|
||||
|
||||
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(),
|
||||
category: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
})
|
||||
.nullable()
|
||||
.optional(),
|
||||
subcategory: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
categoryId: z.string().optional(),
|
||||
})
|
||||
.nullable()
|
||||
.optional(),
|
||||
workSummary: z
|
||||
.object({
|
||||
totalWorkedMs: z.number(),
|
||||
activeSession: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
agentId: z.string(),
|
||||
startedAt: z.number(),
|
||||
})
|
||||
.nullable(),
|
||||
})
|
||||
.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 serverCustomFieldValueSchema = z.object({
|
||||
label: z.string(),
|
||||
type: z.string(),
|
||||
value: z.any().optional(),
|
||||
displayValue: z.string().optional(),
|
||||
});
|
||||
|
||||
const serverTicketWithDetailsSchema = serverTicketSchema.extend({
|
||||
description: z.string().optional().nullable(),
|
||||
customFields: z.record(z.string(), serverCustomFieldValueSchema).optional(),
|
||||
timeline: z.array(serverEventSchema),
|
||||
comments: z.array(serverCommentSchema),
|
||||
});
|
||||
|
||||
export function mapTicketFromServer(input: unknown) {
|
||||
const s = serverTicketSchema.parse(input);
|
||||
const ui = {
|
||||
...s,
|
||||
category: s.category ?? undefined,
|
||||
subcategory: s.subcategory ?? undefined,
|
||||
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,
|
||||
workSummary: s.workSummary
|
||||
? {
|
||||
totalWorkedMs: s.workSummary.totalWorkedMs,
|
||||
activeSession: s.workSummary.activeSession
|
||||
? {
|
||||
...s.workSummary.activeSession,
|
||||
startedAt: new Date(s.workSummary.activeSession.startedAt),
|
||||
}
|
||||
: null,
|
||||
}
|
||||
: undefined,
|
||||
};
|
||||
return ui as unknown as z.infer<typeof ticketSchema>;
|
||||
}
|
||||
|
||||
export function mapTicketsFromServerList(arr: unknown[]) {
|
||||
return arr.map(mapTicketFromServer);
|
||||
}
|
||||
|
||||
export function mapTicketWithDetailsFromServer(input: unknown) {
|
||||
const s = serverTicketWithDetailsSchema.parse(input);
|
||||
const customFields = Object.entries(s.customFields ?? {}).reduce<
|
||||
Record<string, { label: string; type: string; value?: unknown; displayValue?: string }>
|
||||
>(
|
||||
(acc, [key, value]) => {
|
||||
let parsedValue: unknown = value.value;
|
||||
if (value.type === "date" && typeof value.value === "number") {
|
||||
parsedValue = new Date(value.value);
|
||||
}
|
||||
acc[key] = {
|
||||
label: value.label,
|
||||
type: value.type,
|
||||
value: parsedValue,
|
||||
displayValue: value.displayValue,
|
||||
};
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
const ui = {
|
||||
...s,
|
||||
customFields,
|
||||
category: s.category ?? undefined,
|
||||
subcategory: s.subcategory ?? undefined,
|
||||
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),
|
||||
})),
|
||||
workSummary: s.workSummary
|
||||
? {
|
||||
totalWorkedMs: s.workSummary.totalWorkedMs,
|
||||
activeSession: s.workSummary.activeSession
|
||||
? {
|
||||
...s.workSummary.activeSession,
|
||||
startedAt: new Date(s.workSummary.activeSession.startedAt),
|
||||
}
|
||||
: null,
|
||||
}
|
||||
: undefined,
|
||||
};
|
||||
return ui as unknown as z.infer<typeof ticketWithDetailsSchema>;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue