use imphnen_libs::ZodValidate; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; use zod_rs::prelude::*; // ============================================================ // Response DTOs // ============================================================ #[derive(Clone, Debug, Serialize, Deserialize, ToSchema)] pub struct MentorListResponseDto { pub id: String, pub user_id: String, pub fullname: Option, pub email: Option, pub status: String, pub created_at: String, pub updated_at: String, } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema)] pub struct MentorDetailResponseDto { pub id: String, pub user_id: String, 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, 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)] pub struct MentorRegisterResponseDto { pub id: String, pub user_id: String, pub email: Option, pub status: String, pub created_at: String, pub updated_at: String, } // ============================================================ // Request DTOs // ============================================================ #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, ZodSchema)] pub struct MentorUserRegisterRequestDto { #[zod(email, min_length(1))] pub email: String, #[zod(min_length(8), regex(pattern = "^[A-Za-z\\d@$!%*?&]{8,}$"))] pub password: String, #[zod(min_length(2))] pub fullname: String, #[serde(skip_serializing_if = "Option::is_none")] pub phone_number: Option, pub identity_and_verification: IdentityAndVerification, pub professional_profile: ProfessionalProfile, pub mentoring_logistics: MentoringLogistics, } impl ZodValidate for MentorUserRegisterRequestDto { fn zod_validate(value: &serde_json::Value) -> Result { Self::validate_and_parse(value).map_err(|e| e.to_string()) } } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, ZodSchema)] pub struct IdentityAndVerification { #[zod(min_length(3))] pub legal_name: String, #[serde(skip_serializing_if = "Option::is_none")] pub gender: Option, #[serde(skip_serializing_if = "Option::is_none")] pub domicile: Option, #[zod(url)] pub identity_document_url: String, #[zod(min_length(10), max_length(15))] #[serde(skip_serializing_if = "Option::is_none")] pub phone_for_verification: Option, } impl ZodValidate for IdentityAndVerification { fn zod_validate(value: &serde_json::Value) -> Result { Self::validate_and_parse(value).map_err(|e| e.to_string()) } } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, ZodSchema)] pub struct ProfessionalProfile { #[zod(min_length(50))] pub bio: String, #[serde(skip_serializing_if = "Option::is_none")] pub last_education: Option, #[zod(url)] #[serde(skip_serializing_if = "Option::is_none")] pub linkedin_url: Option, #[zod(url)] #[serde(skip_serializing_if = "Option::is_none")] pub github_url: Option, #[zod(url)] #[serde(skip_serializing_if = "Option::is_none")] pub cv_url: Option, #[serde(skip_serializing_if = "Option::is_none")] pub portfolio_url: Option, pub industries: Vec, pub expertise: Vec, pub languages: Vec, #[zod(min_length(1))] pub current_company: String, #[zod(min_length(1))] pub current_role: String, #[zod(min(2.0), int)] pub years_of_experience: i32, } impl ZodValidate for ProfessionalProfile { fn zod_validate(value: &serde_json::Value) -> Result { Self::validate_and_parse(value).map_err(|e| e.to_string()) } } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, ZodSchema)] pub struct MentoringLogistics { pub topics_of_interest: Vec, pub preferred_mentee_level: Vec, pub preferred_mentoring_formats: Vec, #[zod(min_length(5))] pub availability_commitment: String, #[zod(min(1.0))] pub mentoring_rate_amount: u64, } impl ZodValidate for MentoringLogistics { fn zod_validate(value: &serde_json::Value) -> Result { Self::validate_and_parse(value).map_err(|e| e.to_string()) } } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, ZodSchema)] pub struct MentorUpdateRequestDto { #[zod(min_length(3))] #[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, #[zod(min_length(10), max_length(15))] #[serde(skip_serializing_if = "Option::is_none")] pub phone_for_verification: Option, #[zod(min_length(50))] #[serde(skip_serializing_if = "Option::is_none")] pub bio: Option, #[serde(skip_serializing_if = "Option::is_none")] pub last_education: Option, #[zod(url)] #[serde(skip_serializing_if = "Option::is_none")] pub linkedin_url: Option, #[zod(url)] #[serde(skip_serializing_if = "Option::is_none")] pub github_url: Option, #[zod(url)] #[serde(skip_serializing_if = "Option::is_none")] pub cv_url: Option, #[zod(url)] #[serde(skip_serializing_if = "Option::is_none")] pub portfolio_url: Option, #[serde(skip_serializing_if = "Option::is_none")] pub industries: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub expertise: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub languages: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub current_company: Option, #[serde(skip_serializing_if = "Option::is_none")] pub current_role: Option, #[zod(min(2.0), int)] #[serde(skip_serializing_if = "Option::is_none")] pub years_of_experience: Option, #[serde(skip_serializing_if = "Option::is_none")] pub topics_of_interest: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub preferred_mentee_level: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub preferred_mentoring_formats: Option>, #[zod(min_length(5))] #[serde(skip_serializing_if = "Option::is_none")] pub availability_commitment: Option, #[zod(min(1.0))] #[serde(skip_serializing_if = "Option::is_none")] pub mentoring_rate_amount: Option, } impl ZodValidate for MentorUpdateRequestDto { fn zod_validate(value: &serde_json::Value) -> Result { Self::validate_and_parse(value).map_err(|e| e.to_string()) } } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, ZodSchema)] pub struct MentorVerifyRequestDto { #[zod(min_length(1))] pub status: String, } impl ZodValidate for MentorVerifyRequestDto { fn zod_validate(value: &serde_json::Value) -> Result { Self::validate_and_parse(value).map_err(|e| e.to_string()) } } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, ZodSchema, Default)] pub struct MentoringRate { #[zod(min(1.0))] pub amount: u64, #[zod(min_length(1))] pub currency: String, #[zod(min_length(1))] pub per_duration: String, } impl ZodValidate for MentoringRate { fn zod_validate(value: &serde_json::Value) -> Result { Self::validate_and_parse(value).map_err(|e| e.to_string()) } } #[derive(Clone, Debug, Serialize, Deserialize, ToSchema, ZodSchema)] pub struct MentorRegisterFromTokenRequestDto { pub identity_and_verification: IdentityAndVerification, pub professional_profile: ProfessionalProfile, pub mentoring_logistics: MentoringLogistics, } impl ZodValidate for MentorRegisterFromTokenRequestDto { fn zod_validate(value: &serde_json::Value) -> Result { Self::validate_and_parse(value).map_err(|e| e.to_string()) } }