use lan_party_core::user::User; use log::debug; use sycamore::{futures::spawn_local_scoped, prelude::*}; use web_sys::Event; use crate::util::api_request; #[component] pub fn UsersPage<'a, G: Html>(cx: Scope<'a>) -> View { let users = create_signal(cx, Vec::::new()); spawn_local_scoped(cx, async move { users.set( api_request::<_, Vec>(reqwasm::http::Method::GET, "/user", Option::<()>::None) .await .map(|inner| inner.unwrap()) .unwrap(), ); }); let handle_click = move |event: Event| { debug!("{:#?}", event); }; view! { cx, Page { ul { Keyed( iterable=users, view=|cx, user| view! { cx, li { (user.name) } }, key=|user| user.name.clone(), ) } Button(onclick=handle_click,text="Click me".to_string()) } } } // Temp #[derive(Prop)] pub struct PageProps<'a, G: Html> { pub children: Children<'a, G>, } #[component] pub fn Page<'a, G: Html>(cx: Scope<'a>, props: PageProps<'a, G>) -> View { let children = props.children.call(cx); view! { cx, div(class="max-w-7xl mx-auto") { (children) } } } #[derive(Prop)] pub struct Props { pub onclick: F, #[builder(default)] pub text: String, #[builder(default)] pub icon: String, } #[component] pub fn Button<'a, G: Html, F: 'a + FnMut(Event)>(cx: Scope<'a>, props: Props) -> View { let mut icon_class = String::from("mdi text-lg "); if !props.icon.is_empty() { icon_class.push_str(&props.icon); } view! { cx, button(class="bg-gray-700 hover:bg-gray-800 text-gray-400 font-bold py-2 px-2 rounded inline-flex items-center",on:click=props.onclick) { span(class=icon_class) span { (props.text) } } } } #[derive(Prop)] pub struct TableProps<'a, G: Html> { pub headers: Vec, pub rows: Vec>, pub loading: bool, #[builder(default)] pub children: Children<'a, G>, } #[component] pub fn table<'a, G: Html>(props: TableProps<'a, G>) -> View { let children = props.children.call(cx); view! { cx, div(class="inline-block min-w-full py-2 align-middle") { div(class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 md:rounded-lg") { table(class="min-w-full divide-y divide-gray-600") { thead(class="bg-gray-800") { tr { (props.headers.iter().map(|header| view! { cx, th( scope="col", class="px-3 py-3.5 text-left text-sm font-semibold text-gray-400" ) { (header) } }).collect()) } } tbody(class="divide-y divide-gray-600 bg-gray-700") { (props.rows.iter().map(|row| view! { cx, tr { {row.iter().map(|value| html! { td(class="whitespace-nowrap px-3 py-4 text-sm text-gray-400"){ (value) } }).collect()} } }).collect()) (children) (if props.loading == true { view! { tr { td(colspan={(props.headers.len() + 1).to_string()} class="py-3") { div(class="grid place-items-center") { "Loading ..." } } } }} else { view! {} }) } } } } } }