import Joi from 'joi'; // Multi-language validation schema const multiLangSchema = Joi.object({ th: Joi.string().required().messages({ 'any.required': 'Thai text is required' }), en: Joi.string().required().messages({ 'any.required': 'English text is required' }) }).required(); const multiLangOptionalSchema = Joi.object({ th: Joi.string().optional(), en: Joi.string().optional() }).optional(); // ============================================ // Chapter Validators // ============================================ /** * Validator for creating a chapter */ export const CreateChapterValidator = Joi.object({ title: multiLangSchema.messages({ 'any.required': 'Title is required' }), description: multiLangOptionalSchema, sort_order: Joi.number().integer().min(0).optional() }); /** * Validator for updating a chapter */ export const UpdateChapterValidator = Joi.object({ title: multiLangOptionalSchema, description: multiLangOptionalSchema, sort_order: Joi.number().integer().min(0).optional(), is_published: Joi.boolean().optional() }); /** * Validator for reordering a chapter */ export const ReorderChapterValidator = Joi.object({ sort_order: Joi.number().integer().min(0).required().messages({ 'any.required': 'Sort order is required', 'number.min': 'Sort order must be at least 0' }) }); // ============================================ // Lesson Validators // ============================================ /** * Validator for creating a lesson */ export const CreateLessonValidator = Joi.object({ title: multiLangSchema.messages({ 'any.required': 'Title is required' }), content: multiLangOptionalSchema, type: Joi.string().valid('VIDEO', 'QUIZ').required().messages({ 'any.only': 'Type must be either VIDEO or QUIZ', 'any.required': 'Type is required' }), sort_order: Joi.number().integer().min(0).optional() }); /** * Validator for updating a lesson */ export const UpdateLessonValidator = Joi.object({ title: multiLangOptionalSchema, content: multiLangOptionalSchema, duration_minutes: Joi.number().min(0).optional().messages({ 'number.min': 'Duration must be at least 0' }), sort_order: Joi.number().integer().min(0).optional(), prerequisite_lesson_ids: Joi.array().items(Joi.number().integer().positive()).optional(), is_published: Joi.boolean().optional() }); /** * Validator for reordering lessons */ export const ReorderLessonsValidator = Joi.object({ lesson_id: Joi.number().integer().positive().required().messages({ 'any.required': 'Lesson ID is required' }), sort_order: Joi.number().integer().min(0).required().messages({ 'any.required': 'Sort order is required' }) }); // ============================================ // Quiz Question Validators // ============================================ /** * Validator for quiz choice */ const QuizChoiceValidator = Joi.object({ text: multiLangSchema.messages({ 'any.required': 'Choice text is required' }), is_correct: Joi.boolean().required().messages({ 'any.required': 'is_correct is required' }), sort_order: Joi.number().integer().min(0).optional() }); /** * Validator for adding a question to a quiz */ export const AddQuestionValidator = Joi.object({ question: multiLangSchema.messages({ 'any.required': 'Question is required' }), explanation: multiLangOptionalSchema, question_type: Joi.string() .valid('MULTIPLE_CHOICE', 'TRUE_FALSE', 'SHORT_ANSWER') .required() .messages({ 'any.only': 'Question type must be MULTIPLE_CHOICE, TRUE_FALSE, or SHORT_ANSWER', 'any.required': 'Question type is required' }), sort_order: Joi.number().integer().min(0).optional(), choices: Joi.array().items(QuizChoiceValidator).min(1).optional().messages({ 'array.min': 'At least one choice is required for multiple choice questions' }) }); /** * Validator for updating a question */ export const UpdateQuestionValidator = Joi.object({ question: multiLangOptionalSchema, explanation: multiLangOptionalSchema, question_type: Joi.string() .valid('MULTIPLE_CHOICE', 'TRUE_FALSE', 'SHORT_ANSWER') .optional() .messages({ 'any.only': 'Question type must be MULTIPLE_CHOICE, TRUE_FALSE, or SHORT_ANSWER' }), sort_order: Joi.number().integer().min(0).optional(), choices: Joi.array().items(QuizChoiceValidator).min(1).optional().messages({ 'array.min': 'At least one choice is required' }) }); /** * Validator for reordering a question */ export const ReorderQuestionValidator = Joi.object({ sort_order: Joi.number().integer().min(0).required().messages({ 'any.required': 'Sort order is required', 'number.min': 'Sort order must be at least 0' }) }); // ============================================ // Quiz Settings Validator // ============================================ /** * Validator for updating quiz settings */ export const UpdateQuizValidator = Joi.object({ title: multiLangOptionalSchema, description: multiLangOptionalSchema, passing_score: Joi.number().min(0).max(100).optional().messages({ 'number.min': 'Passing score must be at least 0', 'number.max': 'Passing score must not exceed 100' }), time_limit: Joi.number().min(0).optional().messages({ 'number.min': 'Time limit must be at least 0' }), shuffle_questions: Joi.boolean().optional(), shuffle_choices: Joi.boolean().optional(), show_answers_after_completion: Joi.boolean().optional(), is_skippable: Joi.boolean().optional(), allow_multiple_attempts: Joi.boolean().optional() });