use crate::{ domain::PostEntry, routes::AppError, startup::AppState, templates::{PostTemplate, PostsTemplate}, }; use anyhow::Context; use askama::Template; use axum::{ extract::{Path, State}, response::{Html, IntoResponse, Response}, }; use sqlx::PgPool; use uuid::Uuid; pub async fn list_posts( State(AppState { connection_pool, .. }): State, ) -> Result { let posts = get_latest_posts(&connection_pool, 5) .await .context("Could not fetch latest posts") .map_err(AppError::unexpected_page)?; let template = PostsTemplate { posts }; Ok(Html(template.render().unwrap()).into_response()) } async fn get_latest_posts(connection_pool: &PgPool, n: i64) -> Result, sqlx::Error> { sqlx::query_as!( PostEntry, r#" SELECT p.post_id, u.username AS author, p.title, p.content, p.published_at FROM posts p LEFT JOIN users u ON p.author_id = u.user_id ORDER BY p.published_at DESC LIMIT $1 "#, n ) .fetch_all(connection_pool) .await } pub async fn see_post( State(AppState { connection_pool, .. }): State, Path(post_id): Path, ) -> Result { let post = get_post(&connection_pool, post_id) .await .context(format!("Failed to fetch post #{}", post_id)) .map_err(AppError::unexpected_page)? .to_html() .context("Could not render markdown with extension.")?; let template = PostTemplate { post }; Ok(Html(template.render().unwrap()).into_response()) } async fn get_post(connection_pool: &PgPool, post_id: Uuid) -> Result { sqlx::query_as!( PostEntry, r#" SELECT p.post_id, u.username AS author, p.title, p.content, p.published_at FROM posts p LEFT JOIN users u ON p.author_id = u.user_id WHERE p.post_id = $1 "#, post_id ) .fetch_one(connection_pool) .await }