Add lessons Phase 4: lesson sessions with hybrid calendar generation

Individual lesson occurrences generated from schedule slot patterns.
Idempotent session generation with configurable rolling window.
Post-lesson notes workflow with auto-set notesCompletedAt. Status
tracking (scheduled/attended/missed/makeup/cancelled) and date/time
filtering. 13 new tests (64 total lessons tests).
This commit is contained in:
Ryan Moon
2026-03-30 09:29:03 -05:00
parent 93405af3b2
commit 73360cd478
8 changed files with 587 additions and 3 deletions

View File

@@ -81,3 +81,28 @@ export const EnrollmentStatusUpdateSchema = z.object({
status: EnrollmentStatus,
})
export type EnrollmentStatusUpdateInput = z.infer<typeof EnrollmentStatusUpdateSchema>
// --- Lesson Session schemas ---
export const LessonSessionStatus = z.enum(['scheduled', 'attended', 'missed', 'makeup', 'cancelled'])
export type LessonSessionStatus = z.infer<typeof LessonSessionStatus>
export const LessonSessionStatusUpdateSchema = z.object({
status: LessonSessionStatus,
})
export type LessonSessionStatusUpdateInput = z.infer<typeof LessonSessionStatusUpdateSchema>
export const LessonSessionNotesSchema = z.object({
instructorNotes: opt(z.string()),
memberNotes: opt(z.string()),
homeworkAssigned: opt(z.string()),
nextLessonGoals: opt(z.string()),
topicsCovered: z.array(z.string()).optional(),
})
export type LessonSessionNotesInput = z.infer<typeof LessonSessionNotesSchema>
export const LessonSessionUpdateSchema = z.object({
actualStartTime: opt(z.string().regex(/^\d{2}:\d{2}$/, 'Must be HH:MM format')),
actualEndTime: opt(z.string().regex(/^\d{2}:\d{2}$/, 'Must be HH:MM format')),
})
export type LessonSessionUpdateInput = z.infer<typeof LessonSessionUpdateSchema>