fitness-web/app/routers/dashboard.py

90 lines
2.9 KiB
Python

from datetime import date, timedelta
from fastapi import APIRouter, Request, Depends
from fastapi.responses import HTMLResponse
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
from app.models.checkin import Checkin
from app.models.measurement import Measurement, MeasurementType
from app.auth import get_current_user
router = APIRouter()
templates = Jinja2Templates(directory="app/templates")
def _week_bounds() -> tuple[str, str]:
today = date.today()
monday = today - timedelta(days=today.weekday())
sunday = monday + timedelta(days=6)
return monday.isoformat(), sunday.isoformat()
@router.get("/", response_class=HTMLResponse)
async def root_redirect():
from fastapi.responses import RedirectResponse
return RedirectResponse(url="/dashboard")
@router.get("/dashboard", response_class=HTMLResponse)
async def dashboard(request: Request, user: User = Depends(get_current_user)):
week_start, week_end = _week_bounds()
async with async_session() as session:
result = await session.execute(
select(Workout)
.where(Workout.user_id == user.id)
.order_by(desc(Workout.date))
.limit(5)
)
recent_workouts = result.scalars().all()
result = await session.execute(
select(Checkin)
.where(Checkin.user_id == user.id)
.order_by(desc(Checkin.date))
.limit(1)
)
latest_checkin = result.scalar_one_or_none()
result = await session.execute(
select(Phase).order_by(Phase.start_date.desc().nulls_last()).limit(1)
)
current_phase = result.scalar_one_or_none()
result = await session.execute(
select(Workout)
.where(
Workout.user_id == user.id,
Workout.date >= week_start,
Workout.date <= week_end,
)
.order_by(Workout.date)
)
this_week = result.scalars().all()
result = await session.execute(
select(Measurement)
.join(MeasurementType, Measurement.measurement_type_id == MeasurementType.id)
.where(
Measurement.user_id == user.id,
MeasurementType.name == "Weight",
)
.order_by(desc(Measurement.date))
.limit(1)
)
latest_weight = result.scalar_one_or_none()
return templates.TemplateResponse(request, "dashboard.html", {
"user": user,
"recent_workouts": recent_workouts,
"latest_checkin": latest_checkin,
"current_phase": current_phase,
"this_week": this_week,
"week_start": week_start,
"week_end": week_end,
"latest_weight": latest_weight.value if latest_weight else None,
})