Add current time indicator to week view
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -81,6 +81,31 @@ pub fn week_view(props: &WeekViewProps) -> Html {
|
|||||||
|
|
||||||
let pending_recurring_edit = use_state(|| None::<PendingRecurringEdit>);
|
let pending_recurring_edit = use_state(|| None::<PendingRecurringEdit>);
|
||||||
|
|
||||||
|
// 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
|
// Helper function to get calendar color for an event
|
||||||
let get_event_color = |event: &VEvent| -> String {
|
let get_event_color = |event: &VEvent| -> String {
|
||||||
if let Some(calendar_path) = &event.calendar_path {
|
if let Some(calendar_path) = &event.calendar_path {
|
||||||
@@ -1089,6 +1114,29 @@ pub fn week_view(props: &WeekViewProps) -> Html {
|
|||||||
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! {
|
||||||
|
<div class="current-time-indicator-container">
|
||||||
|
<div
|
||||||
|
class="current-time-indicator"
|
||||||
|
style={format!("top: {}px;", current_time_position)}
|
||||||
|
>
|
||||||
|
<div class="current-time-dot"></div>
|
||||||
|
<div class="current-time-line"></div>
|
||||||
|
<div class="current-time-label">{current_time_str}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
html! {}
|
||||||
|
}
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}).collect::<Html>()
|
}).collect::<Html>()
|
||||||
|
|||||||
@@ -1052,6 +1052,76 @@ body {
|
|||||||
background: linear-gradient(135deg, var(--event-color, #3B82F6), rgba(255,255,255,0.1)) !important;
|
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) */
|
/* Legacy Week Grid (for backward compatibility) */
|
||||||
.week-grid {
|
.week-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|||||||
Reference in New Issue
Block a user