113 lines
3.3 KiB
Rust
113 lines
3.3 KiB
Rust
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<AppState> {
|
|
Router::new().route("/", get(page).post(submit))
|
|
}
|
|
|
|
async fn page(State(state): State<AppState>) -> Result<Markup, AppError> {
|
|
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<AppState>,
|
|
Form(form): Form<FormData>,
|
|
) -> Result<Markup, AppError> {
|
|
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!"
|
|
}
|
|
})
|
|
}
|