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::prelude::{Props, component, dioxus_elements, rsx};
use dioxus_core::Element;
use dioxus_i18n::t;
use dioxus_router::Link;
use oparl_types::{DateTime, Meeting};
use time::{OffsetDateTime, format_description};

use crate::route::{Route, UrlEncoded};

#[derive(Debug, Clone, PartialEq, Props)]
pub struct MeetingProps {
    meeting: Meeting,
}

#[component]
pub fn Meeting(props: MeetingProps) -> Element {
    rsx! {
        Link {
            to: Route::Meeting { meeting_url: UrlEncoded::from(props.meeting.id) },
            span {
                class: "infobox",
                span {
                    class: "label",
                    if let Some(name) = props.meeting.name {
                        "{name}"
                    } else {
                        i {
                            { t!("meeting-unknown") }
                        }
                    }
                }
                br {}
                if let Some(timespan) = timespan(props.meeting.start,props.meeting.end) {
                    "{timespan}"
                }
                br {}
                { t!("count-agenda-items", count: {props.meeting.agenda_item.len()}) }
            }
        }
    }
}

fn timespan(start: Option<DateTime>, end: Option<DateTime>) -> Option<String> {
    let date_format_string = t!("date-format-string");
    let time_format_string = t!("time-format-string");
    let date_time_format_string = t!("date-time-format-string");

    let date_format = format_description::parse(&date_format_string).unwrap();
    let time_format = format_description::parse(&time_format_string).unwrap();
    let date_time_format = format_description::parse(&date_time_format_string).unwrap();

    let start: Option<OffsetDateTime> = start.map(Into::into);
    let end: Option<OffsetDateTime> = end.map(Into::into);

    match (start, end) {
        (Some(start), Some(end)) if start.date() == end.date() => {
            let date = start.format(&date_format).unwrap();
            let start_time = start.format(&time_format).unwrap();
            let end_time = end.format(&time_format).unwrap();
            Some(
                t!("meeting-date-time-duration-same-day", date: date, start_time: start_time, end_time: end_time),
            )
        }
        (Some(start), Some(end)) => {
            let start_date = start.format(&date_format).unwrap();
            let start_time = start.format(&time_format).unwrap();

            let end_date = start.format(&date_format).unwrap();
            let end_time = end.format(&time_format).unwrap();
            Some(
                t!("meeting-date-time-duration-different-days", start_date: start_date, start_time: start_time, end_date: end_date, end_time: end_time),
            )
        }
        (Some(start), None) => Some(start.format(&date_time_format).unwrap()),
        (None, _) => None,
    }
}