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, dioxus_elements, rsx},
    signals::ReadableExt as _,
};
use dioxus_core::Element;
use dioxus_i18n::t;
use oparl_types::BodyUrl;

use crate::{
    client::{get_body, get_meetings, get_organizations, get_persons},
    components::{MeetingList, OrganizationList, PersonList},
    route::UrlEncoded,
};

#[derive(Debug, Clone, PartialEq, Props)]
pub struct BodyProps {
    body_url: UrlEncoded<BodyUrl>,
}

struct BodyData {
    body: oparl_types::Body,
    persons: Vec<oparl_types::Person>,
    organizations: Vec<oparl_types::Organization>,
    meetings: Vec<oparl_types::Meeting>,
}

impl BodyData {
    async fn get(body_url: &BodyUrl) -> Result<Self, String> {
        let body = get_body(body_url).await?;
        let persons = get_persons(&body.person).await?;
        let organizations = get_organizations(&body.organization).await?;
        let meetings = get_meetings(&body.meeting).await?;
        Ok(Self {
            body,
            persons: persons.data,
            organizations: organizations.data,
            meetings: meetings.data,
        })
    }
}

#[component]
pub fn Body(props: BodyProps) -> Element {
    let body_url = use_signal(|| props.body_url.get_inner().unwrap().clone());
    let data = { use_resource(move || async move { BodyData::get(&body_url()).await }) };
    rsx! {
        match &*data.read_unchecked() {
            Some(Ok(data)) => rsx! {
                dioxus::document::Title { { t!("body-label", name: data.body.name.as_str() ) } }
                h1 {
                    { t!("body-label", name: data.body.name.as_str() ) }
                }
                MeetingList {
                    meetings: data.meetings.clone()
                }
                OrganizationList {
                    organizations: data.organizations.clone()
                }
                PersonList {
                    persons: data.persons.clone()
                }
            },
            Some(Err(e)) => rsx! {
                dioxus::document::Title { { t!("loading-failed") } },
                p { { t!("loading-body-failed", error: e.to_string()) } }
            },
            None =>  rsx! {
                dioxus::document::Title { { t!("loading") } },
                p { { t!("loading") } }
            }
        }
    }
}