import { z } from "zod"; // Shared between apps/api (server-side validation, source of truth) and // apps/web (client-side validation for instant feedback on the contact // form). Same rationale as schemas/auth.ts — one set of rules, French // messages surfaced as-is in the form. /** * The kind of a contact-form message. A plain `String` in Postgres backed by * this const (see `ContactMessage.type` in schema.prisma) rather than a * Postgres enum — adding a value is one line here, no migration. `type` * structures the admin-side triage; the user picks it from a small select. */ export const CONTACT_MESSAGE_TYPES = ["bug", "suggestion", "other"] as const; export type ContactMessageType = (typeof CONTACT_MESSAGE_TYPES)[number]; /** * Payload accepted by `POST /contact` (issue #80). `message` is the only * thing the user actually types; `pageUrl` / `appVersion` are captured * automatically by the client (`window.location.pathname`, `__APP_VERSION__`) * and are optional so a direct API call or an older client can omit them. * `userAgent` is NOT here — the server reads it from the request header, * never trusting the client for it. */ export const submitContactMessageSchema = z.object({ type: z.enum(CONTACT_MESSAGE_TYPES), message: z .string() .trim() .min(10, "Le message doit faire au moins 10 caractères") .max(5000, "Le message ne peut pas dépasser 5000 caractères"), pageUrl: z.string().max(500).optional(), appVersion: z.string().max(50).optional(), }); export type SubmitContactMessageInput = z.infer;