128 lines
5.7 KiB
TypeScript
128 lines
5.7 KiB
TypeScript
import { z } from 'zod';
|
|
import { SchedulingPollStatus, PollVoteValue } from '@prisma/client';
|
|
|
|
export const createPollSchema = z.object({
|
|
title: z.string().min(1, 'Title is required').max(200),
|
|
description: z.string().max(2000).optional(),
|
|
location: z.string().max(500).optional(),
|
|
timezone: z.string().default('America/Edmonton'),
|
|
allowAnonymous: z.boolean().optional().default(true),
|
|
isPrivate: z.boolean().optional().default(false),
|
|
notifyOnVote: z.boolean().optional().default(true),
|
|
votingDeadline: z.string().datetime().optional(),
|
|
autoFinalize: z.boolean().optional().default(false),
|
|
autoFinalizeThreshold: z.number().int().min(1).max(100).nullable().optional(),
|
|
autoConvertToCalendar: z.boolean().optional().default(false),
|
|
autoConvertToGancio: z.boolean().optional().default(false),
|
|
autoConvertToShift: z.boolean().optional().default(false),
|
|
tieBreaker: z.enum(['earliest', 'organizer_choice']).optional().default('earliest'),
|
|
autoEnrollVoters: z.boolean().optional().default(true),
|
|
options: z.array(z.object({
|
|
date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be YYYY-MM-DD'),
|
|
startTime: z.string().regex(/^\d{2}:\d{2}$/, 'Start time must be HH:MM'),
|
|
endTime: z.string().regex(/^\d{2}:\d{2}$/, 'End time must be HH:MM'),
|
|
})).min(1, 'At least 1 option required').max(20, 'Maximum 20 options'),
|
|
});
|
|
|
|
export const updatePollSchema = z.object({
|
|
title: z.string().min(1).max(200).optional(),
|
|
description: z.string().max(2000).nullable().optional(),
|
|
location: z.string().max(500).nullable().optional(),
|
|
timezone: z.string().optional(),
|
|
allowAnonymous: z.boolean().optional(),
|
|
isPrivate: z.boolean().optional(),
|
|
notifyOnVote: z.boolean().optional(),
|
|
votingDeadline: z.string().datetime().nullable().optional(),
|
|
status: z.nativeEnum(SchedulingPollStatus).optional(),
|
|
autoFinalize: z.boolean().optional(),
|
|
autoFinalizeThreshold: z.number().int().min(1).max(100).nullable().optional(),
|
|
autoConvertToCalendar: z.boolean().optional(),
|
|
autoConvertToGancio: z.boolean().optional(),
|
|
autoConvertToShift: z.boolean().optional(),
|
|
tieBreaker: z.enum(['earliest', 'organizer_choice']).optional(),
|
|
autoEnrollVoters: z.boolean().optional(),
|
|
});
|
|
|
|
export const addOptionsSchema = z.object({
|
|
options: z.array(z.object({
|
|
date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be YYYY-MM-DD'),
|
|
startTime: z.string().regex(/^\d{2}:\d{2}$/, 'Start time must be HH:MM'),
|
|
endTime: z.string().regex(/^\d{2}:\d{2}$/, 'End time must be HH:MM'),
|
|
})).min(1).max(20),
|
|
});
|
|
|
|
export const participantNeedsInlineSchema = z.object({
|
|
needsWheelchair: z.boolean().optional(),
|
|
needsGroundFloor: z.boolean().optional(),
|
|
needsHearingLoop: z.boolean().optional(),
|
|
needsSignLanguage: z.boolean().optional(),
|
|
otherAccessibility: z.string().max(1000).nullable().optional(),
|
|
isVegan: z.boolean().optional(),
|
|
isVegetarian: z.boolean().optional(),
|
|
isGlutenFree: z.boolean().optional(),
|
|
isHalal: z.boolean().optional(),
|
|
isKosher: z.boolean().optional(),
|
|
hasNutAllergy: z.boolean().optional(),
|
|
otherDietary: z.string().max(1000).nullable().optional(),
|
|
needsChildcare: z.boolean().optional(),
|
|
childcareDetails: z.string().max(1000).nullable().optional(),
|
|
needsTransportation: z.boolean().optional(),
|
|
transportationNotes: z.string().max(1000).nullable().optional(),
|
|
preferredLanguage: z.string().max(10).nullable().optional(),
|
|
needsTranslation: z.boolean().optional(),
|
|
translationLanguage: z.string().max(100).nullable().optional(),
|
|
visibilityConsent: z.enum(['organizer_only', 'shared_with_hosts', 'public']).optional().default('organizer_only'),
|
|
}).optional();
|
|
|
|
export const submitVotesSchema = z.object({
|
|
voterName: z.string().min(1, 'Name is required').max(100),
|
|
voterEmail: z.preprocess(
|
|
(val) => (typeof val === 'string' && val.trim() === '' ? undefined : val),
|
|
z.string().email('Please enter a valid email address').max(200).optional(),
|
|
),
|
|
voterToken: z.string().optional(),
|
|
votes: z.array(z.object({
|
|
optionId: z.string().min(1),
|
|
value: z.nativeEnum(PollVoteValue),
|
|
})).min(1, 'At least one vote required'),
|
|
participantNeeds: participantNeedsInlineSchema,
|
|
});
|
|
|
|
export const submitCommentSchema = z.object({
|
|
authorName: z.string().min(1, 'Name is required').max(100),
|
|
content: z.string().min(1, 'Comment is required').max(2000),
|
|
});
|
|
|
|
export const finalizePollSchema = z.object({
|
|
optionId: z.string().min(1, 'Option ID is required'),
|
|
});
|
|
|
|
export const convertToShiftSchema = z.object({
|
|
maxVolunteers: z.number().int().min(1).default(10),
|
|
isPublic: z.boolean().optional().default(true),
|
|
cutId: z.string().optional(),
|
|
});
|
|
|
|
export const updateOptionSchema = z.object({
|
|
date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be YYYY-MM-DD').optional(),
|
|
startTime: z.string().regex(/^\d{2}:\d{2}$/, 'Start time must be HH:MM').optional(),
|
|
endTime: z.string().regex(/^\d{2}:\d{2}$/, 'End time must be HH:MM').optional(),
|
|
});
|
|
|
|
export const listPollsSchema = z.object({
|
|
page: z.coerce.number().int().positive().default(1),
|
|
limit: z.coerce.number().int().positive().max(100).default(20),
|
|
search: z.string().optional(),
|
|
status: z.nativeEnum(SchedulingPollStatus).optional(),
|
|
});
|
|
|
|
export type CreatePollInput = z.infer<typeof createPollSchema>;
|
|
export type UpdatePollInput = z.infer<typeof updatePollSchema>;
|
|
export type AddOptionsInput = z.infer<typeof addOptionsSchema>;
|
|
export type SubmitVotesInput = z.infer<typeof submitVotesSchema>;
|
|
export type SubmitCommentInput = z.infer<typeof submitCommentSchema>;
|
|
export type FinalizePollInput = z.infer<typeof finalizePollSchema>;
|
|
export type ConvertToShiftInput = z.infer<typeof convertToShiftSchema>;
|
|
export type UpdateOptionInput = z.infer<typeof updateOptionSchema>;
|
|
export type ListPollsInput = z.infer<typeof listPollsSchema>;
|