|
@@ -0,0 +1,108 @@
|
|
|
|
|
+use serde::Serialize;
|
|
|
|
|
+use sqlx::{PgPool, Postgres};
|
|
|
|
|
+use time::OffsetDateTime;
|
|
|
|
|
+use uuid::Uuid;
|
|
|
|
|
+
|
|
|
|
|
+use super::exercise::ExerciseType;
|
|
|
|
|
+
|
|
|
|
|
+#[derive(sqlx::FromRow, Serialize)]
|
|
|
|
|
+pub struct Session {
|
|
|
|
|
+ pub id: Uuid,
|
|
|
|
|
+ pub workout: Uuid,
|
|
|
|
|
+ pub user_id: Uuid,
|
|
|
|
|
+ #[serde(with = "time::serde::iso8601")]
|
|
|
|
|
+ pub created_at: OffsetDateTime,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+impl Session {
|
|
|
|
|
+ pub async fn create<'c, E>(executor: E, workout_id: Uuid, user_id: Uuid) -> Result<Session, sqlx::Error>
|
|
|
|
|
+ where
|
|
|
|
|
+ E: sqlx::Executor<'c, Database = Postgres>,
|
|
|
|
|
+ {
|
|
|
|
|
+ sqlx::query_as::<_, Session>(
|
|
|
|
|
+ "INSERT INTO sessions (workout, user_id) VALUES ($1, $2) RETURNING *",
|
|
|
|
|
+ )
|
|
|
|
|
+ .bind(workout_id)
|
|
|
|
|
+ .bind(user_id)
|
|
|
|
|
+ .fetch_one(executor)
|
|
|
|
|
+ .await
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub async fn find_by_id(pool: &PgPool, id: Uuid) -> Result<Option<Session>, sqlx::Error> {
|
|
|
|
|
+ sqlx::query_as::<_, Session>("SELECT * FROM sessions WHERE id = $1")
|
|
|
|
|
+ .bind(id)
|
|
|
|
|
+ .fetch_optional(pool)
|
|
|
|
|
+ .await
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub async fn find_by_user(pool: &PgPool, user_id: Uuid) -> Result<Vec<Session>, sqlx::Error> {
|
|
|
|
|
+ sqlx::query_as::<_, Session>(
|
|
|
|
|
+ "SELECT * FROM sessions WHERE user_id = $1 ORDER BY created_at DESC",
|
|
|
|
|
+ )
|
|
|
|
|
+ .bind(user_id)
|
|
|
|
|
+ .fetch_all(pool)
|
|
|
|
|
+ .await
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#[derive(sqlx::FromRow, Serialize, Clone)]
|
|
|
|
|
+pub struct SessionExercise {
|
|
|
|
|
+ pub id: Uuid,
|
|
|
|
|
+ pub session: Uuid,
|
|
|
|
|
+ pub exercise: Uuid,
|
|
|
|
|
+ pub name: String,
|
|
|
|
|
+ pub notes: Option<String>,
|
|
|
|
|
+ pub exercise_type: ExerciseType,
|
|
|
|
|
+ pub position: i32,
|
|
|
|
|
+ pub sets: Option<i32>,
|
|
|
|
|
+ pub reps: Option<i32>,
|
|
|
|
|
+ pub weight: Option<f64>,
|
|
|
|
|
+ pub duration_seconds: Option<i32>,
|
|
|
|
|
+ pub distance_meters: Option<f64>,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+impl SessionExercise {
|
|
|
|
|
+ pub async fn find_by_session(pool: &PgPool, session_id: Uuid) -> Result<Vec<SessionExercise>, sqlx::Error> {
|
|
|
|
|
+ sqlx::query_as::<_, SessionExercise>("SELECT * FROM session_exercises WHERE session = $1 ORDER BY position")
|
|
|
|
|
+ .bind(session_id)
|
|
|
|
|
+ .fetch_all(pool)
|
|
|
|
|
+ .await
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub async fn create<'c, E>(
|
|
|
|
|
+ executor: E,
|
|
|
|
|
+ session_id: Uuid,
|
|
|
|
|
+ exercise_id: Uuid,
|
|
|
|
|
+ name: &str,
|
|
|
|
|
+ notes: Option<&str>,
|
|
|
|
|
+ exercise_type: ExerciseType,
|
|
|
|
|
+ position: i32,
|
|
|
|
|
+ sets: Option<i32>,
|
|
|
|
|
+ reps: Option<i32>,
|
|
|
|
|
+ weight: Option<f64>,
|
|
|
|
|
+ duration_seconds: Option<i32>,
|
|
|
|
|
+ distance_meters: Option<f64>,
|
|
|
|
|
+ ) -> Result<SessionExercise, sqlx::Error>
|
|
|
|
|
+ where
|
|
|
|
|
+ E: sqlx::Executor<'c, Database = Postgres>,
|
|
|
|
|
+ {
|
|
|
|
|
+ sqlx::query_as::<_, SessionExercise>(
|
|
|
|
|
+ r#"INSERT INTO session_exercises
|
|
|
|
|
+ (session, exercise, name, notes, exercise_type, position, sets, reps, weight, duration_seconds, distance_meters)
|
|
|
|
|
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING *"#,
|
|
|
|
|
+ )
|
|
|
|
|
+ .bind(session_id)
|
|
|
|
|
+ .bind(exercise_id)
|
|
|
|
|
+ .bind(name)
|
|
|
|
|
+ .bind(notes)
|
|
|
|
|
+ .bind(exercise_type)
|
|
|
|
|
+ .bind(position)
|
|
|
|
|
+ .bind(sets)
|
|
|
|
|
+ .bind(reps)
|
|
|
|
|
+ .bind(weight)
|
|
|
|
|
+ .bind(duration_seconds)
|
|
|
|
|
+ .bind(distance_meters)
|
|
|
|
|
+ .fetch_one(executor)
|
|
|
|
|
+ .await
|
|
|
|
|
+ }
|
|
|
|
|
+}
|