all: Set steps to be a single Vec & fix 'ingerdient' typo
This commit is contained in:
parent
b01f08ba2f
commit
0c7e52bd8b
9 changed files with 78 additions and 81 deletions
|
|
@ -89,7 +89,7 @@ pub struct CreateRecipeRequest {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub rating: u8,
|
pub rating: u8,
|
||||||
pub ingredients: Vec<(i64, f64)>,
|
pub ingredients: Vec<(i64, f64)>,
|
||||||
pub steps: Vec<String>,
|
pub steps: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
|
@ -105,7 +105,7 @@ pub struct ListRecipesResponse {
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct RecipeInfo {
|
pub struct RecipeInfo {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub steps: Vec<String>,
|
pub steps: String,
|
||||||
pub ingredients: Vec<(i64, IngredientInfo, f64)>,
|
pub ingredients: Vec<(i64, IngredientInfo, f64)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -421,7 +421,7 @@ fn AddIngredientInner(props: &AddIngredientProps) -> HtmlResult {
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
err.set(Some(format!("Could not add ingredient: {e}")));
|
err.set(Some(format!("Could not add ingredient: {e}")));
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -612,8 +612,8 @@ fn RecipeViewerInner(props: &RecipeViewerInnerProps) -> HtmlResult {
|
||||||
}})}
|
}})}
|
||||||
</ul>
|
</ul>
|
||||||
<AddIngredient
|
<AddIngredient
|
||||||
token={props.token.clone()}
|
token={props.token.clone()}
|
||||||
household={props.household}
|
household={props.household}
|
||||||
recipe={props.id}
|
recipe={props.id}
|
||||||
update={update.clone()}
|
update={update.clone()}
|
||||||
/>
|
/>
|
||||||
|
|
@ -622,7 +622,7 @@ fn RecipeViewerInner(props: &RecipeViewerInnerProps) -> HtmlResult {
|
||||||
<div class="text-start">
|
<div class="text-start">
|
||||||
<h2>{"Steps"}</h2>
|
<h2>{"Steps"}</h2>
|
||||||
<ul class="list-group list-group-flush">
|
<ul class="list-group list-group-flush">
|
||||||
{for r.steps.iter().map(|text| html!{
|
{for r.steps.split('\n').map(|text| html!{
|
||||||
<li class="list-group-item">{text}</li>
|
<li class="list-group-item">{text}</li>
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -290,26 +290,9 @@ pub fn RecipeCreator() -> Html {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let steps = use_state(im::Vector::new);
|
let steps = use_state(String::new);
|
||||||
|
let on_step_change = {
|
||||||
let s = steps.clone();
|
let steps = steps.clone();
|
||||||
let on_add_step = Callback::from(move |_| {
|
|
||||||
let mut steps = (*s).clone();
|
|
||||||
steps.push_back(String::new());
|
|
||||||
s.set(steps);
|
|
||||||
});
|
|
||||||
|
|
||||||
let mk_step_del = |idx| {
|
|
||||||
let s = steps.clone();
|
|
||||||
Callback::from(move |_| {
|
|
||||||
let mut steps = (*s).clone();
|
|
||||||
steps.remove(idx);
|
|
||||||
s.set(steps);
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let mk_step_change = |idx| {
|
|
||||||
let s = steps.clone();
|
|
||||||
Callback::from(move |e: Event| {
|
Callback::from(move |e: Event| {
|
||||||
let Some(target) = e.target() else {
|
let Some(target) = e.target() else {
|
||||||
return;
|
return;
|
||||||
|
|
@ -319,9 +302,7 @@ pub fn RecipeCreator() -> Html {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut steps = (*s).clone();
|
steps.set(target.value());
|
||||||
steps[idx] = target.value();
|
|
||||||
s.set(steps);
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -376,7 +357,7 @@ pub fn RecipeCreator() -> Html {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|rcp_ig: &RecipeIngredient| (rcp_ig.id, rcp_ig.amount / (*pc) as f64))
|
.map(|rcp_ig: &RecipeIngredient| (rcp_ig.id, rcp_ig.amount / (*pc) as f64))
|
||||||
.collect(),
|
.collect(),
|
||||||
steps: (*s).iter().cloned().collect(),
|
steps: (*s).clone(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|
@ -519,27 +500,11 @@ pub fn RecipeCreator() -> Html {
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h2>{"Steps"}</h2>
|
<h2>{"Steps"}</h2>
|
||||||
<ul class="list-group list-group-flush">
|
<textarea
|
||||||
{for (*steps).iter().enumerate().map(|(idx, step)| {
|
class="form-control"
|
||||||
html!{
|
value={(*steps).clone()}
|
||||||
<li class="list-group-item">
|
onchange={on_step_change}
|
||||||
<textarea
|
/>
|
||||||
class="form-control"
|
|
||||||
value={step.clone()}
|
|
||||||
onchange={mk_step_change(idx)}
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
class="btn btn-danger mt-1"
|
|
||||||
onclick={mk_step_del(idx)}
|
|
||||||
>
|
|
||||||
{"Remove"}
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
<button class="btn btn-primary" onclick={on_add_step}>{"Add Step"}</button>
|
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<ModalToggleButton classes={classes!("btn", "btn-lg", "btn-primary")} modal_id="newRcpModal">
|
<ModalToggleButton classes={classes!("btn", "btn-lg", "btn-primary")} modal_id="newRcpModal">
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,10 @@ impl Related<super::household::Entity> for Entity {
|
||||||
|
|
||||||
impl Related<super::recipe::Entity> for Entity {
|
impl Related<super::recipe::Entity> for Entity {
|
||||||
fn to() -> RelationDef {
|
fn to() -> RelationDef {
|
||||||
super::recipe_ingerdients::Relation::Recipe.def()
|
super::recipe_ingredients::Relation::Recipe.def()
|
||||||
}
|
}
|
||||||
fn via() -> Option<RelationDef> {
|
fn via() -> Option<RelationDef> {
|
||||||
Some(super::recipe_ingerdients::Relation::Ingredient.def().rev())
|
Some(super::recipe_ingredients::Relation::Ingredient.def().rev())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,5 @@ pub mod household;
|
||||||
pub mod household_members;
|
pub mod household_members;
|
||||||
pub mod ingredient;
|
pub mod ingredient;
|
||||||
pub mod recipe;
|
pub mod recipe;
|
||||||
pub mod recipe_ingerdients;
|
pub mod recipe_ingredients;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,5 @@ pub use super::household::Entity as Household;
|
||||||
pub use super::household_members::Entity as HouseholdMembers;
|
pub use super::household_members::Entity as HouseholdMembers;
|
||||||
pub use super::ingredient::Entity as Ingredient;
|
pub use super::ingredient::Entity as Ingredient;
|
||||||
pub use super::recipe::Entity as Recipe;
|
pub use super::recipe::Entity as Recipe;
|
||||||
pub use super::recipe_ingerdients::Entity as RecipeIngerdients;
|
pub use super::recipe_ingredients::Entity as RecipeIngredients;
|
||||||
pub use super::user::Entity as User;
|
pub use super::user::Entity as User;
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,10 @@ impl Related<super::household::Entity> for Entity {
|
||||||
|
|
||||||
impl Related<super::ingredient::Entity> for Entity {
|
impl Related<super::ingredient::Entity> for Entity {
|
||||||
fn to() -> RelationDef {
|
fn to() -> RelationDef {
|
||||||
super::recipe_ingerdients::Relation::Ingredient.def()
|
super::recipe_ingredients::Relation::Ingredient.def()
|
||||||
}
|
}
|
||||||
fn via() -> Option<RelationDef> {
|
fn via() -> Option<RelationDef> {
|
||||||
Some(super::recipe_ingerdients::Relation::Recipe.def().rev())
|
Some(super::recipe_ingredients::Relation::Recipe.def().rev())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
48
src/entity/recipe_ingredients.rs
Normal file
48
src/entity/recipe_ingredients.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
|
||||||
|
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "recipe_ingredients")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub recipe_id: i64,
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub ingredient_id: i64,
|
||||||
|
#[sea_orm(column_type = "Double")]
|
||||||
|
pub amount: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::ingredient::Entity",
|
||||||
|
from = "Column::IngredientId",
|
||||||
|
to = "super::ingredient::Column::Id",
|
||||||
|
on_update = "Restrict",
|
||||||
|
on_delete = "Restrict"
|
||||||
|
)]
|
||||||
|
Ingredient,
|
||||||
|
#[sea_orm(
|
||||||
|
belongs_to = "super::recipe::Entity",
|
||||||
|
from = "Column::RecipeId",
|
||||||
|
to = "super::recipe::Column::Id",
|
||||||
|
on_update = "Restrict",
|
||||||
|
on_delete = "Restrict"
|
||||||
|
)]
|
||||||
|
Recipe,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::ingredient::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Ingredient.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::recipe::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
Relation::Recipe.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
@ -11,7 +11,7 @@ use axum::{
|
||||||
};
|
};
|
||||||
use sea_orm::{prelude::*, ActiveValue, TransactionTrait};
|
use sea_orm::{prelude::*, ActiveValue, TransactionTrait};
|
||||||
|
|
||||||
use crate::entity::{ingredient, prelude::*, recipe, recipe_ingerdients, recipe_steps};
|
use crate::entity::{ingredient, prelude::*, recipe, recipe_ingredients};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
household::AuthorizedHousehold, ingredients::IngredientExtractor, AppState, JsonResult,
|
household::AuthorizedHousehold, ingredients::IngredientExtractor, AppState, JsonResult,
|
||||||
|
|
@ -31,19 +31,11 @@ pub(super) async fn create_recipe(
|
||||||
name: ActiveValue::Set(request.name),
|
name: ActiveValue::Set(request.name),
|
||||||
ranking: ActiveValue::Set(request.rating as i32),
|
ranking: ActiveValue::Set(request.rating as i32),
|
||||||
household: ActiveValue::Set(household.id),
|
household: ActiveValue::Set(household.id),
|
||||||
|
steps: ActiveValue::Set(request.steps),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let recipe = model.insert(txn).await?;
|
let recipe = model.insert(txn).await?;
|
||||||
for (num, text) in request.steps.into_iter().enumerate() {
|
|
||||||
let model = recipe_steps::ActiveModel {
|
|
||||||
num: ActiveValue::Set(num as _),
|
|
||||||
recipe_id: ActiveValue::Set(recipe.id),
|
|
||||||
text: ActiveValue::Set(text),
|
|
||||||
};
|
|
||||||
|
|
||||||
model.insert(txn).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ig, amount) in request.ingredients {
|
for (ig, amount) in request.ingredients {
|
||||||
if 0 == household
|
if 0 == household
|
||||||
|
|
@ -57,7 +49,7 @@ pub(super) async fn create_recipe(
|
||||||
)))?;
|
)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let model = recipe_ingerdients::ActiveModel {
|
let model = recipe_ingredients::ActiveModel {
|
||||||
recipe_id: ActiveValue::Set(recipe.id),
|
recipe_id: ActiveValue::Set(recipe.id),
|
||||||
ingredient_id: ActiveValue::Set(ig),
|
ingredient_id: ActiveValue::Set(ig),
|
||||||
amount: ActiveValue::Set(amount),
|
amount: ActiveValue::Set(amount),
|
||||||
|
|
@ -130,14 +122,6 @@ pub(super) async fn fetch_recipe(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
RecipeExtractor(recipe): RecipeExtractor,
|
RecipeExtractor(recipe): RecipeExtractor,
|
||||||
) -> JsonResult<RecipeInfo> {
|
) -> JsonResult<RecipeInfo> {
|
||||||
let steps = recipe
|
|
||||||
.find_related(RecipeSteps)
|
|
||||||
.all(&state.db)
|
|
||||||
.await?
|
|
||||||
.into_iter()
|
|
||||||
.map(|m| m.text)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let recipe_ingredients = recipe.find_related(Ingredient).all(&state.db).await?;
|
let recipe_ingredients = recipe.find_related(Ingredient).all(&state.db).await?;
|
||||||
|
|
||||||
let mut ingredients = Vec::new();
|
let mut ingredients = Vec::new();
|
||||||
|
|
@ -149,7 +133,7 @@ pub(super) async fn fetch_recipe(
|
||||||
name: ingredient.name,
|
name: ingredient.name,
|
||||||
unit: ingredient.unit,
|
unit: ingredient.unit,
|
||||||
},
|
},
|
||||||
RecipeIngerdients::find_by_id((recipe.id, ingredient.id))
|
RecipeIngredients::find_by_id((recipe.id, ingredient.id))
|
||||||
.one(&state.db)
|
.one(&state.db)
|
||||||
.await?
|
.await?
|
||||||
.expect("Ingredient should exist as it was fetched")
|
.expect("Ingredient should exist as it was fetched")
|
||||||
|
|
@ -159,7 +143,7 @@ pub(super) async fn fetch_recipe(
|
||||||
|
|
||||||
Ok(RecipeInfo {
|
Ok(RecipeInfo {
|
||||||
name: recipe.name,
|
name: recipe.name,
|
||||||
steps,
|
steps: recipe.steps,
|
||||||
ingredients,
|
ingredients,
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
|
|
@ -187,7 +171,7 @@ pub(super) async fn edit_ig_amount(
|
||||||
IngredientExtractor(ingredient): IngredientExtractor,
|
IngredientExtractor(ingredient): IngredientExtractor,
|
||||||
Json(req): Json<RecipeIngredientEditRequest>,
|
Json(req): Json<RecipeIngredientEditRequest>,
|
||||||
) -> JsonResult<EmptyResponse> {
|
) -> JsonResult<EmptyResponse> {
|
||||||
let active_model = recipe_ingerdients::ActiveModel {
|
let active_model = recipe_ingredients::ActiveModel {
|
||||||
recipe_id: ActiveValue::Set(recipe.id),
|
recipe_id: ActiveValue::Set(recipe.id),
|
||||||
ingredient_id: ActiveValue::Set(ingredient.id),
|
ingredient_id: ActiveValue::Set(ingredient.id),
|
||||||
amount: ActiveValue::Set(req.amount),
|
amount: ActiveValue::Set(req.amount),
|
||||||
|
|
@ -203,7 +187,7 @@ pub(super) async fn delete_ig(
|
||||||
RecipeExtractor(recipe): RecipeExtractor,
|
RecipeExtractor(recipe): RecipeExtractor,
|
||||||
IngredientExtractor(ingredient): IngredientExtractor,
|
IngredientExtractor(ingredient): IngredientExtractor,
|
||||||
) -> JsonResult<EmptyResponse> {
|
) -> JsonResult<EmptyResponse> {
|
||||||
RecipeIngerdients::delete_by_id((recipe.id, ingredient.id))
|
RecipeIngredients::delete_by_id((recipe.id, ingredient.id))
|
||||||
.exec(&state.db)
|
.exec(&state.db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
@ -216,7 +200,7 @@ pub(super) async fn add_ig_request(
|
||||||
IngredientExtractor(ingredient): IngredientExtractor,
|
IngredientExtractor(ingredient): IngredientExtractor,
|
||||||
Json(req): Json<AddRecipeIngredientRequest>,
|
Json(req): Json<AddRecipeIngredientRequest>,
|
||||||
) -> JsonResult<EmptyResponse> {
|
) -> JsonResult<EmptyResponse> {
|
||||||
let model = recipe_ingerdients::ActiveModel {
|
let model = recipe_ingredients::ActiveModel {
|
||||||
recipe_id: ActiveValue::Set(recipe.id),
|
recipe_id: ActiveValue::Set(recipe.id),
|
||||||
ingredient_id: ActiveValue::Set(ingredient.id),
|
ingredient_id: ActiveValue::Set(ingredient.id),
|
||||||
amount: ActiveValue::Set(req.amount),
|
amount: ActiveValue::Set(req.amount),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue