use crate::v1::mentors::MentorSchema; use crate::v1::sessions::sessions_schema::Thing; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; use validator::Validate; #[derive(Clone, Debug, Serialize, Deserialize, ToSchema)] pub struct MentorListResponseDto { pub id: String, pub fullname: Option, pub email: Option, pub status: String, pub created_at: String, pub updated_at: String, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct MentorDetailWithUserDto { pub id: String, pub user_id: String, // Personal data is now in UsersSchema, access via user_id // Removed: fullname, email, legal_name, identity_document_url, // phone_for_verification, bio, linkedin_url, github_url, cv_url pub industries: Vec, pub expertise: Vec, pub languages: Vec, pub current_company: String, pub current_role: String, pub years_of_experience: i32, pub topics_of_interest: Vec, pub preferred_mentee_level: Vec, pub preferred_mentoring_formats: Vec, pub availability_commitment: String, pub mentoring_rate: f64, pub status: String, pub is_deleted: bool, pub created_at: String, pub updated_at: String, } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema)] pub struct MentorDetailResponseDto { pub id: String, pub user_id: String, // Personal data fields from UsersSchema pub fullname: Option, pub email: Option, pub legal_name: Option, pub gender: Option, pub domicile: Option, pub phone_for_verification: Option, pub bio: Option, pub last_education: Option, pub linkedin_url: Option, pub github_url: Option, pub cv_url: Option, pub portfolio_url: Option, // Professional data from MentorSchema pub industries: Vec, pub expertise: Vec, pub languages: Vec, pub current_company: String, pub current_role: String, pub years_of_experience: i32, pub topics_of_interest: Vec, pub preferred_mentee_level: Vec, pub preferred_mentoring_formats: Vec, pub availability_commitment: String, pub mentoring_rate: f64, pub status: String, pub created_at: String, pub updated_at: String, } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)] pub struct MentorRegisterResponseDto { pub id: String, pub user_id: String, pub email: Option, pub status: String, pub created_at: String, pub updated_at: String, } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)] pub struct MentorUpdateRequestDto { #[validate(length( min = 3, message = "Legal name must be at least 3 characters" ))] #[serde(skip_serializing_if = "Option::is_none")] pub legal_name: Option, #[serde(skip_serializing_if = "Option::is_none")] pub gender: Option, #[serde(skip_serializing_if = "Option::is_none")] pub domicile: Option, #[validate(length( min = 10, max = 15, message = "Phone must be 10-15 characters" ))] #[serde(skip_serializing_if = "Option::is_none")] pub phone_for_verification: Option, #[validate(length(min = 50, message = "Bio must be at least 50 characters"))] #[serde(skip_serializing_if = "Option::is_none")] pub bio: Option, #[serde(skip_serializing_if = "Option::is_none")] pub last_education: Option, #[validate(url(message = "Invalid LinkedIn URL"))] #[serde(skip_serializing_if = "Option::is_none")] pub linkedin_url: Option, #[validate(url(message = "Invalid GitHub URL"))] #[serde(skip_serializing_if = "Option::is_none")] pub github_url: Option, #[validate(url(message = "Invalid CV URL"))] #[serde(skip_serializing_if = "Option::is_none")] pub cv_url: Option, #[validate(url(message = "Invalid portfolio URL"))] #[serde(skip_serializing_if = "Option::is_none")] pub portfolio_url: Option, #[validate(length(min = 1, message = "At least 1 industry required"))] #[serde(skip_serializing_if = "Option::is_none")] pub industries: Option>, #[validate(length(min = 1, message = "At least 1 expertise required"))] #[serde(skip_serializing_if = "Option::is_none")] pub expertise: Option>, #[validate(length(min = 1, message = "At least 1 language required"))] #[serde(skip_serializing_if = "Option::is_none")] pub languages: Option>, #[validate(length(min = 1, message = "Current company required"))] #[serde(skip_serializing_if = "Option::is_none")] pub current_company: Option, #[validate(length(min = 1, message = "Current role required"))] #[serde(skip_serializing_if = "Option::is_none")] pub current_role: Option, #[validate(range(min = 2, message = "At least 2 years of experience required"))] #[serde(skip_serializing_if = "Option::is_none")] pub years_of_experience: Option, #[validate(length(min = 1, message = "At least 1 topic required"))] #[serde(skip_serializing_if = "Option::is_none")] pub topics_of_interest: Option>, #[validate(length(min = 1, message = "At least 1 mentee level required"))] #[serde(skip_serializing_if = "Option::is_none")] pub preferred_mentee_level: Option>, #[validate(length(min = 1, message = "At least 1 mentoring format required"))] #[serde(skip_serializing_if = "Option::is_none")] pub preferred_mentoring_formats: Option>, #[validate(length( min = 5, message = "Availability commitment must be at least 5 characters" ))] #[serde(skip_serializing_if = "Option::is_none")] pub availability_commitment: Option, #[validate(range(min = 1, message = "Amount must be at least 1"))] #[serde(skip_serializing_if = "Option::is_none")] pub mentoring_rate_amount: Option, } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)] pub struct MentorUserRegisterRequestDto { #[validate( length(min = 1, message = "Email cannot be empty"), email(message = "Email not valid") )] pub email: String, #[validate(length( min = 8, message = "Password must have at least 8 characters" ))] #[validate(custom( function = "imphnen_iam::v1::auth::auth_dto::validate_password_complexity", message = "Password must include uppercase, lowercase, number, and special character" ))] pub password: String, #[validate(length(min = 2, message = "Fullname at least have 2 character"))] pub fullname: String, #[serde(skip_serializing_if = "Option::is_none")] pub phone_number: Option, #[validate(nested)] pub identity_and_verification: IdentityAndVerification, #[validate(nested)] pub professional_profile: ProfessionalProfile, #[validate(nested)] pub mentoring_logistics: MentoringLogistics, } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)] pub struct MentorRegisterFromTokenRequestDto { #[validate(nested)] pub identity_and_verification: IdentityAndVerification, #[validate(nested)] pub professional_profile: ProfessionalProfile, #[validate(nested)] pub mentoring_logistics: MentoringLogistics, } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)] pub struct IdentityAndVerification { #[validate(length( min = 3, message = "Legal name must be at least 3 characters" ))] pub legal_name: String, #[serde(skip_serializing_if = "Option::is_none")] pub gender: Option, #[serde(skip_serializing_if = "Option::is_none")] pub domicile: Option, #[validate(url(message = "Invalid identity document URL"))] pub identity_document_url: String, #[validate(length( min = 10, max = 15, message = "Phone must be 10-15 characters" ))] #[serde(skip_serializing_if = "Option::is_none")] pub phone_for_verification: Option, } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)] pub struct ProfessionalProfile { #[validate(length(min = 50, message = "Bio must be at least 50 characters"))] pub bio: String, #[serde(skip_serializing_if = "Option::is_none")] pub last_education: Option, #[validate(url(message = "Invalid LinkedIn URL"))] #[serde(skip_serializing_if = "Option::is_none")] pub linkedin_url: Option, #[validate(url(message = "Invalid GitHub URL"))] #[serde(skip_serializing_if = "Option::is_none")] pub github_url: Option, #[validate(url(message = "Invalid CV URL"))] #[serde(skip_serializing_if = "Option::is_none")] pub cv_url: Option, #[serde(skip_serializing_if = "Option::is_none")] pub portfolio_url: Option, #[validate(length(min = 1, message = "At least 1 industry required"))] pub industries: Vec, #[validate(length(min = 1, message = "At least 1 expertise required"))] pub expertise: Vec, #[validate(length(min = 1, message = "At least 1 language required"))] pub languages: Vec, #[validate(length(min = 1, message = "Current company required"))] pub current_company: String, #[validate(length(min = 1, message = "Current role required"))] pub current_role: String, #[validate(range(min = 2, message = "At least 2 years of experience required"))] pub years_of_experience: i32, } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)] pub struct MentoringLogistics { #[validate(length(min = 1, message = "At least 1 topic required"))] pub topics_of_interest: Vec, #[validate(length(min = 1, message = "At least 1 mentee level required"))] pub preferred_mentee_level: Vec, #[validate(length(min = 1, message = "At least 1 mentoring format required"))] pub preferred_mentoring_formats: Vec, #[validate(length( min = 5, message = "Availability commitment must be at least 5 characters" ))] pub availability_commitment: String, #[validate(range(min = 1, message = "Amount must be at least 1"))] pub mentoring_rate_amount: u64, } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate, Default)] pub struct MentoringRate { #[validate(range(min = 1, message = "Amount must be at least 1"))] pub amount: u64, #[validate(length(min = 1, message = "Currency is required"))] pub currency: String, #[validate(length(min = 1, message = "Per duration is required"))] pub per_duration: String, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct MentorInsertDto { pub id: Thing, pub user_id: Option, // Personal data removed - now stored in UsersSchema pub industries: Vec, pub expertise: Vec, pub languages: Vec, pub current_company: String, pub current_role: String, pub years_of_experience: i32, pub topics_of_interest: Vec, pub preferred_mentee_level: Vec, pub preferred_mentoring_formats: Vec, pub availability_commitment: String, pub mentoring_rate: f64, pub status: String, pub is_deleted: bool, pub created_at: String, pub updated_at: String, } impl From for MentorInsertDto { fn from(schema: MentorSchema) -> Self { MentorInsertDto { id: schema.id, user_id: schema.user_id, // Personal data removed from MentorSchema industries: schema.industries, expertise: schema.expertise, languages: schema.languages, current_company: schema.current_company, current_role: schema.current_role, years_of_experience: schema.years_of_experience, topics_of_interest: schema.topics_of_interest, preferred_mentee_level: schema.preferred_mentee_level, preferred_mentoring_formats: schema.preferred_mentoring_formats, availability_commitment: schema.availability_commitment, mentoring_rate: schema.mentoring_rate, status: schema.status, is_deleted: schema.is_deleted, created_at: schema.created_at, updated_at: schema.updated_at, } } } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)] pub struct MentorVerifyRequestDto { #[validate(length(min = 1, message = "Status is required"))] pub status: String, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct MentorDetailQueryDto { pub id: Thing, pub user_id: Thing, // Personal data has been moved to UsersSchema // Use user_id to get: fullname, email, legal_name, gender, domicile, // identity_document_url, phone_for_verification, bio, last_education, // linkedin_url, github_url, cv_url, portfolio_url pub industries: Vec, pub expertise: Vec, pub languages: Vec, pub current_company: String, pub current_role: String, pub years_of_experience: i32, pub topics_of_interest: Vec, pub preferred_mentee_level: Vec, pub preferred_mentoring_formats: Vec, pub availability_commitment: String, pub mentoring_rate: f64, pub status: String, pub is_deleted: bool, pub created_at: String, pub updated_at: String, } impl From for MentorListResponseDto { fn from(dto: MentorDetailQueryDto) -> Self { Self { id: dto.id.clone(), fullname: None, // now in user table, must be populated from service layer email: None, // now in user table, must be populated from service layer status: dto.status, created_at: dto.created_at, updated_at: dto.updated_at, } } } impl From for MentorDetailResponseDto { fn from(dto: MentorDetailQueryDto) -> Self { Self { id: dto.id.clone(), user_id: dto.user_id.clone(), // Personal data fields are populated in service layer from UsersSchema fullname: None, // populated from user table in service layer email: None, // populated from user table in service layer legal_name: None, // populated from user table in service layer gender: None, // populated from user table in service layer domicile: None, // populated from user table in service layer phone_for_verification: None, // populated from user table in service layer bio: None, // populated from user table in service layer last_education: None, // populated from user table in service layer linkedin_url: None, // populated from user table in service layer github_url: None, // populated from user table in service layer cv_url: None, // populated from user table in service layer portfolio_url: None, // populated from user table in service layer // Professional data from mentor industries: dto.industries, expertise: dto.expertise, languages: dto.languages, current_company: dto.current_company, current_role: dto.current_role, years_of_experience: dto.years_of_experience, topics_of_interest: dto.topics_of_interest, preferred_mentee_level: dto.preferred_mentee_level, preferred_mentoring_formats: dto.preferred_mentoring_formats, availability_commitment: dto.availability_commitment, mentoring_rate: dto.mentoring_rate, status: dto.status, created_at: dto.created_at, updated_at: dto.updated_at, } } } impl From for MentorRegisterResponseDto { fn from(schema: MentorSchema) -> Self { Self { id: schema.id.to_string(), user_id: schema.user_id.unwrap_or_default(), email: None, // schema.email - now in user table status: schema.status, created_at: schema.created_at, updated_at: schema.updated_at, } } } impl From for MentorDetailQueryDto { fn from(dto: MentorDetailWithUserDto) -> Self { MentorDetailQueryDto { id: dto.id, user_id: dto.user_id, // Personal data removed from MentorDetailWithUserDto - now in UsersSchema industries: dto.industries, expertise: dto.expertise, languages: dto.languages, current_company: dto.current_company, current_role: dto.current_role, years_of_experience: dto.years_of_experience, topics_of_interest: dto.topics_of_interest, preferred_mentee_level: dto.preferred_mentee_level, preferred_mentoring_formats: dto.preferred_mentoring_formats, availability_commitment: dto.availability_commitment, mentoring_rate: dto.mentoring_rate, status: dto.status, is_deleted: dto.is_deleted, created_at: dto.created_at, updated_at: dto.updated_at, } } }