113 lines
4.3 KiB
TypeScript
113 lines
4.3 KiB
TypeScript
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<typeof recordVisitSchema>;
|
|
export type BulkRecordVisitInput = z.infer<typeof bulkRecordVisitSchema>;
|
|
export type StartSessionInput = z.infer<typeof startSessionSchema>;
|
|
export type WalkingRouteInput = z.infer<typeof walkingRouteSchema>;
|
|
export type ListMyVisitsInput = z.infer<typeof listMyVisitsSchema>;
|
|
export type AdminActivityInput = z.infer<typeof adminActivitySchema>;
|
|
export type AdminVisitsInput = z.infer<typeof adminVisitsSchema>;
|
|
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<typeof volunteerUpdateLocationSchema>;
|
|
export type VolunteerCreateLocationInput = z.infer<typeof volunteerCreateLocationSchema>;
|
|
export type OutcomeTrendsQueryInput = z.infer<typeof outcomeTrendsQuerySchema>;
|