//#![allow(unused_imports)] //#![allow(dead_code)] //#![allow(unused_variables)] // Suppress leptos_router warnings about reactive signal access outside tracking context #![allow(clippy::redundant_closure)] //#![allow(unused_assignments)] //use crate::defs::{NAV_LINK_CLASS, ROUTES}; use crate::auth::AuthProvider; use crate::components::NavbarLogo; use crate::i18n::{I18nProvider, LanguageSelector, use_i18n}; use crate::pages::{AboutPage, DaisyUIPage, FeaturesDemoPage, HomePage}; use crate::state::*; use crate::utils::{get_initial_path, make_navigate, make_on_link_click, make_popstate_effect}; use leptos::children::Children; use leptos::prelude::*; use leptos_meta::{MetaTags, Title, provide_meta_context}; // use regex::Regex; use shared::{get_bundle, load_menu_toml, t}; use std::collections::HashMap; //// Wrapper component for consistent layout. #[component] fn Wrapper(children: Children) -> impl IntoView { view! { <>{children()} } } /// NotFoundPage component for 404s. #[component] fn NotFoundPage() -> impl IntoView { view! {
"Page not found."
} } /// Navigation menu component, maps over ROUTES. #[component] pub fn NavMenu(path: ReadSignal, set_path: WriteSignal) -> impl IntoView { let navigate = make_navigate(set_path.clone()); let on_link_click = make_on_link_click(set_path.clone(), navigate.clone()); let i18n = use_i18n(); let menu_items = load_menu_toml().unwrap_or_default(); println!("NavMenu rendered"); view! { } // view! { // //} } /// Main app component with SSR path awareness and SPA routing. #[component] pub fn App() -> impl IntoView { provide_meta_context(); let (path, set_path) = signal(get_initial_path()); make_popstate_effect(set_path); let (lang, _set_lang) = signal("en".to_string()); // --- Unit test placeholder for route matching --- // #[cfg(test)] // mod tests { // use super::*; // #[test] // fn test_user_route() { // let re = Regex::new(r"^/user/(\\d+)$").expect("Valid regex"); // assert!(re.is_match("/user/42")); // } // } view! { <header class="absolute inset-x-0 top-0 z-50"> <Wrapper><NavMenu path=path set_path=set_path /></Wrapper> </header> <div class="min-h-screen bg-gray-50"> <main class="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8"> { let lang = lang.clone(); let path = path.clone(); move || { let p = path.get(); let lang_val = lang.get(); let bundle = get_bundle(&lang_val).unwrap_or_else(|_| { // Fallback to a simple bundle if loading fails use fluent::FluentBundle; use unic_langid::LanguageIdentifier; let langid: LanguageIdentifier = "en".parse().unwrap_or_else(|e| { web_sys::console::error_1(&format!("Failed to parse default language 'en': {:?}", e).into()); // This should never happen, but create a minimal fallback LanguageIdentifier::from_parts( unic_langid::subtags::Language::from_bytes(b"en").unwrap_or_else(|e| { web_sys::console::error_1(&format!("Critical error: failed to create 'en' language: {:?}", e).into()); // Fallback to creating a new language identifier from scratch match "en".parse::<unic_langid::subtags::Language>() { Ok(lang) => lang, Err(_) => { // If even this fails, we'll use the default language web_sys::console::error_1(&"Using default language as final fallback".into()); unic_langid::subtags::Language::default() } } }), None, None, &[], ) }); FluentBundle::new(vec![langid]) }); let content = match p.as_str() { "/" => t(&bundle, "main-desc", None), "/about" => t(&bundle, "about-desc", None), "/daisyui" => "DaisyUI Components Demo".to_string(), "/features-demo" => "New Features Demo".to_string(), _ if p.starts_with("/user/") => { if let Some(id) = p.strip_prefix("/user/") { let mut args = HashMap::new(); args.insert("id", id); t(&bundle, "user-page", Some(&args)) } else { t(&bundle, "not-found", None) } }, _ => t(&bundle, "not-found", None), }; view! { <Wrapper> <div>{content}</div> {match p.as_str() { "/" => view! { <div><HomePage /></div> }.into_any(), "/about" => view! { <div><AboutPage /></div> }.into_any(), "/daisyui" => view! { <div><DaisyUIPage /></div> }.into_any(), "/features-demo" => view! { <div><FeaturesDemoPage /></div> }.into_any(), _ => view! { <div>Not found</div> }.into_any(), }} </Wrapper> } }} </main> </div> </AppStateProvider> </UserProvider> </AuthProvider> </ToastProvider> </I18nProvider> </ThemeProvider> </GlobalStateProvider> } } /// The SSR shell for Leptos/Axum integration. pub fn shell(options: LeptosOptions) -> impl IntoView { view! { <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <AutoReload options=options.clone() /> <HydrationScripts options/> <link rel="stylesheet" id="leptos" href="/pkg/website.css"/> <link rel="shortcut icon" type="image/ico" href="/favicon.ico"/> <MetaTags/> </head> <body> <App /> </body> </html> } }