334 lines
13 KiB
Rust
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(())
|
|
}
|