use dioxus::{
hooks::{use_resource, use_signal},
prelude::{Props, component, dioxus_elements, rsx},
signals::ReadableExt as _,
};
use dioxus_core::Element;
use dioxus_i18n::t;
use dioxus_router::Link;
use oparl_types::PersonUrl;
use crate::{
client::{get_body, get_organization, get_person},
components::Organization,
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)) => {
let person_label =
if let Some(name) = &data.person.name {
t!("person-label", name: name.as_str())
} else {
t!("person-unknown-label")
};
rsx! {
dioxus::document::Title { "{person_label}" }
h1 { "{person_label}" }
Link {
to: Route::Body{body_url: UrlEncoded::from(data.body.id.clone())},
{ t!("body-label", name: data.body.name.as_str()) }
}
div {
class: "card",
div {
class: "header",
h2 { { t!("memberships") } }
}
div {
class: "content",
ul {
class: "sectional",
style: "list-style-type: '🛖 '; padding-left: 1.5em;",
for (membership, organization) in data.memberships.iter().cloned() {
li {
key: "{membership.id}",
Organization { organization },
}
}
}
}
}
}
},
Some(Err(e)) => rsx! {
dioxus::document::Title { { t!("loading-failed") } },
p { { t!("loading-person-failed", error: e.to_string()) } }
},
None => rsx! {
dioxus::document::Title { { t!("loading") } },
p { { t!("loading") } }
}
}
}
}