use std::{fmt::Display, str::FromStr};
use dioxus::prelude::{VNode, rsx};
use dioxus_router::Routable;
use oparl_types::{AgendaItemUrl, BodyUrl, MeetingUrl, OrganizationUrl, PersonUrl, SystemUrl};
use crate::views::{AgendaItem, Body, Home, Meeting, OParlSystem, Organization, Person};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum UrlEncoded<T: Display + FromStr> {
Valid(T),
Invalid(String),
}
impl<T: Display + FromStr> From<T> for UrlEncoded<T> {
fn from(value: T) -> Self {
Self::Valid(value)
}
}
impl<T: Display + FromStr> UrlEncoded<T> {
pub fn get_inner(&self) -> Option<&T> {
let Self::Valid(inner) = self else {
return None;
};
Some(inner)
}
}
impl<T: Display + FromStr> Display for UrlEncoded<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UrlEncoded::Valid(value) => write!(f, "{}", urlencoding::encode(&value.to_string())),
UrlEncoded::Invalid(invalid) => write!(f, "{invalid}"),
}
}
}
impl<T: Display + FromStr> FromStr for UrlEncoded<T> {
type Err = T::Err;
fn from_str(s: &str) -> Result<UrlEncoded<T>, Self::Err> {
match urlencoding::decode(s) {
Ok(decoded) => {
if let Ok(parsed) = decoded.parse() {
Ok(Self::Valid(parsed))
} else {
Ok(Self::Invalid(s.to_string()))
}
}
Err(_e) => Ok(Self::Invalid(s.to_string())),
}
}
}
#[derive(Debug, Clone, Routable, PartialEq)]
pub(crate) enum Route {
#[route("/")]
Home {},
#[route("/system/:system_url")]
OParlSystem { system_url: UrlEncoded<SystemUrl> },
#[route("/body/:body_url")]
Body { body_url: UrlEncoded<BodyUrl> },
#[route("/organization/:organization_url")]
Organization {
organization_url: UrlEncoded<OrganizationUrl>,
},
#[route("/person/:person_url")]
Person { person_url: UrlEncoded<PersonUrl> },
#[route("/meeting/:meeting_url")]
Meeting { meeting_url: UrlEncoded<MeetingUrl> },
#[route("/agenda_item/:agenda_item_url")]
AgendaItem {
agenda_item_url: UrlEncoded<AgendaItemUrl>,
},
}