This is the initial push of the outline of the life dashboard
This commit is contained in:
137
backend/app/routers/workout.py
Normal file
137
backend/app/routers/workout.py
Normal file
@@ -0,0 +1,137 @@
|
||||
from datetime import date
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session, selectinload
|
||||
|
||||
from app.auth import get_current_user
|
||||
from app.database import get_db
|
||||
from app.models.workout import Exercise, Workout, WorkoutSet
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/api", tags=["workouts"], dependencies=[Depends(get_current_user)]
|
||||
)
|
||||
|
||||
|
||||
# --- Schemas ---
|
||||
|
||||
|
||||
class ExerciseCreate(BaseModel):
|
||||
name: str
|
||||
category: str
|
||||
|
||||
|
||||
class ExerciseRead(ExerciseCreate):
|
||||
id: int
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class WorkoutSetCreate(BaseModel):
|
||||
exercise_id: int
|
||||
set_number: int
|
||||
reps: int | None = None
|
||||
weight_lbs: float | None = None
|
||||
duration_min: float | None = None
|
||||
|
||||
|
||||
class WorkoutSetRead(WorkoutSetCreate):
|
||||
id: int
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class WorkoutCreate(BaseModel):
|
||||
date: date
|
||||
name: str | None = None
|
||||
notes: str | None = None
|
||||
sets: list[WorkoutSetCreate] = []
|
||||
|
||||
|
||||
class WorkoutRead(BaseModel):
|
||||
id: int
|
||||
date: date
|
||||
name: str | None
|
||||
notes: str | None
|
||||
sets: list[WorkoutSetRead]
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
# --- Exercise endpoints ---
|
||||
|
||||
|
||||
@router.get("/exercises", response_model=list[ExerciseRead])
|
||||
def list_exercises(db: Session = Depends(get_db)):
|
||||
return db.scalars(select(Exercise).order_by(Exercise.name)).all()
|
||||
|
||||
|
||||
@router.post("/exercises", response_model=ExerciseRead, status_code=201)
|
||||
def create_exercise(body: ExerciseCreate, db: Session = Depends(get_db)):
|
||||
ex = Exercise(**body.model_dump())
|
||||
db.add(ex)
|
||||
db.commit()
|
||||
db.refresh(ex)
|
||||
return ex
|
||||
|
||||
|
||||
# --- Workout endpoints ---
|
||||
|
||||
|
||||
@router.get("/workouts", response_model=list[WorkoutRead])
|
||||
def list_workouts(
|
||||
from_date: date | None = Query(None, alias="from"),
|
||||
to_date: date | None = Query(None, alias="to"),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
q = (
|
||||
select(Workout)
|
||||
.options(selectinload(Workout.sets))
|
||||
.order_by(Workout.date.desc())
|
||||
)
|
||||
if from_date:
|
||||
q = q.where(Workout.date >= from_date)
|
||||
if to_date:
|
||||
q = q.where(Workout.date <= to_date)
|
||||
return db.scalars(q).all()
|
||||
|
||||
|
||||
@router.post("/workouts", response_model=WorkoutRead, status_code=201)
|
||||
def create_workout(body: WorkoutCreate, db: Session = Depends(get_db)):
|
||||
sets_data = body.sets
|
||||
workout = Workout(
|
||||
date=body.date,
|
||||
name=body.name,
|
||||
notes=body.notes,
|
||||
sets=[WorkoutSet(**s.model_dump()) for s in sets_data],
|
||||
)
|
||||
db.add(workout)
|
||||
db.commit()
|
||||
db.refresh(workout)
|
||||
return workout
|
||||
|
||||
|
||||
@router.put("/workouts/{workout_id}", response_model=WorkoutRead)
|
||||
def update_workout(
|
||||
workout_id: int, body: WorkoutCreate, db: Session = Depends(get_db)
|
||||
):
|
||||
workout = db.get(Workout, workout_id, options=[selectinload(Workout.sets)])
|
||||
if not workout:
|
||||
raise HTTPException(status_code=404, detail="Workout not found")
|
||||
workout.date = body.date
|
||||
workout.name = body.name
|
||||
workout.notes = body.notes
|
||||
# Replace sets
|
||||
workout.sets.clear()
|
||||
for s in body.sets:
|
||||
workout.sets.append(WorkoutSet(**s.model_dump()))
|
||||
db.commit()
|
||||
db.refresh(workout)
|
||||
return workout
|
||||
|
||||
|
||||
@router.delete("/workouts/{workout_id}", status_code=204)
|
||||
def delete_workout(workout_id: int, db: Session = Depends(get_db)):
|
||||
workout = db.get(Workout, workout_id)
|
||||
if not workout:
|
||||
raise HTTPException(status_code=404, detail="Workout not found")
|
||||
db.delete(workout)
|
||||
db.commit()
|
||||
Reference in New Issue
Block a user