wrbapp/src/components/settings.rs
2024-10-09 12:14:56 +02:00

334 lines
13 KiB
Rust

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::<Signal<Option<User>>>();
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<Vec<Member>, 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(())
}