from fastapi import APIRouter, Depends, Request from fastapi.templating import Jinja2Templates from sqlalchemy import select from app.db import get_db from app.models import JobRun from app.security.deps import require_auth from app.services import beets_service, credential_service, playlist_service router = APIRouter(tags=["dashboard"]) templates = Jinja2Templates(directory="app/templates") def _human_bytes(n: int) -> str: size = float(n) for unit in ("B", "KB", "MB", "GB", "TB"): if size < 1024 or unit == "TB": return f"{size:.1f} {unit}" size /= 1024 return f"{size:.1f} TB" @router.get("/") async def dashboard(request: Request, user: dict = Depends(require_auth), db=Depends(get_db)): stats = beets_service.stats() playlists = playlist_service.list_all(db) recent_runs = list( db.execute(select(JobRun).order_by(JobRun.started_at.desc()).limit(10)).scalars() ) return templates.TemplateResponse( request, "dashboard.html", { "user": user, "stats": stats, "total_size_human": _human_bytes(stats.get("total_bytes", 0)), "playlist_count": len(playlists), "active_playlist_count": len([p for p in playlists if p.active]), "recent_runs": recent_runs, "auth_states": credential_service.auth_states(db), }, )