use dioxus::prelude::*; use crate::components::layout::icons; use crate::util::model::{member::Member, session::Session, user::User}; #[component] pub fn Settings() -> Element { rsx! { div { class: "w-full max-w-2xl space-y-3", Account {}, Password {}, Members {}, } } } fn Account() -> Element { let user_state = use_context::>>(); let user = user_state().unwrap(); let mut is_open = use_signal(|| false); let mut input_email = use_signal(|| user.email); let mut loading = use_signal(|| false); let submit = move |_| async move { loading.set(true); if let Ok(_) = change_email(input_email()).await { tracing::info!("User email changed"); }; loading.set(false); }; rsx! { div { class: "collapse collapse-arrow bg-base-200", class: if is_open() { "collapse-open" }, div { class: "collapse-title text-lg font-medium hover:cursor-pointer select-none", onclick: move |_| is_open.toggle(), "Account", }, div { class: "collapse-content", div { class: "pl-2 flex flex-col gap-3", label { class: "form-control w-full", div { class: "label", span { class: "label-text", "Account ID" } } b { class: "select-all", "{user.id}" }, } label { class: "form-control w-full", div { class: "label", span { class: "label-text", "Email" } } input { r#type: "text", class: "input input-bordered w-full", oninput: move |event| input_email.set(event.value()), value: "{input_email}", } } div { class: "w-full flex mt-5", button { class: "btn btn-outline btn-error", onclick: move |_| async move { loading.set(true); if let Ok(_) = logout().await { let window = web_sys::window().expect("Could not find window"); window.location().reload().expect("Could not reload window"); } loading.set(false); }, disabled: loading(), if loading() { span { class: "loading loading-spinner" } } "Uitloggen", } button { class: "ml-auto btn btn-primary", onclick: submit, disabled: loading(), if loading() { span { class: "loading loading-spinner" } } "Opslaan", } } } }, }, } } #[server] async fn logout() -> Result<(), ServerFnError> { let session_token = Session::get_token_from_cookie().await?; Session::delete_session(session_token).await?; Session::delete_cookie().await?; Ok(()) } #[server] async fn change_email(new_email: String) -> Result<(), ServerFnError> { let user = Session::fetch_current_user().await?; user.change_email(new_email).await?; Ok(()) } fn Password() -> Element { let mut is_open = use_signal(|| false); let mut input_old_password = use_signal(|| "".to_string()); let mut input_new_password = use_signal(|| "".to_string()); let mut input_new_password_repeat = use_signal(|| "".to_string()); let mut loading = use_signal(|| false); let submit = move |_| async move { loading.set(true); if let Ok(_) = change_password(input_old_password(), input_new_password()).await { tracing::info!("User password changed"); }; loading.set(false); }; rsx! { div { class: "collapse collapse-arrow bg-base-200", class: if is_open() { "collapse-open" }, div { class: "collapse-title text-lg font-medium hover:cursor-pointer select-none", onclick: move |_| is_open.toggle(), "Wachtwoord", }, div { class: "collapse-content", div { class: "pl-2 flex flex-col gap-3", label { class: "form-control w-full", div { class: "label", span { class: "label-text", "Huidig wachtwoord" } } input { r#type: "password", class: "input input-bordered w-full", oninput: move |event| input_old_password.set(event.value()), value: "{input_old_password}", } } label { class: "form-control w-full", div { class: "label", span { class: "label-text", "Nieuw wachtwoord" } } input { r#type: "password", class: "input input-bordered w-full", oninput: move |event| input_new_password.set(event.value()), value: "{input_new_password}", } } label { class: "form-control w-full", div { class: "label", span { class: "label-text", "Herhaal nieuw wachtwoord" } } input { r#type: "password", class: "input input-bordered w-full", oninput: move |event| input_new_password_repeat.set(event.value()), value: "{input_new_password_repeat}", } } div { class: "w-full flex mt-5", button { class: "ml-auto btn btn-primary", onclick: submit, disabled: loading(), if loading() { span { class: "loading loading-spinner" } } "Opslaan", } } } }, }, } } #[server] async fn change_password(old_password: String, new_password: String) -> Result<(), ServerFnError> { let user = Session::fetch_current_user().await?; user.change_password(old_password, new_password).await?; Ok(()) } fn Members() -> Element { let mut members = use_resource(fetch_members); let mut is_open = use_signal(|| false); let mut input_registration_token = use_signal(|| "".to_string()); rsx! { div { class: "collapse collapse-arrow bg-base-200", class: if is_open() { "collapse-open" }, div { class: "collapse-title text-lg font-medium hover:cursor-pointer select-none", onclick: move |_| is_open.toggle(), "Leden", }, div { class: "collapse-content", div { class: "pl-2 flex flex-col gap-3", match &*members.read() { Some(Ok(res)) => { let members_state = res.to_owned(); rsx! { for member in members_state { div { class: "flex items-center", div { class: "flex flex-col", div { class: "", span { class: "font-bold", "{member.name.full}", } span { class: "mx-1.5", "•" } span { "{member.id}" } } div { class: "", if let Some(d) = member.diploma { span { "{d}" } span { class: "mx-1.5", "•" } } span { {member.hours.join(", ")} } } }, div { class: "ml-auto mr-3 h-full text-error hover:cursor-pointer", onclick: move |_| { let id = member.id.clone(); async move { if let Ok(_res) = delete_member_relation(id).await { members.restart(); } } }, icons::Trash {} } } div { class: "divider my-0" } } 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) = relate_member(input_registration_token()).await { members.restart(); input_registration_token.set("".to_string()); } }, icons::UserPlus {}, "Toevoegen", } } } }, Some(Err(_)) => rsx! { "Error" }, None => rsx! { div { "Loading..." } }, } } }, }, } } #[server] async fn fetch_members() -> Result, ServerFnError> { let user = Session::fetch_current_user().await?; let members = Member::fetch_from_user(&user.id).await?; Ok(members) } #[server] async fn relate_member(registration_token: String) -> Result<(), ServerFnError> { let user = Session::fetch_current_user().await?; let member_id = Member::fetch_from_registration_token(registration_token).await?; user.relate_member(&member_id.id).await?; Ok(()) } #[server] async fn delete_member_relation(member_id: String) -> Result<(), ServerFnError> { let user = Session::fetch_current_user().await?; user.remove_relation(&member_id).await?; Ok(()) }