diff --git a/web/src/' b/web/src/' deleted file mode 100644 index cbbf641..0000000 --- a/web/src/' +++ /dev/null @@ -1,139 +0,0 @@ -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! {} }) - } - } - } - } - } -} diff --git a/web/src/event_old.rs b/web/src/event_old.rs deleted file mode 100644 index 9f70a58..0000000 --- a/web/src/event_old.rs +++ /dev/null @@ -1,448 +0,0 @@ -use crate::components::*; -use std::collections::{HashMap, HashSet}; - -use lan_party_core::event::{ - free_for_all_game::{FreeForAllGame, FreeForAllGameRanking, FreeForAllGameSpec}, - team_game::{TeamGame, TeamGameSpec}, - test::{Test, TestSpec}, - *, -}; -use paste::paste; -use wasm_bindgen::JsValue; -use yew::prelude::*; - -use crate::{bind, bind_change, bind_value, clone, clone_cb}; - -macro_rules! view_fields { - ($(($name:expr, $prop:expr)),* $(,)?) => { - html! { - <> - $( -

- { $name } - { $prop.view() } -

- )* - - } - }; -} - -macro_rules! view_struct { - ($struct:path: $title:expr => $(($name:expr, $prop:ident)),* $(,)?) => { - impl View for $struct { - fn view(&self) -> Html { - html! { - - { view_fields!( - $(($name, self.$prop),)* - )} - - } - } - } - }; - ($struct:path as $self:ident => $body:expr) => { - impl View for $struct { - fn view(&$self) -> Html { - $body - } - } - }; -} - -macro_rules! view_enum_simple { - ($enum:path: $($variant:ident),* $(,)?) => { - impl View for $enum { - fn view(&self) -> Html { - html! { - {match self { - $( - Self::$variant(i) => html! { - <> - { i.view() } - - }, - )* - }} - } - } - } - }; -} - -#[derive(Debug, Clone, Properties, PartialEq)] -pub struct BlockProps { - title: String, - children: Children, -} - -#[function_component(Block)] -pub fn block(props: &BlockProps) -> Html { - let open = use_state(|| false); - let mut class = classes!("overflow-hidden"); - - if !*open { - class.push("max-h-1"); - } - - html! { - <> -
-

move |_| open.set(!*open))}>{ &props.title }

