pib-viewer 0.8.0

A viewer for public governmental data served over OParl
// SPDX-FileCopyrightText: Politik im Blick developers
// SPDX-FileCopyrightText: Wolfgang Silbermayr <wolfgang@silbermayr.at>
//
// SPDX-License-Identifier: AGPL-3.0-or-later OR EUPL-1.2

use dioxus::{
    hooks::{use_resource, use_signal},
    prelude::{Props, component, rsx},
    signals::ReadableExt as _,
};
use dioxus_core::Element;
use oparl_types::{Membership, MembershipUrl};

use crate::{
    client::{get_membership, get_person},
    components::Person,
};

struct OrganizationMembershipData {
    membership: Membership,
    person: oparl_types::Person,
}

impl OrganizationMembershipData {
    async fn get(membership_url: &MembershipUrl) -> Result<Self, String> {
        let membership = get_membership(membership_url).await?;
        let person = get_person(membership.person.as_ref().unwrap()).await?;
        Ok(Self { membership, person })
    }
}

#[derive(Debug, Clone, PartialEq, Props)]
pub struct OrganizationMembershipProps {
    membership_url: MembershipUrl,
}

#[component]
pub fn OrganizationMembership(
    OrganizationMembershipProps { membership_url }: OrganizationMembershipProps,
) -> Element {
    let membership_url = use_signal(|| membership_url);
    let data = {
        use_resource(
            move || async move { OrganizationMembershipData::get(&membership_url()).await },
        )
    };

    rsx! {
        match &*data.read_unchecked() {
            Some(Ok(data)) => rsx! {
                Person { person: data.person.clone() }
                if let Some(role) = &data.membership.role {
                    " ({ role })"
                } else {
                    " (unknown role)"
                }
            },
            Some(Err(e)) => rsx! { "Loading membership failed, {e}" },
            None => rsx! { "Loading…" },
        }
    }
}