use dioxus::prelude::*; use crate::components::layout::icons; use crate::util::model::member::Member; use crate::util::model::session::Session; use crate::util::model::user::User; use std::collections::HashMap; pub fn Auth() -> Element { let mut register = use_signal(|| false); rsx! { div { class: "flex flex-col items-center", h1 { class: "font-bold text-primary text-center text-2xl mt-16", "Waddinxveense Reddingsbrigade" }, div { class: "card bg-base-200 mt-8 w-full max-w-lg shadow-xl", div { class: "card-body", div { role: "tablist", class: "tabs tabs-boxed bg-base-300 mx-auto w-full mb-6", button { onclick: move |_| register.set(false), role: "tab", class: "tab", class: if !register() { "tab-active" }, "Inloggen" }, button { onclick: move |_| register.set(true), role: "tab", class: "tab", class: if register() { "tab-active" }, "Registreren" }, } if !register() { Login { } } else { Register { } } } } } } } fn Login() -> Element { let mut input_email = use_signal(|| "".to_string()); let mut input_password = use_signal(|| "".to_string()); let submit = move |_| async move { if let Ok(_) = login(input_email(), input_password()).await { let window = web_sys::window().expect("Could not find window"); window.location().reload().expect("Could not reload window"); } }; rsx! { label { class: "form-control w-full", div { class: "label", span { class: "label-text", "Email" }, } input { r#type: "email", class: "input input-bordered w-full", value: "{input_email}", oninput: move |event| input_email.set(event.value()) }, } label { class: "form-control w-full mt-3", div { class: "label", span { class: "label-text", "Wachtwoord" }, } input { r#type: "password", class: "input input-bordered w-full", value: "{input_password}", oninput: move |event| input_password.set(event.value()) }, } div { class: "card-actions mt-5", button { class: "btn btn-primary", onclick: submit, "Inloggen", } } } } fn Register() -> Element { let mut members: Signal> = use_signal(|| HashMap::new()); let mut input_registration_token = use_signal(|| "".to_string()); let mut input_email = use_signal(|| "".to_string()); let mut input_password = use_signal(|| "".to_string()); let mut input_password_repeat = use_signal(|| "".to_string()); let submit = move |_| async move { let members_set: Vec = members().into_keys().collect(); if let Ok(_) = register(input_email(), input_password(), members_set).await { let window = web_sys::window().expect("Could not find window"); window.location().reload().expect("Could not reload window"); } }; rsx! { label { class: "form-control w-full join-item", div { class: "label", span { class: "label-text", "Registratie code" }, } div { class: "w-full join", input { r#type: "text", class: "input input-bordered w-full join-item", value: "{input_registration_token}", oninput: move |event| input_registration_token.set(event.value()) }, button { class: "btn join-item btn-neutral", onclick: move |_| async move { if let Ok(res) = fetch_member(input_registration_token()).await { members.write().insert(res.id.clone(), res); input_registration_token.set("".to_string()); } }, icons::UserPlus {}, "Toevoegen", } } div { class: "flex gap-1 pt-2 flex-wrap", for (id, member) in members() { div { class: "badge badge-md badge-neutral h-8 gap-1 hover:cursor-pointer hover:line-through whitespace-nowrap", onclick: move |_| { members.write().remove(&id); }, "{member.name.full}" icons::XMark {}, } } } label { class: "form-control w-full mt-3", div { class: "label", span { class: "label-text", "Email" }, } input { r#type: "email", class: "input input-bordered w-full", value: "{input_email}", oninput: move |event| input_email.set(event.value()) }, } label { class: "form-control w-full mt-3", div { class: "label", span { class: "label-text", "Wachtwoord" }, } input { r#type: "password", class: "input input-bordered w-full", value: "{input_password}", oninput: move |event| input_password.set(event.value()) }, } label { class: "form-control w-full mt-3", div { class: "label", span { class: "label-text", "Herhaal wachtwoord" }, } input { r#type: "password", class: "input input-bordered w-full", value: "{input_password_repeat}", oninput: move |event| input_password_repeat.set(event.value()) }, } } div { class: "card-actions mt-5", button { class: "btn btn-primary", onclick: submit, "Registreren" } } } } #[server] async fn login(email: String, password: String) -> Result<(), ServerFnError> { // Verify username and password let user_id = User::verify_credentials(email, password).await?; // Create a new session let session = Session::new(user_id).await?; session.set_cookie()?; Ok(()) } #[server] async fn register( email: String, password: String, member_ids: Vec, ) -> Result<(), ServerFnError> { // Creat a new user let user = User::new(email, password, member_ids).await?; // Generate a session and set the cookie let session = Session::new(user.id).await?; session.set_cookie()?; Ok(()) } #[server] async fn fetch_member(registration_token: String) -> Result { let member = Member::fetch_from_registration_token(registration_token).await?; match member { Some(m) => Ok(m), None => Err(ServerFnError::new("Lid niet gevonden")), } }