feat: wire frontend pages to live APIs and standardize response contracts (P1)
- Backend: Add COUNT query and paginated response shape to conversations endpoint
Returns { conversations: [...], total, page, per_page } instead of flat array
- Frontend: Replace mock data in DashboardPage with fetchAnalytics() API calls
- Frontend: Replace mock data in ReplayListPage with fetchConversations() API calls
- Frontend: Replace mock data in ReplayPage with fetchReplay() API calls
- Add proper loading, empty, and error states to all three pages
- Align ConversationSummary type with actual DB columns (created_at, status)
- Update unit and E2E tests for new paginated conversation response shape
- Add fetchone() to FakeCursor for COUNT query support in E2E tests
This commit is contained in:
@@ -14,6 +14,10 @@ if TYPE_CHECKING:
|
||||
|
||||
router = APIRouter(prefix="/api", tags=["replay"])
|
||||
|
||||
_COUNT_CONVERSATIONS_SQL = """
|
||||
SELECT COUNT(*) FROM conversations
|
||||
"""
|
||||
|
||||
_LIST_CONVERSATIONS_SQL = """
|
||||
SELECT thread_id, created_at, last_activity, status, total_tokens, total_cost_usd
|
||||
FROM conversations
|
||||
@@ -48,13 +52,22 @@ async def list_conversations(
|
||||
pool = await get_pool(request)
|
||||
offset = (page - 1) * per_page
|
||||
async with pool.connection() as conn:
|
||||
count_cursor = await conn.execute(_COUNT_CONVERSATIONS_SQL)
|
||||
count_row = await count_cursor.fetchone()
|
||||
total = count_row[0] if count_row else 0
|
||||
|
||||
cursor = await conn.execute(
|
||||
_LIST_CONVERSATIONS_SQL,
|
||||
{"limit": per_page, "offset": offset},
|
||||
)
|
||||
rows = await cursor.fetchall()
|
||||
|
||||
return _envelope([dict(row) for row in rows])
|
||||
return _envelope({
|
||||
"conversations": [dict(row) for row in rows],
|
||||
"total": total,
|
||||
"page": page,
|
||||
"per_page": per_page,
|
||||
})
|
||||
|
||||
|
||||
@router.get("/replay/{thread_id}")
|
||||
|
||||
Reference in New Issue
Block a user