lan-party-backend/web/src/main.rs

134 lines
3.6 KiB
Rust

mod components;
mod pages;
pub mod util;
use pages::{EventsPage, 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! { <EventsPage /> },
}
}
#[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>();
}