added advanced workout
This commit is contained in:
@@ -2,7 +2,7 @@ from datetime import date, datetime, timedelta, timezone
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.auth.deps import get_current_user
|
||||
@@ -124,6 +124,34 @@ class WorkoutCreate(BaseModel):
|
||||
logged_at: str | None = None
|
||||
|
||||
|
||||
class WorkoutResultsUpdate(BaseModel):
|
||||
distance_m: float | None = Field(default=None, ge=0)
|
||||
avg_heart_rate: int | None = Field(default=None, ge=30, le=250)
|
||||
max_heart_rate: int | None = Field(default=None, ge=30, le=250)
|
||||
avg_pace: float | None = Field(default=None, ge=0)
|
||||
avg_cadence: int | None = Field(default=None, ge=0)
|
||||
max_cadence: int | None = Field(default=None, ge=0)
|
||||
avg_stride_length_cm: float | None = Field(default=None, ge=0)
|
||||
training_load: float | None = Field(default=None, ge=0)
|
||||
aerobic_effect: float | None = Field(default=None, ge=0)
|
||||
anaerobic_effect: float | None = Field(default=None, ge=0)
|
||||
vo2max: float | None = Field(default=None, ge=0)
|
||||
recovery_hours: float | None = Field(default=None, ge=0)
|
||||
intervals: list[dict[str, Any]] | dict[str, Any] | None = None
|
||||
heart_rate_zones: list[dict[str, Any]] | dict[str, Any] | None = None
|
||||
perceived_effort: int | None = Field(default=None, ge=1, le=5)
|
||||
exercises: list[dict[str, Any]] | None = None
|
||||
|
||||
@field_validator("intervals", "heart_rate_zones")
|
||||
@classmethod
|
||||
def validate_json_payload(cls, value: Any) -> Any:
|
||||
if value is None:
|
||||
return value
|
||||
if not isinstance(value, (list, dict)):
|
||||
raise ValueError("must be a JSON array or object")
|
||||
return value
|
||||
|
||||
|
||||
class ReminderUpdate(BaseModel):
|
||||
enabled: bool | None = None
|
||||
hour: int | None = Field(default=None, ge=0, le=23)
|
||||
@@ -355,6 +383,38 @@ async def create_workout(
|
||||
)
|
||||
|
||||
|
||||
@router.get("/fitness/workouts/{log_id}/results")
|
||||
def get_workout_results(
|
||||
log_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Depends(get_current_user),
|
||||
) -> dict[str, Any]:
|
||||
result = FitnessService(db, user.id).get_workout_results(log_id)
|
||||
if not result:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
return result
|
||||
|
||||
|
||||
@router.post("/fitness/workouts/{log_id}/results")
|
||||
def save_workout_results(
|
||||
log_id: int,
|
||||
payload: WorkoutResultsUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Depends(get_current_user),
|
||||
) -> dict[str, Any]:
|
||||
updates = payload.model_dump(exclude_unset=True)
|
||||
if not updates:
|
||||
raise HTTPException(status_code=400, detail="No fields to update")
|
||||
service = FitnessService(db, user.id)
|
||||
try:
|
||||
result = service.save_workout_results(log_id, updates)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=422, detail=str(exc)) from exc
|
||||
if not result:
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
return result
|
||||
|
||||
|
||||
@router.get("/fitness/body-metrics")
|
||||
def list_metrics(
|
||||
limit: int = 30,
|
||||
|
||||
Reference in New Issue
Block a user