116 lines
4.3 KiB
Rust
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>
|
|
}
|
|
}
|