Presentation-only follow-on to supporthub-api's already-complete 015-reporting-dashboards, per the same backend-first pattern used throughout this session. Plan applies the dataviz skill methodology given the user's explicit request for production-level design. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
10 KiB
Feature Specification: Reporting and Analytics Dashboards UI
Feature Branch: 002-reporting-dashboards-ui
Created: 2026-09-09
Status: Draft
Input: User description: "Reporting and analytics dashboards UI: a production-quality admin surface presenting the four dashboards (Management, Product, Support, AI) supporthub-api's 015-reporting-dashboards feature now exposes — date-range filtering, stat tiles, distributions, and ranked lists, following this project's established loading/empty/error/ready query-state discipline and design system."
User Scenarios & Testing (mandatory)
User Story 1 - Admin sees organization-wide health at a glance (Priority: P1)
An admin opens the reports area and immediately sees, for a chosen date range, how support is doing overall: total cases, how many were resolved and by whom (AI vs. a human), how many are still open, whether SLA is being met, and average response/resolution time.
Why this priority: This is the dashboard the roadmap's own top-level success criteria map to most directly — it's the first thing anyone opens the reports area to see.
Independent Test: Can be fully tested by loading the Management tab against a backend with known data and confirming every figure on screen matches the API response exactly, with correct loading/empty/error presentation.
Acceptance Scenarios:
- Given the backend has ticket/SLA/escalation data for the default period, When the
admin opens the Management dashboard, Then every stat tile and the SLA compliance figure
show the real values from
GET /admin/reports/management, not placeholder text. - Given the admin changes the date range, When the new range is applied, Then the dashboard re-fetches and every figure updates to match the new range.
- Given a rate or average is
null(no qualifying data), When the dashboard renders, Then it shows an explicit "No data" treatment, neverNaN,undefined, or a bare0that could be misread as a real zero. - Given the backend request fails, When the dashboard renders, Then it shows the established error state (never a blank screen or a silently stale view).
User Story 2 - Admin drills into one product's support health (Priority: P1)
An admin picks a product and sees that product's own support volume, problem-category breakdown, AI/human resolution split, and most frequent error codes — never another product's data mixed in.
Why this priority: Per-product visibility is as fundamental as the org-wide view for a platform serving multiple SaaS products, and pairs directly with the Management view.
Independent Test: Can be fully tested by selecting two different products against a backend with data for both and confirming each product's own figures show only its own data.
Acceptance Scenarios:
- Given a product is selected, When the Product dashboard loads, Then support volume, the problem-category breakdown, and the AI/human resolution rates all reflect only that product.
- Given the admin switches products, When the new product's data loads, Then the previous product's figures are fully replaced, never blended or stale.
- Given a product has no error-code lookups in range, When the dashboard renders, Then the "top errors" section shows an explicit empty state, not a blank gap.
User Story 3 - Admin sees team workload and SLA risk (Priority: P2)
An admin sees current per-agent workload and which tickets are approaching or past their SLA due date, alongside response/resolution performance for the period.
Why this priority: Operational, day-to-day utility rather than a new class of information — P2 relative to the two org/product-level views above.
Independent Test: Can be fully tested against a backend with known assignment/SLA data and confirming per-agent workload and at-risk/breached counts match exactly.
Acceptance Scenarios:
- Given agents have current open assignments, When the Support dashboard loads, Then each agent's workload is shown, ranked by load.
- Given some SLA runs are at risk and others already breached, When the dashboard renders, Then the two counts are visually distinct, never merged into one figure.
User Story 4 - Admin sees how well the AI is performing (Priority: P2)
An admin sees the AI's resolution rate, human-handoff rate, knowledge-match rate, confidence distribution, and tool success/failure for the period.
Why this priority: Validates the AI-first design's premise for a narrower audience than the org/product views — P2.
Independent Test: Can be fully tested against a backend with known AI session/diagnosis/tool data and confirming every figure matches.
Acceptance Scenarios:
- Given AI sessions resolved and escalated in the period, When the AI dashboard loads, Then the resolution/handoff rates and the confidence distribution (proceed/ask/escalate) match the real session data.
- Given tool invocations succeeded and failed, When the dashboard renders, Then the success/failure split is shown with each outcome visually distinct and labeled, never color alone.
Edge Cases
- What happens while a request is in flight? A loading state distinct from both "empty" and
"error" — the existing
getQueryStatediscipline, never a flash of zeroed-out figures. - What happens if the selected date range is invalid (
fromafterto)? The date-range control itself prevents choosing an invalid range; if the backend still rejects one, the error state shows the backend's own message. - What happens on a narrow viewport? Every dashboard degrades to a single-column layout — stat tiles stack, ranked lists remain fully readable, nothing is clipped or requires horizontal scroll.
- What happens in dark mode? Every figure, bar, and status color remains legible and uses this project's existing dark-mode tokens — not a separate, unvalidated color set.
- What happens with a very long category/error-code name in a ranked list? It truncates with an accessible full-text affordance (title attribute at minimum), never breaking the layout or overlapping the value.
Requirements (mandatory)
Functional Requirements
- FR-001: System MUST present all four dashboards (Management, Product, Support, AI) from
specs/002-reporting-dashboards-ui's own admin reports area, each independently loadable. - FR-002: The Management, Product, and AI dashboards MUST support a date-range filter
(
from/to), re-fetching on change; the Support dashboard's workload/risk figures are current-state (per the backend contract) and are not range-filtered, matchingsupporthub-api's ownSupportDashboard.generatedAtframing. - FR-003: The Product dashboard MUST require a product to be selected before fetching, and MUST show the backend's own error when an unknown product is requested.
- FR-004: Every rate/average field that the backend returns as
nullMUST render as an explicit "No data" treatment — neverNaN, a blank cell, or a0indistinguishable from a real zero value. - FR-005: Every data view MUST follow the project's established
getQueryStatediscipline (loading/empty/error/ready), never conflating any two of those states. - FR-006: Ranked lists (problem categories, top errors, agent workload) MUST be sorted descending by the backend's own ordering and MUST visually encode magnitude (not just list the numbers as plain text) per this project's data-visualization standard.
- FR-007: Status-flavored distributions (AI confidence bands, tool success/failure, SLA met/breached) MUST use this project's existing status colors (success/warning/destructive) consistently with their real-world meaning, MUST include a visible legend/label (never color alone), and MUST remain legible and validated in both light and dark mode.
- FR-008: This feature MUST NOT introduce any new backend endpoint or change any existing
one — it is a pure presentation layer over
supporthub-api's already-complete 015-reporting-dashboards contract. - FR-009: The reports area MUST remain reachable only to an authenticated admin session, consistent with every other admin surface in this application.
Key Entities
- Dashboard view-model: The frontend-side shape each dashboard's API response is mapped into for rendering — never persisted, recomputed on every fetch.
- Date range selection: UI-local state (
from/to) driving the Management/Product/AI dashboards' queries; not synced to a URL param in this first cut (Assumptions).
Success Criteria (mandatory)
Measurable Outcomes
- SC-001: An admin can answer "how is support doing," "how is this product doing," "who's overloaded," and "is the AI helping" each within one screen, with no figure requiring a separate lookup to interpret.
- SC-002: Every figure on every dashboard is independently verifiable against the backend's own response for the same request — no discrepancy, no client-side recomputation that could drift from what the API actually returned.
- SC-003: The reports area is fully usable — legible, correctly laid out, no clipped or overlapping content — from a narrow mobile viewport up through a large desktop screen, and in both light and dark mode.
Assumptions
- Scope is presentation only, per the user's own explicit direction to build the backend first (015-reporting-dashboards, already complete) and the frontend as a distinct follow-on — consistent with every prior feature this session that spanned both repos.
- Date-range selection is local component state, not persisted to the URL or local storage in this first cut — a shareable/bookmarkable link to a specific range is a reasonable future enhancement, not required here.
- The Product dashboard's product picker reuses the existing product list already available to
the admin UI (
GET /admin/products, 012-admin-list-views) rather than introducing a new lookup endpoint. - "Visually encode magnitude" (FR-006) means a simple proportional bar behind/beside each ranked row — not a full charting library. This project has no charting dependency today, and introducing one for a handful of ranked lists and status splits would be disproportionate to the need (this session's own "don't add complexity beyond what the task requires" standard).