use crate::components::multiselect; use crate::util::string_into_vec; use crate::{AppError, layouts, util::AppState}; use axum::{Form, Router, extract::State, http::StatusCode, routing::get}; use maud::{Markup, html}; use serde::Deserialize; use uuid::Uuid; pub fn routes() -> Router { Router::new().route("/", get(page).post(submit)) } async fn page(State(state): State) -> Result { let muscles = sqlx::query_as!(crate::models::Muscle, "SELECT * FROM muscles") .fetch_all(&state.pool) .await?; let muscles_map: Vec<(String, String)> = muscles.into_iter().map(|m| (m.muscle_id, m.name)).collect(); let categories = sqlx::query_as!(crate::models::Category, "SELECT * FROM categories") .fetch_all(&state.pool) .await?; let categories_map: Vec<(String, String)> = categories .into_iter() .map(|c| (c.category_id, c.name)) .collect(); let content = html! { form hx-post="/exercises/new" class="space-y-1" { fieldset class="fieldset" { legend class="fieldset-legend" { "Name" } input required="true" name="name" class="input" {} } fieldset class="fieldset" { legend class="fieldset-legend" { "Description" } textarea required="true" name="description" class="textarea" {} } (multiselect(muscles_map, "muscles", "Muscles")) (multiselect(categories_map, "categories", "Categories")) input type="submit" class="btn" value="save" { } } }; Ok(layouts::desktop(content, "New Exercise", true)) } #[derive(Deserialize, Debug)] struct FormData { name: String, description: String, muscles: String, categories: String, } async fn submit( State(state): State, Form(form): Form, ) -> Result { let exercise_id = Uuid::new_v4(); let muscle_ids = string_into_vec(form.muscles); let category_ids = string_into_vec(form.categories); let mut transaction = state.pool.begin().await?; sqlx::query!( "INSERT INTO exercises (exercise_id, name, description) VALUES ($1, $2, $3)", exercise_id, form.name, form.description ) .execute(&mut *transaction) .await?; tracing::info!("{:?} and {:?}", muscle_ids, category_ids); // Create and insert relationship between muscles and exercises if !muscle_ids.is_empty() { let exercise_ids = vec![exercise_id; muscle_ids.len()]; sqlx::query!( "INSERT INTO exercise_muscles (exercise_id, muscle_id) SELECT * FROM UNNEST($1::uuid[], $2::varchar[])", &exercise_ids, &muscle_ids ).execute(&mut *transaction).await?; } // Create and insert relationship between categories and exercises if !category_ids.is_empty() { let exercise_ids = vec![exercise_id; category_ids.len()]; sqlx::query!( "INSERT INTO exercise_categories (exercise_id, category_id) SELECT * FROM UNNEST($1::uuid[], $2::varchar[])", &exercise_ids, &category_ids ).execute(&mut *transaction).await?; } transaction.commit().await?; Ok(html! { p { "New exercise has been created!" } }) }