import { z } from 'zod'; import { VisitOutcome, SupportLevel } from '@prisma/client'; export const recordVisitSchema = z.object({ addressId: z.string().min(1), // Changed from locationId outcome: z.nativeEnum(VisitOutcome), supportLevel: z.nativeEnum(SupportLevel).optional(), signRequested: z.boolean().optional().default(false), signSize: z.string().optional(), notes: z.string().optional(), durationSeconds: z.number().int().optional(), sessionId: z.string().optional(), shiftId: z.string().optional(), updateLocation: z.boolean().optional().default(true), }); export const bulkRecordVisitSchema = z.object({ locationId: z.string().min(1), // Building ID outcome: z.enum(['NOT_HOME', 'REFUSED', 'MOVED']), // Only non-contact outcomes notes: z.string().optional(), sessionId: z.string().optional(), shiftId: z.string().optional(), }); export const startSessionSchema = z.object({ cutId: z.string().min(1), shiftId: z.string().optional(), startLatitude: z.number().optional(), startLongitude: z.number().optional(), }); export const endSessionSchema = z.object({ // no body required — session id from URL }); export const walkingRouteSchema = z.object({ excludeVisited: z.coerce.boolean().optional().default(false), startLatitude: z.coerce.number().optional(), startLongitude: z.coerce.number().optional(), }); export const listMyVisitsSchema = z.object({ page: z.coerce.number().int().positive().default(1), limit: z.coerce.number().int().positive().max(100).default(20), }); export const adminActivitySchema = z.object({ page: z.coerce.number().int().positive().default(1), limit: z.coerce.number().int().positive().max(100).default(20), cutId: z.string().optional(), userId: z.string().optional(), outcome: z.nativeEnum(VisitOutcome).optional(), }); export const adminVisitsSchema = z.object({ page: z.coerce.number().int().positive().default(1), limit: z.coerce.number().int().positive().max(100).default(50), cutId: z.string().optional(), userId: z.string().optional(), shiftId: z.string().optional(), outcome: z.nativeEnum(VisitOutcome).optional(), sortBy: z.enum(['visitedAt', 'outcome']).optional().default('visitedAt'), sortOrder: z.enum(['asc', 'desc']).optional().default('desc'), }); export const volunteerUpdateLocationSchema = z.object({ supportLevel: z.nativeEnum(SupportLevel).nullable().optional(), sign: z.boolean().optional(), signSize: z.string().nullable().optional(), notes: z.string().nullable().optional(), // Admin-only fields (stripped by service for non-admins) firstName: z.string().nullable().optional(), lastName: z.string().nullable().optional(), address: z.string().nullable().optional(), unitNumber: z.string().nullable().optional(), email: z.string().email().nullable().optional().or(z.literal('')), phone: z.string().nullable().optional(), }); export const volunteerCreateLocationSchema = z.object({ address: z.string().min(1, 'Address is required'), latitude: z.number().min(-90).max(90), longitude: z.number().min(-180).max(180), unitNumber: z.string().optional(), // USER+ fields (stripped by route for TEMPs) supportLevel: z.nativeEnum(SupportLevel).optional(), sign: z.boolean().optional().default(false), signSize: z.string().optional(), notes: z.string().optional(), // Admin-only fields firstName: z.string().optional(), lastName: z.string().optional(), email: z.string().email().optional().or(z.literal('')), phone: z.string().optional(), }); export type RecordVisitInput = z.infer; export type BulkRecordVisitInput = z.infer; export type StartSessionInput = z.infer; export type WalkingRouteInput = z.infer; export type ListMyVisitsInput = z.infer; export type AdminActivityInput = z.infer; export type AdminVisitsInput = z.infer; export const outcomeTrendsQuerySchema = z.object({ granularity: z.enum(['day', 'week']).default('day'), dateFrom: z.string().optional(), dateTo: z.string().optional(), }); export type VolunteerUpdateLocationInput = z.infer; export type VolunteerCreateLocationInput = z.infer; export type OutcomeTrendsQueryInput = z.infer;