Good changes

This commit is contained in:
Andras Schmelczer 2026-03-11 20:44:34 +00:00
parent 80a5a2a774
commit 791bc6976b
24 changed files with 890 additions and 312 deletions

View file

@ -0,0 +1,58 @@
use std::sync::Arc;
use axum::http::StatusCode;
use axum::response::Json;
use serde::{Deserialize, Serialize};
use crate::state::AppState;
#[derive(Deserialize)]
pub struct JourneyQuery {
postcode: String,
mode: String,
slug: String,
}
#[derive(Serialize)]
pub struct JourneyResponse {
/// Raw JSON array of journey legs, or null if no journey data available.
journey: Option<serde_json::Value>,
/// Median (50th percentile) total travel time in minutes.
minutes: Option<i16>,
/// Best-case (5th percentile) total travel time in minutes (transit only).
best_minutes: Option<i16>,
}
pub async fn get_journey(
state: Arc<AppState>,
query: axum::extract::Query<JourneyQuery>,
) -> Result<Json<JourneyResponse>, (StatusCode, String)> {
let store = &state.travel_time_store;
if !store.has_destination(&query.mode, &query.slug) {
return Err((
StatusCode::NOT_FOUND,
format!("No travel data for mode={} slug={}", query.mode, query.slug),
));
}
let travel_data = store.get(&query.mode, &query.slug).map_err(|e| {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Failed to load travel data: {e}"),
)
})?;
let row = travel_data.get(&query.postcode);
let journey = row
.and_then(|r| r.journey.as_ref())
.and_then(|j| serde_json::from_str::<serde_json::Value>(j).ok());
let minutes = row.map(|r| r.minutes);
let best_minutes = row.and_then(|r| r.best_minutes);
Ok(Json(JourneyResponse {
journey,
minutes,
best_minutes,
}))
}