Added members management system
This commit is contained in:
parent
aa1063a344
commit
a53ad775dc
@ -2927,6 +2927,10 @@ details.collapse summary::-webkit-details-marker {
|
|||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mr-3 {
|
||||||
|
margin-right: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.mt-10 {
|
.mt-10 {
|
||||||
margin-top: 2.5rem;
|
margin-top: 2.5rem;
|
||||||
}
|
}
|
||||||
@ -3180,6 +3184,11 @@ details.collapse summary::-webkit-details-marker {
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-error {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: var(--fallback-er,oklch(var(--er)/var(--tw-text-opacity)));
|
||||||
|
}
|
||||||
|
|
||||||
.text-primary {
|
.text-primary {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)));
|
color: var(--fallback-p,oklch(var(--p)/var(--tw-text-opacity)));
|
||||||
|
@ -235,8 +235,5 @@ async fn register(
|
|||||||
async fn fetch_member(registration_token: String) -> Result<Member, ServerFnError> {
|
async fn fetch_member(registration_token: String) -> Result<Member, ServerFnError> {
|
||||||
let member = Member::fetch_from_registration_token(registration_token).await?;
|
let member = Member::fetch_from_registration_token(registration_token).await?;
|
||||||
|
|
||||||
match member {
|
Ok(member)
|
||||||
Some(m) => Ok(m),
|
|
||||||
None => Err(ServerFnError::new("Lid niet gevonden")),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -121,3 +121,22 @@ pub fn XMark() -> Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Trash() -> Element {
|
||||||
|
rsx! {
|
||||||
|
svg {
|
||||||
|
"fill": "none",
|
||||||
|
"stroke": "currentColor",
|
||||||
|
"xmlns": "http://www.w3.org/2000/svg",
|
||||||
|
"stroke-width": "1.5",
|
||||||
|
"viewBox": "0 0 24 24",
|
||||||
|
class: "size-6",
|
||||||
|
path {
|
||||||
|
"stroke-linecap": "round",
|
||||||
|
"stroke-linejoin": "round",
|
||||||
|
"d": "m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
use crate::components::layout::icons;
|
||||||
use crate::util::model::{member::Member, session::Session, user::User};
|
use crate::util::model::{member::Member, session::Session, user::User};
|
||||||
|
|
||||||
use super::admin::members;
|
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Settings() -> Element {
|
pub fn Settings() -> Element {
|
||||||
rsx! {
|
rsx! {
|
||||||
@ -216,9 +215,10 @@ async fn change_password(old_password: String, new_password: String) -> Result<(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn Members() -> Element {
|
fn Members() -> Element {
|
||||||
let members = use_resource(fetch_members);
|
let mut members = use_resource(fetch_members);
|
||||||
|
|
||||||
let mut is_open = use_signal(|| false);
|
let mut is_open = use_signal(|| false);
|
||||||
|
let mut input_registration_token = use_signal(|| "".to_string());
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
div {
|
div {
|
||||||
@ -233,25 +233,71 @@ fn Members() -> Element {
|
|||||||
class: "collapse-content",
|
class: "collapse-content",
|
||||||
div {
|
div {
|
||||||
class: "pl-2 flex flex-col gap-3",
|
class: "pl-2 flex flex-col gap-3",
|
||||||
div {
|
match &*members.read() {
|
||||||
class: "flex",
|
Some(Ok(res)) => {
|
||||||
div {
|
let members_state = res.to_owned();
|
||||||
class: "flex flex-col",
|
|
||||||
div {
|
rsx! {
|
||||||
class: "",
|
for member in members_state {
|
||||||
span { class: "font-bold", "Timo Boomers", }
|
div {
|
||||||
span { class: "mx-1.5", "•" }
|
class: "flex items-center",
|
||||||
span { "123" }
|
div {
|
||||||
|
class: "flex flex-col",
|
||||||
|
div {
|
||||||
|
class: "",
|
||||||
|
span { class: "font-bold", "{member.name.full}", }
|
||||||
|
span { class: "mx-1.5", "•" }
|
||||||
|
span { "{member.id}" }
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
class: "",
|
||||||
|
span { "LS2" },
|
||||||
|
span { class: "mx-1.5", "•" }
|
||||||
|
span { "A1, B2" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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",
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
div {
|
},
|
||||||
class: "",
|
Some(Err(_)) => rsx! {
|
||||||
span { "LS2" },
|
"Error"
|
||||||
span { class: "mx-1.5", "•" }
|
},
|
||||||
span { "A1, B2" }
|
None => rsx! { div { "Loading..." } },
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
div { class: "divider my-0" }
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -266,3 +312,20 @@ async fn fetch_members() -> Result<Vec<Member>, ServerFnError> {
|
|||||||
|
|
||||||
Ok(members)
|
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(())
|
||||||
|
}
|
||||||
|
@ -41,15 +41,16 @@ impl Member {
|
|||||||
|
|
||||||
pub async fn fetch_from_registration_token(
|
pub async fn fetch_from_registration_token(
|
||||||
registration_token: String,
|
registration_token: String,
|
||||||
) -> Result<Option<Self>, surrealdb::Error> {
|
) -> Result<Self, crate::Error> {
|
||||||
let mut res = DB
|
let mut res = DB
|
||||||
.query("SELECT id, name.first, name.full, hours, groups, diploma, registration_token FROM ONLY member WHERE registration_token = $registration_token LIMIT 1")
|
.query("SELECT 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))
|
.bind(("registration_token", registration_token))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let member: Option<Self> = res.take(0)?;
|
match res.take(0)? {
|
||||||
|
Some(m) => Ok(m),
|
||||||
Ok(member)
|
None => Err(crate::Error::NoDocument),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn fetch_from_user(user_id: String) -> Result<Vec<Self>, crate::Error> {
|
pub async fn fetch_from_user(user_id: String) -> Result<Vec<Self>, crate::Error> {
|
||||||
@ -60,8 +61,6 @@ impl Member {
|
|||||||
.bind(("user_id", user_id))
|
.bind(("user_id", user_id))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
tracing::info!("{res:?}");
|
|
||||||
|
|
||||||
let members: Vec<Self> = res.take(0)?;
|
let members: Vec<Self> = res.take(0)?;
|
||||||
|
|
||||||
Ok(members)
|
Ok(members)
|
||||||
|
@ -45,6 +45,40 @@ impl User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn relate_member(&self, member_id: String) -> Result<(), crate::Error> {
|
||||||
|
let mut res = DB
|
||||||
|
.query("
|
||||||
|
IF (SELECT * FROM ONLY user_to_member WHERE in = type::thing('user', $user_id) AND out = type::thing('member', $member_id) LIMIT 1) == NONE {
|
||||||
|
RELATE ONLY (type::thing('user', $user_id))->user_to_member->(type::thing('member', $member_id));
|
||||||
|
} ELSE {
|
||||||
|
THROW 'Relation already exists'
|
||||||
|
};
|
||||||
|
")
|
||||||
|
.bind(("user_id", self.id.to_string()))
|
||||||
|
.bind(("member_id", member_id))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if res.take_errors().len() != 0 {
|
||||||
|
return Err(crate::Error::NoDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn remove_relation(&self, member_id: String) -> Result<(), crate::Error> {
|
||||||
|
let mut res = DB
|
||||||
|
.query("DELETE type::thing('user', $user_id)->user_to_member WHERE out = type::thing('member', $member_id)")
|
||||||
|
.bind(("user_id", self.id.clone()))
|
||||||
|
.bind(("member_id", member_id))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if res.take_errors().len() != 0 {
|
||||||
|
return Err(crate::Error::NoDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn verify_credentials(
|
pub async fn verify_credentials(
|
||||||
email: String,
|
email: String,
|
||||||
password: String,
|
password: String,
|
||||||
@ -99,8 +133,6 @@ impl User {
|
|||||||
.bind(("new_password", new_password))
|
.bind(("new_password", new_password))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
tracing::info!("{res:?}");
|
|
||||||
|
|
||||||
if res.take_errors().len() != 0 {
|
if res.take_errors().len() != 0 {
|
||||||
return Err(crate::Error::NoDocument);
|
return Err(crate::Error::NoDocument);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user