344 lines
15 KiB
Rust
344 lines
15 KiB
Rust
use crate::util::surrealdb::{client::Time, schemas};
|
|
use leptos::*;
|
|
|
|
cfg_if::cfg_if! {
|
|
if #[cfg(feature = "ssr")] {
|
|
use crate::util::surrealdb::{DB, schemas::Participant};
|
|
use crate::util::websocket::{server, ParticipantsAction};
|
|
use leptos::logging;
|
|
}
|
|
}
|
|
|
|
#[server(ModifyParticipant)]
|
|
async fn modify_participant(
|
|
mut participant: schemas::ParticipantUpdate,
|
|
id: String,
|
|
) -> Result<(), ServerFnError> {
|
|
let websocket_state = &server::WEBSOCKET_STATE;
|
|
|
|
let updated: Option<schemas::ParticipantRecord> = DB
|
|
.update(("participant", &id))
|
|
.content(&participant)
|
|
.await?;
|
|
|
|
match updated {
|
|
Some(participant_updated) => {
|
|
logging::log!(
|
|
"Updated participant: {} ({})",
|
|
participant_updated.name,
|
|
participant_updated.group
|
|
);
|
|
let action = ParticipantsAction::Replace {
|
|
participant: Participant {
|
|
name: participant_updated.name.clone(),
|
|
group: participant_updated.group.clone(),
|
|
id,
|
|
events: participant_updated.events.clone(),
|
|
},
|
|
};
|
|
|
|
match websocket_state.apply(action) {
|
|
Ok(_) => Ok(()),
|
|
Err(_) => Err(ServerFnError::new("Error sending websocket action")),
|
|
}
|
|
}
|
|
None => Err(ServerFnError::ServerError(String::from(
|
|
"Could not update participant",
|
|
))),
|
|
}
|
|
}
|
|
|
|
/// Renders the home page of your application.
|
|
#[component]
|
|
pub fn Modal() -> impl IntoView {
|
|
let participant_id = use_context::<RwSignal<Option<String>>>().unwrap();
|
|
let participants = use_context::<schemas::ParticipantsContext>().unwrap();
|
|
|
|
let time_lifesaver = create_rw_signal(Time {
|
|
minutes: 0,
|
|
seconds: 0,
|
|
milliseconds: 0,
|
|
});
|
|
|
|
let time_hindernis = create_rw_signal(Time {
|
|
minutes: 0,
|
|
seconds: 0,
|
|
milliseconds: 0,
|
|
});
|
|
|
|
let time_popduiken = create_rw_signal(Time {
|
|
minutes: 0,
|
|
seconds: 0,
|
|
milliseconds: 0,
|
|
});
|
|
|
|
let name = create_rw_signal(String::from(""));
|
|
let group = create_rw_signal(String::from(""));
|
|
|
|
let participant = move || {
|
|
let x = participants
|
|
.get()
|
|
.into_iter()
|
|
.filter(|item| item.id == participant_id.get().unwrap_or("".to_string()))
|
|
.collect::<Vec<schemas::ParticipantSignal>>();
|
|
|
|
match x.get(0) {
|
|
Some(participant) => {
|
|
let participant_clone = participant.value.get_untracked();
|
|
|
|
name.set(participant_clone.name);
|
|
group.set(participant_clone.group);
|
|
|
|
time_lifesaver.set(Time::from_milliseconds(match participant_clone.events {
|
|
Some(ref events) => events.lifesaver.unwrap_or(0),
|
|
None => 0,
|
|
}));
|
|
|
|
time_hindernis.set(Time::from_milliseconds(match participant_clone.events {
|
|
Some(ref events) => events.hindernis.unwrap_or(0),
|
|
None => 0,
|
|
}));
|
|
|
|
time_popduiken.set(Time::from_milliseconds(match participant_clone.events {
|
|
Some(ref events) => events.popduiken.unwrap_or(0),
|
|
None => 0,
|
|
}));
|
|
|
|
Some(participant.value)
|
|
}
|
|
None => None,
|
|
}
|
|
};
|
|
|
|
let modify_participant_action =
|
|
create_action(|input: &(schemas::ParticipantUpdate, String)| {
|
|
let input = input.to_owned();
|
|
async move { modify_participant(input.0, input.1).await }
|
|
});
|
|
|
|
let form_submit = move |ev: ev::SubmitEvent| {
|
|
ev.prevent_default();
|
|
|
|
let p = schemas::ParticipantUpdate {
|
|
name: name.get(),
|
|
group: group.get(),
|
|
events: Some(schemas::Events {
|
|
lifesaver: Some(time_lifesaver.get().as_milliseconds()),
|
|
hindernis: Some(time_hindernis.get().as_milliseconds()),
|
|
popduiken: Some(time_popduiken.get().as_milliseconds()),
|
|
}),
|
|
};
|
|
|
|
modify_participant_action.dispatch((p, participant().unwrap().get().id));
|
|
|
|
participant_id.set(None);
|
|
};
|
|
|
|
view! {
|
|
{ move || match participant() {
|
|
Some(_p) => view! {
|
|
<div class="modal-background">
|
|
<div class="modal">
|
|
<form on:submit=form_submit>
|
|
<h2>"Deelnemer bewerken"</h2>
|
|
<label>Naam</label>
|
|
<input
|
|
type="text"
|
|
autocomplete="off"
|
|
on:input=move |ev| {
|
|
name.set(event_target_value(&ev))
|
|
}
|
|
prop:value=name
|
|
/>
|
|
<label>Groep</label>
|
|
<select
|
|
name="group"
|
|
autocomplete="off"
|
|
on:change=move |ev| {
|
|
group.set(event_target_value(&ev))
|
|
}
|
|
>
|
|
<SelectOption value=group is="A1" />
|
|
<SelectOption value=group is="A2" />
|
|
<SelectOption value=group is="A3" />
|
|
<SelectOption value=group is="A4" />
|
|
<SelectOption value=group is="A5" />
|
|
<SelectOption value=group is="A6" />
|
|
|
|
<SelectOption value=group is="B1" />
|
|
<SelectOption value=group is="B2" />
|
|
<SelectOption value=group is="B3" />
|
|
<SelectOption value=group is="B4" />
|
|
<SelectOption value=group is="B5" />
|
|
<SelectOption value=group is="B6" />
|
|
|
|
<SelectOption value=group is="C1" />
|
|
<SelectOption value=group is="C2" />
|
|
<SelectOption value=group is="C3" />
|
|
<SelectOption value=group is="C4" />
|
|
<SelectOption value=group is="C5" />
|
|
<SelectOption value=group is="C6" />
|
|
|
|
<SelectOption value=group is="D1" />
|
|
<SelectOption value=group is="D2" />
|
|
<SelectOption value=group is="D3" />
|
|
<SelectOption value=group is="D4" />
|
|
<SelectOption value=group is="D5" />
|
|
<SelectOption value=group is="D6" />
|
|
|
|
<SelectOption value=group is="Z1" />
|
|
<SelectOption value=group is="Z2" />
|
|
<SelectOption value=group is="Z3" />
|
|
<SelectOption value=group is="Z4" />
|
|
<SelectOption value=group is="Z5" />
|
|
<SelectOption value=group is="Z6" />
|
|
</select>
|
|
<label>Tijd Lifesaver</label>
|
|
<div class="time">
|
|
<input type="number"
|
|
autocomplete="off"
|
|
placeholder="mm"
|
|
min=0
|
|
max=99
|
|
on:input=move |ev| {
|
|
time_lifesaver.update(|time| time.minutes = match event_target_value(&ev).parse::<u32>() {
|
|
Ok(x) => x,
|
|
Err(_) => 0,
|
|
});
|
|
}
|
|
prop:value=move || time_lifesaver.get().minutes
|
|
/>
|
|
<input type="number"
|
|
autocomplete="off"
|
|
placeholder="ss"
|
|
min=0
|
|
max=59
|
|
on:input=move |ev| {
|
|
time_lifesaver.update(|time| time.seconds = match event_target_value(&ev).parse::<u32>() {
|
|
Ok(x) => x,
|
|
Err(_) => 0,
|
|
});
|
|
}
|
|
prop:value=move || time_lifesaver.get().seconds
|
|
/>
|
|
<input type="number"
|
|
autocomplete="off"
|
|
placeholder="ms"
|
|
min=0
|
|
max=99
|
|
on:input=move |ev| {
|
|
time_lifesaver.update(|time| time.milliseconds = match event_target_value(&ev).parse::<u32>() {
|
|
Ok(x) => x,
|
|
Err(_) => 0,
|
|
});
|
|
}
|
|
prop:value=move || time_lifesaver.get().milliseconds
|
|
/>
|
|
</div>
|
|
<label>Tijd Hindernis</label>
|
|
<div class="time">
|
|
<input type="number"
|
|
autocomplete="off"
|
|
placeholder="mm"
|
|
min=0
|
|
max=99
|
|
on:input=move |ev| {
|
|
time_hindernis.update(|time| time.minutes = match event_target_value(&ev).parse::<u32>() {
|
|
Ok(x) => x,
|
|
Err(_) => 0,
|
|
});
|
|
}
|
|
prop:value=move || time_hindernis.get().minutes
|
|
/>
|
|
<input type="number"
|
|
autocomplete="off"
|
|
placeholder="ss"
|
|
min=0
|
|
max=59
|
|
on:input=move |ev| {
|
|
time_hindernis.update(|time| time.seconds = match event_target_value(&ev).parse::<u32>() {
|
|
Ok(x) => x,
|
|
Err(_) => 0,
|
|
});
|
|
}
|
|
prop:value=move || time_hindernis.get().seconds
|
|
/>
|
|
<input type="number"
|
|
autocomplete="off"
|
|
placeholder="ms"
|
|
min=0
|
|
max=99
|
|
on:input=move |ev| {
|
|
time_hindernis.update(|time| time.milliseconds = match event_target_value(&ev).parse::<u32>() {
|
|
Ok(x) => x,
|
|
Err(_) => 0,
|
|
});
|
|
}
|
|
prop:value=move || time_hindernis.get().milliseconds
|
|
/>
|
|
</div>
|
|
<label>Tijd Popduiken</label>
|
|
<div class="time">
|
|
<input type="number"
|
|
autocomplete="off"
|
|
placeholder="mm"
|
|
min=0
|
|
max=99
|
|
on:input=move |ev| {
|
|
time_popduiken.update(|time| time.minutes = match event_target_value(&ev).parse::<u32>() {
|
|
Ok(x) => x,
|
|
Err(_) => 0,
|
|
});
|
|
}
|
|
prop:value=move || time_popduiken.get().minutes
|
|
/>
|
|
<input type="number"
|
|
autocomplete="off"
|
|
placeholder="ss"
|
|
min=0
|
|
max=59
|
|
on:input=move |ev| {
|
|
time_popduiken.update(|time| time.seconds = match event_target_value(&ev).parse::<u32>() {
|
|
Ok(x) => x,
|
|
Err(_) => 0,
|
|
});
|
|
}
|
|
prop:value=move || time_popduiken.get().seconds
|
|
/>
|
|
<input type="number"
|
|
autocomplete="off"
|
|
placeholder="ms"
|
|
min=0
|
|
max=99
|
|
on:input=move |ev| {
|
|
time_popduiken.update(|time| time.milliseconds = match event_target_value(&ev).parse::<u32>() {
|
|
Ok(x) => x,
|
|
Err(_) => 0,
|
|
});
|
|
}
|
|
prop:value=move || time_popduiken.get().milliseconds
|
|
/>
|
|
</div>
|
|
<input type="submit" value="Deelnemer bewerken" />
|
|
</form>
|
|
</div>
|
|
</div>
|
|
}.into_view(),
|
|
None => view! {}.into_view()
|
|
|
|
}}
|
|
}
|
|
}
|
|
|
|
#[component]
|
|
pub fn SelectOption(is: &'static str, value: RwSignal<String>) -> impl IntoView {
|
|
view! {
|
|
<option
|
|
value=is
|
|
selected=move || value.get() == is
|
|
>
|
|
{is}
|
|
</option>
|
|
}
|
|
}
|