recipe_id: i64,
date: NaiveDate,
servings: u32,
- add_ingredients_element: bool,
+ add_ingredients_to_shopping_list: bool,
) -> Result<AddScheduledRecipeResult> {
let mut tx = self.tx().await?;
}
Ok(insert_result) => {
- if add_ingredients_element {
+ if add_ingredients_to_shopping_list {
sqlx::query(
r#"
INSERT INTO [ShoppingEntry] ([ingredient_id], [user_id], [recipe_scheduled_id], [servings])
user_id: i64,
recipe_id: i64,
date: NaiveDate,
+ remove_ingredients_from_shopping_list: bool,
) -> Result<()> {
+ let mut tx = self.tx().await?;
+
+ if remove_ingredients_from_shopping_list {
+ sqlx::query(
+ r#"
+DELETE FROM [ShoppingEntry]
+WHERE [recipe_scheduled_id] IN (
+ SELECT [id] FROM [RecipeScheduled]
+ WHERE [user_id] = $1 AND [recipe_id] = $2 AND [date] = $3
+)
+ "#,
+ )
+ .bind(user_id)
+ .bind(recipe_id)
+ .bind(date)
+ .execute(&mut *tx)
+ .await?;
+ }
+
sqlx::query(
r#"
- DELETE FROM [RecipeScheduled]
- WHERE [user_id] = $1 AND [recipe_id] = $2 AND [date] = $3
+DELETE FROM [RecipeScheduled]
+WHERE [user_id] = $1 AND [recipe_id] = $2 AND [date] = $3
"#,
)
.bind(user_id)
.bind(recipe_id)
.bind(date)
- .execute(&self.pool)
- .await
- .map(|_| ())
- .map_err(DBError::from)
+ .execute(&mut *tx)
+ .await?;
+
+ tx.commit().await?;
+
+ Ok(())
}
pub async fn get_scheduled_recipes(
pub async fn rm_scheduled_recipe(
State(connection): State<db::Connection>,
Extension(user): Extension<Option<model::User>>,
- ExtractRon(ron): ExtractRon<common::ron_api::ScheduledRecipe>,
+ ExtractRon(ron): ExtractRon<common::ron_api::RemoveScheduledRecipe>,
) -> Result<impl IntoResponse> {
check_user_rights_recipe(&connection, &user, ron.recipe_id).await?;
if let Some(user) = user {
connection
- .rm_scheduled_recipe(user.id, ron.recipe_id, ron.date)
+ .rm_scheduled_recipe(
+ user.id,
+ ron.recipe_id,
+ ron.date,
+ ron.remove_ingredients_from_shopping_list,
+ )
.await?;
}
Ok(StatusCode::OK)
CalendarAddToPlannerAlreadyExists,
CalendarDateFormat, // See https://docs.rs/chrono/latest/chrono/format/strftime/index.html.
CalendarAddIngredientsToShoppingList,
+ CalendarRemoveIngredientsFromShoppingList,
CalendarUnscheduleConfirmation,
}
<div class="scheduled-recipe-with-link-and-remove"><a></a><span class="remove-scheduled-recipe">X</span></div>
<div class="scheduled-recipe"></div>
- <span class="unschedule-confirmation">{{ tr.t(Sentence::CalendarUnscheduleConfirmation) }}</span>
+ <div class="unschedule-confirmation">
+ <div>{{ tr.t(Sentence::CalendarUnscheduleConfirmation) }}</div>
+ <input
+ id="input-remove-ingredients-from-shopping-list"
+ type="checkbox"
+ checked
+ />
+ <label for="input-remove-ingredients-from-shopping-list">
+ {{ tr.t(Sentence::CalendarRemoveIngredientsFromShoppingList) }}
+ </label>
+ </div>
+
<span class="calendar-date-format">{{ tr.t(Sentence::CalendarDateFormat) }}</span>
</div>
</div>
\ No newline at end of file
(CalendarAddToPlannerAlreadyExists, "Recipe {title} has already been scheduled for {date}"),
(CalendarDateFormat, "%A, %-d %B, %C%y"), // See https://docs.rs/chrono/latest/chrono/format/strftime/index.html.
(CalendarAddIngredientsToShoppingList, "Add ingredients to shopping list"),
+ (CalendarRemoveIngredientsFromShoppingList, "Remove ingredients from shopping list"),
(CalendarUnscheduleConfirmation, "Are you sure to remove {title} on {date}"),
]
),
(CalendarAddToPlannerAlreadyExists, "La recette {title} a été déjà été agendée pour le {date}"),
(CalendarDateFormat, "%A %-d %B %C%y"), // See https://docs.rs/chrono/latest/chrono/format/strftime/index.html.
(CalendarAddIngredientsToShoppingList, "Ajouter les ingrédients à la liste de course"),
+ (CalendarRemoveIngredientsFromShoppingList, "Enlever les ingrédients de la liste de course"),
(CalendarUnscheduleConfirmation, "Êtes-vous sûr de vouloir enlever {title} du {date}"),
]
)
}
#[derive(Serialize, Deserialize, Clone, Debug)]
-pub struct ScheduledRecipe {
+pub struct RemoveScheduledRecipe {
pub recipe_id: i64,
pub date: NaiveDate,
+ pub remove_ingredients_from_shopping_list: bool,
}
/*** Shopping list ***/
use chrono::{offset::Local, Datelike, Days, Months, NaiveDate, Weekday};
use common::{ron_api, utils::substitute_with_names};
-use gloo::{console::log, events::EventListener, utils::document};
+use gloo::{
+ console::log,
+ events::EventListener,
+ utils::{document, window},
+};
use scanf::sscanf;
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::spawn_local;
-use web_sys::Element;
+use web_sys::{Element, HtmlInputElement};
use crate::{
modal_dialog,
let title = target.previous_element_sibling().unwrap().inner_html();
- if modal_dialog::show_and_initialize(
- "#hidden-templates-calendar .unschedule-confirmation",
- async |element| {
- let date_format =
- selector::<Element>("#hidden-templates-calendar .calendar-date-format")
- .inner_html();
- element.set_inner_html(&substitute_with_names(
- &element.inner_html(),
- &["{title}", "{date}"],
- &[
- &title,
- &date
- .format_localized(&date_format, get_locale())
- .to_string(),
- ],
- ));
- },
- )
- .await
- .is_some()
+ if let Some(remove_ingredients_from_shopping_list) =
+ modal_dialog::show_and_initialize_with_ok(
+ "#hidden-templates-calendar .unschedule-confirmation",
+ async |element| {
+ let date_format = selector::<Element>(
+ "#hidden-templates-calendar .calendar-date-format",
+ )
+ .inner_html();
+ element.set_inner_html(&substitute_with_names(
+ &element.inner_html(),
+ &["{title}", "{date}"],
+ &[
+ &title,
+ &date
+ .format_localized(&date_format, get_locale())
+ .to_string(),
+ ],
+ ));
+ },
+ |element, _| {
+ let remove_ingredients_element: HtmlInputElement =
+ element.selector("#input-remove-ingredients-from-shopping-list");
+ remove_ingredients_element.checked()
+ },
+ )
+ .await
{
- let body = ron_api::ScheduledRecipe { recipe_id, date };
+ let body = ron_api::RemoveScheduledRecipe {
+ recipe_id,
+ date,
+ remove_ingredients_from_shopping_list,
+ };
let _ =
request::delete::<(), _>("calendar/remove_scheduled_recipe", body).await;
- target.parent_element().unwrap().remove();
+ window().location().reload().unwrap();
}
});
}