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 dioxus_router::Link;
use oparl_types::AgendaItemUrl;

use crate::{
    client::{get_agenda_item, get_meeting},
    route::{Route, UrlEncoded},
};

#[derive(Debug, Clone, PartialEq, Props)]
pub struct AgendaItemProps {
    agenda_item_url: UrlEncoded<AgendaItemUrl>,
}

struct AgendaItemData {
    agenda_item: oparl_types::AgendaItem,
    meeting: oparl_types::Meeting,
}

impl AgendaItemData {
    async fn get(agenda_item_url: &AgendaItemUrl) -> Result<Self, String> {
        let agenda_item = get_agenda_item(agenda_item_url).await?;

        let meeting = get_meeting(agenda_item.meeting.as_ref().unwrap()).await?;

        Ok(Self {
            agenda_item,
            meeting,
        })
    }
}

#[component]
pub fn AgendaItem(props: AgendaItemProps) -> Element {
    let agenda_item_url = use_signal(|| props.agenda_item_url.get_inner().unwrap().clone());
    let data =
        { use_resource(move || async move { AgendaItemData::get(&agenda_item_url()).await }) };
    rsx! {
        match &*data.read_unchecked() {
            Some(Ok(data)) => {
                let agenda_item_label =
                    if let Some(name) = &data.agenda_item.name {
                        { t!("agenda-item-label", name: name.as_str()) }
                    } else {
                        { t!("agenda-item-label-unknown") }
                    };
                rsx! {
                    dioxus::document::Title { "{agenda_item_label}" }
                    h1 { "{agenda_item_label}" },
                    Link {
                        to: Route::Meeting{ meeting_url: UrlEncoded::from(data.meeting.id.clone())},
                        if let Some(name) = &data.meeting.name {
                            { t!("meeting-label", name: name.as_str()) }
                        } else {
                            i { { t!("meeting-unknown-label") } }
                        }
                    }
                }
            },
            Some(Err(e)) => rsx! { p { { t!("loading-agenda-item-failed", error: e.to_string()) } } },
            None =>  rsx! { p { { t!("loading") } } }
        }
    }
}