Started working on members management
This commit is contained in:
parent
062fbf6bbc
commit
24008ed668
@ -17,7 +17,7 @@ axum = { version = "0.7", optional = true }
|
||||
axum-extra = { version = "0.9", features = ["cookie"], optional = true }
|
||||
time = { version = "0.3", optional = true }
|
||||
once_cell = { version = "1.19", optional = true }
|
||||
surrealdb = { version = "2.0", features = ["kv-rocksdb"], optional = true }
|
||||
surrealdb = { version = "2.0", features = [], optional = true }
|
||||
thiserror = { version = "1.0" }
|
||||
|
||||
csv = { version = "1.3", optional = true }
|
||||
@ -29,5 +29,5 @@ manganis = "0.2"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
server = [ "dioxus/axum", "tokio", "axum", "axum-extra", "time", "once_cell", "surrealdb", "csv" ]
|
||||
web = ["dioxus/web"]
|
||||
server = [ "dioxus/axum", "tokio", "axum", "axum-extra", "time", "once_cell", "surrealdb/kv-rocksdb", "csv" ]
|
||||
web = ["dioxus/web", "surrealdb"]
|
||||
|
@ -1007,6 +1007,27 @@ html {
|
||||
min-height: fit-content;
|
||||
}
|
||||
|
||||
.divider {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
height: 1rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.divider:before,
|
||||
.divider:after {
|
||||
height: 0.125rem;
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
--tw-content: '';
|
||||
content: var(--tw-content);
|
||||
background-color: var(--fallback-bc,oklch(var(--bc)/0.1));
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
@ -2039,6 +2060,10 @@ details.collapse summary::-webkit-details-marker {
|
||||
content: "−";
|
||||
}
|
||||
|
||||
.divider:not(:empty) {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.dropdown.dropdown-open .dropdown-content,
|
||||
.dropdown:focus .dropdown-content,
|
||||
.dropdown:focus-within .dropdown-content {
|
||||
@ -2866,11 +2891,26 @@ details.collapse summary::-webkit-details-marker {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.mx-1 {
|
||||
margin-left: 0.25rem;
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
.mx-1\.5 {
|
||||
margin-left: 0.375rem;
|
||||
margin-right: 0.375rem;
|
||||
}
|
||||
|
||||
.mx-auto {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.my-0 {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.mb-1 {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
use dioxus::prelude::*;
|
||||
|
||||
use crate::util::model::{session::Session, user::User};
|
||||
use crate::util::model::{member::Member, session::Session, user::User};
|
||||
|
||||
use super::admin::members;
|
||||
|
||||
#[component]
|
||||
pub fn Settings() -> Element {
|
||||
@ -9,6 +11,7 @@ pub fn Settings() -> Element {
|
||||
class: "w-full max-w-2xl space-y-3",
|
||||
Account {},
|
||||
Password {},
|
||||
Members {},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -20,10 +23,14 @@ fn Account() -> Element {
|
||||
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! {
|
||||
@ -65,16 +72,26 @@ fn Account() -> Element {
|
||||
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",
|
||||
}
|
||||
}
|
||||
@ -109,10 +126,14 @@ fn Password() -> Element {
|
||||
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! {
|
||||
@ -172,6 +193,10 @@ fn Password() -> Element {
|
||||
button {
|
||||
class: "ml-auto btn btn-primary",
|
||||
onclick: submit,
|
||||
disabled: loading(),
|
||||
if loading() {
|
||||
span { class: "loading loading-spinner" }
|
||||
}
|
||||
"Opslaan",
|
||||
}
|
||||
}
|
||||
@ -189,3 +214,55 @@ async fn change_password(old_password: String, new_password: String) -> Result<(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn Members() -> Element {
|
||||
let members = use_resource(fetch_members);
|
||||
|
||||
let mut is_open = use_signal(|| 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(),
|
||||
"Leden",
|
||||
},
|
||||
div {
|
||||
class: "collapse-content",
|
||||
div {
|
||||
class: "pl-2 flex flex-col gap-3",
|
||||
div {
|
||||
class: "flex",
|
||||
div {
|
||||
class: "flex flex-col",
|
||||
div {
|
||||
class: "",
|
||||
span { class: "font-bold", "Timo Boomers", }
|
||||
span { class: "mx-1.5", "•" }
|
||||
span { "123" }
|
||||
}
|
||||
div {
|
||||
class: "",
|
||||
span { "LS2" },
|
||||
span { class: "mx-1.5", "•" }
|
||||
span { "A1, B2" }
|
||||
}
|
||||
}
|
||||
}
|
||||
div { class: "divider my-0" }
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
|
@ -41,10 +41,8 @@ impl Member {
|
||||
pub async fn fetch_from_registration_token(
|
||||
registration_token: String,
|
||||
) -> Result<Option<Self>, surrealdb::Error> {
|
||||
let query = format!("SELECT record::id(id) as id, name.first, name.full, hours, groups, diploma, registration_token FROM ONLY member WHERE registration_token = $registration_token LIMIT 1");
|
||||
|
||||
let mut res = DB
|
||||
.query(query)
|
||||
.query("SELECT record::id(id) as id, name.first, name.full, hours, groups, diploma, registration_token FROM ONLY member WHERE registration_token = $registration_token LIMIT 1")
|
||||
.bind(("registration_token", registration_token))
|
||||
.await?;
|
||||
|
||||
@ -52,6 +50,21 @@ impl Member {
|
||||
|
||||
Ok(member)
|
||||
}
|
||||
|
||||
pub async fn fetch_from_user(user_id: String) -> Result<Vec<Self>, crate::Error> {
|
||||
let mut res = DB
|
||||
.query(
|
||||
"SELECT VALUE array::map(->user_to_member->member.*, |$obj| {{ id: record::id($obj.id), }}) FROM ONLY type::thing('user', $user_id)",
|
||||
)
|
||||
.bind(("user_id", user_id))
|
||||
.await?;
|
||||
|
||||
tracing::info!("{res:?}");
|
||||
|
||||
let members: Vec<Self> = res.take(0)?;
|
||||
|
||||
Ok(members)
|
||||
}
|
||||
}
|
||||
|
||||
impl MembersMigration {
|
||||
|
Loading…
Reference in New Issue
Block a user