app: Allow to edit the default person count of a recipe
This commit is contained in:
parent
fe187c2885
commit
e54bb35ff4
1 changed files with 141 additions and 13 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use api::{
|
use api::{
|
||||||
AddRecipeIngredientRequest, IngredientInfo, RecipeEditRating, RecipeEditStepsRequest,
|
AddRecipeIngredientRequest, IngredientInfo, RecipeEditPersonCount, RecipeEditRating,
|
||||||
RecipeInfo, RecipeIngredientEditRequest, RecipeRenameRequest,
|
RecipeEditStepsRequest, RecipeInfo, RecipeIngredientEditRequest, RecipeRenameRequest,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
@ -758,6 +758,122 @@ fn EditRating(props: &EditRatingProps) -> Html {
|
||||||
</>}
|
</>}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn do_edit_person_count(
|
||||||
|
token: String,
|
||||||
|
household: Uuid,
|
||||||
|
recipe: i64,
|
||||||
|
person_count: u32,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let rsp =
|
||||||
|
gloo_net::http::Request::patch(api!("household/{household}/recipe/{recipe}/person_count"))
|
||||||
|
.json(&RecipeEditPersonCount { person_count })?
|
||||||
|
.header("Authorization", &format!("Bearer {token}"))
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if !rsp.ok() {
|
||||||
|
let body = rsp.text().await.unwrap_or_default();
|
||||||
|
anyhow::bail!(
|
||||||
|
"Could not edit person_count (code={}): {body}",
|
||||||
|
rsp.status()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Properties, PartialEq, Clone)]
|
||||||
|
struct EditPersonCountProps {
|
||||||
|
token: String,
|
||||||
|
household: Uuid,
|
||||||
|
recipe: i64,
|
||||||
|
person_count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[function_component]
|
||||||
|
fn EditPersonCount(props: &EditPersonCountProps) -> Html {
|
||||||
|
let person_count = use_state(|| props.person_count);
|
||||||
|
|
||||||
|
let error = use_state(|| None::<String>);
|
||||||
|
|
||||||
|
let onchange = {
|
||||||
|
let person_count = person_count.clone();
|
||||||
|
Callback::from(move |e: Event| {
|
||||||
|
let Some(target) = e.target() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(target) = target.dyn_into::<HtmlInputElement>() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if !target.report_validity() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
person_count.set(target.value().parse().expect("invalid number"));
|
||||||
|
})
|
||||||
|
};
|
||||||
|
let on_submit = {
|
||||||
|
let person_count = person_count.clone();
|
||||||
|
let token = props.token.clone();
|
||||||
|
let household = props.household;
|
||||||
|
let recipe = props.recipe;
|
||||||
|
let error = error.clone();
|
||||||
|
Callback::from(move |_| {
|
||||||
|
let token = token.clone();
|
||||||
|
let person_count = person_count.clone();
|
||||||
|
let error = error.clone();
|
||||||
|
|
||||||
|
wasm_bindgen_futures::spawn_local(async move {
|
||||||
|
match do_edit_person_count(token.clone(), household, recipe, *person_count)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => {
|
||||||
|
let modal = bs::Modal::get_instance("#rcpEditPersonCount");
|
||||||
|
modal.hide();
|
||||||
|
error.set(None);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error.set(Some(format!("Could not edit person count: {e}")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
html! {<>
|
||||||
|
<ModalToggleButton modal_id="rcpEditPersonCount" classes={classes!("btn", "btn-secondary")}>
|
||||||
|
{"Edit"}
|
||||||
|
</ModalToggleButton>
|
||||||
|
<FormModal
|
||||||
|
id="rcpEditPersonCount"
|
||||||
|
fade=true
|
||||||
|
centered=true
|
||||||
|
submit_label="Edit"
|
||||||
|
title="Edit default person count"
|
||||||
|
{on_submit}
|
||||||
|
>
|
||||||
|
if let Some(e) = &*error {
|
||||||
|
<div class={classes!("alert", "alert-danger")} role="alert">
|
||||||
|
{e}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div class="form-floating">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
class="form-control"
|
||||||
|
id="rcpEditPersonCountInp"
|
||||||
|
value={(*person_count).to_string()}
|
||||||
|
{onchange}
|
||||||
|
/>
|
||||||
|
<label for="rcpEditPersonCountInp">{"Default person count"}</label>
|
||||||
|
</div>
|
||||||
|
</FormModal>
|
||||||
|
</>}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Properties, PartialEq, Clone)]
|
#[derive(Properties, PartialEq, Clone)]
|
||||||
struct RecipeInfoProps {
|
struct RecipeInfoProps {
|
||||||
token: String,
|
token: String,
|
||||||
|
|
@ -832,17 +948,29 @@ fn RecipeInfoView(props: &RecipeInfoProps) -> Html {
|
||||||
update={props.update.clone()}
|
update={props.update.clone()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2">
|
<div class="mt-2 container text-start">
|
||||||
<div class="w-50 text-start input-group">
|
<div class="row">
|
||||||
<input
|
<div class="col-8">
|
||||||
class="form-control"
|
<div class="input-group">
|
||||||
type="number"
|
<input
|
||||||
id="rcpPeopleCount"
|
class="form-control"
|
||||||
min="1"
|
type="number"
|
||||||
value={person_count.to_string()}
|
id="rcpPeopleCount"
|
||||||
{onchange}
|
min="1"
|
||||||
/>
|
value={person_count.to_string()}
|
||||||
<span class="input-group-text">{"people"}</span>
|
{onchange}
|
||||||
|
/>
|
||||||
|
<span class="input-group-text">{"people"}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<EditPersonCount
|
||||||
|
token={props.token.clone()}
|
||||||
|
recipe={props.recipe_id}
|
||||||
|
household={props.household}
|
||||||
|
person_count={props.info.person_count}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
if let Some(e) = &*error {
|
if let Some(e) = &*error {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue