Download app/api/dashboard.py from nvikou/ReplyFlow: direct link, hf CLI and curl.
- Browser
- Download file 2.72 kB
-
https://huggingface.co/spaces/nvikou/ReplyFlow/resolve/main/app/api/dashboard.py
- Command line
-
hf download hf://spaces/nvikou/ReplyFlow/app/api/dashboard.py
-
curl -L -o dashboard.py https://huggingface.co/spaces/nvikou/ReplyFlow/resolve/main/app/api/dashboard.py
2.72 kB
| """Dashboard metrics API.""" | |
| from fastapi import APIRouter, Depends | |
| from sqlalchemy import func, select | |
| from sqlalchemy.ext.asyncio import AsyncSession | |
| from app.db import get_db | |
| from app.models import Conversation, Lead, UnansweredQuestion | |
| from app.schemas import DashboardStats | |
| router = APIRouter(prefix="/api/dashboard", tags=["dashboard"]) | |
| async def dashboard_stats( | |
| db: AsyncSession = Depends(get_db), | |
| ) -> DashboardStats: | |
| """Aggregate KPIs for the operator dashboard.""" | |
| total = await db.scalar( | |
| select(func.count(Conversation.id)) | |
| ) or 0 | |
| resolved = await db.scalar( | |
| select(func.count(Conversation.id)).where( | |
| Conversation.resolved_without_human.is_(True) | |
| ) | |
| ) or 0 | |
| appointments = await db.scalar( | |
| select(func.count(Conversation.id)).where( | |
| Conversation.appointment_booked.is_(True) | |
| ) | |
| ) or 0 | |
| handed = await db.scalar( | |
| select(func.count(Conversation.id)).where( | |
| Conversation.handed_off.is_(True) | |
| ) | |
| ) or 0 | |
| unanswered = await db.scalar( | |
| select(func.count(UnansweredQuestion.id)) | |
| ) or 0 | |
| leads_complete = await db.scalar( | |
| select(func.count(Lead.id)).where(Lead.complete.is_(True)) | |
| ) or 0 | |
| channel_rows = ( | |
| await db.execute( | |
| select( | |
| Conversation.channel, | |
| func.count(Conversation.id), | |
| ).group_by(Conversation.channel) | |
| ) | |
| ).all() | |
| language_rows = ( | |
| await db.execute( | |
| select( | |
| Conversation.language, | |
| func.count(Conversation.id), | |
| ).group_by(Conversation.language) | |
| ) | |
| ).all() | |
| recent = ( | |
| await db.execute( | |
| select(UnansweredQuestion) | |
| .order_by(UnansweredQuestion.created_at.desc()) | |
| .limit(10) | |
| ) | |
| ).scalars().all() | |
| rate = (resolved / total * 100.0) if total else 0.0 | |
| return DashboardStats( | |
| total_conversations=int(total), | |
| resolved_without_human=int(resolved), | |
| resolution_rate=round(rate, 1), | |
| appointments_booked=int(appointments), | |
| handed_off=int(handed), | |
| unanswered_count=int(unanswered), | |
| leads_complete=int(leads_complete), | |
| by_channel={c: int(n) for c, n in channel_rows}, | |
| by_language={lang: int(n) for lang, n in language_rows}, | |
| recent_unanswered=[ | |
| { | |
| "id": q.id, | |
| "conversation_id": q.conversation_id, | |
| "question": q.question, | |
| "created_at": q.created_at.isoformat(), | |
| } | |
| for q in recent | |
| ], | |
| ) | |