v2: Program research, Groq extraction, and workout tracking (REVIEW — not deployed)
Backend: - New models: ProgramCatalog, CatalogWorkout, CrawlQueue, WorkoutLog - Program.py: added catalog_id, current_week, current_day columns - program_research.py: ttp-crawler integration, Groq Llama 3.3 70B extraction, known sources map, validation - crawl_scheduler.py: priority queue with off-peak/weekend scheduling - catalog.py router: research, catalog browse, adopt, schedule, complete, progress endpoints - Points: 75pts/workout, 50pts weekly bonus, 200pts completion bonus - config.py: added groq_api_key setting - main.py: catalog router, background scheduler, v2 migration Frontend: - ProgramSearch.jsx: search, research submission, catalog browsing, adopt programs - ProgramDetail.jsx: schedule view, today's workout, completion modal, progress tracking - App.jsx: Programs nav tab, new routes - api.js: catalog and tracking API functions Config: - docker-compose.yml: GROQ_API_KEY env var NOT DEPLOYED — requires Groq API key and Scot review
This commit is contained in:
parent
a81ca9c275
commit
93f24fff83
13 changed files with 1738 additions and 9 deletions
|
|
@ -41,12 +41,29 @@ async def lifespan(app: FastAPI):
|
|||
except Exception as e:
|
||||
logger.warning(f"Resource seeding failed (non-fatal): {e}")
|
||||
|
||||
# Start background crawl queue scheduler
|
||||
crawl_task = None
|
||||
try:
|
||||
from app.services.crawl_scheduler import crawl_queue_loop
|
||||
crawl_task = asyncio.create_task(crawl_queue_loop())
|
||||
logger.info("Crawl queue scheduler started")
|
||||
except Exception as e:
|
||||
logger.warning(f"Crawl scheduler failed to start (non-fatal): {e}")
|
||||
|
||||
logger.info("Fitness Rewards backend started")
|
||||
yield
|
||||
|
||||
# Shutdown
|
||||
if crawl_task:
|
||||
crawl_task.cancel()
|
||||
try:
|
||||
await crawl_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
logger.info("Fitness Rewards backend shutting down")
|
||||
|
||||
|
||||
app = FastAPI(title="Fitness Rewards", version="0.1.0", lifespan=lifespan)
|
||||
app = FastAPI(title="Fitness Rewards", version="0.2.0", lifespan=lifespan)
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
|
|
@ -64,6 +81,7 @@ from app.routers.food import router as food_router
|
|||
from app.routers.points import router as points_router, rewards_router
|
||||
from app.routers.integrations import router as integrations_router
|
||||
from app.routers.programs import router as programs_router
|
||||
from app.routers.catalog import router as catalog_router
|
||||
|
||||
app.include_router(auth_router)
|
||||
app.include_router(onboarding_router)
|
||||
|
|
@ -73,11 +91,12 @@ app.include_router(points_router)
|
|||
app.include_router(rewards_router)
|
||||
app.include_router(integrations_router)
|
||||
app.include_router(programs_router)
|
||||
app.include_router(catalog_router)
|
||||
|
||||
|
||||
@app.get("/api/health")
|
||||
async def health():
|
||||
return {"status": "ok", "version": "0.1.0"}
|
||||
return {"status": "ok", "version": "0.2.0"}
|
||||
|
||||
|
||||
|
||||
|
|
@ -87,7 +106,7 @@ async def run_migrations():
|
|||
from sqlalchemy import text
|
||||
|
||||
async with engine.begin() as conn:
|
||||
# Add equipment_list JSONB column if missing
|
||||
# v1: Add equipment_list JSONB column if missing
|
||||
await conn.execute(text("""
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE user_profiles ADD COLUMN IF NOT EXISTS equipment_list JSONB DEFAULT '[]';
|
||||
|
|
@ -95,6 +114,16 @@ async def run_migrations():
|
|||
END $$;
|
||||
"""))
|
||||
|
||||
# v2: Add catalog columns to programs table
|
||||
await conn.execute(text("""
|
||||
DO $$ BEGIN
|
||||
ALTER TABLE programs ADD COLUMN IF NOT EXISTS catalog_id UUID REFERENCES program_catalog(id);
|
||||
ALTER TABLE programs ADD COLUMN IF NOT EXISTS current_week INTEGER DEFAULT 1;
|
||||
ALTER TABLE programs ADD COLUMN IF NOT EXISTS current_day INTEGER DEFAULT 1;
|
||||
EXCEPTION WHEN undefined_table THEN NULL;
|
||||
END $$;
|
||||
"""))
|
||||
|
||||
|
||||
async def seed_resources():
|
||||
"""Seed the resource library with curated fitness programs."""
|
||||
|
|
@ -232,4 +261,4 @@ async def seed_resources():
|
|||
|
||||
for r in resources:
|
||||
db.add(r)
|
||||
await db.commit()
|
||||
await db.commit()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue