use crate::{AppError, layouts, util::AppState}; use axum::{ Form, Router, extract::{Path, State}, http::HeaderMap, response::IntoResponse, routing::get, }; use maud::{Markup, html}; use serde::Deserialize; use uuid::Uuid; pub fn routes() -> Router { Router::new() .route("/", get(page).delete(delete).put(submit_edit)) .route("/edit", get(edit)) } async fn page(State(state): State, Path(id): Path) -> Result { let exercise = sqlx::query_as!( crate::models::Exercise, "SELECT exercise_id, name, description FROM exercises WHERE exercise_id = $1", id ) .fetch_one(&state.pool) .await?; let content = html! { div { div class="flex w-full" { h1 { (exercise.name) } a href={"/exercises/" (exercise.exercise_id) "/edit" } class="ml-auto btn" { "Edit" } } p { (exercise.description) } button hx-delete={ "/exercises/" (exercise.exercise_id) } hx-confirm="Are you sure that you want to delete this exercise?" class="btn btn-error" { "Delete Exercise" } } }; Ok(layouts::desktop(content, "Exercises")) } async fn delete( State(state): State, Path(id): Path, ) -> Result { sqlx::query_as!( crate::models::Exercise, "DELETE FROM exercises WHERE exercise_id = $1", id ) .execute(&state.pool) .await?; let mut headers = HeaderMap::new(); headers.insert("hx-location", "/exercises".parse().unwrap()); Ok((headers, html! {})) } async fn edit( State(state): State, Path(id): Path, ) -> Result { let exercise = sqlx::query_as!( crate::models::Exercise, "SELECT exercise_id, name, description FROM exercises WHERE exercise_id = $1", id ) .fetch_one(&state.pool) .await?; let content = html! { h1 class="mb-5" { "Edit Exercise" } form hx-put={"/exercises/" (exercise.exercise_id)} class="space-y-1" { fieldset class="fieldset" { legend class="fieldset-legend" { "Name" } input required="true" name="name" class="input" value={(exercise.name)} {} } fieldset class="fieldset" { legend class="fieldset-legend" { "Description" } textarea required="true" name="description" class="textarea" { (exercise.description) } } input type="submit" class="btn" value="save" { } } }; Ok(layouts::desktop(content, "Edit Exercises")) } #[derive(Deserialize, Debug)] struct FormData { name: String, description: String, } async fn submit_edit( State(state): State, Path(id): Path, Form(form): Form, ) -> Result { sqlx::query_as!( crate::models::Exercise, "UPDATE exercises SET name = $1, description = $2 WHERE exercise_id = $3", form.name, form.description, id ) .execute(&state.pool) .await?; let mut headers = HeaderMap::new(); let location = format!("/exercises/{}", id); headers.insert("hx-location", location.parse().unwrap()); Ok((headers, html! {})) }