From d8641d4db66504d9ecc4010eb69dcfbef59fcfdb Mon Sep 17 00:00:00 2001 From: Greg Burri <greg.burri@gmail.com> Date: Sun, 2 Feb 2025 12:50:12 +0100 Subject: [PATCH] Calendar (WIP): user can select a day --- Cargo.lock | 20 ++--- backend/scss/calendar.scss | 8 ++ backend/templates/calendar.html | 9 +- frontend/src/calendar.rs | 154 ++++++++++++++++---------------- 4 files changed, 100 insertions(+), 91 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 04b5c9f..aef3812 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -123,9 +123,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.85" +version = "0.1.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" +checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" dependencies = [ "proc-macro2", "quote", @@ -333,9 +333,9 @@ checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.2.10" +version = "1.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" +checksum = "e4730490333d58093109dc02c23174c3f4d490998c3fed3cc8e82d57afedb9cf" dependencies = [ "shlex", ] @@ -2126,9 +2126,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.21" +version = "0.23.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" +checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7" dependencies = [ "log", "once_cell", @@ -2605,9 +2605,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.96" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -3154,9 +3154,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.7" +version = "0.26.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" +checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" dependencies = [ "rustls-pki-types", ] diff --git a/backend/scss/calendar.scss b/backend/scss/calendar.scss index 77e5a9b..c14668b 100644 --- a/backend/scss/calendar.scss +++ b/backend/scss/calendar.scss @@ -45,6 +45,14 @@ &.current-month { background-color: blue; } + + &.today { + font-weight: bold; + } + + &.selected-day { + background-color: red; + } } } } \ No newline at end of file diff --git a/backend/templates/calendar.html b/backend/templates/calendar.html index 435e48e..9793da8 100644 --- a/backend/templates/calendar.html +++ b/backend/templates/calendar.html @@ -36,9 +36,12 @@ {% endfor %} <ul class="days"> - {% for i in 0..7 %} - {% for j in 0..5 %} - <li id="day-{{i}}{{j}}"><div class="number"></div><div class="scheduled-recipes"></div></li> + {% for i in 0..5 %} + {% for j in 0..7 %} + <li id="day-grid-{{i}}{{j}}"> + <div class="number"></div> + <div class="scheduled-recipes"></div> + </li> {% endfor %} {% endfor %} </ul> diff --git a/frontend/src/calendar.rs b/frontend/src/calendar.rs index b715117..dec6540 100644 --- a/frontend/src/calendar.rs +++ b/frontend/src/calendar.rs @@ -1,9 +1,6 @@ -use std::sync::{ - atomic::{AtomicI32, AtomicU32, Ordering}, - Arc, Mutex, -}; +use std::sync::{Arc, Mutex}; -use chrono::{offset::Local, DateTime, Datelike, Days, Months, NaiveDate, Weekday}; +use chrono::{offset::Local, DateTime, Datelike, Days, Months, Weekday}; use common::ron_api; use gloo::{console::log, events::EventListener}; use wasm_bindgen::prelude::*; @@ -12,11 +9,11 @@ use web_sys::Element; use crate::{ request, - utils::{by_id, selector, SelectorExt}, + utils::{by_id, SelectorExt}, }; struct CalendarStateInternal { - current_date: DateTime<Local>, + displayed_date: DateTime<Local>, selected_date: DateTime<Local>, } @@ -30,39 +27,33 @@ impl CalendarState { let current_date = Local::now(); Self { internal_state: Arc::new(Mutex::new(CalendarStateInternal { - current_date, + displayed_date: current_date, selected_date: current_date, })), } } - pub fn to_next_month(&self) -> DateTime<Local> { + pub fn displayed_date_next_month(&self) { let mut locker = self.internal_state.lock().unwrap(); - let new_date = locker - .current_date - .checked_add_months(Months::new(1)) - .unwrap(); - locker.current_date = new_date; - new_date + locker.displayed_date = locker.displayed_date + Months::new(1); } - pub fn to_previous_month(&self) -> DateTime<Local> { + pub fn displayed_date_previous_month(&self) { let mut locker = self.internal_state.lock().unwrap(); - let new_date = locker - .current_date - .checked_sub_months(Months::new(1)) - .unwrap(); - locker.current_date = new_date; - new_date + locker.displayed_date = locker.displayed_date - Months::new(1); } - pub fn get_current_date(&self) -> DateTime<Local> { - self.internal_state.lock().unwrap().current_date + pub fn get_displayed_date(&self) -> DateTime<Local> { + self.internal_state.lock().unwrap().displayed_date } pub fn get_selected_date(&self) -> DateTime<Local> { self.internal_state.lock().unwrap().selected_date } + + pub fn set_selected_date(&self, date: DateTime<Local>) { + self.internal_state.lock().unwrap().selected_date = date; + } } pub fn setup(calendar: Element) { @@ -71,55 +62,49 @@ pub fn setup(calendar: Element) { let state = CalendarState::new(); - display_month(&calendar, state.get_current_date()); + display_month(&calendar, state.clone()); + // Click on previous month. let calendar_clone = calendar.clone(); let state_clone = state.clone(); EventListener::new(&prev, "click", move |_event| { - let m = state_clone.to_previous_month(); - display_month(&calendar_clone, m); + state_clone.displayed_date_previous_month(); + display_month(&calendar_clone, state_clone.clone()); }) .forget(); + // Click on next month. let calendar_clone = calendar.clone(); let state_clone = state.clone(); EventListener::new(&next, "click", move |_event| { - let m = state_clone.to_next_month(); - display_month(&calendar_clone, m); + state_clone.displayed_date_next_month(); + display_month(&calendar_clone, state_clone.clone()); }) .forget(); - // let days: Element = calendar.selector(".days"); - // let state_clone = state.clone(); - // EventListener::new(&days, "click", move |event| { - // log!(event); - // let target: Element = event.target().unwrap().dyn_into().unwrap(); - // if - // }) - // .forget(); - - // let calendar_clone = calendar.clone(); - // let current_month_clone = current_month.clone(); - // let current_year_clone = current_year.clone(); - // EventListener::new(&next, "click", move |_event| { - // let mut m = current_month_clone.load(Ordering::Relaxed) + 1; - // if m == 13 { - // current_year_clone.fetch_add(1, Ordering::Relaxed); - // m = 1 - // } - // current_month_clone.store(m, Ordering::Relaxed); - // display_month( - // &calendar_clone, - // current_year_clone.load(Ordering::Relaxed), - // m, - // ); - // }) - // .forget(); + // Click on a day of the current month. + let days: Element = calendar.selector(".days"); + let calendar_clone = calendar.clone(); + let state_clone = state.clone(); + EventListener::new(&days, "click", move |event| { + let target: Element = event.target().unwrap().dyn_into().unwrap(); + if target.class_name() == "number" { + let first_day = first_grid_day(state_clone.get_displayed_date()); + let day_grid_id = target.parent_element().unwrap().id(); + let day_offset = day_grid_id[9..10].parse::<u64>().unwrap() * 7 + + day_grid_id[10..11].parse::<u64>().unwrap(); + state_clone.set_selected_date(first_day + Days::new(day_offset)); + display_month(&calendar_clone, state_clone.clone()); + } + }) + .forget(); } const NB_CALENDAR_ROW: u64 = 5; -fn display_month(calendar: &Element, date: DateTime<Local>) { +fn display_month(calendar: &Element, state: CalendarState) { + let date = state.get_displayed_date(); + calendar .selector::<Element>(".year") .set_inner_html(&date.year().to_string()); @@ -136,31 +121,36 @@ fn display_month(calendar: &Element, date: DateTime<Local>) { } } - let mut current = date; - - while (current - Days::new(1)).month() == date.month() { - current = current - Days::new(1); - } - - while current.weekday() != Weekday::Mon { - current = current - Days::new(1); - } - - let first_day = current; + let first_day = first_grid_day(date); + let mut current = first_day; - for i in 0..7 { - for j in 0..NB_CALENDAR_ROW { - let day_element: Element = by_id(&format!("day-{}{}", i, j)); + for i in 0..NB_CALENDAR_ROW { + for j in 0..7 { + let day_element: Element = by_id(&format!("day-grid-{}{}", i, j)); let day_content: Element = day_element.selector(".number"); day_content.set_inner_html(¤t.day().to_string()); - if current == Local::now() { - day_element.set_class_name("current-month today"); - } else if current.month() == date.month() { - day_element.set_class_name("current-month"); - } else { - day_element.set_class_name(""); + let mut class_name = String::new(); + + if current.month() == date.month() { + if !class_name.is_empty() { + class_name += " "; + } + class_name += "current-month"; + } + if current.date_naive() == Local::now().date_naive() { + if !class_name.is_empty() { + class_name += " "; + } + class_name += "today"; + } + if current.date_naive() == state.get_selected_date().date_naive() { + if !class_name.is_empty() { + class_name += " "; + } + class_name += "selected-day" } + day_element.set_class_name(&class_name); current = current + Days::new(1); } @@ -185,7 +175,15 @@ fn display_month(calendar: &Element, date: DateTime<Local>) { for recipe in scheduled_recipes.recipes { log!(recipe.1); } - - // create_tag_elements(recipe_id, &tags.tags); }); } + +fn first_grid_day(mut date: DateTime<Local>) -> DateTime<Local> { + while (date - Days::new(1)).month() == date.month() { + date = date - Days::new(1); + } + while date.weekday() != Weekday::Mon { + date = date - Days::new(1); + } + date +} -- 2.49.0