Implement comprehensive calendar UX improvements

- Add time range display to week view events showing "start - end" format
- Optimize time display with smart AM/PM formatting to reduce redundancy
- Fix context menu overlap by adding stop_propagation to event handlers
- Implement persistent view mode (Month/Week) across page refreshes using localStorage
- Replace month-based tracking with intelligent selected date tracking
- Add day selection in month view with visual feedback and click handlers
- Fix view switching to navigate to week containing selected day, not first week of month
- Separate selected_date from display_date for proper context switching
- Simplify week view header to show "Month Year" instead of "Week of Month Day"
- Add backward compatibility for existing localStorage keys

Greatly improves calendar navigation and user experience with persistent state

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Connor Johnstone
2025-08-29 10:44:44 -04:00
parent 5d0628878b
commit a8bb2c8164
5 changed files with 169 additions and 46 deletions

View File

@@ -18,6 +18,10 @@ pub struct MonthViewProps {
pub on_event_context_menu: Option<Callback<(web_sys::MouseEvent, CalendarEvent)>>,
#[prop_or_default]
pub on_calendar_context_menu: Option<Callback<(web_sys::MouseEvent, NaiveDate)>>,
#[prop_or_default]
pub selected_date: Option<NaiveDate>,
#[prop_or_default]
pub on_day_select: Option<Callback<NaiveDate>>,
}
#[function_component(MonthView)]
@@ -65,11 +69,27 @@ pub fn month_view(props: &MonthViewProps) -> Html {
(1..=days_in_month).map(|day| {
let date = props.current_month.with_day(day).unwrap();
let is_today = date == props.today;
let is_selected = props.selected_date == Some(date);
let day_events = props.events.get(&date).cloned().unwrap_or_default();
html! {
<div
class={classes!("calendar-day", if is_today { Some("today") } else { None })}
class={classes!(
"calendar-day",
if is_today { Some("today") } else { None },
if is_selected { Some("selected") } else { None }
)}
onclick={
if let Some(callback) = &props.on_day_select {
let callback = callback.clone();
Some(Callback::from(move |e: web_sys::MouseEvent| {
e.stop_propagation(); // Prevent other handlers
callback.emit(date);
}))
} else {
None
}
}
oncontextmenu={
if let Some(callback) = &props.on_calendar_context_menu {
let callback = callback.clone();