webtest/src/app.rs
2025-08-08 08:32:23 +02:00

116 lines
4.3 KiB
Rust

use yew::prelude::*;
use yew_router::prelude::*;
use gloo_utils::document;
use gloo_storage::{LocalStorage, Storage};
use serde::{Deserialize, Serialize};
use crate::home::HomePage;
use crate::kanban::KanbanBoard;
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
enum Theme {
Light,
Dark,
}
impl Theme {
fn as_str(&self) -> &'static str {
match self {
Theme::Light => "light-theme",
Theme::Dark => "dark-theme",
}
}
}
#[derive(Clone, Routable, PartialEq)]
enum Route {
#[at("/")]
Home,
#[at("/kanban")]
Kanban,
#[not_found]
#[at("/404")]
NotFound,
}
fn switch(routes: Route) -> Html {
match routes {
Route::Home => html! { <HomePage /> },
Route::Kanban => html! { <KanbanBoard /> },
Route::NotFound => html! { <h1>{ "404 - Page not found" }</h1> },
}
}
#[function_component(App)]
pub fn app() -> Html {
let theme = use_state(|| {
LocalStorage::get("theme").unwrap_or(Theme::Light)
});
let onclick_theme_toggle = {
let theme = theme.clone();
Callback::from(move |_| {
let new_theme = if *theme == Theme::Light { Theme::Dark } else { Theme::Light };
theme.set(new_theme);
})
};
use_effect_with(theme.clone(), move |theme| {
let body = document().body().expect("body element not found");
body.set_class_name(theme.as_str());
LocalStorage::set("theme", **theme).unwrap();
});
let navbar_class = if *theme == Theme::Dark { "navbar navbar-expand-lg navbar-dark" } else { "navbar navbar-expand-lg navbar-light" };
html! {
<BrowserRouter>
<nav class={navbar_class}>
<div class="container-fluid">
<Link<Route> to={Route::Home} classes="navbar-brand fw-bold">
{"🦀 Yew Bootstrap App"}
</Link<Route>>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<Link<Route> to={Route::Home} classes="nav-link">
<i class="bi bi-house-fill me-1"></i>{"Home"}
</Link<Route>>
</li>
<li class="nav-item">
<Link<Route> to={Route::Kanban} classes="nav-link">
<i class="bi bi-kanban me-1"></i>{"Kanban"}
</Link<Route>>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="bi bi-star-fill me-1"></i>{"Features"}
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="bi bi-currency-dollar me-1"></i>{"Pricing"}
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="bi bi-envelope-fill me-1"></i>{"Contact"}
</a>
</li>
</ul>
<div class="form-check form-switch d-flex align-items-center">
<i class="bi bi-sun-fill me-2 text-warning"></i>
<input class="form-check-input me-2" type="checkbox" id="flexSwitchCheckDefault" onclick={onclick_theme_toggle} checked={*theme == Theme::Dark} />
<i class="bi bi-moon-stars-fill text-info"></i>
</div>
</div>
</div>
</nav>
<Switch<Route> render={switch} />
</BrowserRouter>
}
}