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:
		
							
								
								
									
										89
									
								
								src/components/sidebar.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/components/sidebar.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| use yew::prelude::*; | ||||
| use yew_router::prelude::*; | ||||
| use crate::services::calendar_service::UserInfo; | ||||
| use crate::components::CalendarListItem; | ||||
|  | ||||
| #[derive(Clone, Routable, PartialEq)] | ||||
| pub enum Route { | ||||
|     #[at("/")] | ||||
|     Home, | ||||
|     #[at("/login")] | ||||
|     Login, | ||||
|     #[at("/calendar")] | ||||
|     Calendar, | ||||
| } | ||||
|  | ||||
| #[derive(Properties, PartialEq)] | ||||
| pub struct SidebarProps { | ||||
|     pub user_info: Option<UserInfo>, | ||||
|     pub on_logout: Callback<()>, | ||||
|     pub on_create_calendar: Callback<()>, | ||||
|     pub color_picker_open: Option<String>, | ||||
|     pub on_color_change: Callback<(String, String)>, | ||||
|     pub on_color_picker_toggle: Callback<String>, | ||||
|     pub available_colors: Vec<String>, | ||||
|     pub on_calendar_context_menu: Callback<(MouseEvent, String)>, | ||||
| } | ||||
|  | ||||
| #[function_component(Sidebar)] | ||||
| pub fn sidebar(props: &SidebarProps) -> Html { | ||||
|     html! { | ||||
|         <aside class="app-sidebar"> | ||||
|             <div class="sidebar-header"> | ||||
|                 <h1>{"Calendar App"}</h1> | ||||
|                 { | ||||
|                     if let Some(ref info) = props.user_info { | ||||
|                         html! { | ||||
|                             <div class="user-info"> | ||||
|                                 <div class="username">{&info.username}</div> | ||||
|                                 <div class="server-url">{&info.server_url}</div> | ||||
|                             </div> | ||||
|                         } | ||||
|                     } else { | ||||
|                         html! { <div class="user-info loading">{"Loading..."}</div> } | ||||
|                     } | ||||
|                 } | ||||
|             </div> | ||||
|             <nav class="sidebar-nav"> | ||||
|                 <Link<Route> to={Route::Calendar} classes="nav-link">{"Calendar"}</Link<Route>> | ||||
|             </nav> | ||||
|             { | ||||
|                 if let Some(ref info) = props.user_info { | ||||
|                     if !info.calendars.is_empty() { | ||||
|                         html! { | ||||
|                             <div class="calendar-list"> | ||||
|                                 <h3>{"My Calendars"}</h3> | ||||
|                                 <ul> | ||||
|                                     { | ||||
|                                         info.calendars.iter().map(|cal| { | ||||
|                                             html! { | ||||
|                                                 <CalendarListItem | ||||
|                                                     calendar={cal.clone()} | ||||
|                                                     color_picker_open={props.color_picker_open.as_ref() == Some(&cal.path)} | ||||
|                                                     on_color_change={props.on_color_change.clone()} | ||||
|                                                     on_color_picker_toggle={props.on_color_picker_toggle.clone()} | ||||
|                                                     available_colors={props.available_colors.clone()} | ||||
|                                                     on_context_menu={props.on_calendar_context_menu.clone()} | ||||
|                                                 /> | ||||
|                                             } | ||||
|                                         }).collect::<Html>() | ||||
|                                     } | ||||
|                                 </ul> | ||||
|                             </div> | ||||
|                         } | ||||
|                     } else { | ||||
|                         html! { <div class="no-calendars">{"No calendars found"}</div> } | ||||
|                     } | ||||
|                 } else { | ||||
|                     html! {} | ||||
|                 } | ||||
|             } | ||||
|             <div class="sidebar-footer"> | ||||
|                 <button onclick={props.on_create_calendar.reform(|_| ())} class="create-calendar-button"> | ||||
|                     {"+ Create Calendar"} | ||||
|                 </button> | ||||
|                 <button onclick={props.on_logout.reform(|_| ())} class="logout-button">{"Logout"}</button> | ||||
|             </div> | ||||
|         </aside> | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Connor Johnstone
					Connor Johnstone