"""Exercise browser routes with HTMX search/filter support. All filtering is done via HTMX partial responses — no JSON APIs. """ import structlog from fastapi import APIRouter, Depends, Query, Request from fastapi.responses import HTMLResponse from sqlmodel import Session from app.database import get_db_session from app.models.user import User from app.services.exercise_service import ExerciseService from app.utils.auth import get_current_admin_user logger = structlog.get_logger(__name__) router = APIRouter(prefix="/exercises", tags=["exercises"]) @router.get("", response_class=HTMLResponse) async def exercise_browser( request: Request, session: Session = Depends(get_db_session), admin: User = Depends(get_current_admin_user), ): """Render the exercise browser page with all exercises. Args: request: The incoming HTTP request. session: Database session. admin: The authenticated admin user. Returns: Rendered exercise browser page. """ exercise_service = ExerciseService(session) exercises = exercise_service.list_exercises() workout_days = exercise_service.list_workout_days() # Collect unique muscle groups for the filter dropdown muscle_groups = sorted(set(ex.muscle_group for ex in exercises)) templates = request.app.state.templates return templates.TemplateResponse("pages/exercise_browser.html", { "request": request, "exercises": exercises, "workout_days": workout_days, "muscle_groups": muscle_groups, "admin": admin, }) @router.get("/search", response_class=HTMLResponse) async def exercise_search( request: Request, session: Session = Depends(get_db_session), admin: User = Depends(get_current_admin_user), workout_day: str = Query(default="", alias="workout_day"), muscle_group: str = Query(default="", alias="muscle_group"), ): """Return filtered exercise list as an HTMX partial. Called via hx-get from the exercise browser filter dropdowns. Args: request: The incoming HTTP request. session: Database session. admin: The authenticated admin user. workout_day: Filter by workout day name. muscle_group: Filter by muscle group. Returns: Rendered exercise list partial HTML. """ exercise_service = ExerciseService(session) exercises = exercise_service.list_exercises( workout_day=workout_day or None, muscle_group=muscle_group or None, ) templates = request.app.state.templates return templates.TemplateResponse("partials/exercise_list.html", { "request": request, "exercises": exercises, })