Added group view

This commit is contained in:
xeovalyte 2024-04-11 19:45:47 +02:00
parent 1f96cbcba6
commit 1261f53987
No known key found for this signature in database
9 changed files with 239 additions and 32 deletions

View File

@ -40,6 +40,7 @@ pub fn App() -> impl IntoView {
<Route path="/" view=pages::index::HomePage />
<Route path="/add-participant" view=pages::add_participant::AddParticipant />
<Route path="/add-time" view=pages::add_time::AddTime />
<Route path="/groups" view=pages::groups::Groups />
</Routes>
</main>
</Router>

View File

@ -1,48 +1,53 @@
use crate::util::surrealdb::{client::sort_participants, client::Time, schemas};
use crate::util::surrealdb::{client::Time, schemas};
use leptos::*;
/// Renders the home page of your application.
#[component]
pub fn Participants() -> impl IntoView {
let participants_context = use_context::<schemas::ParticipantsContext>().unwrap();
let name = create_rw_signal("".to_string());
let participants_sorted =
create_memo(move |_| sort_participants(participants_context.get(), name.get()));
pub fn Participants(
participants: Signal<Vec<schemas::ParticipantSignal>>,
#[prop(default = true)] show_group: bool,
#[prop(default = true)] show_lifesaver: bool,
#[prop(default = true)] show_hindernis: bool,
#[prop(default = true)] show_popduiken: bool,
) -> impl IntoView {
view! {
<input type="search"
class="participants-search"
placeholder="Search"
autocomplete="off"
autofocus=true
on:input=move |ev| {
name.set(event_target_value(&ev));
}
prop:value=name
/>
<table class="participants-table">
<tr>
<th>"Naam"</th>
<th>"Groep"</th>
<th>"Lifesaver"</th>
<th>"Hindernis"</th>
<th>"Popduiken"</th>
<Show when=move || show_group>
<th>"Groep"</th>
</Show>
<Show when=move || show_lifesaver>
<th>"Lifesaver"</th>
</Show>
<Show when=move || show_hindernis>
<th>"Hindernis"</th>
</Show>
<Show when=move || show_popduiken>
<th>"Popduiken"</th>
</Show>
</tr>
<For
each=move || participants_sorted.get()
each=move || participants.get()
key=|state| state.id.clone()
let:child
>
<tr>
<td>{ move || child.value.get().name }</td>
<td>{ move || child.value.get().group }</td>
<Show when=move || show_group>
<td>{ move || child.value.get().group }</td>
</Show>
{ move || match child.value.get().events {
Some(events) => view! {
<td>{ Time::from_milliseconds_to_string(events.lifesaver.unwrap_or(0)) }</td>
<td>{ Time::from_milliseconds_to_string(events.hindernis.unwrap_or(0)) }</td>
<td>{ Time::from_milliseconds_to_string(events.popduiken.unwrap_or(0)) }</td>
<Show when=move || show_lifesaver>
<td>{ Time::from_milliseconds_to_string(events.lifesaver.unwrap_or(0)) }</td>
</Show>
<Show when=move || show_hindernis>
<td>{ Time::from_milliseconds_to_string(events.hindernis.unwrap_or(0)) }</td>
</Show>
<Show when=move || show_popduiken>
<td>{ Time::from_milliseconds_to_string(events.popduiken.unwrap_or(0)) }</td>
</Show>
},
None => view! {
<td>"0"</td>

View File

@ -1,3 +1,4 @@
pub mod add_participant;
pub mod add_time;
pub mod groups;
pub mod index;

View File

@ -0,0 +1,138 @@
use crate::components;
use crate::util::surrealdb::schemas;
use leptos::*;
/// Renders the home page of your application.
#[component]
pub fn Groups() -> impl IntoView {
let group_hour = create_rw_signal("A");
let group_lane = create_rw_signal("1");
let participants_context = use_context::<schemas::ParticipantsContext>().unwrap();
let participants_filtered: Memo<Vec<schemas::ParticipantSignal>> = create_memo(move |_| {
participants_context
.get()
.into_iter()
.filter(|participant| {
participant.value.get().group == group_hour.get().to_owned() + group_lane.get()
})
.collect()
});
let (participants_lifesaver, participants_hindernis, participants_popduiken) =
sort_by_events(participants_filtered);
view! {
<h2>"Groups"</h2>
<div class="groups-select-container">
<div class="groups-select-row">
<div on:click=move |_| group_hour.set("A") class:selected=move || group_hour.get() == "A">"A"</div>
<div on:click=move |_| group_hour.set("B") class:selected=move || group_hour.get() == "B">"B"</div>
<div on:click=move |_| group_hour.set("C") class:selected=move || group_hour.get() == "C">"C"</div>
<div on:click=move |_| group_hour.set("D") class:selected=move || group_hour.get() == "D">"D"</div>
<div on:click=move |_| group_hour.set("Z") class:selected=move || group_hour.get() == "Z">"Z"</div>
</div>
<div class="groups-select-row">
<div on:click=move |_| group_lane.set("1") class:selected=move || group_lane.get() == "1">"1"</div>
<div on:click=move |_| group_lane.set("2") class:selected=move || group_lane.get() == "2">"2"</div>
<div on:click=move |_| group_lane.set("3") class:selected=move || group_lane.get() == "3">"3"</div>
<div on:click=move |_| group_lane.set("4") class:selected=move || group_lane.get() == "4">"4"</div>
<div on:click=move |_| group_lane.set("5") class:selected=move || group_lane.get() == "5">"5"</div>
<div on:click=move |_| group_lane.set("6") class:selected=move || group_lane.get() == "6">"6"</div>
</div>
</div>
<h3>"Algemene score"</h3>
<components::participants::Participants participants=participants_filtered.into() show_group=false />
<div class="events-container">
<div>
<h3>"Lifesaver"</h3>
<components::participants::Participants participants=participants_lifesaver.into() show_group=false show_popduiken=false show_hindernis=false />
</div>
<div>
<h3>"Hindernis"</h3>
<components::participants::Participants participants=participants_hindernis.into() show_group=false show_popduiken=false show_lifesaver=false />
</div>
<div>
<h3>"Popduiken"</h3>
<components::participants::Participants participants=participants_popduiken.into() show_group=false show_hindernis=false show_lifesaver=false />
</div>
</div>
}
}
fn sort_by_events(
participants_filtered: Memo<Vec<schemas::ParticipantSignal>>,
) -> (
Memo<Vec<schemas::ParticipantSignal>>,
Memo<Vec<schemas::ParticipantSignal>>,
Memo<Vec<schemas::ParticipantSignal>>,
) {
let lifesaver: Memo<Vec<schemas::ParticipantSignal>> = create_memo(move |_| {
let mut participants: Vec<(usize, schemas::ParticipantSignal)> = participants_filtered
.get()
.into_iter()
.enumerate()
.collect();
participants.sort_by(|(_, a), (_, b)| {
let event_a = match a.value.get().events {
Some(events) => events.lifesaver.unwrap_or(6_000_000),
None => 6_000_000,
};
let event_b = match b.value.get().events {
Some(events) => events.lifesaver.unwrap_or(5_999_100),
None => 6_000_000,
};
event_a.cmp(&event_b)
});
participants.into_iter().map(|(_, value)| value).collect()
});
let hindernis: Memo<Vec<schemas::ParticipantSignal>> = create_memo(move |_| {
let mut participants: Vec<(usize, schemas::ParticipantSignal)> = participants_filtered
.get()
.into_iter()
.enumerate()
.collect();
participants.sort_by(|(_, a), (_, b)| {
let event_a = match a.value.get().events {
Some(events) => events.hindernis.unwrap_or(6_000_000),
None => 6_000_000,
};
let event_b = match b.value.get().events {
Some(events) => events.hindernis.unwrap_or(6_000_000),
None => 6_000_000,
};
event_a.cmp(&event_b)
});
participants.into_iter().map(|(_, value)| value).collect()
});
let popduiken: Memo<Vec<schemas::ParticipantSignal>> = create_memo(move |_| {
let mut participants: Vec<(usize, schemas::ParticipantSignal)> = participants_filtered
.get()
.into_iter()
.enumerate()
.collect();
participants.sort_by(|(_, a), (_, b)| {
let event_a = match a.value.get().events {
Some(events) => events.popduiken.unwrap_or(6_000_000),
None => 6_000_000,
};
let event_b = match b.value.get().events {
Some(events) => events.popduiken.unwrap_or(6_000_000),
None => 6_000_000,
};
event_a.cmp(&event_b)
});
participants.into_iter().map(|(_, value)| value).collect()
});
(lifesaver, hindernis, popduiken)
}

View File

@ -1,15 +1,34 @@
use crate::components;
use crate::util::surrealdb::{client::sort_participants, schemas};
use leptos::*;
use leptos_router::*;
/// Renders the home page of your application.
#[component]
pub fn HomePage() -> impl IntoView {
let participants_context = use_context::<schemas::ParticipantsContext>().unwrap();
let name = create_rw_signal("".to_string());
let participants_sorted =
create_memo(move |_| sort_participants(participants_context.get(), name.get()));
view! {
<div class="actions-container">
<A href="/add-participant">Deelnemer toevoegen</A>
<A href="/add-time">Tijd toevoegen</A>
<A href="/add-participant">"Deelnemer toevoegen"</A>
<A href="/add-time">"Tijd toevoegen"</A>
<A href="/groups">"Group view"</A>
</div>
<components::participants::Participants />
<input type="search"
class="participants-search"
placeholder="Search"
autocomplete="off"
autofocus=true
on:input=move |ev| {
name.set(event_target_value(&ev));
}
prop:value=name
/>
<components::participants::Participants participants=participants_sorted.into() />
}
}

View File

@ -12,6 +12,7 @@ pub fn init_websocket() {
} = use_websocket("ws://localhost:3000/ws");
provide_context(ready_state);
let participants_context = use_context::<schemas::ParticipantsContext>().unwrap();
let owner = Owner::current().unwrap();

View File

@ -0,0 +1,37 @@
.groups-select-container {
display: flex;
flex-direction: column;
gap: 10px;
}
.groups-select-row {
display: flex;
gap: 8px;
}
.groups-select-row div {
background-color: $secondary-bg-color-light;
border-radius: 10px;
width: 50px;
padding: 2px 0;
text-align: center;
}
.groups-select-row div:hover {
cursor: pointer;
background-color: $secondary-color;
}
.groups-select-row .selected {
background-color: $primary-color;
}
.events-container {
display: flex;
justify-content: space-between;
gap: 10px;
}
.events-container div {
width: 100%;
}

View File

@ -8,7 +8,7 @@ a {
display: flex;
width: 100%;
margin-top: 20px;
gap: 20px;
gap: 10px;
}
.actions-container a {

View File

@ -12,6 +12,7 @@ $text-color: #f3efef;
@import "forms";
@import "header";
@import "index";
@import "groups";
html,
body {
@ -33,3 +34,7 @@ main {
width: 100%;
max-width: 800px;
}
h3 {
margin-top: 30px;
}