134 lines
3.6 KiB
Rust
134 lines
3.6 KiB
Rust
mod components;
|
|
mod pages;
|
|
pub mod util;
|
|
|
|
use pages::UsersPage;
|
|
use yew::prelude::*;
|
|
use yew_router::prelude::*;
|
|
|
|
#[derive(Clone, Debug, Routable, PartialEq)]
|
|
enum Route {
|
|
#[at("/")]
|
|
Home,
|
|
#[at("/users")]
|
|
Users,
|
|
#[at("/events")]
|
|
Events,
|
|
}
|
|
|
|
struct Model {
|
|
pages: Vec<Page>,
|
|
}
|
|
|
|
impl Component for Model {
|
|
type Message = ();
|
|
type Properties = ();
|
|
|
|
fn create(_ctx: &Context<Self>) -> Self {
|
|
Self {
|
|
pages: vec![
|
|
Page {
|
|
target: Route::Home,
|
|
name: "Home".into(),
|
|
},
|
|
Page {
|
|
target: Route::Users,
|
|
name: "Users".into(),
|
|
},
|
|
Page {
|
|
target: Route::Events,
|
|
name: "Events".into(),
|
|
},
|
|
],
|
|
}
|
|
}
|
|
|
|
fn view(&self, _ctx: &Context<Self>) -> Html {
|
|
html! {
|
|
<BrowserRouter>
|
|
<Navbar pages={self.pages.clone()} />
|
|
<Switch<Route> render={Switch::render(switch)} />
|
|
</BrowserRouter>
|
|
}
|
|
}
|
|
}
|
|
|
|
fn switch(routes: &Route) -> Html {
|
|
match routes {
|
|
Route::Home => html! { <h1>{ "Home" }</h1> },
|
|
Route::Users => html! {
|
|
<UsersPage />
|
|
},
|
|
Route::Events => html! { <h1>{ "Events" }</h1> },
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
struct Page {
|
|
name: String,
|
|
target: Route,
|
|
}
|
|
|
|
#[derive(Properties, PartialEq, Default)]
|
|
struct NavbarProps {
|
|
#[prop_or_default]
|
|
pub children: Children,
|
|
|
|
pub pages: Vec<Page>,
|
|
}
|
|
|
|
#[function_component(Navbar)]
|
|
fn navbar(props: &NavbarProps) -> Html {
|
|
let active_target = use_state(|| 0);
|
|
|
|
let history = use_history().unwrap();
|
|
|
|
let onclick = |i: usize| {
|
|
let active_target = active_target.clone();
|
|
let history = history.clone();
|
|
let route = props.pages[i].target.clone();
|
|
|
|
Callback::from(move |_| {
|
|
history.push(route.clone());
|
|
active_target.set(i)
|
|
})
|
|
};
|
|
|
|
html! {
|
|
<nav class="bg-gray-800">
|
|
<div class="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
|
|
<div class="relative flex h-16 items-center justify-between">
|
|
<div class="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
|
|
<div class="hidden sm:ml-6 sm:block">
|
|
<div class="flex space-x-4">
|
|
{
|
|
props.pages.iter().enumerate().map(|(i, page)| {
|
|
let mut link_class =
|
|
Classes::from(&["text-sm", "font-medium", "rounded-md", "px-3", "py-2"] as &[&'static str]);
|
|
|
|
if *active_target == i {
|
|
link_class.push(&["bg-gray-900", "text-gray-400"] as &[&'static str])
|
|
} else {
|
|
link_class.push(&["hover:bg-gray-700", "text-gray-400"] as &[&'static str])
|
|
}
|
|
|
|
html! {
|
|
<a role={"button"} onclick={onclick(i)} class={link_class}>{&page.name}</a>
|
|
}
|
|
}).collect::<Html>()
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{ for props.children.iter() }
|
|
</div>
|
|
</nav>
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
yew::start_app::<Model>();
|
|
}
|