Files
TapTrack-Hub/.paul/phases/15-ux-polish/README.md

89 lines
3.5 KiB
Markdown

# Phase 15: UX Polish + Super Admin Ops Tools
**Status:** Not started
**Depends on:** All previous phases
## Goal
Production-ready polish: audit log viewer, global search, bulk operations, mobile-responsive
portal, keyboard shortcuts, error boundaries, and production security hardening.
## Planned Scope
### Backend
**Audit log viewer endpoint**
- `GET /api/audit-logs` — paginated, filterable by school, action, actor, date range
- Already have `audit_logs` table — just need the endpoint + frontend
**Global search endpoint**
- `GET /api/search?q={query}` — searches across schools, invoices, tickets
- Returns grouped results: `{ schools: [...], invoices: [...], tickets: [...] }`
- Limit 5 results per category
**Bulk school actions**
- `POST /api/schools/export-csv` — export school list as CSV (name, status, tier, credits, license)
- `POST /api/schools/bulk-status` — change status for multiple school IDs (super admin)
**Rate limiting on auth endpoints**
- Add `slowapi` middleware: `POST /auth/login` — max 10 req/min per IP
- Return `429 Too Many Requests` with Retry-After header
**HTTPS redirect**
- Add redirect middleware in `main.py` (X-Forwarded-Proto check)
- Update `nginx.conf` to pass X-Forwarded-Proto header
### Frontend
**Audit log page** (`AuditLogPage.vue` — new or sub-section in admin)
- Table: timestamp, actor, action, entity type, entity name, IP
- Filters: date range, actor, action type
**Global search** (keyboard shortcut `/`)
- `SearchModal.vue` — command palette style
- Press `/` anywhere → modal opens with search input
- Results grouped by type, click navigates to entity
**Keyboard shortcuts**
- `/` — open global search
- `N` — new school (when on /schools)
- `Esc` — close any open modal
**Mobile-responsive portal**
- PortalSidebar: collapsible on mobile (hamburger menu)
- PortalLayout: responsive header
- All portal pages: responsive table → card layout on mobile
**Error boundary component** (`ErrorBoundary.vue`)
- Wraps page content in AppLayout/PortalLayout
- On uncaught error: shows friendly "Something went wrong" card with retry button
**Empty state illustrations**
- SchoolsPage: "No schools yet" with Add School CTA
- TicketsPage: "No tickets" with Submit Ticket CTA
- BillingPage: "No invoices yet" with Generate Invoices CTA
**Dashboard refresh UX**
- Auto-refresh every 5 minutes (setInterval)
- Show "Data may be stale" banner after 10 minutes without refresh
**CSV export button** in SchoolsPage toolbar
## Key Files to Create/Modify
- `backend/app/routers/search.py` (new)
- `backend/app/routers/audit.py` (new — expose existing audit_logs table)
- `backend/app/routers/schools.py` — bulk-status + export-csv endpoints
- `backend/app/main.py` — include search + audit routers, add rate limit + HTTPS middleware
- `backend/requirements.txt` — add `slowapi`
- `frontend/src/pages/AuditLogPage.vue` (new)
- `frontend/src/components/ui/SearchModal.vue` (new)
- `frontend/src/components/ui/ErrorBoundary.vue` (new)
- `frontend/src/layouts/AppLayout.vue` — global keyboard shortcut handler
- `frontend/src/layouts/PortalLayout.vue` — mobile responsive
- `frontend/src/components/sidebar/PortalSidebar.vue` — mobile collapsible
- `frontend/src/pages/SchoolsPage.vue` — bulk actions, CSV export, empty state
- `frontend/src/router/index.ts` — /audit-logs route
- `frontend/src/components/sidebar/AppSidebar.vue` — audit logs nav item
- `frontend/src/lib/api.ts` — globalSearch, getAuditLogs, exportSchoolsCsv, bulkSchoolStatus