295 lines
24 KiB
Rust
295 lines
24 KiB
Rust
//#![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! { <div class="text-center">"Page not found."</div> }
|
|
}
|
|
|
|
/// Navigation menu component, maps over ROUTES.
|
|
#[component]
|
|
pub fn NavMenu(path: ReadSignal<String>, set_path: WriteSignal<String>) -> 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! {
|
|
<nav class="rounded-lg border shadow-lg overflow-hidden p-2 bg-white border-stone-200 shadow-stone-950/5 mx-auto w-full max-w-screen-xl">
|
|
<div class="flex items-center">
|
|
<NavbarLogo size="small".to_string() />
|
|
<hr class="ml-1 mr-1.5 hidden h-5 w-px border-l border-t-0 border-secondary-dark lg:block" />
|
|
<div class="hidden lg:block">
|
|
<ul class="mt-4 flex flex-col gap-x-3 gap-y-1.5 lg:mt-0 lg:flex-row lg:items-center">
|
|
{menu_items.menu.into_iter().map(|item| {
|
|
let on_link_click = on_link_click.clone();
|
|
let route = item.route.clone();
|
|
let route_for_click = route.clone();
|
|
let route_for_aria = route.clone();
|
|
let lang_val = i18n.lang_code();
|
|
let label = match lang_val.as_str() {
|
|
"es" => item.label.es.clone(),
|
|
_ => item.label.en.clone(),
|
|
};
|
|
view! {
|
|
<li><a
|
|
href={route.clone()}
|
|
on:click=move |ev| on_link_click(ev, Box::leak(route_for_click.clone().into_boxed_str()))
|
|
class="font-sans antialiased text-sm text-current flex items-center gap-x-2 p-1 hover:text-primary"
|
|
aria-current=move || if path.get() == route_for_aria { Some("page") } else { None as Option<&'static str> }
|
|
>
|
|
<svg width="1.5em" height="1.5em" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="h-4 w-4"><path d="M7 18H10.5H14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 14H7.5H8" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 10H8.5H10" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 2L16.5 2L21 6.5V19" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 20.5V6.5C3 5.67157 3.67157 5 4.5 5H14.2515C14.4106 5 14.5632 5.06321 14.6757 5.17574L17.8243 8.32426C17.9368 8.43679 18 8.5894 18 8.74853V20.5C18 21.3284 17.3284 22 16.5 22H4.5C3.67157 22 3 21.3284 3 20.5Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M14 5V8.4C14 8.73137 14.2686 9 14.6 9H18" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
|
{label}</a>
|
|
</li>
|
|
}
|
|
}).collect_view()}
|
|
<li>
|
|
<a href="#" class="font-sans antialiased text-sm text-current flex items-center gap-x-2 p-1 hover:text-primary">
|
|
<svg width="1.5em" height="1.5em" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="h-4 w-4"><path d="M7 18H10.5H14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 14H7.5H8" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 10H8.5H10" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 2L16.5 2L21 6.5V19" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 20.5V6.5C3 5.67157 3.67157 5 4.5 5H14.2515C14.4106 5 14.5632 5.06321 14.6757 5.17574L17.8243 8.32426C17.9368 8.43679 18 8.5894 18 8.74853V20.5C18 21.3284 17.3284 22 16.5 22H4.5C3.67157 22 3 21.3284 3 20.5Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M14 5V8.4C14 8.73137 14.2686 9 14.6 9H18" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
|
{i18n.t("pages")}</a>
|
|
</li>
|
|
<li>
|
|
<LanguageSelector class="ml-2".to_string() />
|
|
</li>
|
|
// <li>
|
|
// <a href="#" class="font-sans antialiased text-sm text-current flex items-center gap-x-2 p-1 hover:text-primary"><svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="h-4 w-4"><path d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M4.271 18.3457C4.271 18.3457 6.50002 15.5 12 15.5C17.5 15.5 19.7291 18.3457 19.7291 18.3457" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 12C13.6569 12 15 10.6569 15 9C15 7.34315 13.6569 6 12 6C10.3431 6 9 7.34315 9 9C9 10.6569 10.3431 12 12 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg>Account</a>
|
|
// </li>
|
|
// <li>
|
|
// <a href="#" class="font-sans antialiased text-sm text-current flex items-center gap-x-2 p-1 hover:text-primary"><svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="h-4 w-4"><path d="M21 7.35304L21 16.647C21 16.8649 20.8819 17.0656 20.6914 17.1715L12.2914 21.8381C12.1102 21.9388 11.8898 21.9388 11.7086 21.8381L3.30861 17.1715C3.11814 17.0656 3 16.8649 3 16.647L2.99998 7.35304C2.99998 7.13514 3.11812 6.93437 3.3086 6.82855L11.7086 2.16188C11.8898 2.06121 12.1102 2.06121 12.2914 2.16188L20.6914 6.82855C20.8818 6.93437 21 7.13514 21 7.35304Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3.52844 7.29357L11.7086 11.8381C11.8898 11.9388 12.1102 11.9388 12.2914 11.8381L20.5 7.27777" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 21L12 12" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11.6914 11.8285L3.89139 7.49521C3.49147 7.27304 3 7.56222 3 8.01971V16.647C3 16.8649 3.11813 17.0656 3.30861 17.1715L11.1086 21.5048C11.5085 21.727 12 21.4378 12 20.9803V12.353C12 12.1351 11.8819 11.9344 11.6914 11.8285Z" fill="currentColor" stroke="currentColor" stroke-linejoin="round"></path></svg>Blocks</a>
|
|
// </li>
|
|
// <li>
|
|
// <a href="#" class="font-sans antialiased text-sm text-current flex items-center gap-x-2 p-1 hover:text-primary"><svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="h-4 w-4"><path d="M7 6L17 6" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 9L17 9" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M9 17H15" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 12H2.6C2.26863 12 2 12.2686 2 12.6V21.4C2 21.7314 2.26863 22 2.6 22H21.4C21.7314 22 22 21.7314 22 21.4V12.6C22 12.2686 21.7314 12 21.4 12H21M3 12V2.6C3 2.26863 3.26863 2 3.6 2H20.4C20.7314 2 21 2.26863 21 2.6V12M3 12H21" stroke="currentColor"></path></svg>Docs</a>
|
|
// </li>
|
|
</ul>
|
|
</div>
|
|
<div class="ml-auto flex items-center space-x-2">
|
|
<LanguageSelector />
|
|
<div class="w-40">
|
|
<div class="relative w-full">
|
|
<input placeholder="Search here..." type="search" class="w-full aria-disabled:cursor-not-allowed outline-none focus:outline-none text-stone-800 dark:text-white placeholder:text-stone-600/60 ring-transparent border border-stone-200 transition-all ease-in disabled:opacity-50 disabled:pointer-events-none select-none text-sm py-1.5 pl-8 pr-2 ring shadow-sm bg-white rounded-lg duration-100 hover:border-stone-300 hover:ring-none focus:border-stone-400 focus:ring-none peer" />
|
|
<span class="pointer-events-none absolute left-2 top-1/2 -translate-y-1/2 text-stone-600/70 peer-focus:text-stone-800 peer-focus:text-stone-800 dark:peer-hover:text-white dark:peer-focus:text-white transition-all duration-300 ease-in overflow-hidden w-4 h-4"><svg width="1.5em" height="1.5em" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="h-full w-full"><path d="M17 17L21 21" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 11C3 15.4183 6.58172 19 11 19C13.213 19 15.2161 18.1015 16.6644 16.6493C18.1077 15.2022 19 13.2053 19 11C19 6.58172 15.4183 3 11 3C6.58172 3 3 6.58172 3 11Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<button data-dui-toggle="collapse" data-dui-target="#navbar-collapse-search" aria-expanded="false" aria-controls="navbar-collapse-search" class="place-items-center border align-middle select-none font-sans font-medium text-center transition-all duration-300 ease-in disabled:opacity-50 disabled:shadow-none disabled:pointer-events-none text-sm min-w-[34px] min-h-[34px] rounded-md bg-transparent border-transparent text-stone-800 hover:bg-stone-800/5 hover:border-stone-800/5 shadow-none hover:shadow-none ml-1 grid lg:hidden"><svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="h-4 w-4"><path d="M3 5H21" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 12H21" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 19H21" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
|
</button>
|
|
</div>
|
|
<div class="overflow-hidden transition-[max-height] duration-300 ease-in-out max-h-0 lg:hidden" id="navbar-collapse-search">
|
|
<ul class="flex flex-col gap-0.5 mt-2">
|
|
<li>
|
|
<a href="#" class="font-sans antialiased text-sm text-current flex items-center gap-x-2 p-1 hover:text-primary"><svg width="1.5em" height="1.5em" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="h-4 w-4"><path d="M7 18H10.5H14" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 14H7.5H8" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 10H8.5H10" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 2L16.5 2L21 6.5V19" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 20.5V6.5C3 5.67157 3.67157 5 4.5 5H14.2515C14.4106 5 14.5632 5.06321 14.6757 5.17574L17.8243 8.32426C17.9368 8.43679 18 8.5894 18 8.74853V20.5C18 21.3284 17.3284 22 16.5 22H4.5C3.67157 22 3 21.3284 3 20.5Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M14 5V8.4C14 8.73137 14.2686 9 14.6 9H18" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg>{i18n.t("pages")}</a>
|
|
</li>
|
|
<li>
|
|
<a href="#" class="font-sans antialiased text-sm text-current flex items-center gap-x-2 p-1 hover:text-primary"><svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="h-4 w-4"><path d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M4.271 18.3457C4.271 18.3457 6.50002 15.5 12 15.5C17.5 15.5 19.7291 18.3457 19.7291 18.3457" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 12C13.6569 12 15 10.6569 15 9C15 7.34315 13.6569 6 12 6C10.3431 6 9 7.34315 9 9C9 10.6569 10.3431 12 12 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg>Account</a>
|
|
</li>
|
|
<li>
|
|
<a href="#" class="font-sans antialiased text-sm text-current flex items-center gap-x-2 p-1 hover:text-primary"><svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="h-4 w-4"><path d="M21 7.35304L21 16.647C21 16.8649 20.8819 17.0656 20.6914 17.1715L12.2914 21.8381C12.1102 21.9388 11.8898 21.9388 11.7086 21.8381L3.30861 17.1715C3.11814 17.0656 3 16.8649 3 16.647L2.99998 7.35304C2.99998 7.13514 3.11812 6.93437 3.3086 6.82855L11.7086 2.16188C11.8898 2.06121 12.1102 2.06121 12.2914 2.16188L20.6914 6.82855C20.8818 6.93437 21 7.13514 21 7.35304Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3.52844 7.29357L11.7086 11.8381C11.8898 11.9388 12.1102 11.9388 12.2914 11.8381L20.5 7.27777" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 21L12 12" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11.6914 11.8285L3.89139 7.49521C3.49147 7.27304 3 7.56222 3 8.01971V16.647C3 16.8649 3.11813 17.0656 3.30861 17.1715L11.1086 21.5048C11.5085 21.727 12 21.4378 12 20.9803V12.353C12 12.1351 11.8819 11.9344 11.6914 11.8285Z" fill="currentColor" stroke="currentColor" stroke-linejoin="round"></path></svg>Blocks</a>
|
|
</li>
|
|
<li>
|
|
<a href="#" class="font-sans antialiased text-sm text-current flex items-center gap-x-2 p-1 hover:text-primary"><svg width="1.5em" height="1.5em" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="h-4 w-4"><path d="M7 6L17 6" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M7 9L17 9" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M9 17H15" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 12H2.6C2.26863 12 2 12.2686 2 12.6V21.4C2 21.7314 2.26863 22 2.6 22H21.4C21.7314 22 22 21.7314 22 21.4V12.6C22 12.2686 21.7314 12 21.4 12H21M3 12V2.6C3 2.26863 3.26863 2 3.6 2H20.4C20.7314 2 21 2.26863 21 2.6V12M3 12H21" stroke="currentColor"></path></svg>Docs</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
}
|
|
// view! {
|
|
// <nav class="bg-white shadow-sm border-b">
|
|
// <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
// <div class="flex justify-between h-16">
|
|
// <div class="flex items-center">
|
|
// <a href="/" on:click={ let on_link_click = on_link_click.clone(); move |ev| on_link_click(ev, "/") } class="text-xl font-bold text-gray-900">"Leptos App"</a>
|
|
// </div>
|
|
// <div class="flex items-center space-x-4">
|
|
// //{ROUTES.iter().map(|(route, label)| {
|
|
// {menu_items.menu.into_iter().map(|item| {
|
|
// let on_link_click = on_link_click.clone();
|
|
// let route = item.route.clone();
|
|
// let route_for_click = route.clone();
|
|
// let route_for_aria = route.clone();
|
|
// let lang_val = lang.get();
|
|
// let label = match lang_val.as_str() {
|
|
// "es" => item.label.es.as_str(),
|
|
// _ => item.label.en.as_str(),
|
|
// };
|
|
// view! {
|
|
// <a
|
|
// href={route.as_str()}
|
|
// on:click=move |ev| on_link_click(ev, Box::leak(route_for_click.clone().into_boxed_str()))
|
|
// class=NAV_LINK_CLASS
|
|
// aria-current=move || if path.get() == route_for_aria { Some("page") } else { None }
|
|
// >{label}</a>
|
|
// }
|
|
// }).collect_view()}
|
|
// { view! {
|
|
// <div class=move || if path.get() != "/" {
|
|
// "flex flex-1 justify-end"
|
|
// } else {
|
|
// "hidden"
|
|
// }>
|
|
// <a href="/" on:click=move |ev| on_link_click(ev, "/")
|
|
// aria-current=move || Some("page")
|
|
// >
|
|
// <span class="-m-1.5 text-gray-900 dark:text-gray-100 hover:text-gray-600 dark:hover:text-gray-300 border border-dashed rounded-xl px-4 py-2 opacity-50 hover:opacity-100 transition-all duration-300">Home</span>
|
|
// </a>
|
|
// </div>
|
|
// }}
|
|
// </div>
|
|
// </div>
|
|
// </div>
|
|
// </nav>
|
|
//}
|
|
}
|
|
|
|
/// 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! {
|
|
<GlobalStateProvider>
|
|
<ThemeProvider>
|
|
<I18nProvider>
|
|
<ToastProvider>
|
|
<AuthProvider>
|
|
<UserProvider>
|
|
<AppStateProvider>
|
|
<Title text="Welcome to Leptos"/>
|
|
<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>
|
|
}
|
|
}
|