#14 — Structured logging
- app/core/logging_config.py: configure_logging() sets stdout handler
with timestamped format; called at import time in main.py
- Global FastAPI exception_handler logs 500s with full traceback
- opportunities.py: logger added; create/approve/mark-posted/dismiss
each emit an info line so failures are traceable
#15 — Frontend error handling
- frontend/src/composables/useToast.ts: shared toast composable
(error/success/info, auto-dismiss, module-level singleton)
- frontend/src/components/ToastList.vue: fixed-position overlay,
theme-aware, accessible (role=alert, aria-live=polite)
- OpportunitiesView: all 6 async actions have catch + toast.error()
- CampaignDetail: onMounted + all 6 mutation functions wrapped
#16 — Aggregate stats
- app/api/endpoints/stats.py: GET /api/v1/stats — single DB pass
via GROUP BY; returns posts totals, 7-day count, top communities,
platform breakdown, and opportunity queue counts
- frontend/src/components/StatsBar.vue: slim header bar above
router-view; chips for posts ok/failed/week, queue pending/approved/
posted, top community; hides gracefully on API error