Phase 2 Complete - Backend Refactoring: - Extracted all endpoints to dedicated router modules - main.py: 1878 → 75 lines (-96% reduction) - Created modular structure for maintainability Router Structure (60 endpoints total): ├── auth.py - 7 endpoints (login, logout, password reset) ├── profiles.py - 7 endpoints (CRUD + current user) ├── weight.py - 5 endpoints (tracking + stats) ├── circumference.py - 4 endpoints (body measurements) ├── caliper.py - 4 endpoints (skinfold tracking) ├── activity.py - 6 endpoints (workouts + Apple Health import) ├── nutrition.py - 4 endpoints (diet + FDDB import) ├── photos.py - 3 endpoints (progress photos) ├── insights.py - 8 endpoints (AI analysis + pipeline) ├── prompts.py - 2 endpoints (AI prompt management) ├── admin.py - 7 endpoints (user management) ├── stats.py - 1 endpoint (dashboard stats) ├── exportdata.py - 3 endpoints (CSV/JSON/ZIP export) └── importdata.py - 1 endpoint (ZIP import) Core modules maintained: - db.py: PostgreSQL connection + helpers - auth.py: Auth functions (hash, verify, sessions) - models.py: 11 Pydantic models Benefits: - Self-contained modules with clear responsibilities - Easier to navigate and modify specific features - Improved code organization and readability - 100% functional compatibility maintained - All syntax checks passed Updated CLAUDE.md with new architecture documentation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
61 lines
1.9 KiB
Python
61 lines
1.9 KiB
Python
"""
|
|
AI Prompts Management Endpoints for Mitai Jinkendo
|
|
|
|
Handles prompt template configuration (admin-editable).
|
|
"""
|
|
from fastapi import APIRouter, Depends
|
|
|
|
from db import get_db, get_cursor, r2d
|
|
from auth import require_auth, require_admin
|
|
|
|
router = APIRouter(prefix="/api/prompts", tags=["prompts"])
|
|
|
|
|
|
@router.get("")
|
|
def list_prompts(session: dict=Depends(require_auth)):
|
|
"""
|
|
List AI prompts.
|
|
- Admins: see ALL prompts (including pipeline and inactive)
|
|
- Users: see only active single-analysis prompts
|
|
"""
|
|
with get_db() as conn:
|
|
cur = get_cursor(conn)
|
|
is_admin = session.get('role') == 'admin'
|
|
|
|
if is_admin:
|
|
# Admin sees everything
|
|
cur.execute("SELECT * FROM ai_prompts ORDER BY sort_order, slug")
|
|
else:
|
|
# Users see only active, non-pipeline prompts
|
|
cur.execute("SELECT * FROM ai_prompts WHERE active=true AND slug NOT LIKE 'pipeline_%' ORDER BY sort_order")
|
|
|
|
return [r2d(r) for r in cur.fetchall()]
|
|
|
|
|
|
@router.put("/{prompt_id}")
|
|
def update_prompt(prompt_id: str, data: dict, session: dict=Depends(require_admin)):
|
|
"""Update AI prompt template (admin only)."""
|
|
with get_db() as conn:
|
|
cur = get_cursor(conn)
|
|
updates = []
|
|
values = []
|
|
if 'name' in data:
|
|
updates.append('name=%s')
|
|
values.append(data['name'])
|
|
if 'description' in data:
|
|
updates.append('description=%s')
|
|
values.append(data['description'])
|
|
if 'template' in data:
|
|
updates.append('template=%s')
|
|
values.append(data['template'])
|
|
if 'active' in data:
|
|
updates.append('active=%s')
|
|
# Convert to boolean (accepts true/false, 1/0)
|
|
values.append(bool(data['active']))
|
|
|
|
if updates:
|
|
cur.execute(f"UPDATE ai_prompts SET {', '.join(updates)}, updated=CURRENT_TIMESTAMP WHERE id=%s",
|
|
values + [prompt_id])
|
|
|
|
return {"ok": True}
|