2024-12-10 18:38:58 +01:00

370 lines
12 KiB
Rust

use crate::util::model::news::{Target, TargetKind};
use std::collections::HashMap;
use dioxus::prelude::*;
#[derive(PartialEq)]
enum Steps {
Message,
Targets,
Verify,
Done,
}
#[derive(Props, Clone, PartialEq, Debug)]
struct Form {
title: Signal<String>,
body: Signal<String>,
targets: Signal<HashMap<u32, Target>>,
}
impl Default for Form {
fn default() -> Self {
Self {
title: use_signal(|| String::new()),
body: use_signal(|| String::new()),
targets: use_signal(|| {
HashMap::from([(
0,
Target {
kind: TargetKind::None,
value: String::new(),
},
)])
}),
}
}
}
#[component]
pub fn NewsCreate() -> Element {
let step = use_signal(|| Steps::Message);
let form = Form::default();
rsx! {
div {
class: "w-full max-w-2xl space-y-3 flex flex-col",
h1 { class: "text-xl font-bold text-primary", "Nieuw bericht" }
ul {
class: "steps pb-10 mx-auto",
li { class: "step step-primary", "Inhoud" },
li {
class: "step",
class: if let Steps::Targets | Steps::Done | Steps::Verify = *step.read() { "step-primary" },
"Naar"
}
li {
class: "step",
class: if let Steps::Verify | Steps::Done = *step.read() { "step-primary" },
"Controleren"
}
li {
class: "step",
class: if let Steps::Done = *step.read() { "step-primary" },
"Klaar"
}
}
div {
class: "flex flex-col gap-y-5",
div {
class: if let Steps::Message = *step.read() { "" } else { "hidden" },
Message {
step: step,
title: form.title,
body: form.body,
}
}
div {
class: if let Steps::Targets = *step.read() { "" } else { "hidden" },
TargetSelect {
step: step,
targets: form.targets,
}
}
}
}
}
}
#[component]
fn Message(step: Signal<Steps>, title: Signal<String>, body: Signal<String>) -> Element {
let submit = move |event: FormEvent| {
title.set(event.values()["title"].as_value());
body.set(event.values()["body"].as_value());
step.set(Steps::Targets);
};
rsx! {
form {
class: "flex flex-col w-full gap-y-5",
onsubmit: submit,
label {
class: "form-control w-full",
div {
class: "label",
span { class: "label-text", "Titel" }
},
input {
r#type: "text",
required: true,
name: "title",
class: "input input-bordered w-full",
}
}
label {
class: "form-control w-full",
div {
class: "label",
span { class: "label-text", "Bericht" }
},
textarea {
name: "body",
class: "textarea textarea-bordered w-full",
required: true,
}
},
div {
class: "w-full flex gap-x-3 justify-end",
input {
r#type: "submit",
class: "btn btn-primary",
value: "Volgende",
}
}
}
}
}
#[component]
fn TargetSelect(step: Signal<Steps>, targets: Signal<HashMap<u32, Target>>) -> Element {
let mut target_id = use_signal(|| 1);
let target_ids = use_memo(move || {
let mut filtered_targets = targets.read().iter().map(|x| *x.0).collect::<Vec<_>>();
filtered_targets.sort_unstable();
filtered_targets
});
let submit = move |_| {
step.set(Steps::Verify);
};
rsx! {
form {
class: "w-full",
onsubmit: submit,
label {
class: "form-control w-full",
div {
class: "label",
span { class: "label-text", "Naar" }
},
for id in target_ids() {
TargetEntry { key: "{id}", id, targets }
}
button {
class: "btn btn-primary btn-sm mt-3 mr-auto",
r#type: "button",
onclick: move |_| {
let id = target_id();
let target = Target {
kind: TargetKind::None,
value: String::new(),
};
targets.write().insert(id, target);
target_id += 1;
},
"Conditie toevoegen",
}
}
div {
class: "w-full flex gap-x-3 justify-end",
button {
class: "btn",
r#type: "button",
onclick: move |_| {
step.set(Steps::Message)
},
"Terug",
}
button {
class: "btn btn-primary",
"Volgende",
}
}
}
}
}
#[component]
fn TargetEntry(mut targets: Signal<HashMap<u32, Target>>, id: u32) -> Element {
let kind = use_memo(move || targets.read().get(&id).unwrap().kind);
rsx! {
div {
class: "join w-full mt-3",
select {
class: "select select-bordered join-item w-1/3",
required: true,
oninput: move |event| {
let target_kind = TargetKind::from_string(&event.value());
targets.write().get_mut(&id).unwrap().kind = target_kind;
targets.write().get_mut(&id).unwrap().value = String::from("");
},
option { disabled: true, selected: true, value: "", "Selecteer een type" },
option { value: "all", "Iedereen" }
option { value: "group", "Groep" }
option { value: "day", "Dag" }
option { value: "hour", "Uur" }
option { value: "hourgroup", "Lesgroep" }
option { value: "member", "Lid" }
option { value: "account", "Account" }
}
TargetValueInput { target_kind: kind, targets: targets, id: id }
}
}
}
#[component]
fn TargetValueInput(
target_kind: Memo<TargetKind>,
targets: Signal<HashMap<u32, Target>>,
id: u32,
) -> Element {
let groups = use_context::<crate::Groups>();
let value = use_memo(move || targets.read().get(&id).unwrap().value.clone());
tracing::info!("Input rendered");
rsx! {
match target_kind() {
TargetKind::Group => {
rsx! {
select {
class: "select select-bordered join-item w-2/3",
required: true,
oninput: move |event| {
targets.write().get_mut(&id).unwrap().value = event.value();
},
option { disabled: true, selected: true, value: "", "Selecteer een groep" }
for (group_id, group_name) in groups.0 {
option { value: group_id, "{group_name}" }
}
}
}
},
TargetKind::Day => {
rsx! {
select {
class: "select select-bordered join-item w-2/3",
required: true,
oninput: move |event| {
targets.write().get_mut(&id).unwrap().value = event.value();
},
option { disabled: true, selected: true, value: "", "Selecteer een dag" }
option {
value: "friday",
"Vrijdag",
}
option {
value: "saturday",
"Zaterdag"
}
}
}
},
TargetKind::Hourgroup => {
rsx! {
select {
class: "select select-bordered join-item w-1/3",
required: true,
option { disabled: true, selected: true, value: "", "Selecteer een uur" }
option {
value: "a",
"A",
}
option {
value: "b",
"B",
}
option {
value: "c",
"C",
}
option {
value: "d",
"D",
}
option {
value: "e",
"E",
}
option {
value: "z",
"Z",
}
}
select {
class: "select select-bordered join-item w-1/3",
required: true,
option { disabled: true, selected: true, value: "", "Selecteer een groep" }
for i in 1..7 {
option { "{i}" }
}
}
}
},
TargetKind::Hour => {
rsx! {
select {
class: "select select-bordered join-item w-2/3",
required: true,
option { disabled: true, selected: true, value: "", "Selecteer een uur" }
option {
value: "a",
"A",
}
option {
value: "b",
"B",
}
option {
value: "c",
"C",
}
option {
value: "d",
"D",
}
option {
value: "e",
"E",
}
option {
value: "z",
"Z",
}
}
}
},
TargetKind::Member | TargetKind::Account => {
rsx! {
input {
class: "input input-bordered join-item w-2/3",
required: true,
oninput: move |event| {
targets.write().get_mut(&id).unwrap().value = event.value();
},
}
}
},
_ => rsx! {
div { class: "input input-bordered w-2/3 join-item" }
}
}
}
}