feat: certification rules, content sanitization, handle draft course updates and reset content, better redis logging

This commit is contained in:
Rotimi Best
2026-03-30 08:24:55 +01:00
parent ff2ad59377
commit 5a8f50f67b
131 changed files with 5643 additions and 2134 deletions
+13 -2
View File
@@ -279,6 +279,18 @@ export const ZCourseLandingPageMetadataUpdate = z.object({
});
export type TCourseLandingPageMetadataUpdate = z.infer<typeof ZCourseLandingPageMetadataUpdate>;
export const ZCertificationSettings = z.object({
isDownloadable: z.boolean().optional(),
theme: z.string().optional(),
/** ISO 8601 datetime string or null to clear */
deadline: z.union([z.string().min(1), z.null()]).optional(),
threshold: z.number().int().min(0).max(100).optional(),
requiredExerciseId: z.union([z.string().uuid(), z.null()]).optional(),
exerciseMinScorePercent: z.number().int().min(0).max(100).nullable().optional(),
emailMessage: z.string().max(5000).nullable().optional()
});
export type TCertificationSettings = z.infer<typeof ZCertificationSettings>;
export const ZCourseUpdate = z.object({
title: z.string().min(1).optional(),
description: z.string().min(1).optional(),
@@ -290,8 +302,7 @@ export const ZCourseUpdate = z.object({
metadata: ZCourseMetadata.optional(),
cost: z.number().int().min(0).optional(),
currency: z.enum(['NGN', 'USD']).optional(),
isCertificateDownloadable: z.boolean().optional(),
certificateTheme: z.string().optional(),
certificate: ZCertificationSettings.optional(),
tagIds: z.array(z.uuid()).max(100).optional()
});
export type TCourseUpdate = z.infer<typeof ZCourseUpdate>;