From 6421074931aaadf88cb7452dd594045eccd16a98 Mon Sep 17 00:00:00 2001 From: Djeeberjr Date: Mon, 13 Oct 2025 16:32:28 +0200 Subject: [PATCH] added routes for listing days & getting days /api/days?from=...&to=... /api/day?day=... --- src/webserver/api.rs | 68 +++++++++++++++++++++++++++++++++----------- src/webserver/app.rs | 4 ++- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/webserver/api.rs b/src/webserver/api.rs index 778a0ff..5f1e887 100644 --- a/src/webserver/api.rs +++ b/src/webserver/api.rs @@ -1,11 +1,12 @@ +use esp_println::dbg; use picoserve::{ - extract::{Json, State}, + extract::{Json, Query, State}, response::{self, IntoResponse}, }; use serde::Deserialize; use crate::{ - store::{Name, tally_id::TallyID}, + store::{self, Name, day::Day, tally_id::TallyID}, webserver::{app::AppState, sse::IDEvents}, }; @@ -15,27 +16,25 @@ pub struct NewMapping { name: Name, } -// struct MappingWrapper(IDMapping); -// -// impl Serialize for MappingWrapper { -// fn serialize(&self, serializer: S) -> Result -// where -// S: serde::Serializer, -// { -// use serde::ser::SerializeMap; -// let mut map = serializer.serialize_map(Some(self.0.id_map.len()))?; -// for (k, v) in &self.0.id_map { -// map.serialize_entry(tally_id_to_hex_string(*k).unwrap().as_str(), &v)?; -// } -// map.end() -// } -// } +#[derive(Deserialize)] +pub struct QueryTimespan { + from: u64, + to: u64, +} +#[derive(Deserialize)] +pub struct QueryDay { + timestamp: Option, + day: Option, +} + +// GET /api/mapping pub async fn get_mapping(State(state): State) -> impl IntoResponse { let store = state.store.lock().await; response::Json(store.mapping.clone()) } +// POST /api/mapping pub async fn add_mapping( State(state): State, Json(data): Json, @@ -44,6 +43,41 @@ pub async fn add_mapping( store.mapping.add_mapping(data.id, data.name); } +// SSE /api/idevent pub async fn get_idevent(State(state): State) -> impl IntoResponse { response::EventStream(IDEvents(state.chan.subscriber().unwrap())) } + +// GET /api/days +pub async fn get_days( + State(state): State, + Query(QueryTimespan { from, to }): Query, +) -> impl IntoResponse { + let from_day = Day::new_from_timestamp(from); + let to_day = Day::new_from_timestamp(to); + + let mut store = state.store.lock().await; + + let days = store.list_days_in_timespan(from_day, to_day).await; + + response::Json(days) +} + +// GET /api/day +pub async fn get_day( + State(state): State, + Query(QueryDay { timestamp, day }): Query, +) -> Result { + + let parsed_day = timestamp + .map(Day::new_from_timestamp) + .or_else(|| day.map(Day::new)) + .ok_or((response::StatusCode::NOT_FOUND, "Not found"))?; + + let mut store = state.store.lock().await; + + match store.load_day(parsed_day).await { + Some(att_day) => Ok(response::Json(att_day)), + None => Err((response::StatusCode::NOT_FOUND, "Not found")), + } +} diff --git a/src/webserver/app.rs b/src/webserver/app.rs index 210621f..e4c24ea 100644 --- a/src/webserver/app.rs +++ b/src/webserver/app.rs @@ -5,7 +5,7 @@ use picoserve::{AppWithStateBuilder, routing::get}; use crate::{ TallyChannel, UsedStore, webserver::{ - api::{add_mapping, get_idevent, get_mapping}, + api::{add_mapping, get_day, get_days, get_idevent, get_mapping}, assets::Assets, }, }; @@ -26,5 +26,7 @@ impl AppWithStateBuilder for AppProps { picoserve::Router::from_service(Assets) .route("/api/mapping", get(get_mapping).post(add_mapping)) .route("/api/idevent", get(get_idevent)) + .route("/api/days", get(get_days)) + .route("/api/day", get(get_day)) } }