2025-09-26 15:05:45 +07:00
|
|
|
use imphnen_iam::v1::users::UsersSchema;
|
2025-10-11 23:23:51 +07:00
|
|
|
use lazy_static::lazy_static;
|
|
|
|
|
use regex::Regex;
|
2025-06-29 00:01:00 +07:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use surrealdb::sql::Thing;
|
|
|
|
|
use utoipa::ToSchema;
|
2025-10-11 23:23:51 +07:00
|
|
|
use validator::{Validate, ValidationError};
|
|
|
|
|
|
|
|
|
|
// Custom validator for content length and format
|
|
|
|
|
pub fn validate_testimonial_content(content: &str) -> Result<(), ValidationError> {
|
|
|
|
|
lazy_static! {
|
|
|
|
|
static ref CONTENT_REGEX: Regex = Regex::new(r"^[a-zA-Z0-9\s.,!?'-]+$").unwrap();
|
|
|
|
|
}
|
|
|
|
|
if CONTENT_REGEX.is_match(content) && content.len() <= 1000 {
|
|
|
|
|
Ok(())
|
|
|
|
|
} else {
|
|
|
|
|
Err(ValidationError::new("invalid_content"))
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-06-29 00:01:00 +07:00
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)]
|
|
|
|
|
pub struct TestimonialsCreateRequestDto {
|
2025-10-11 23:23:51 +07:00
|
|
|
#[validate(length(min = 1, max = 100, message = "Role must be between 1 and 100 characters"))]
|
2025-06-29 00:01:00 +07:00
|
|
|
pub role: String,
|
2025-10-11 23:23:51 +07:00
|
|
|
|
2025-06-29 00:01:00 +07:00
|
|
|
#[validate(length(
|
|
|
|
|
min = 1,
|
2025-10-11 23:23:51 +07:00
|
|
|
max = 1000,
|
|
|
|
|
message = "Content must be between 1 and 1000 characters"
|
|
|
|
|
))]
|
|
|
|
|
#[validate(custom(
|
|
|
|
|
function = "validate_testimonial_content",
|
|
|
|
|
message = "Content contains invalid characters or is too long"
|
2025-06-29 00:01:00 +07:00
|
|
|
))]
|
|
|
|
|
pub content: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema, Validate)]
|
|
|
|
|
pub struct TestimonialsUpdateRequestDto {
|
2025-10-11 23:23:51 +07:00
|
|
|
#[validate(length(min = 1, max = 100, message = "Role must be between 1 and 100 characters"))]
|
2025-06-29 00:01:00 +07:00
|
|
|
pub role: String,
|
2025-10-11 23:23:51 +07:00
|
|
|
|
2025-06-29 00:01:00 +07:00
|
|
|
#[validate(length(
|
|
|
|
|
min = 1,
|
2025-10-11 23:23:51 +07:00
|
|
|
max = 1000,
|
|
|
|
|
message = "Content must be between 1 and 1000 characters"
|
|
|
|
|
))]
|
|
|
|
|
#[validate(custom(
|
|
|
|
|
function = "validate_testimonial_content",
|
|
|
|
|
message = "Content contains invalid characters or is too long"
|
2025-06-29 00:01:00 +07:00
|
|
|
))]
|
|
|
|
|
pub content: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
|
|
|
|
pub struct TestimonialsListItemDto {
|
|
|
|
|
pub id: String,
|
|
|
|
|
pub user_id: String,
|
2025-07-21 21:29:04 +07:00
|
|
|
pub user_fullname: String,
|
2025-06-29 00:01:00 +07:00
|
|
|
pub role: String,
|
|
|
|
|
pub content: String,
|
|
|
|
|
pub created_at: String,
|
|
|
|
|
pub is_deleted: bool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
|
|
|
|
|
pub struct TestimonialsDetailItemDto {
|
|
|
|
|
pub id: String,
|
|
|
|
|
pub user_id: String,
|
2025-07-21 21:29:04 +07:00
|
|
|
pub user_fullname: String,
|
2025-06-29 00:01:00 +07:00
|
|
|
pub role: String,
|
|
|
|
|
pub content: String,
|
|
|
|
|
pub created_at: String,
|
|
|
|
|
pub updated_at: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
|
|
|
pub struct TestimonialsQueryDto {
|
|
|
|
|
pub id: Thing,
|
2025-07-21 21:29:04 +07:00
|
|
|
pub user: UsersSchema,
|
2025-06-29 00:01:00 +07:00
|
|
|
pub role: String,
|
|
|
|
|
pub content: String,
|
|
|
|
|
pub is_deleted: bool,
|
|
|
|
|
pub created_at: String,
|
|
|
|
|
pub updated_at: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl TestimonialsQueryDto {
|
|
|
|
|
pub fn from(self) -> TestimonialsListItemDto {
|
|
|
|
|
TestimonialsListItemDto {
|
|
|
|
|
id: self.id.id.to_raw(),
|
|
|
|
|
user_id: self.user.id.id.to_raw(),
|
2025-07-21 21:29:04 +07:00
|
|
|
user_fullname: self.user.fullname,
|
2025-06-29 00:01:00 +07:00
|
|
|
role: self.role,
|
|
|
|
|
content: self.content,
|
|
|
|
|
created_at: self.created_at,
|
|
|
|
|
is_deleted: self.is_deleted,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|