Refactor app.rs by extracting components for better organization
Split monolithic app.rs into focused, reusable components: - Sidebar component for user info, navigation and calendar management - CalendarListItem component for individual calendar items with color picker - RouteHandler component to eliminate duplicated routing logic - Reduced app.rs from 645 to 338 lines (47% reduction) - Improved separation of concerns and maintainability - Clean props-based component communication 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
		
							
								
								
									
										75
									
								
								src/components/calendar_list_item.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/components/calendar_list_item.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| use yew::prelude::*; | ||||
| use web_sys::MouseEvent; | ||||
| use crate::services::calendar_service::CalendarInfo; | ||||
|  | ||||
| #[derive(Properties, PartialEq)] | ||||
| pub struct CalendarListItemProps { | ||||
|     pub calendar: CalendarInfo, | ||||
|     pub color_picker_open: bool, | ||||
|     pub on_color_change: Callback<(String, String)>, // (calendar_path, color) | ||||
|     pub on_color_picker_toggle: Callback<String>, // calendar_path | ||||
|     pub available_colors: Vec<String>, | ||||
|     pub on_context_menu: Callback<(MouseEvent, String)>, // (event, calendar_path) | ||||
| } | ||||
|  | ||||
| #[function_component(CalendarListItem)] | ||||
| pub fn calendar_list_item(props: &CalendarListItemProps) -> Html { | ||||
|     let on_color_click = { | ||||
|         let cal_path = props.calendar.path.clone(); | ||||
|         let on_color_picker_toggle = props.on_color_picker_toggle.clone(); | ||||
|         Callback::from(move |e: MouseEvent| { | ||||
|             e.stop_propagation(); | ||||
|             on_color_picker_toggle.emit(cal_path.clone()); | ||||
|         }) | ||||
|     }; | ||||
|  | ||||
|     let on_context_menu = { | ||||
|         let cal_path = props.calendar.path.clone(); | ||||
|         let on_context_menu = props.on_context_menu.clone(); | ||||
|         Callback::from(move |e: MouseEvent| { | ||||
|             e.prevent_default(); | ||||
|             on_context_menu.emit((e, cal_path.clone())); | ||||
|         }) | ||||
|     }; | ||||
|  | ||||
|     html! { | ||||
|         <li key={props.calendar.path.clone()} oncontextmenu={on_context_menu}> | ||||
|             <span class="calendar-color"  | ||||
|                   style={format!("background-color: {}", props.calendar.color)} | ||||
|                   onclick={on_color_click}> | ||||
|                 { | ||||
|                     if props.color_picker_open { | ||||
|                         html! { | ||||
|                             <div class="color-picker"> | ||||
|                                 { | ||||
|                                     props.available_colors.iter().map(|color| { | ||||
|                                         let color_str = color.clone(); | ||||
|                                         let cal_path = props.calendar.path.clone(); | ||||
|                                         let on_color_change = props.on_color_change.clone(); | ||||
|                                          | ||||
|                                         let on_color_select = Callback::from(move |_: MouseEvent| { | ||||
|                                             on_color_change.emit((cal_path.clone(), color_str.clone())); | ||||
|                                         }); | ||||
|                                          | ||||
|                                         let is_selected = props.calendar.color == *color; | ||||
|                                         let class_name = if is_selected { "color-option selected" } else { "color-option" }; | ||||
|                                          | ||||
|                                         html! { | ||||
|                                             <div class={class_name} | ||||
|                                                  style={format!("background-color: {}", color)} | ||||
|                                                  onclick={on_color_select}> | ||||
|                                             </div> | ||||
|                                         } | ||||
|                                     }).collect::<Html>() | ||||
|                                 } | ||||
|                             </div> | ||||
|                         } | ||||
|                     } else { | ||||
|                         html! {} | ||||
|                     } | ||||
|                 } | ||||
|             </span> | ||||
|             <span class="calendar-name">{&props.calendar.display_name}</span> | ||||
|         </li> | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Connor Johnstone
					Connor Johnstone