use dioxus::{
document,
hooks::use_signal,
prelude::{component, dioxus_elements, rsx},
};
use dioxus_core::Element;
use dioxus_signals::{ReadableExt as _, WritableExt as _};
use manganis::{Asset, asset};
use tracing::{info, warn};
use url::Url;
use crate::{
client::{Config, Contents},
components::ConnectDialog,
route::{Route, UrlEncoded},
};
const WELCOME_PAGE_CSS: Asset = asset!("/assets/styling/components/welcome_page.css");
#[component]
pub fn WelcomePage() -> Element {
let mut config_state = use_signal(|| ConfigState::Initial);
#[derive(Debug, Clone, PartialEq, Eq)]
enum ConfigState {
Initial,
Loading,
Failed { message: String },
NoConfigPresent,
ConfigLoaded { config: Config },
}
let initialize_config = move |_| async move {
if !matches!(&*config_state.read(), ConfigState::Initial) {
return;
}
*config_state.write() = ConfigState::Loading;
let Ok(base_url) = document::eval("return document.URL;").await else {
warn!("couldn't load base url.");
*config_state.write() = ConfigState::Failed {
message: "couldn't load base url.".to_string(),
};
return;
};
let serde_json::Value::String(base_url) = base_url else {
warn!("not a string value: {base_url}");
*config_state.write() = ConfigState::Failed {
message: format!("not a string value: {base_url}"),
};
return;
};
info!("base url: {base_url:?}");
let base_url = match base_url.parse::<Url>() {
Ok(url) => url,
Err(e) => {
warn!("Couldn't parse base url {base_url}, reason: {e}");
*config_state.write() = ConfigState::Failed {
message: format!("Couldn't parse base url {base_url}, reason: {e}"),
};
return;
}
};
match crate::client::get_initial_config(base_url).await {
Ok(Some(config)) => {
*config_state.write() = ConfigState::ConfigLoaded { config };
}
Ok(None) => {
*config_state.write() = ConfigState::NoConfigPresent;
}
Err(e) => {
*config_state.write() = ConfigState::Failed {
message: format!("Failed to load config: {e}"),
};
}
}
};
rsx! {
document::Link { rel: "stylesheet", href: WELCOME_PAGE_CSS }
div {
onmounted: initialize_config,
id: "welcome_page",
h1 { "🗒️ PiB Viewer" }
p {
"👋 Hi! "
b { "PiB Viewer" }
" allows you to view public administration data from an "
a {
href: "https://oparl.org/",
"OParl v1.1 service"
}
"."
}
match &*config_state.read_unchecked() {
ConfigState::ConfigLoaded { config } => rsx! {
match &config.contents {
Contents::SingleSystem { system } => rsx! {
div {
dioxus_router::Link {
to: Route::OParlSystem {
system_url: UrlEncoded::from(system.url.clone()),
},
"Go to {system.name}…"
}
}
},
Contents::SingleBody { body } => rsx! {
div {
dioxus_router::Link {
to: Route::Body {
body_url: UrlEncoded::from(body.url.clone()),
},
"Go to 🏛️ {body.name}…"
}
}
},
Contents::ConnectDialog => rsx! {
ConnectDialog {},
}
}
},
ConfigState::NoConfigPresent => rsx! {
ConnectDialog {},
},
ConfigState::Failed{message} => rsx! {
div {
p { "Loading config failed, {message}" }
button {
class: "button",
"data-style": "primary",
onclick: move |_| async move {
*config_state.write() = ConfigState::NoConfigPresent
},
"Show connect dialog"
}
}
},
ConfigState::Loading | ConfigState::Initial=> rsx! { p { "Loading config..." } }
}
}
}
}