feat: Add contact fields to hackathon and submission data; update registration service to handle string ID
This commit is contained in:
@@ -338,9 +338,17 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
project_name: Some(project_name.into()),
|
project_name: Some(project_name.into()),
|
||||||
description: Some(description.into()),
|
description: Some(description.into()),
|
||||||
repository_url,
|
repository_url,
|
||||||
|
upload_file_url: None,
|
||||||
demo_url,
|
demo_url,
|
||||||
slides_url,
|
slides_url,
|
||||||
technologies: Some(technologies),
|
technologies: Some(technologies),
|
||||||
|
contact_instagram: None,
|
||||||
|
contact_twitter: None,
|
||||||
|
contact_linkedin: None,
|
||||||
|
contact_facebook: None,
|
||||||
|
contact_youtube: None,
|
||||||
|
contact_tiktok: None,
|
||||||
|
contact_other: None,
|
||||||
submission_status: Some(submission_status),
|
submission_status: Some(submission_status),
|
||||||
submitted_at: Some(DateTime::parse_from_rfc3339(submitted_at)?.with_timezone(&Utc)),
|
submitted_at: Some(DateTime::parse_from_rfc3339(submitted_at)?.with_timezone(&Utc)),
|
||||||
is_deleted: false,
|
is_deleted: false,
|
||||||
|
|||||||
@@ -402,9 +402,17 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
project_name: Some(project_name.into()),
|
project_name: Some(project_name.into()),
|
||||||
description: Some(description.into()),
|
description: Some(description.into()),
|
||||||
repository_url,
|
repository_url,
|
||||||
|
upload_file_url: None,
|
||||||
demo_url,
|
demo_url,
|
||||||
slides_url,
|
slides_url,
|
||||||
technologies: Some(technologies),
|
technologies: Some(technologies),
|
||||||
|
contact_instagram: None,
|
||||||
|
contact_twitter: None,
|
||||||
|
contact_linkedin: None,
|
||||||
|
contact_facebook: None,
|
||||||
|
contact_youtube: None,
|
||||||
|
contact_tiktok: None,
|
||||||
|
contact_other: None,
|
||||||
submission_status: Some(submission_status),
|
submission_status: Some(submission_status),
|
||||||
judge_feedback: None,
|
judge_feedback: None,
|
||||||
submitted_at: Some(DateTime::parse_from_rfc3339(submitted_at)?.with_timezone(&Utc)),
|
submitted_at: Some(DateTime::parse_from_rfc3339(submitted_at)?.with_timezone(&Utc)),
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ use super::hackathon_schema::SubmissionStatus;
|
|||||||
use crate::v1::hackathon::HackathonRepository;
|
use crate::v1::hackathon::HackathonRepository;
|
||||||
use crate::{AppState, ResponseSuccessDto, ErrorDto};
|
use crate::{AppState, ResponseSuccessDto, ErrorDto};
|
||||||
use imphnen_entities::{PermissionsEnum, UsersDetailQueryDto};
|
use imphnen_entities::{PermissionsEnum, UsersDetailQueryDto};
|
||||||
use imphnen_libs::{MetaRequestDto, ResponseListSuccessDto, ValidatedJson};
|
use imphnen_libs::{MetaRequestDto, ResponseListSuccessDto};
|
||||||
use imphnen_iam::require_permissions;
|
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{Extension, Path, Query},
|
extract::{Extension, Path, Query},
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
use super::notification_dto::{
|
use super::notification_dto::{
|
||||||
DeleteNotificationResponseDto, MarkAllAsReadResponseDto, MarkAsReadResponseDto,
|
DeleteNotificationResponseDto, MarkAllAsReadResponseDto, MarkAsReadResponseDto, NotificationListQueryDto, NotificationListResponseDto,
|
||||||
NotificationDto, NotificationListQueryDto, NotificationListResponseDto,
|
|
||||||
UnreadCountResponseDto,
|
UnreadCountResponseDto,
|
||||||
};
|
};
|
||||||
use super::notification_service::Service;
|
use super::notification_service::Service;
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{Extension, Path, Query},
|
extract::{Extension, Path, Query},
|
||||||
http::{HeaderMap, Response, StatusCode},
|
http::{HeaderMap, Response, StatusCode},
|
||||||
response::IntoResponse,
|
|
||||||
routing::{delete, get, put},
|
routing::{delete, get, put},
|
||||||
Router, body::Body,
|
Router, body::Body,
|
||||||
};
|
};
|
||||||
use imphnen_entities::common_dto::ResponseSuccessDto;
|
|
||||||
use imphnen_libs::AppState;
|
use imphnen_libs::AppState;
|
||||||
use imphnen_utils::{extract_email::extract_email, response_format::common_response};
|
use imphnen_utils::{extract_email::extract_email, response_format::common_response};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::v1::notifications::notification_schema::NotificationSchema;
|
use crate::v1::notifications::notification_schema::NotificationSchema;
|
||||||
use imphnen_libs::AppState;
|
use imphnen_libs::AppState;
|
||||||
use imphnen_utils::{get_id, make_thing};
|
use imphnen_utils::get_id;
|
||||||
use surrealdb::sql::Thing;
|
use surrealdb::sql::Thing;
|
||||||
|
|
||||||
pub struct Repository<'a> {
|
pub struct Repository<'a> {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ pub async fn post_register_hackathon(
|
|||||||
let hackathon_id = make_thing_from_enum(ResourceEnum::Hackathons, &id);
|
let hackathon_id = make_thing_from_enum(ResourceEnum::Hackathons, &id);
|
||||||
|
|
||||||
let service = RegistrationsService::new(&state);
|
let service = RegistrationsService::new(&state);
|
||||||
service.register_hackathon(&hackathon_id, &user_email, data).await
|
service.register_hackathon(&hackathon_id, &id, &user_email, data).await
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|||||||
@@ -105,8 +105,7 @@ impl<'a> RegistrationsRepository<'a> {
|
|||||||
WHERE hackathon_id = $hackathon_id
|
WHERE hackathon_id = $hackathon_id
|
||||||
AND status = $status
|
AND status = $status
|
||||||
AND is_deleted = false
|
AND is_deleted = false
|
||||||
FETCH hackathon_id, user_id, team_id
|
FETCH hackathon_id, user_id, team_id;
|
||||||
ORDER BY registration_date DESC
|
|
||||||
"#
|
"#
|
||||||
} else {
|
} else {
|
||||||
r#"
|
r#"
|
||||||
@@ -129,8 +128,7 @@ impl<'a> RegistrationsRepository<'a> {
|
|||||||
FROM hackathon_registrations
|
FROM hackathon_registrations
|
||||||
WHERE hackathon_id = $hackathon_id
|
WHERE hackathon_id = $hackathon_id
|
||||||
AND is_deleted = false
|
AND is_deleted = false
|
||||||
FETCH hackathon_id, user_id, team_id
|
FETCH hackathon_id, user_id, team_id;
|
||||||
ORDER BY registration_date DESC
|
|
||||||
"#
|
"#
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -172,7 +170,7 @@ impl<'a> RegistrationsRepository<'a> {
|
|||||||
.map_err(|e| format!("Failed to parse registrations: {}", e))?;
|
.map_err(|e| format!("Failed to parse registrations: {}", e))?;
|
||||||
|
|
||||||
// Convert to full DTO with all fetched data
|
// Convert to full DTO with all fetched data
|
||||||
let registrations = simple
|
let mut registrations: Vec<RegistrationListQueryDto> = simple
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|r| RegistrationListQueryDto {
|
.map(|r| RegistrationListQueryDto {
|
||||||
id: r.id,
|
id: r.id,
|
||||||
@@ -185,7 +183,7 @@ impl<'a> RegistrationsRepository<'a> {
|
|||||||
team_name: r.team_name,
|
team_name: r.team_name,
|
||||||
status: r.status,
|
status: r.status,
|
||||||
role: r.role,
|
role: r.role,
|
||||||
registration_date: r.registration_date,
|
registration_date: r.registration_date.clone(),
|
||||||
checked_in: r.checked_in,
|
checked_in: r.checked_in,
|
||||||
check_in_time: r.check_in_time,
|
check_in_time: r.check_in_time,
|
||||||
experience_level: r.experience_level,
|
experience_level: r.experience_level,
|
||||||
@@ -193,6 +191,9 @@ impl<'a> RegistrationsRepository<'a> {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
// Sort by registration_date DESC (newest first)
|
||||||
|
registrations.sort_by(|a, b| b.registration_date.cmp(&a.registration_date));
|
||||||
|
|
||||||
Ok(registrations)
|
Ok(registrations)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,8 +220,7 @@ impl<'a> RegistrationsRepository<'a> {
|
|||||||
FROM hackathon_registrations
|
FROM hackathon_registrations
|
||||||
WHERE user_id = $user_id
|
WHERE user_id = $user_id
|
||||||
AND is_deleted = false
|
AND is_deleted = false
|
||||||
FETCH hackathon_id, team_id
|
FETCH hackathon_id, team_id;
|
||||||
ORDER BY registration_date DESC
|
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let user_id_clone = user_id.clone();
|
let user_id_clone = user_id.clone();
|
||||||
@@ -251,7 +251,7 @@ impl<'a> RegistrationsRepository<'a> {
|
|||||||
.map_err(|e| format!("Failed to parse user hackathons: {}", e))?;
|
.map_err(|e| format!("Failed to parse user hackathons: {}", e))?;
|
||||||
|
|
||||||
// Convert to full DTO with all fetched data
|
// Convert to full DTO with all fetched data
|
||||||
let hackathons = simple
|
let mut hackathons: Vec<UserHackathonQueryDto> = simple
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|h| UserHackathonQueryDto {
|
.map(|h| UserHackathonQueryDto {
|
||||||
registration_id: h.registration_id,
|
registration_id: h.registration_id,
|
||||||
@@ -262,13 +262,16 @@ impl<'a> RegistrationsRepository<'a> {
|
|||||||
end_date: h.end_date,
|
end_date: h.end_date,
|
||||||
status: h.status,
|
status: h.status,
|
||||||
role: h.role,
|
role: h.role,
|
||||||
registration_date: h.registration_date,
|
registration_date: h.registration_date.clone(),
|
||||||
checked_in: h.checked_in,
|
checked_in: h.checked_in,
|
||||||
team_id: h.team_id,
|
team_id: h.team_id,
|
||||||
team_name: h.team_name,
|
team_name: h.team_name,
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
// Sort by registration_date DESC (newest first)
|
||||||
|
hackathons.sort_by(|a, b| b.registration_date.cmp(&a.registration_date));
|
||||||
|
|
||||||
Ok(hackathons)
|
Ok(hackathons)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ impl<'a> RegistrationsService<'a> {
|
|||||||
pub async fn register_hackathon(
|
pub async fn register_hackathon(
|
||||||
&self,
|
&self,
|
||||||
hackathon_id: &Thing,
|
hackathon_id: &Thing,
|
||||||
|
hackathon_id_str: &str,
|
||||||
user_email: &str,
|
user_email: &str,
|
||||||
data: RegistrationRequestDto,
|
data: RegistrationRequestDto,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
@@ -47,14 +48,17 @@ impl<'a> RegistrationsService<'a> {
|
|||||||
|
|
||||||
// Check if hackathon exists
|
// Check if hackathon exists
|
||||||
let hackathon_repo = HackathonRepository::new(self.state);
|
let hackathon_repo = HackathonRepository::new(self.state);
|
||||||
match hackathon_repo.get_by_id(hackathon_id).await {
|
// Use the raw string ID from the path parameter
|
||||||
Ok(None) => {
|
match hackathon_repo.get_hackathon_by_id(hackathon_id_str.to_string()).await {
|
||||||
return common_response(StatusCode::NOT_FOUND, "Hackathon not found");
|
|
||||||
}
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
// Method returns error if hackathon not found or is deleted
|
||||||
|
let error_msg = e.to_string();
|
||||||
|
if error_msg.contains("not found") || error_msg.contains("Hackathon not found") {
|
||||||
|
return common_response(StatusCode::NOT_FOUND, "Hackathon not found");
|
||||||
|
}
|
||||||
return common_response(StatusCode::INTERNAL_SERVER_ERROR, &format!("Failed to verify hackathon: {}", e));
|
return common_response(StatusCode::INTERNAL_SERVER_ERROR, &format!("Failed to verify hackathon: {}", e));
|
||||||
}
|
}
|
||||||
Ok(Some(_)) => {} // Hackathon exists, continue
|
Ok(_) => {} // Hackathon exists, continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if user already registered
|
// Check if user already registered
|
||||||
|
|||||||
Reference in New Issue
Block a user