use axum::{ extract::{Path, State}, http::StatusCode, Json, }; use sea_orm::DatabaseConnection; use serde::{Deserialize, Serialize}; #[allow(unused_imports)] // че за хуйня раст? use serde_json::json; use utoipa::ToSchema; use crate::models::shopping_item::Model as ShoppingItemModel; use crate::services::ShoppingItemService; #[derive(Debug, Deserialize, ToSchema)] #[schema(example = json!({"name": "Milk"}))] pub struct CreateShoppingItemRequest { pub name: String, } #[derive(Debug, Deserialize, ToSchema)] #[schema(example = json!({"name": "Updated item name"}))] pub struct UpdateShoppingItemRequest { pub name: String, } #[derive(Debug, Deserialize, ToSchema)] #[schema(example = json!({"is_purchased": true}))] pub struct MarkAsPurchasedRequest { pub is_purchased: bool, } #[derive(Debug, Serialize, ToSchema)] #[schema(example = json!({"affected_rows": 5}))] pub struct BulkOperationResponse { pub affected_rows: u64, } #[utoipa::path( post, path = "/families/{family_id}/shopping-items", tag = "shopping-items", params( ("family_id" = i32, Path, description = "Family ID") ), request_body = CreateShoppingItemRequest, responses( (status = 200, description = "Shopping item created successfully", body = ShoppingItemModel), (status = 500, description = "Internal server error") ) )] pub async fn create_shopping_item( State(db): State, Path(family_id): Path, Json(payload): Json, ) -> Result, StatusCode> { ShoppingItemService::create(&db, family_id, payload.name) .await .map(Json) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR) } #[utoipa::path( get, path = "/families/{family_id}/shopping-items", tag = "shopping-items", params( ("family_id" = i32, Path, description = "Family ID") ), responses( (status = 200, description = "List of shopping items", body = Vec), (status = 500, description = "Internal server error") ) )] pub async fn get_shopping_items_by_family( State(db): State, Path(family_id): Path, ) -> Result>, StatusCode> { ShoppingItemService::find_by_family(&db, family_id) .await .map(Json) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR) } #[utoipa::path( get, path = "/families/{family_id}/shopping-items/{id}", tag = "shopping-items", params( ("family_id" = i32, Path, description = "Family ID"), ("id" = i32, Path, description = "Shopping item ID") ), responses( (status = 200, description = "Shopping item found", body = ShoppingItemModel), (status = 404, description = "Shopping item not found"), (status = 500, description = "Internal server error") ) )] pub async fn get_shopping_item( State(db): State, Path((_family_id, id)): Path<(i32, i32)>, ) -> Result, StatusCode> { ShoppingItemService::find_by_id(&db, id) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? .map(Json) .ok_or(StatusCode::NOT_FOUND) } #[utoipa::path( put, path = "/families/{family_id}/shopping-items/{id}", tag = "shopping-items", params( ("family_id" = i32, Path, description = "Family ID"), ("id" = i32, Path, description = "Shopping item ID") ), request_body = UpdateShoppingItemRequest, responses( (status = 200, description = "Shopping item updated successfully", body = ShoppingItemModel), (status = 500, description = "Internal server error") ) )] pub async fn update_shopping_item( State(db): State, Path((_family_id, id)): Path<(i32, i32)>, Json(payload): Json, ) -> Result, StatusCode> { ShoppingItemService::update(&db, id, payload.name) .await .map(Json) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR) } #[utoipa::path( delete, path = "/families/{family_id}/shopping-items/{id}", tag = "shopping-items", params( ("family_id" = i32, Path, description = "Family ID"), ("id" = i32, Path, description = "Shopping item ID") ), responses( (status = 204, description = "Shopping item deleted successfully"), (status = 500, description = "Internal server error") ) )] pub async fn delete_shopping_item( State(db): State, Path((_family_id, id)): Path<(i32, i32)>, ) -> Result { ShoppingItemService::delete(&db, id) .await .map(|_| StatusCode::NO_CONTENT) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR) } #[utoipa::path( patch, path = "/families/{family_id}/shopping-items/{id}/purchased", tag = "shopping-items", params( ("family_id" = i32, Path, description = "Family ID"), ("id" = i32, Path, description = "Shopping item ID") ), request_body = MarkAsPurchasedRequest, responses( (status = 200, description = "Shopping item marked as purchased", body = ShoppingItemModel), (status = 500, description = "Internal server error") ) )] pub async fn mark_as_purchased( State(db): State, Path((_family_id, id)): Path<(i32, i32)>, Json(payload): Json, ) -> Result, StatusCode> { ShoppingItemService::mark_as_purchased(&db, id, payload.is_purchased) .await .map(Json) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR) } #[utoipa::path( post, path = "/families/{family_id}/shopping-items/mark-all-purchased", tag = "shopping-items", params( ("family_id" = i32, Path, description = "Family ID") ), responses( (status = 200, description = "All shopping items marked as purchased", body = BulkOperationResponse), (status = 500, description = "Internal server error") ) )] pub async fn mark_all_as_purchased( State(db): State, Path(family_id): Path, ) -> Result, StatusCode> { ShoppingItemService::mark_all_as_purchased(&db, family_id) .await .map(|affected_rows| Json(BulkOperationResponse { affected_rows })) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR) } #[utoipa::path( delete, path = "/families/{family_id}/shopping-items/clear-all", tag = "shopping-items", params( ("family_id" = i32, Path, description = "Family ID") ), responses( (status = 200, description = "All shopping items cleared", body = BulkOperationResponse), (status = 500, description = "Internal server error") ) )] pub async fn clear_all( State(db): State, Path(family_id): Path, ) -> Result, StatusCode> { ShoppingItemService::clear_all(&db, family_id) .await .map(|result| Json(BulkOperationResponse { affected_rows: result.rows_affected })) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR) }