diff options
| author | zwlucas <lucas.fariamo08@gmail.com> | 2026-07-25 21:23:29 +0000 |
|---|---|---|
| committer | zwlucas <lucas.fariamo08@gmail.com> | 2026-07-25 21:23:29 +0000 |
| commit | ef55d9bb24430610b60c1b77821307cd72c08c55 (patch) | |
| tree | e6935a810b34370b0a4c821e55f6397aac50c832 /api/src/modules/tickets/tickets.schema.ts | |
| download | helpdesk-master.tar.gz helpdesk-master.zip | |
Signed-off-by: zwlucas <lucas.fariamo08@gmail.com>
Diffstat (limited to 'api/src/modules/tickets/tickets.schema.ts')
| -rw-r--r-- | api/src/modules/tickets/tickets.schema.ts | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/api/src/modules/tickets/tickets.schema.ts b/api/src/modules/tickets/tickets.schema.ts new file mode 100644 index 0000000..43d94cf --- /dev/null +++ b/api/src/modules/tickets/tickets.schema.ts @@ -0,0 +1,89 @@ +/** + * tickets.schema.ts + * + * Schemas Zod para validação de entrada e saída do módulo de tickets. + * Usados tanto pelo Fastify (validação automática de requests) + * quanto pelo TypeScript (inferência de tipos). + */ + +import { z } from 'zod'; +import { TICKET_PRIORITIES, TICKET_STATUSES } from '@/db/schema.js'; + +// ─── Criação de Ticket ──────────────────────────────────────────────────────── + +export const createTicketBodySchema = z.object({ + title: z + .string({ required_error: 'Título é obrigatório' }) + .min(5, 'Título deve ter no mínimo 5 caracteres') + .max(150, 'Título deve ter no máximo 150 caracteres') + .trim(), + + description: z + .string({ required_error: 'Descrição é obrigatória' }) + .min(10, 'Descrição deve ter no mínimo 10 caracteres') + .trim(), + + priority: z.enum(TICKET_PRIORITIES).default('medium'), + + categoryId: z.number().int().positive().optional(), + + // Em uma implementação real, o creatorId viria do token JWT. + // Por ora, aceita no body para facilitar o desenvolvimento iterativo. + creatorId: z + .number({ required_error: 'creatorId é obrigatório' }) + .int() + .positive(), +}); + +export type CreateTicketBody = z.infer<typeof createTicketBodySchema>; + +// ─── Listagem de Tickets (filtros + paginação) ──────────────────────────────── + +export const listTicketsQuerySchema = z.object({ + status: z.enum(TICKET_STATUSES).optional(), + priority: z.enum(TICKET_PRIORITIES).optional(), + assigneeId: z.coerce.number().int().positive().optional(), + creatorId: z.coerce.number().int().positive().optional(), + categoryId: z.coerce.number().int().positive().optional(), + + // Paginação + page: z.coerce.number().int().min(1).default(1), + limit: z.coerce.number().int().min(1).max(100).default(20), +}); + +export type ListTicketsQuery = z.infer<typeof listTicketsQuerySchema>; + +// ─── Parâmetros de rota ─────────────────────────────────────────────────────── + +export const ticketParamsSchema = z.object({ + id: z.coerce.number().int().positive(), +}); + +export type TicketParams = z.infer<typeof ticketParamsSchema>; + +// ─── Shape de resposta ──────────────────────────────────────────────────────── + +export const ticketResponseSchema = z.object({ + id: z.number(), + title: z.string(), + description: z.string(), + status: z.enum(TICKET_STATUSES), + priority: z.enum(TICKET_PRIORITIES), + creatorId: z.number(), + assigneeId: z.number().nullable(), + categoryId: z.number().nullable(), + dueAt: z.string().nullable(), + resolvedAt: z.string().nullable(), + createdAt: z.string(), + updatedAt: z.string(), +}); + +export const listTicketsResponseSchema = z.object({ + data: z.array(ticketResponseSchema), + meta: z.object({ + page: z.number(), + limit: z.number(), + total: z.number(), + totalPages: z.number(), + }), +}); |