sistema-de-chamados/src/lib/schemas/ticket.ts
2025-11-04 19:53:54 -03:00

211 lines
6.8 KiB
TypeScript

import { z } from "zod"
export const ticketStatusSchema = z.enum([
"PENDING",
"AWAITING_ATTENDANCE",
"PAUSED",
"RESOLVED",
])
export type TicketStatus = z.infer<typeof ticketStatusSchema>
export const ticketPrioritySchema = z.enum(["LOW", "MEDIUM", "HIGH", "URGENT"])
export type TicketPriority = z.infer<typeof ticketPrioritySchema>
export const ticketChannelSchema = z.enum([
"EMAIL",
"WHATSAPP",
"CHAT",
"PHONE",
"API",
"MANUAL",
])
export type TicketChannel = z.infer<typeof ticketChannelSchema>
export const commentVisibilitySchema = z.enum(["PUBLIC", "INTERNAL"])
export type CommentVisibility = z.infer<typeof commentVisibilitySchema>
export const userSummarySchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
avatarUrl: z.string().url().optional(),
teams: z.array(z.string()).default([]),
})
export type UserSummary = z.infer<typeof userSummarySchema>
export const ticketCompanySummarySchema = z.object({
id: z.string(),
name: z.string(),
isAvulso: z.boolean().optional(),
})
export type TicketCompanySummary = z.infer<typeof ticketCompanySummarySchema>
export const ticketMachineSummarySchema = z.object({
id: z.string().nullable(),
hostname: z.string().nullable().optional(),
persona: z.string().nullable().optional(),
assignedUserName: z.string().nullable().optional(),
assignedUserEmail: z.string().nullable().optional(),
status: z.string().nullable().optional(),
})
export type TicketMachineSummary = z.infer<typeof ticketMachineSummarySchema>
export const ticketCategorySummarySchema = z.object({
id: z.string(),
name: z.string(),
})
export type TicketCategorySummary = z.infer<typeof ticketCategorySummarySchema>
export const ticketSubcategorySummarySchema = z.object({
id: z.string(),
name: z.string(),
categoryId: z.string().optional(),
})
export type TicketSubcategorySummary = z.infer<typeof ticketSubcategorySummarySchema>
export const ticketAgentWorkTotalSchema = z.object({
agentId: z.string(),
agentName: z.string().nullable().optional(),
agentEmail: z.string().nullable().optional(),
avatarUrl: z.string().nullable().optional(),
totalWorkedMs: z.number(),
internalWorkedMs: z.number().optional().default(0),
externalWorkedMs: z.number().optional().default(0),
})
export type TicketAgentWorkTotal = z.infer<typeof ticketAgentWorkTotalSchema>
export const ticketCommentSchema = z.object({
id: z.string(),
author: userSummarySchema,
visibility: commentVisibilitySchema,
body: z.string(),
attachments: z
.array(
z.object({
id: z.string(),
name: z.string(),
size: z.number().optional(),
type: z.string().optional(),
url: z.string().url().optional(),
})
)
.default([]),
createdAt: z.coerce.date(),
updatedAt: z.coerce.date(),
})
export type TicketComment = z.infer<typeof ticketCommentSchema>
export const ticketEventSchema = z.object({
id: z.string(),
type: z.string(),
payload: z.record(z.string(), z.any()).optional(),
createdAt: z.coerce.date(),
})
export type TicketEvent = z.infer<typeof ticketEventSchema>
export const ticketFieldTypeSchema = z.enum(["text", "number", "select", "date", "boolean"])
export type TicketFieldType = z.infer<typeof ticketFieldTypeSchema>
export const ticketCustomFieldValueSchema = z.object({
label: z.string(),
type: ticketFieldTypeSchema,
value: z.union([z.string(), z.number(), z.boolean(), z.coerce.date()]).optional(),
displayValue: z.string().optional(),
})
export type TicketCustomFieldValue = z.infer<typeof ticketCustomFieldValueSchema>
export const ticketSchema = z.object({
id: z.string(),
reference: z.number(),
tenantId: z.string(),
subject: z.string(),
summary: z.string().optional(),
status: ticketStatusSchema,
priority: ticketPrioritySchema,
channel: ticketChannelSchema,
queue: z.string().nullable(),
requester: userSummarySchema,
assignee: userSummarySchema.nullable(),
company: ticketCompanySummarySchema.optional().nullable(),
machine: ticketMachineSummarySchema.nullable().optional(),
slaPolicy: z
.object({
id: z.string(),
name: z.string(),
targetMinutesToFirstResponse: z.number().nullable(),
targetMinutesToResolution: z.number().nullable(),
})
.nullable(),
dueAt: z.coerce.date().nullable(),
firstResponseAt: z.coerce.date().nullable(),
resolvedAt: z.coerce.date().nullable(),
updatedAt: z.coerce.date(),
createdAt: z.coerce.date(),
tags: z.array(z.string()).default([]),
lastTimelineEntry: z.string().optional(),
metrics: z
.object({
timeWaitingMinutes: z.number().nullable(),
timeOpenedMinutes: z.number().nullable(),
})
.nullable(),
relatedTicketIds: z.array(z.string()).optional(),
resolvedWithTicketId: z.string().nullable().optional(),
reopenDeadline: z.number().nullable().optional(),
reopenWindowDays: z.number().nullable().optional(),
reopenedAt: z.number().nullable().optional(),
reopenedBy: z.string().nullable().optional(),
chatEnabled: z.boolean().optional(),
formTemplate: z.string().nullable().optional(),
csatScore: z.number().nullable().optional(),
csatMaxScore: z.number().nullable().optional(),
csatComment: z.string().nullable().optional(),
csatRatedAt: z.coerce.date().nullable().optional(),
csatRatedBy: z.string().nullable().optional(),
category: ticketCategorySummarySchema.nullable().optional(),
subcategory: ticketSubcategorySummarySchema.nullable().optional(),
workSummary: z
.object({
totalWorkedMs: z.number(),
internalWorkedMs: z.number().optional().default(0),
externalWorkedMs: z.number().optional().default(0),
serverNow: z.number().optional(),
activeSession: z
.object({
id: z.string(),
agentId: z.string(),
startedAt: z.coerce.date(),
workType: z.string().optional(),
})
.nullable(),
perAgentTotals: z.array(ticketAgentWorkTotalSchema).optional(),
})
.nullable()
.optional(),
})
export type Ticket = z.infer<typeof ticketSchema>
export const ticketWithDetailsSchema = ticketSchema.extend({
description: z.string().optional(),
customFields: z.record(z.string(), ticketCustomFieldValueSchema).optional(),
timeline: z.array(ticketEventSchema),
comments: z.array(ticketCommentSchema),
})
export type TicketWithDetails = z.infer<typeof ticketWithDetailsSchema>
export const ticketQueueSummarySchema = z.object({
id: z.string(),
name: z.string(),
pending: z.number(),
inProgress: z.number(),
paused: z.number(),
breached: z.number(),
})
export type TicketQueueSummary = z.infer<typeof ticketQueueSummarySchema>
export const ticketPlayContextSchema = z.object({
queue: ticketQueueSummarySchema,
nextTicket: ticketSchema.nullable(),
})
export type TicketPlayContext = z.infer<typeof ticketPlayContextSchema>