370 lines
12 KiB
Rust
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" }
|
|
}
|
|
}
|
|
}
|
|
}
|