diff --git a/web/dist/index.html b/web/dist/index.html index fd21a3f..42c435a 100644 --- a/web/dist/index.html +++ b/web/dist/index.html @@ -6,7 +6,7 @@ LAN Party - - + + - \ No newline at end of file + \ No newline at end of file diff --git a/web/src/components/event.rs b/web/src/components/event.rs index 80fe39e..ee5c52f 100644 --- a/web/src/components/event.rs +++ b/web/src/components/event.rs @@ -1,4 +1,4 @@ -use std::str::FromStr; +use std::{marker::PhantomData, str::FromStr}; use crate::components::Block; use lan_party_core::event::{ @@ -32,7 +32,7 @@ macro_rules! edit_fields { macro_rules! link_fields { ($cx:ident, $($field:ident),* $(,)? => $state:ident as $t:ident) => { - $(let $field = create_signal($cx, $state.get().$field.clone());)* + $(let $field = create_signal($cx, $state.get_untracked().$field.clone());)* create_effect($cx, || { $state.set($t { @@ -69,7 +69,7 @@ macro_rules! link_variants { ($cx:ident, $selected:ident => $($index:literal: $var_name:ident = $variant:ident: $var_type:ty),* $(,)? => $state:ident as $t:ident) => { let $selected = create_signal($cx, String::from("0")); - $(let $var_name = if let $t::$variant(v) = $state.get().as_ref().clone() { + $(let $var_name = if let $t::$variant(v) = $state.get_untracked().as_ref().clone() { create_signal($cx, v.clone()) } else { create_signal($cx, <$var_type>::default()) @@ -104,8 +104,9 @@ macro_rules! edit_enum { select(bind:value=$selected) { $(option(value={stringify!($index)}, selected=$index==0) { (stringify!($variant)) })* } - (match state.get().as_ref().clone() { - $($enum::$variant(_) => $var_name.edit(cx),)* + (match $selected.get().as_str() { + $(stringify!($index) => $var_name.edit(cx),)* + _ => unreachable!() }) } } @@ -145,7 +146,12 @@ pub trait Edit<'a, G: Html>: Sized { fn edit(cx: Scope<'a>, props: EditProps<'a, Self>) -> View; } -impl<'a, G: Html, E: Editor<'a, G, Type>, Type: Editable<'a, G, Editor = E>> Edit<'a, G> for Type { +impl<'a, G, E, Type> Edit<'a, G> for Type +where + G: Html, + E: Editor<'a, G, Type>, + Type: Editable<'a, G, Editor = E>, +{ fn edit(cx: Scope<'a>, props: EditProps<'a, Self>) -> View { E::edit(cx, props) } @@ -168,7 +174,7 @@ edit_enum!(EventTypeSpec => selected => ); edit_struct!(TestSpec => ("Number of players", num_players)); -edit_struct!(TeamGameSpec => ); +edit_struct!(TeamGameSpec => ("Win rewards", win_rewards)); edit_struct!(FreeForAllGameSpec => ); pub struct StringEdit; @@ -196,8 +202,6 @@ where } } -//editable!(EventTypeSpec => StubEdit); - pub struct InputEdit; impl<'a, G: Html, T> Editor<'a, G, T> for InputEdit @@ -205,7 +209,7 @@ where T: Editable<'a, G, Editor = InputEdit> + FromStr + ToString + Default, { fn edit(cx: Scope<'a>, props: EditProps<'a, T>) -> View { - let value = create_signal(cx, props.state.get().to_string()); + let value = create_signal(cx, props.state.get_untracked().to_string()); create_effect(cx, || { props @@ -242,7 +246,66 @@ impl<'a, G: Html> Editor<'a, G, bool> for BoolEdit { editable!(bool => BoolEdit); -#[derive(Default, Clone)] +pub struct VecEdit; + +impl<'a, G, T, I> Editor<'a, G, I> for VecEdit +where + G: Html, + T: Editable<'a, G> + Clone + PartialEq + 'a, + I: IntoIterator + FromIterator + Clone, +{ + fn edit(cx: Scope<'a>, props: EditProps<'a, I>) -> View { + let vec = create_signal( + cx, + props + .state + .get_untracked() + .as_ref() + .clone() + .into_iter() + .map(|x| create_signal(cx, x)) + .collect::>(), + ); + //let signal = create_signal(cx, 0); + //let vec2 = vec.get().as_ref().clone(); + //let signal = create_ref(cx, vec.get(0).unwrap()); + + create_effect(cx, || { + props.state.set( + vec.get() + .as_ref() + .iter() + .cloned() + .map(|x| x.get().as_ref().clone()) + .collect(), + ) + }); + + /* + view! { cx, + Indexed( + iterable=vec, + view=|cx: BoundedScope<'_, 'a>, x| { + let signal = create_ref(cx, x); + view! { cx, + (T::edit(cx, x.into())) + } + }, + ) + } + */ + } +} + +impl<'a, G, T> Editable<'a, G> for Vec +where + G: Html, + T: Editable<'a, G> + Clone + PartialEq + 'a, +{ + type Editor = VecEdit; +} + +#[derive(Default, Clone, Debug)] pub struct Test { inner: TestInner, inner2: TestInner, @@ -250,7 +313,7 @@ pub struct Test { edit_struct!(Test => ("Inner", inner), ("Inner 2", inner2)); -#[derive(Default, Clone)] +#[derive(Default, Clone, Debug)] pub struct TestInner { some_text: String, some_number: usize, diff --git a/web/src/components/mod.rs b/web/src/components/mod.rs index b7e0dfe..559a396 100644 --- a/web/src/components/mod.rs +++ b/web/src/components/mod.rs @@ -1,7 +1,9 @@ pub mod event; +use log::debug; use sycamore::prelude::*; use web_sys::Event; +use yew::use_effect; #[derive(Prop)] pub struct Props { diff --git a/web/src/pages/events.rs b/web/src/pages/events.rs index a6a5a06..314e9e9 100644 --- a/web/src/pages/events.rs +++ b/web/src/pages/events.rs @@ -11,13 +11,11 @@ use crate::components::{ #[component] pub fn EventsPage<'a, G: Html>(cx: Scope<'a>) -> View { let event_spec = create_signal(cx, EventSpec::default()); - let test = create_signal(cx, Test::default()); view! { cx, Block(title="Create new event".into()) { - EventSpec::edit(EditProps { state: event_spec }) + (event_spec.edit(cx)) Button(icon="mdi-check".into(), onclick=move |_| debug!("{:#?}", event_spec.get())) - (test.edit(cx)) } } }