- Merge opencode-serve into the web container via entrypoint script - Add /api/agent/* JSON endpoints for workouts, sets, checkins - Rewrite fitness-trainer.md to use API instead of markdown files - Pass recent workouts and check-ins as chat context to the coach - Show current training phase on dashboard - Clarify check-ins as morning check-ins (calories/steps = yesterday) - Add NixOS deployment section to README - Make all check-in fields explicitly optional in UI
66 lines
2.0 KiB
Python
66 lines
2.0 KiB
Python
from datetime import date, 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.checkin import Checkin
|
|
from app.auth import get_current_user
|
|
|
|
router = APIRouter()
|
|
templates = Jinja2Templates(directory="app/templates")
|
|
|
|
|
|
@router.get("/checkins", response_class=HTMLResponse)
|
|
async def checkin_list(request: Request, user: User = Depends(get_current_user)):
|
|
async with async_session() as session:
|
|
result = await session.execute(
|
|
select(Checkin)
|
|
.where(Checkin.user_id == user.id)
|
|
.order_by(desc(Checkin.date))
|
|
)
|
|
checkins = result.scalars().all()
|
|
return templates.TemplateResponse(request, "checkins.html", {
|
|
"user": user,
|
|
"checkins": checkins,
|
|
})
|
|
|
|
|
|
@router.get("/checkins/new", response_class=HTMLResponse)
|
|
async def new_checkin_page(request: Request, user: User = Depends(get_current_user)):
|
|
return templates.TemplateResponse(request, "checkin_new.html", {
|
|
"user": user,
|
|
"today": date.today().isoformat(),
|
|
})
|
|
|
|
|
|
@router.post("/checkins/new")
|
|
async def new_checkin(
|
|
request: Request,
|
|
user: User = Depends(get_current_user),
|
|
date: str = Form(),
|
|
feeling: str = Form(default=""),
|
|
weight_lb: float = Form(default=None),
|
|
calories: int = Form(default=None),
|
|
steps: int = Form(default=None),
|
|
sleep_hours: float = Form(default=None),
|
|
notes: str = Form(default=""),
|
|
):
|
|
async with async_session() as session:
|
|
checkin = Checkin(
|
|
user_id=user.id,
|
|
date=date,
|
|
feeling=feeling,
|
|
weight_lb=weight_lb,
|
|
calories=calories,
|
|
steps=steps,
|
|
sleep_hours=sleep_hours,
|
|
notes=notes,
|
|
)
|
|
session.add(checkin)
|
|
await session.commit()
|
|
|
|
return RedirectResponse(url="/checkins", status_code=303)
|