Scheduled recipes can now be removed
authorGreg Burri <greg.burri@gmail.com>
Tue, 11 Feb 2025 23:22:50 +0000 (00:22 +0100)
committerGreg Burri <greg.burri@gmail.com>
Tue, 11 Feb 2025 23:22:50 +0000 (00:22 +0100)
Cargo.lock
backend/src/translation.rs
backend/templates/calendar.html
backend/templates/home.html
backend/translation.ron
frontend/Cargo.toml
frontend/src/calendar.rs
frontend/src/recipe_edit.rs

index 2ee9bcf..c99f661 100644 (file)
@@ -712,6 +712,7 @@ dependencies = [
  "futures",
  "gloo",
  "ron",
+ "scanf",
  "serde",
  "serde_html_form",
  "thiserror 2.0.11",
@@ -2188,6 +2189,15 @@ version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
 
+[[package]]
+name = "scanf"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbf5845f2587e0dd28b0dc313d1bbe0b7aa70aedb8e236785f670dcd1df1f677"
+dependencies = [
+ "nom",
+]
+
 [[package]]
 name = "scopeguard"
 version = "1.2.0"
index 72bd392..8e89ca2 100644 (file)
@@ -146,6 +146,7 @@ pub enum Sentence {
     CalendarAddToPlannerAlreadyExists,
     CalendarDateFormat, // See https://docs.rs/chrono/latest/chrono/format/strftime/index.html.
     CalendarAddIngredientsToShoppingList,
+    CalendarUnscheduleConfirmation,
 }
 
 pub const DEFAULT_LANGUAGE_CODE: &str = "en";
index b186826..ac60471 100644 (file)
@@ -49,5 +49,8 @@
     <div id="hidden-templates-calendar">
         <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>
+        <span class="calendar-date-format">{{ tr.t(Sentence::CalendarDateFormat) }}</span>
     </div>
 </div>
\ No newline at end of file
index ebe80fb..3bd50a8 100644 (file)
@@ -17,6 +17,7 @@
         <div class="item-scheduled-recipe"><a></a></div>
         <div class="item-delete"></div>
     </div>
+
     <span class="calendar-date-format">{{ tr.t(Sentence::CalendarDateFormat) }}</span>
 </div>
 
index 8d1f028..fa8a54e 100644 (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"),
+            (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"),
+            (CalendarUnscheduleConfirmation, "Êtes-vous sûr de vouloir enlever {title} du {date}"),
         ]
     )
 ]
\ No newline at end of file
index 44e2476..f2f9612 100644 (file)
@@ -22,6 +22,8 @@ thiserror = "2"
 
 futures = "0.3"
 
+scanf = "1.2"
+
 wasm-bindgen = "0.2"
 wasm-bindgen-futures = "0.4"
 web-sys = { version = "0.3", features = [
index a0a4e29..ef942be 100644 (file)
@@ -1,14 +1,18 @@
 use std::{cell::RefCell, rc::Rc};
 
 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 scanf::sscanf;
 use wasm_bindgen::prelude::*;
 use wasm_bindgen_futures::spawn_local;
 use web_sys::Element;
 
 use crate::{
+    modal_dialog,
     recipe_scheduler::RecipeScheduler,
-    utils::{by_id, selector, selector_all, SelectorExt},
+    request,
+    utils::{by_id, get_locale, selector, selector_all, SelectorExt},
 };
 
 struct CalendarStateInternal {
@@ -123,7 +127,46 @@ pub fn setup(
                 recipe_scheduler,
             );
         } else if target.class_name() == "remove-scheduled-recipe" {
-            log!("REMOVE"); // TODO.
+            spawn_local(async move {
+                let mut recipe_id: i64 = 0;
+                let mut date: NaiveDate = NaiveDate::default();
+                sscanf!(
+                    &target.parent_element().unwrap().id(),
+                    "scheduled-recipe-{}-{}",
+                    recipe_id,
+                    date
+                )
+                .unwrap();
+
+                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()
+                {
+                    let body = ron_api::ScheduledRecipe { recipe_id, date };
+                    let _ =
+                        request::delete::<(), _>("calendar/remove_scheduled_recipe", body).await;
+                    target.parent_element().unwrap().remove();
+                }
+            });
         }
     })
     .forget();
index 96e18b2..eb282f3 100644 (file)
@@ -267,16 +267,11 @@ pub fn setup_page(recipe_id: i64) -> Result<(), JsValue> {
                 let body = ron_api::Id { id: recipe_id };
                 let _ = request::delete::<(), _>("recipe/remove", body).await;
                 window().location().set_href("/").unwrap();
-
-                // by_id::<Element>(&format!("group-{}", group_id)).remove();
             }
         });
     })
     .forget();
 
-    // let group_dropzone: Element = selector(".dropzone-group");
-    // setup_dragzone_events(&group_dropzone);
-
     // Load initial groups, steps and ingredients.
     {
         spawn_local(async move {