adding favorite feature

This commit is contained in:
DioCrafts
2025-04-02 03:43:44 +02:00
parent 705cb5b069
commit 7069a54d8d
21 changed files with 1395 additions and 8 deletions
@@ -0,0 +1,118 @@
use std::sync::Arc;
use axum::{
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
Json,
};
use serde::{Deserialize, Serialize};
use tracing::{error, info};
use uuid::Uuid;
use crate::application::ports::favorites_ports::FavoritesUseCase;
use crate::application::dtos::favorites_dto::FavoriteItemDto;
use crate::common::errors::{Result, DomainError, ErrorKind};
/// Handler for favorite-related API endpoints
pub async fn get_favorites(
State(favorites_service): State<Arc<dyn FavoritesUseCase>>,
) -> impl IntoResponse {
// For demo purposes, we're using a fixed user ID
let user_id = "00000000-0000-0000-0000-000000000000";
match favorites_service.get_favorites(user_id).await {
Ok(favorites) => {
info!("Retrieved {} favorites for user", favorites.len());
(StatusCode::OK, Json(serde_json::json!(favorites))).into_response()
},
Err(err) => {
error!("Error retrieving favorites: {}", err);
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(serde_json::json!({
"error": format!("Failed to retrieve favorites: {}", err)
}))
).into_response()
}
}
}
/// Add an item to user's favorites
pub async fn add_favorite(
State(favorites_service): State<Arc<dyn FavoritesUseCase>>,
Path((item_type, item_id)): Path<(String, String)>,
) -> impl IntoResponse {
// For demo purposes, we're using a fixed user ID
let user_id = "00000000-0000-0000-0000-000000000000";
// Validate item_type
if item_type != "file" && item_type != "folder" {
return (
StatusCode::BAD_REQUEST,
Json(serde_json::json!({
"error": "Item type must be 'file' or 'folder'"
}))
);
}
match favorites_service.add_to_favorites(user_id, &item_id, &item_type).await {
Ok(_) => {
info!("Added {} '{}' to favorites", item_type, item_id);
(
StatusCode::CREATED,
Json(serde_json::json!({
"message": "Item added to favorites"
}))
)
},
Err(err) => {
error!("Error adding to favorites: {}", err);
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(serde_json::json!({
"error": format!("Failed to add to favorites: {}", err)
}))
)
}
}
}
/// Remove an item from user's favorites
pub async fn remove_favorite(
State(favorites_service): State<Arc<dyn FavoritesUseCase>>,
Path((item_type, item_id)): Path<(String, String)>,
) -> impl IntoResponse {
// For demo purposes, we're using a fixed user ID
let user_id = "00000000-0000-0000-0000-000000000000";
match favorites_service.remove_from_favorites(user_id, &item_id, &item_type).await {
Ok(removed) => {
if removed {
info!("Removed {} '{}' from favorites", item_type, item_id);
(
StatusCode::OK,
Json(serde_json::json!({
"message": "Item removed from favorites"
}))
)
} else {
info!("Item {} '{}' was not in favorites", item_type, item_id);
(
StatusCode::NOT_FOUND,
Json(serde_json::json!({
"message": "Item was not in favorites"
}))
)
}
},
Err(err) => {
error!("Error removing from favorites: {}", err);
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(serde_json::json!({
"error": format!("Failed to remove from favorites: {}", err)
}))
)
}
}
}
+1
View File
@@ -6,6 +6,7 @@ pub mod auth_handler;
pub mod trash_handler;
pub mod search_handler;
pub mod share_handler;
pub mod favorites_handler;
/// Tipo de resultado para controladores de API
pub type ApiResult<T> = Result<T, (axum::http::StatusCode, String)>;
+19 -1
View File
@@ -25,6 +25,7 @@ use crate::application::services::batch_operations::BatchOperationService;
use crate::application::ports::trash_ports::TrashUseCase;
use crate::application::ports::inbound::SearchUseCase;
use crate::application::ports::share_ports::ShareUseCase;
use crate::application::ports::favorites_ports::FavoritesUseCase;
use crate::interfaces::api::handlers::folder_handler::FolderHandler;
use crate::interfaces::api::handlers::file_handler::FileHandler;
@@ -43,6 +44,7 @@ pub fn create_api_routes(
trash_service: Option<Arc<dyn TrashUseCase>>,
search_service: Option<Arc<dyn SearchUseCase>>,
share_service: Option<Arc<dyn ShareUseCase>>,
favorites_service: Option<Arc<dyn FavoritesUseCase>>,
) -> Router<crate::common::di::AppState> {
// Create a simplified AppState for the trash view
// Setup required components for repository construction
@@ -106,11 +108,13 @@ pub fn create_api_routes(
trash_service: trash_service.clone(), // Include the trash service here too for consistency
search_service: search_service.clone(), // Include the search service
share_service: share_service.clone(), // Include the share service
favorites_service: favorites_service.clone(), // Include the favorites service
},
db_pool: None,
auth_service: None,
trash_service: trash_service.clone(), // This is the important part - include the trash service
share_service: share_service.clone() // Include the share service for routes
share_service: share_service.clone(), // Include the share service for routes
favorites_service: favorites_service.clone() // Include the favorites service for routes
};
// Inicializar el servicio de operaciones por lotes
let batch_service = Arc::new(BatchOperationService::default(
@@ -324,6 +328,19 @@ pub fn create_api_routes(
};
// Create a router without the i18n routes
// Create routes for favorites if the service is available
let favorites_router = if let Some(favorites_service) = favorites_service.clone() {
use crate::interfaces::api::handlers::favorites_handler;
Router::new()
.route("/", get(favorites_handler::get_favorites))
.route("/{item_type}/{item_id}", post(favorites_handler::add_favorite))
.route("/{item_type}/{item_id}", delete(favorites_handler::remove_favorite))
.with_state(favorites_service.clone())
} else {
Router::new()
};
let mut router = Router::new()
.nest("/folders", folders_router)
.nest("/files", files_router)
@@ -331,6 +348,7 @@ pub fn create_api_routes(
.nest("/search", search_router)
.nest("/shares", share_router)
.nest("/s", public_share_router)
.nest("/favorites", favorites_router)
;
// Store the share service in app_state for future use