- Created dedicated EventModal component in src/components/event_modal.rs - Extracted modal logic and styling from calendar component for better separation - Updated data flow to pass full CalendarEvent objects instead of strings - Added PartialEq derive to CalendarEvent for component props - Updated service layer to group events by CalendarEvent objects - Enhanced event click handling to show detailed event information - Modal displays title, description, location, start/end times, and status - Maintained existing modal styling and user interaction patterns 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
101 lines
3.6 KiB
Rust
101 lines
3.6 KiB
Rust
use yew::prelude::*;
|
||
use chrono::{DateTime, Utc};
|
||
use crate::services::CalendarEvent;
|
||
|
||
#[derive(Properties, PartialEq)]
|
||
pub struct EventModalProps {
|
||
pub event: Option<CalendarEvent>,
|
||
pub on_close: Callback<()>,
|
||
}
|
||
|
||
#[function_component]
|
||
pub fn EventModal(props: &EventModalProps) -> Html {
|
||
let close_modal = {
|
||
let on_close = props.on_close.clone();
|
||
Callback::from(move |_| {
|
||
on_close.emit(());
|
||
})
|
||
};
|
||
|
||
let backdrop_click = {
|
||
let on_close = props.on_close.clone();
|
||
Callback::from(move |e: MouseEvent| {
|
||
if e.target() == e.current_target() {
|
||
on_close.emit(());
|
||
}
|
||
})
|
||
};
|
||
|
||
if let Some(ref event) = props.event {
|
||
html! {
|
||
<div class="modal-backdrop" onclick={backdrop_click}>
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h3>{"Event Details"}</h3>
|
||
<button class="modal-close" onclick={close_modal}>{"×"}</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="event-detail">
|
||
<strong>{"Title:"}</strong>
|
||
<span>{event.get_title()}</span>
|
||
</div>
|
||
{
|
||
if let Some(ref description) = event.description {
|
||
html! {
|
||
<div class="event-detail">
|
||
<strong>{"Description:"}</strong>
|
||
<span>{description}</span>
|
||
</div>
|
||
}
|
||
} else {
|
||
html! {}
|
||
}
|
||
}
|
||
{
|
||
if let Some(ref location) = event.location {
|
||
html! {
|
||
<div class="event-detail">
|
||
<strong>{"Location:"}</strong>
|
||
<span>{location}</span>
|
||
</div>
|
||
}
|
||
} else {
|
||
html! {}
|
||
}
|
||
}
|
||
<div class="event-detail">
|
||
<strong>{"Start:"}</strong>
|
||
<span>{format_datetime(&event.start, event.all_day)}</span>
|
||
</div>
|
||
{
|
||
if let Some(ref end) = event.end {
|
||
html! {
|
||
<div class="event-detail">
|
||
<strong>{"End:"}</strong>
|
||
<span>{format_datetime(end, event.all_day)}</span>
|
||
</div>
|
||
}
|
||
} else {
|
||
html! {}
|
||
}
|
||
}
|
||
<div class="event-detail">
|
||
<strong>{"Status:"}</strong>
|
||
<span>{&event.status}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
}
|
||
} else {
|
||
html! {}
|
||
}
|
||
}
|
||
|
||
fn format_datetime(dt: &DateTime<Utc>, all_day: bool) -> String {
|
||
if all_day {
|
||
dt.format("%B %d, %Y").to_string()
|
||
} else {
|
||
dt.format("%B %d, %Y at %I:%M %p").to_string()
|
||
}
|
||
} |