182 lines
5.5 KiB
Python
182 lines
5.5 KiB
Python
from datetime import datetime, timezone
|
|
from fastapi import APIRouter, Request, Depends, Form
|
|
from fastapi.responses import HTMLResponse, RedirectResponse
|
|
from fastapi.templating import Jinja2Templates
|
|
from sqlalchemy import select, desc
|
|
|
|
from app.models.base import async_session
|
|
from app.models.user import User
|
|
from app.models.workout import Phase, Workout, WorkoutSet
|
|
from app.auth import get_current_user
|
|
|
|
router = APIRouter()
|
|
templates = Jinja2Templates(directory="app/templates")
|
|
|
|
|
|
@router.get("/workouts", response_class=HTMLResponse)
|
|
async def workout_list(request: Request, user: User = Depends(get_current_user)):
|
|
async with async_session() as session:
|
|
result = await session.execute(
|
|
select(Workout)
|
|
.where(Workout.user_id == user.id)
|
|
.order_by(desc(Workout.date))
|
|
)
|
|
workouts = result.scalars().all()
|
|
return templates.TemplateResponse(request, "workouts.html", {
|
|
"user": user,
|
|
"workouts": workouts,
|
|
})
|
|
|
|
|
|
@router.get("/workouts/new", response_class=HTMLResponse)
|
|
async def new_workout_page(request: Request, user: User = Depends(get_current_user)):
|
|
async with async_session() as session:
|
|
result = await session.execute(select(Phase))
|
|
phases = result.scalars().all()
|
|
return templates.TemplateResponse(request, "workout_new.html", {
|
|
"user": user,
|
|
"phases": phases,
|
|
})
|
|
|
|
|
|
@router.post("/workouts/new")
|
|
async def new_workout(
|
|
request: Request,
|
|
user: User = Depends(get_current_user),
|
|
name: str = Form(),
|
|
date: str = Form(),
|
|
phase_id: int = Form(default=None),
|
|
notes: str = Form(default=""),
|
|
):
|
|
async with async_session() as session:
|
|
workout = Workout(
|
|
user_id=user.id,
|
|
phase_id=phase_id,
|
|
name=name,
|
|
date=date,
|
|
notes=notes,
|
|
status="plan",
|
|
)
|
|
session.add(workout)
|
|
await session.commit()
|
|
await session.refresh(workout)
|
|
workout_id = workout.id
|
|
|
|
return RedirectResponse(url=f"/workouts/{workout_id}", status_code=303)
|
|
|
|
|
|
@router.get("/workouts/{workout_id}", response_class=HTMLResponse)
|
|
async def workout_detail(
|
|
request: Request,
|
|
workout_id: int,
|
|
user: User = Depends(get_current_user),
|
|
):
|
|
async with async_session() as session:
|
|
result = await session.execute(
|
|
select(Workout).where(
|
|
Workout.id == workout_id,
|
|
Workout.user_id == user.id,
|
|
)
|
|
)
|
|
workout = result.scalar_one_or_none()
|
|
if not workout:
|
|
return templates.TemplateResponse(request, "404.html", status_code=404)
|
|
|
|
result = await session.execute(
|
|
select(WorkoutSet)
|
|
.where(WorkoutSet.workout_id == workout_id)
|
|
.order_by(WorkoutSet.exercise, WorkoutSet.set_number)
|
|
)
|
|
sets = result.scalars().all()
|
|
|
|
phase = None
|
|
if workout.phase_id:
|
|
result = await session.execute(select(Phase).where(Phase.id == workout.phase_id))
|
|
phase = result.scalar_one_or_none()
|
|
|
|
return templates.TemplateResponse(request, "workout_detail.html", {
|
|
"user": user,
|
|
"workout": workout,
|
|
"sets": sets,
|
|
"phase": phase,
|
|
})
|
|
|
|
|
|
@router.post("/workouts/{workout_id}/add-set")
|
|
async def add_set(
|
|
request: Request,
|
|
workout_id: int,
|
|
user: User = Depends(get_current_user),
|
|
exercise: str = Form(),
|
|
set_number: int = Form(),
|
|
reps: int = Form(default=None),
|
|
weight: float = Form(default=None),
|
|
rpe: float = Form(default=None),
|
|
notes: str = Form(default=""),
|
|
):
|
|
async with async_session() as session:
|
|
result = await session.execute(
|
|
select(Workout).where(
|
|
Workout.id == workout_id,
|
|
Workout.user_id == user.id,
|
|
)
|
|
)
|
|
workout = result.scalar_one_or_none()
|
|
if not workout:
|
|
return RedirectResponse(url="/workouts", status_code=303)
|
|
|
|
ws = WorkoutSet(
|
|
workout_id=workout_id,
|
|
exercise=exercise,
|
|
set_number=set_number,
|
|
reps=reps,
|
|
weight=weight,
|
|
rpe=rpe,
|
|
notes=notes,
|
|
)
|
|
session.add(ws)
|
|
await session.commit()
|
|
|
|
return RedirectResponse(url=f"/workouts/{workout_id}", status_code=303)
|
|
|
|
|
|
@router.post("/workouts/{workout_id}/complete")
|
|
async def complete_workout(
|
|
request: Request,
|
|
workout_id: int,
|
|
user: User = Depends(get_current_user),
|
|
):
|
|
async with async_session() as session:
|
|
result = await session.execute(
|
|
select(Workout).where(
|
|
Workout.id == workout_id,
|
|
Workout.user_id == user.id,
|
|
)
|
|
)
|
|
workout = result.scalar_one_or_none()
|
|
if workout:
|
|
workout.status = "complete"
|
|
await session.commit()
|
|
|
|
if not workout:
|
|
return RedirectResponse(url="/workouts", status_code=303)
|
|
|
|
result = await session.execute(
|
|
select(WorkoutSet)
|
|
.where(WorkoutSet.workout_id == workout_id)
|
|
.order_by(WorkoutSet.exercise, WorkoutSet.set_number)
|
|
)
|
|
sets = result.scalars().all()
|
|
|
|
phase = None
|
|
if workout.phase_id:
|
|
result = await session.execute(select(Phase).where(Phase.id == workout.phase_id))
|
|
phase = result.scalar_one_or_none()
|
|
|
|
return templates.TemplateResponse(request, "workout_detail.html", {
|
|
"user": user,
|
|
"workout": workout,
|
|
"sets": sets,
|
|
"phase": phase,
|
|
})
|