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, body: Signal, targets: Signal>, } 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, title: Signal, body: Signal) -> 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, targets: Signal>) -> 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::>(); 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>, 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, targets: Signal>, id: u32, ) -> Element { let groups = use_context::(); 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" } } } } }