use dioxus::{
hooks::{use_resource, use_signal},
prelude::{Props, component, dioxus_elements, rsx},
signals::ReadableExt as _,
};
use dioxus_core::Element;
use dioxus_router::Link;
use oparl_types::PersonUrl;
use crate::{
client::{get_body, get_organization, get_person},
route::{Route, UrlEncoded},
};
#[derive(Debug, Clone, PartialEq, Props)]
pub struct PersonProps {
person_url: UrlEncoded<PersonUrl>,
}
struct PersonData {
person: oparl_types::Person,
memberships: Vec<(oparl_types::Membership, oparl_types::Organization)>,
body: oparl_types::Body,
}
impl PersonData {
async fn get(person_url: &PersonUrl) -> Result<Self, String> {
let person = get_person(person_url).await?;
let body = get_body(person.body.as_ref().unwrap()).await?;
let mut memberships = Vec::new();
for membership in &person.membership {
let organization = get_organization(membership.organization.as_ref().unwrap()).await?;
memberships.push((membership.clone(), organization));
}
Ok(Self {
person,
memberships,
body,
})
}
}
#[component]
pub fn Person(props: PersonProps) -> Element {
let person_url = use_signal(|| props.person_url.get_inner().unwrap().clone());
let data = { use_resource(move || async move { PersonData::get(&person_url()).await }) };
rsx! {
match &*data.read_unchecked() {
Some(Ok(data)) => rsx! {
if let Some(name) = &data.person.name {
dioxus::document::Title { "🧑 {name}" }
} else {
dioxus::document::Title { "🧑 (Unnamed person)" }
}
h1 {
"🧑 "
if let Some(name) = &data.person.name {
"{name}"
} else {
"(Unnamed person)"
}
}
Link {
to: Route::Body{body_url: UrlEncoded::from(data.body.id.clone())},
"🏛️ { data.body.name }"
}
h2 {
"Memberships"
}
ul {
for (membership, organization) in &data.memberships {
li {
key: "{membership.id}",
span {
Link {
to: Route::Organization { organization_url: UrlEncoded::from(organization.id.clone()) },
if let Some(name) = &organization.name {
"{ name }"
} else {
"(Unnamed organization)"
}
}
}
}
}
}
},
Some(Err(e)) => rsx! {
dioxus::document::Title { "Loading failed." },
p { "Loading person failed, {e}" }
},
None => rsx! {
dioxus::document::Title { "Loading…" },
p { "Loading..." }
}
}
}
}