-
-
-
- {for props.children.iter()} -
-
-
- - } -} - -pub trait View { - fn view(&self) -> Html; -} - -impl View for bool { - fn view(&self) -> Html { - html! { - - } - } -} - -pub trait ViewPlain: Into + std::fmt::Display {} - -impl View for T -where - T: ViewPlain, -{ - fn view(&self) -> Html { - self.into() - } -} - -impl ViewPlain for i64 {} -impl ViewPlain for i32 {} -impl ViewPlain for isize {} - -impl ViewPlain for u64 {} -impl ViewPlain for u32 {} -impl ViewPlain for usize {} - -impl ViewPlain for f64 {} -impl ViewPlain for f32 {} - -impl ViewPlain for String {} -impl<'a> ViewPlain for &'a str {} - -macro_rules! view_iter { - ($t:ident => $type:ty) => { - impl<$t: View> View for $type { - fn view(&self) -> Html { - html! { - -
    - { self.iter().map(|x| html! {
  • { x.view() }
  • }).collect::() } -
-
- } - } - } - }; -} - -view_iter!(T => Vec); -view_iter!(T => HashSet); -view_iter!(T => &[T]); - -impl View for Option { - fn view(&self) -> Html { - match self { - Some(content) => content.view(), - None => html! { "None" }, - } - } -} - -impl View for HashMap { - fn view(&self) -> Html { - html! { - - {self.iter().map(|(k, v)| { - html! {

{k.view()}{ ": " }{v.view()}

} - }).collect::()} -
- } - } -} - -view_struct!( - lan_party_core::event::Event: "Event" => - ("Name: ", name), - ("Description: ", description), - ("Concluded: ", concluded), - ("Event type: ", event_type), -); - -view_enum_simple!( - lan_party_core::event::EventType: Test, - TeamGame, - FreeForAllGame -); - -view_struct!( - lan_party_core::event::test::Test: "Test" => - ("Number of players: ", num_players) -); - -view_struct!(FreeForAllGame as self => - html! { - - { view_fields!(("Ranking: ", self.ranking)) } - { view_fields!( - ("Participants: ", self.spec.participants), - ("Win rewards: ", self.spec.win_rewards), - ("Lose rewards: ", self.spec.lose_rewards), - ) } - - } -); - -view_enum_simple!( - lan_party_core::event::free_for_all_game::FreeForAllGameRanking: Ranking, - Scores -); - -view_struct!(TeamGame as self => - html! { - - { view_fields!(("Teams: ", self.teams)) } - { view_fields!(("Ranking: ", self.ffa_game.ranking)) } - { view_fields!( - ("Participants: ", self.ffa_game.spec.participants), - ("Win rewards: ", self.ffa_game.spec.win_rewards), - ("Lose rewards: ", self.ffa_game.spec.lose_rewards), - ) } - - } -); - -macro_rules! edit_fields { - ($(($name:expr, $prop:expr)),* $(,)?) => { - html! { - <> - $( -

- { $name } - { $prop.edit() } -

- )* - - } - }; -} - -macro_rules! link_fields { - ($($field:ident),* $(,)? => $state:ident as $t:ident) => { - $(let $field = use_state(|| $state.$field.clone());)* - - use_effect_with_deps( - clone!($($field,)* $state => - move |_| { - $state.set($t { - $($field: (*$field).clone(),)* - ..Default::default() - }); - || { $(drop($field);)* drop($state); } - } - ), - ($($field.clone(),)*), - ); - }; -} - -macro_rules! link_variants { - ($selected:ident => $($index:literal: $var_name:ident = $variant:ident: $var_type:ty),* $(,)? => $state:ident as $t:ident) => { - let $selected = use_state(|| 0 as usize); - $(let $var_name = if let $t::$variant(v) = &*$state { - use_state(|| v.clone()) - } else { - use_state(|| <$var_type>::default()) - };)* - - use_effect_with_deps( - clone!($($var_name,)* $state, $selected => - move |_| { - match *$selected { - $($index => $state.set($t::$variant((*$var_name).clone())),)* - _ => unreachable!() - } - || { $(drop($var_name);)* drop($selected); drop($state); } - } - ), - ($($var_name.clone(),)* $selected.clone()), - ); - }; -} - -macro_rules! edit_struct { - ($struct:ident => $(($name:expr, $prop:ident)),* $(,)?) => { - paste! { - #[function_component([<$struct Edit>])] - pub fn [<$struct:lower _edit>](props: &EditProps<$struct>) -> Html { - let state = props.state.clone(); - link_fields!($($prop,)* => state as $struct); - html! { - - { edit_fields!($(($name, $prop)),*) } - - } - } - - impl Editable for $struct { - type Edit = [<$struct Edit>]; - } - } - }; -} - -macro_rules! edit_enum { - ($enum:ident => $selected:ident => $($index:literal: $var_name:ident = $variant:ident: $var_type:ty),* $(,)?) => { - paste! { - #[function_component([<$enum Edit>])] - pub fn [<$enum:lower _edit>](props: &EditProps<$enum>) -> Html { - let state = props.state.clone(); - - link_variants!($selected => - $($index: $var_name = $variant: $var_type,)* - => state as $enum - ); - - html! { - - - { match &*state { - $($enum::$variant(_) => $var_name.edit(),)* - }} - - } - } - - impl Editable for $enum { - type Edit = [<$enum Edit>]; - } - } - }; -} - -#[derive(PartialEq, Properties)] -pub struct EditProps { - pub state: UseStateHandle, -} - -pub trait Edit { - fn edit(&self) -> Html; -} - -impl>, Type: Editable + PartialEq> Edit - for UseStateHandle -{ - fn edit(&self) -> Html { - html!() - } -} - -pub trait Editable { - type Edit: Component; -} - -#[function_component(InputEdit)] -pub fn input_edit(props: &EditProps) -> Html -where - T: PartialEq + Clone + 'static, - Binding: From>, -{ - let string = props.state.clone(); - - html! { - - } -} - -impl Editable for T -where - T: PartialEq + Clone + 'static, - Binding: From>, -{ - type Edit = InputEdit; -} - -#[function_component(Stub)] -pub fn stub(props: &EditProps) -> Html { - html! { "stub" } -} - -impl Editable for Vec { - type Edit = Stub>; -} - -impl Editable for HashMap { - type Edit = Stub>; -} - -edit_struct!(EventSpec => ("Name: ", name), ("Description: ", description), ("Event type: ", event_type)); -edit_struct!(TestSpec => ("Number of players: ", num_players)); -edit_struct!(TeamGameSpec => ); -edit_struct!(FreeForAllGameSpec => ); - -edit_enum!(EventTypeSpec => selected => - 0: test = Test: TestSpec, - 1: team_game = TeamGame: TeamGameSpec, - 2: free_for_all_game = FreeForAllGame: FreeForAllGameSpec -); - -edit_enum!(FreeForAllGameRanking => selected => - 0: ranking = Ranking: Vec, - 1: scores = Scores: HashMap, -); - -/* -#[function_component(EventTypeSpecEdit)] -pub fn event_type_spec_edit(props: &EditProps) -> Html { - let state = props.state.clone(); - - link_variants!(selected => - 0: test = Test: TestSpec, - 1: team_game = TeamGame: TeamGameSpec, - 2: free_for_all_game = FreeForAllGame: FreeForAllGameSpec - => state as EventTypeSpec - ); - - html! { - - - { match &*state { - EventTypeSpec::Test(_) => test.edit(), - EventTypeSpec::TeamGame(_) => team_game.edit(), - EventTypeSpec::FreeForAllGame(_) => free_for_all_game.edit(), - }} - - } -} - -impl Editable for EventTypeSpec { - type Edit = EventTypeSpecEdit; -} -*/ diff --git a/web/src/pages/events_old.rs b/web/src/pages/events_old.rs deleted file mode 100644 index 2b37971..0000000 --- a/web/src/pages/events_old.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::{ - components::{ - event::{Edit, EventSpecEdit}, - Button, Page, View, - }, - init, -}; -use lan_party_core::event::EventSpec; -use wasm_bindgen::JsValue; -use wasm_bindgen_futures::spawn_local; -use yew::prelude::*; -use yew_hooks::*; - -use crate::{clone, clone_cb, util::api_request}; - -#[function_component(EventsPage)] -pub fn events_page() -> Html { - let events = use_state(|| Vec::new()); - - init!(events => { - events.set(api_request::<_, Vec>(reqwasm::http::Method::GET, "/event", Option::<()>::None) - .await - .map(|inner| inner.unwrap()) - .unwrap()) - }); - - //let edit_event = use_state(|| EventSpecEditHandle::to_edit(EventSpec::default())); - let event_spec = use_state(|| EventSpec::default()); - - html! { - - { events.view() } - - { event_spec.edit() } - -