Add lessons Phase 6: lesson plans with curriculum tracking
Structured lesson plans with nested sections and items per enrollment. Deep create in one request, one-active-per-enrollment constraint, auto-set startedDate/masteredDate on status transitions, progress % calculation (skipped items excluded). 8 new tests (84 total).
This commit is contained in:
@@ -118,6 +118,10 @@ export {
|
||||
LessonSessionUpdateSchema,
|
||||
GradingScaleCreateSchema,
|
||||
GradingScaleUpdateSchema,
|
||||
LessonPlanItemStatus,
|
||||
LessonPlanCreateSchema,
|
||||
LessonPlanUpdateSchema,
|
||||
LessonPlanItemUpdateSchema,
|
||||
} from './lessons.schema.js'
|
||||
export type {
|
||||
InstructorCreateInput,
|
||||
@@ -134,4 +138,7 @@ export type {
|
||||
LessonSessionUpdateInput,
|
||||
GradingScaleCreateInput,
|
||||
GradingScaleUpdateInput,
|
||||
LessonPlanCreateInput,
|
||||
LessonPlanUpdateInput,
|
||||
LessonPlanItemUpdateInput,
|
||||
} from './lessons.schema.js'
|
||||
|
||||
@@ -131,3 +131,52 @@ export const GradingScaleUpdateSchema = z.object({
|
||||
isDefault: z.boolean().optional(),
|
||||
})
|
||||
export type GradingScaleUpdateInput = z.infer<typeof GradingScaleUpdateSchema>
|
||||
|
||||
// --- Lesson Plan schemas ---
|
||||
|
||||
export const LessonPlanItemStatus = z.enum(['not_started', 'in_progress', 'mastered', 'skipped'])
|
||||
export type LessonPlanItemStatus = z.infer<typeof LessonPlanItemStatus>
|
||||
|
||||
const LessonPlanItemInput = z.object({
|
||||
title: z.string().min(1).max(255),
|
||||
description: opt(z.string()),
|
||||
gradingScaleId: opt(z.string().uuid()),
|
||||
targetGradeValue: opt(z.string().max(50)),
|
||||
sortOrder: z.coerce.number().int(),
|
||||
})
|
||||
|
||||
const LessonPlanSectionInput = z.object({
|
||||
title: z.string().min(1).max(255),
|
||||
description: opt(z.string()),
|
||||
sortOrder: z.coerce.number().int(),
|
||||
items: z.array(LessonPlanItemInput).default([]),
|
||||
})
|
||||
|
||||
export const LessonPlanCreateSchema = z.object({
|
||||
memberId: z.string().uuid(),
|
||||
enrollmentId: z.string().uuid(),
|
||||
title: z.string().min(1).max(255),
|
||||
description: opt(z.string()),
|
||||
startedDate: opt(z.string()),
|
||||
sections: z.array(LessonPlanSectionInput).default([]),
|
||||
})
|
||||
export type LessonPlanCreateInput = z.infer<typeof LessonPlanCreateSchema>
|
||||
|
||||
export const LessonPlanUpdateSchema = z.object({
|
||||
title: z.string().min(1).max(255).optional(),
|
||||
description: opt(z.string()),
|
||||
isActive: z.boolean().optional(),
|
||||
})
|
||||
export type LessonPlanUpdateInput = z.infer<typeof LessonPlanUpdateSchema>
|
||||
|
||||
export const LessonPlanItemUpdateSchema = z.object({
|
||||
title: z.string().min(1).max(255).optional(),
|
||||
description: opt(z.string()),
|
||||
status: LessonPlanItemStatus.optional(),
|
||||
gradingScaleId: opt(z.string().uuid()),
|
||||
currentGradeValue: opt(z.string().max(50)),
|
||||
targetGradeValue: opt(z.string().max(50)),
|
||||
notes: opt(z.string()),
|
||||
sortOrder: z.coerce.number().int().optional(),
|
||||
})
|
||||
export type LessonPlanItemUpdateInput = z.infer<typeof LessonPlanItemUpdateSchema>
|
||||
|
||||
Reference in New Issue
Block a user