use crate::localize_day; use crate::session_date_calculator::{DayIter, NthWeekday}; use chrono::Weekday; use leptos::prelude::*; use leptos::server_fn::request::browser::Request; use serde::{Deserialize, Serialize}; #[component] pub fn App() -> impl IntoView { let session_config = LocalResource::new(|| async { load_config::("session_config").await }); let session_dates = move || { session_config .get() .as_deref() .cloned() .map(|config| match config { Ok(config) => { let config = config.unwrap_or_default(); view! { }.into_any() } Err(e) => view! {

"Error"

{e}

} .into_any(), }) }; view! {
{session_dates}
} } #[component] fn Sessions(config: SessionConfig) -> impl IntoView { let mut session_iter = DayIter::default().filter(move |day| { config .sessions .iter() .any(|session_day| session_day.matches(day)) }); let (session_dates, set_session_dates) = signal(session_iter.by_ref().take(2).collect::>()); view! {

"Anstehende Proben Termine"

{config.motd}

{localize_day(&day)}
} />
"Mehr anzeigen"
} } async fn load_config(name: &str) -> Result, String> where T: for<'a> Deserialize<'a>, { let response = Request::get(&format!("/{name}.json")) .send() .await .map_err(|e| format!("HTTP error: {e}"))?; if response .headers() .get("content-type") .is_none_or(|content_type| content_type != "application/json") { return Ok(None); } let config = response .json() .await .map_err(|e| format!("JSON error: {e}"))?; Ok(Some(config)) } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(default)] pub struct SessionConfig { pub motd: Option, pub sessions: Vec, } impl Default for SessionConfig { fn default() -> Self { Self { motd: Some("Probe jeden ersten Sonntag im Monat um 10:00 Uhr und jeden dritten Dienstag im Monat um 18:30 Uhr".to_string()), sessions: vec![ NthWeekday::new(1, Weekday::Sun), NthWeekday::new(3, Weekday::Tue), ], } } }