changemaker.lite/api/src/modules/calendar/calendar.schemas.ts
bunker-admin 08d8066157 Add ticketed events, Jitsi meeting integration, social features, and calendar system
- Ticketed events: full CRUD, ticket tiers (free/paid/donation), Stripe checkout,
  QR-based check-in scanner, public event pages, ticket confirmation emails
- Event formats: IN_PERSON/ONLINE/HYBRID with auto Jitsi meeting room lifecycle,
  ticket-gated meeting access, moderator JWT tokens, feature-flag guarded
- Social engagement: challenges with scoring/leaderboards, referral tracking,
  volunteer spotlight, impact stories, campaign celebrations, wall of fame
- Social calendar: personal calendar layers, shared calendar items with
  recurrence, scheduling polls, mobile day view
- MCP server: events tool pack with full admin CRUD + meeting token generation
- Unified calendar: eventFormat-aware tags, online event indicators
- Updated docs site, pangolin configs, and various admin UI improvements

Bunker Admin
2026-03-06 14:33:33 -07:00

81 lines
3.5 KiB
TypeScript

import { z } from 'zod';
// --- Layer schemas ---
export const createLayerSchema = z.object({
name: z.string().min(1).max(100),
color: z.string().regex(/^#[0-9a-fA-F]{6}$/, 'Color must be a hex color (#RRGGBB)'),
visibility: z.enum(['PRIVATE', 'FRIENDS', 'PUBLIC']),
});
export const updateLayerSchema = z.object({
name: z.string().min(1).max(100).optional(),
color: z.string().regex(/^#[0-9a-fA-F]{6}$/, 'Color must be a hex color (#RRGGBB)').optional(),
visibility: z.enum(['PRIVATE', 'FRIENDS', 'PUBLIC']).optional(),
isEnabled: z.boolean().optional(),
sortOrder: z.number().int().min(0).optional(),
});
// --- Item schemas ---
const recurrenceRuleSchema = z.object({
frequency: z.enum(['DAILY', 'WEEKLY', 'BIWEEKLY', 'MONTHLY']),
daysOfWeek: z.array(z.number().int().min(1).max(7)).optional(), // 1=Mon...7=Sun
dayOfMonth: z.number().int().min(1).max(31).optional(),
interval: z.number().int().min(1).max(12).optional(),
});
export const createItemSchema = z.object({
layerId: z.string().min(1),
title: z.string().min(1).max(200),
description: z.string().optional(),
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'),
isAllDay: z.boolean().optional(),
itemType: z.enum(['EVENT', 'TIME_BLOCK', 'REMINDER']),
location: z.string().optional(),
color: z.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
visibility: z.enum(['PRIVATE', 'FRIENDS', 'PUBLIC']).optional(),
busyStatus: z.enum(['BUSY', 'TENTATIVE', 'FREE']).optional(),
showDetailsTo: z.enum(['NOBODY', 'FRIENDS', 'EVERYONE']).optional(),
recurrenceRule: recurrenceRuleSchema.optional(),
recurrenceEnd: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Recurrence end must be YYYY-MM-DD').optional(),
});
export const updateItemSchema = z.object({
title: z.string().min(1).max(200).optional(),
description: z.string().nullable().optional(),
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(),
isAllDay: z.boolean().optional(),
itemType: z.enum(['EVENT', 'TIME_BLOCK', 'REMINDER']).optional(),
location: z.string().nullable().optional(),
color: z.string().regex(/^#[0-9a-fA-F]{6}$/).nullable().optional(),
visibility: z.enum(['PRIVATE', 'FRIENDS', 'PUBLIC']).nullable().optional(),
busyStatus: z.enum(['BUSY', 'TENTATIVE', 'FREE']).optional(),
showDetailsTo: z.enum(['NOBODY', 'FRIENDS', 'EVERYONE']).optional(),
recurrenceRule: recurrenceRuleSchema.nullable().optional(),
recurrenceEnd: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional(),
});
// --- Scope for recurring item edits ---
export const seriesEditScopeSchema = z.enum(['THIS_ONLY', 'THIS_AND_FUTURE', 'ALL']);
// --- Date range query ---
export const dateRangeSchema = z.object({
startDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'startDate must be YYYY-MM-DD'),
endDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'endDate must be YYYY-MM-DD'),
});
// --- Exported types ---
export type CreateLayerInput = z.infer<typeof createLayerSchema>;
export type UpdateLayerInput = z.infer<typeof updateLayerSchema>;
export type CreateItemInput = z.infer<typeof createItemSchema>;
export type UpdateItemInput = z.infer<typeof updateItemSchema>;
export type SeriesEditScope = z.infer<typeof seriesEditScopeSchema>;