use std::sync::Arc; use axum::{Router, response::Html, routing::get, extract::{State, Path}}; use serde_derive::Serialize; use tracing::instrument; use crate::{AppState, WebsiteError, post::Post}; pub fn router() -> Router> { Router::new() .route("/", get(index)) .route("/:tag/", get(view)) } #[derive(Serialize, Debug)] struct PageContext<'a> { title: &'a str, } #[instrument(skip(state))] pub async fn index(State(state): State>) -> Result, WebsiteError> { let tags: Vec<_> = state.tags.values().collect(); let ctx = PageContext { title: "Tags" }; let mut c = tera::Context::new(); c.insert("page", &ctx); c.insert("tags", &tags); let res = state.tera.render("tags_index.html", &c)?; Ok(Html(res)) } #[instrument(skip(state))] pub async fn view(Path(tag): Path, State(state): State>) -> Result, WebsiteError> { let mut posts: Vec<&Post> = state.posts.values().filter(|p| p.is_published() && p.tags.contains(&tag)).collect(); posts.sort_by_key(|p| &p.date); posts.reverse(); let title = format!("Posts tagged with #{tag}"); let ctx = PageContext { title: &title }; let mut c = tera::Context::new(); c.insert("page", &ctx); c.insert("posts", &posts); let res = state.tera.render("tag.html", &c)?; Ok(Html(res)) }