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, })