app,server: Allow to edit recipe ingredients
This commit is contained in:
parent
47b547caf4
commit
6004520fb9
6 changed files with 307 additions and 35 deletions
|
|
@ -1,5 +1,7 @@
|
|||
use axum::{
|
||||
extract::{Path, State},
|
||||
async_trait,
|
||||
extract::{FromRef, FromRequestParts, Path, State},
|
||||
http::request::Parts,
|
||||
Json,
|
||||
};
|
||||
|
||||
|
|
@ -10,7 +12,7 @@ use api::{
|
|||
use sea_orm::{prelude::*, ActiveValue};
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::{household::AuthorizedHousehold, AppState, JsonResult};
|
||||
use super::{household::AuthorizedHousehold, AppState, JsonResult, RouteError};
|
||||
use crate::entity::{ingredient, prelude::*};
|
||||
|
||||
pub(super) async fn create_ingredient(
|
||||
|
|
@ -52,37 +54,57 @@ pub(super) async fn list_ingredients(
|
|||
}))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct IngredientId {
|
||||
iid: i64,
|
||||
pub(super) struct IngredientExtractor(pub(super) ingredient::Model);
|
||||
|
||||
#[async_trait]
|
||||
impl<S> FromRequestParts<S> for IngredientExtractor
|
||||
where
|
||||
S: Send + Sync,
|
||||
AppState: FromRef<S>,
|
||||
{
|
||||
type Rejection = RouteError;
|
||||
|
||||
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
|
||||
let State(app_state): State<AppState> = State::from_request_parts(parts, state)
|
||||
.await
|
||||
.expect("No state");
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct IngredientId {
|
||||
iid: i64,
|
||||
}
|
||||
|
||||
let household = AuthorizedHousehold::from_request_parts(parts, state).await?;
|
||||
let Path(ingredient_id): Path<IngredientId> =
|
||||
Path::from_request_parts(parts, state).await?;
|
||||
|
||||
match household
|
||||
.0
|
||||
.find_related(Ingredient)
|
||||
.filter(ingredient::Column::Id.eq(ingredient_id.iid))
|
||||
.one(&app_state.db)
|
||||
.await?
|
||||
{
|
||||
None => Err(RouteError::RessourceNotFound),
|
||||
Some(r) => Ok(Self(r)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) async fn remove_ingredient(
|
||||
AuthorizedHousehold(household): AuthorizedHousehold,
|
||||
State(state): State<AppState>,
|
||||
Path(IngredientId { iid }): Path<IngredientId>,
|
||||
IngredientExtractor(ingredient): IngredientExtractor,
|
||||
) -> JsonResult<EmptyResponse> {
|
||||
Ingredient::delete_by_id(iid)
|
||||
.filter(ingredient::Column::Household.eq(household.id))
|
||||
.exec(&state.db)
|
||||
.await?;
|
||||
ingredient.delete(&state.db).await?;
|
||||
|
||||
Ok(Json(EmptyResponse {}))
|
||||
}
|
||||
|
||||
pub(super) async fn edit_ingredient(
|
||||
AuthorizedHousehold(household): AuthorizedHousehold,
|
||||
State(state): State<AppState>,
|
||||
Path(IngredientId { iid }): Path<IngredientId>,
|
||||
IngredientExtractor(ingredient): IngredientExtractor,
|
||||
Json(request): Json<EditIngredientRequest>,
|
||||
) -> JsonResult<EmptyResponse> {
|
||||
let Some(ingredient) = Ingredient::find_by_id(iid)
|
||||
.filter(ingredient::Column::Household.eq(household.id))
|
||||
.one(&state.db)
|
||||
.await? else {
|
||||
return Err(super::RouteError::RessourceNotFound);
|
||||
};
|
||||
|
||||
let mut ingredient: ingredient::ActiveModel = ingredient.into();
|
||||
|
||||
if let Some(name) = request.name {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use axum::{
|
|||
HeaderValue, Method, StatusCode,
|
||||
},
|
||||
response::IntoResponse,
|
||||
routing::{delete, get, post, put},
|
||||
routing::{delete, get, patch, post, put},
|
||||
Json, Router, TypedHeader,
|
||||
};
|
||||
use jwt_simple::prelude::*;
|
||||
|
|
@ -228,4 +228,10 @@ pub(crate) fn router(api_allowed: Option<HeaderValue>) -> Router<AppState> {
|
|||
.patch(recipe::edit_name)
|
||||
.layer(mk_service(vec![Method::GET, Method::PATCH])),
|
||||
)
|
||||
.route(
|
||||
"/household/:house_id/recipe/:recipe_id/ingredients/:iid",
|
||||
patch(recipe::edit_ig_amount)
|
||||
.delete(recipe::delete_ig)
|
||||
.layer(mk_service(vec![Method::PATCH, Method::DELETE])),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use api::{
|
||||
CreateRecipeRequest, CreateRecipeResponse, EmptyResponse, IngredientInfo, ListRecipesResponse,
|
||||
RecipeInfo, RecipeRenameRequest,
|
||||
RecipeInfo, RecipeIngredientEditRequest, RecipeRenameRequest,
|
||||
};
|
||||
use axum::{
|
||||
async_trait,
|
||||
|
|
@ -12,7 +12,10 @@ use sea_orm::{prelude::*, ActiveValue, TransactionTrait};
|
|||
|
||||
use crate::entity::{ingredient, prelude::*, recipe, recipe_ingerdients, recipe_steps};
|
||||
|
||||
use super::{household::AuthorizedHousehold, AppState, JsonResult, RouteError};
|
||||
use super::{
|
||||
household::AuthorizedHousehold, ingredients::IngredientExtractor, AppState, JsonResult,
|
||||
RouteError,
|
||||
};
|
||||
|
||||
pub(super) async fn create_recipe(
|
||||
AuthorizedHousehold(household): AuthorizedHousehold,
|
||||
|
|
@ -176,3 +179,32 @@ pub(super) async fn edit_name(
|
|||
|
||||
Ok(EmptyResponse {}.into())
|
||||
}
|
||||
|
||||
pub(super) async fn edit_ig_amount(
|
||||
State(state): State<AppState>,
|
||||
RecipeExtractor(recipe): RecipeExtractor,
|
||||
IngredientExtractor(ingredient): IngredientExtractor,
|
||||
Json(req): Json<RecipeIngredientEditRequest>,
|
||||
) -> JsonResult<EmptyResponse> {
|
||||
let active_model = recipe_ingerdients::ActiveModel {
|
||||
recipe_id: ActiveValue::Set(recipe.id),
|
||||
ingredient_id: ActiveValue::Set(ingredient.id),
|
||||
amount: ActiveValue::Set(req.amount),
|
||||
};
|
||||
|
||||
active_model.update(&state.db).await?;
|
||||
|
||||
Ok(EmptyResponse {}.into())
|
||||
}
|
||||
|
||||
pub(super) async fn delete_ig(
|
||||
State(state): State<AppState>,
|
||||
RecipeExtractor(recipe): RecipeExtractor,
|
||||
IngredientExtractor(ingredient): IngredientExtractor,
|
||||
) -> JsonResult<EmptyResponse> {
|
||||
RecipeIngerdients::delete_by_id((recipe.id, ingredient.id))
|
||||
.exec(&state.db)
|
||||
.await?;
|
||||
|
||||
Ok(EmptyResponse {}.into())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue