From efbaea5ac1b20c82de9f861178f4e29fd2bcb980 Mon Sep 17 00:00:00 2001 From: Connor Johnstone Date: Fri, 5 Sep 2025 10:33:07 -0400 Subject: [PATCH] Add current time indicator to week view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add real-time current time indicator that updates every 5 seconds - Display horizontal line with dot and time label on current day only - Position indicator accurately based on time increment mode (15/30 min) - Use theme-aware colors with subdued gray styling for dark mode - Include subtle shadows and proper z-indexing for visibility 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- frontend/src/components/week_view.rs | 48 +++++++++++++++++++ frontend/styles.css | 70 ++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/frontend/src/components/week_view.rs b/frontend/src/components/week_view.rs index 6ee396b..314801c 100644 --- a/frontend/src/components/week_view.rs +++ b/frontend/src/components/week_view.rs @@ -81,6 +81,31 @@ pub fn week_view(props: &WeekViewProps) -> Html { let pending_recurring_edit = use_state(|| None::); + // Current time state for time indicator + let current_time = use_state(|| Local::now()); + + // Update current time every 5 seconds + { + let current_time = current_time.clone(); + use_effect_with((), move |_| { + let interval = gloo_timers::callback::Interval::new(5_000, move || { + current_time.set(Local::now()); + }); + + // Return the interval to keep it alive + move || drop(interval) + }); + } + + // Helper function to calculate current time indicator position + let calculate_current_time_position = |time_increment: u32| -> f64 { + let now = current_time.time(); + let hour = now.hour() as f64; + let minute = now.minute() as f64; + let pixels_per_hour = if time_increment == 15 { 120.0 } else { 60.0 }; + (hour + minute / 60.0) * pixels_per_hour + }; + // Helper function to get calendar color for an event let get_event_color = |event: &VEvent| -> String { if let Some(calendar_path) = &event.calendar_path { @@ -1089,6 +1114,29 @@ pub fn week_view(props: &WeekViewProps) -> Html { html! {} } } + + // Current time indicator - only show on today + { + if *date == props.today { + let current_time_position = calculate_current_time_position(props.time_increment); + let current_time_str = current_time.time().format("%I:%M %p").to_string(); + + html! { +
+
+
+
+
{current_time_str}
+
+
+ } + } else { + html! {} + } + } } }).collect::() diff --git a/frontend/styles.css b/frontend/styles.css index 78a4dd0..43bfb3c 100644 --- a/frontend/styles.css +++ b/frontend/styles.css @@ -1052,6 +1052,76 @@ body { background: linear-gradient(135deg, var(--event-color, #3B82F6), rgba(255,255,255,0.1)) !important; } +/* Current Time Indicator */ +.current-time-indicator-container { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + pointer-events: none; + z-index: 20; +} + +.current-time-indicator { + position: absolute; + left: 0; + right: 0; + height: 2px; + z-index: 20; + display: flex; + align-items: center; + pointer-events: none; +} + +.current-time-dot { + width: 8px; + height: 8px; + border-radius: 50%; + background-color: var(--primary-color, #667eea); + position: absolute; + left: -4px; + z-index: 21; + flex-shrink: 0; +} + +.current-time-line { + flex: 1; + height: 2px; + background-color: var(--primary-color, #667eea); + position: relative; +} + +.current-time-label { + position: absolute; + right: -50px; + top: -10px; + background-color: var(--primary-color, #667eea); + color: white; + padding: 2px 6px; + border-radius: 4px; + font-size: 0.7rem; + font-weight: 600; + white-space: nowrap; + box-shadow: 0 2px 4px rgba(0,0,0,0.2); +} + +/* Dark theme override for current time indicator */ +[data-theme="dark"] .current-time-dot { + background-color: #9ca3af; + box-shadow: 0 0 6px rgba(156, 163, 175, 0.4); +} + +[data-theme="dark"] .current-time-line { + background-color: #9ca3af; + box-shadow: 0 1px 3px rgba(156, 163, 175, 0.3); +} + +[data-theme="dark"] .current-time-label { + background-color: #6b7280; + box-shadow: 0 2px 8px rgba(107, 114, 128, 0.4); +} + /* Legacy Week Grid (for backward compatibility) */ .week-grid { display: grid;