Let admins pick the time range for dashboard trends

Original task: Add a 7d/30d/90d range selector to the admin dashboard
trend cards/chart and have /stats/admin accept a matching range parameter.

Changes:
- OpenAPI (lib/api-spec/openapi.yaml): added optional `range` query
  parameter (enum 7d|30d|90d, default 7d) to GET /stats/admin and
  refactored AdminStats fields to be range-agnostic — added `range`
  and `rangeDays`, renamed `*Last7Days`/`*Prev7Days` to `*InRange`/
  `*PrevRange`. Regenerated api-client-react and api-zod.
- API server (artifacts/api-server/src/routes/stats.ts): parses and
  validates the `range` param, computes range/prev-range windows
  generically, and returns daily series sized to rangeDays.
- Admin UI (artifacts/teaboy-os/src/pages/admin.tsx): adds a segmented
  range selector at the top of the dashboard, passes the selected
  range into the stats query (with proper queryKey), and adapts the
  trend chart for denser ranges (skipped per-bar count text >14 days,
  every-Nth date label, month/day formatting for 30d/90d).
- Locale files (en.json/ar.json): added range/prevRange labels,
  trends/rangeSelector strings, and *Ranged variants of summary keys.
  Old keys kept to avoid stale references.

Verification:
- pnpm typecheck passes across libs and artifacts.
- e2e test (login as admin → toggle 7d/30d/90d → verify chart bar
  counts and aria-pressed state, plus API responses for each range)
  passes.

Notes / deviations:
- Had to (re)create the `app_opens` table in the dev DB and reset the
  seeded admin password hash to run the e2e test; both were preexisting
  environment drift unrelated to this task.
- Followed up with: custom date range, persisting last-used range.

Replit-Task-Id: 8066030b-b5c4-4b5c-a630-65616df5449e
This commit is contained in:
riyadhafraa
2026-04-20 15:38:28 +00:00
parent ea77b92120
commit 4451877244
9 changed files with 276 additions and 109 deletions
+26 -10
View File
@@ -730,6 +730,15 @@ paths:
operationId: getAdminStats
tags: [stats]
summary: Get admin dashboard trend stats
parameters:
- in: query
name: range
required: false
schema:
type: string
enum: ["7d", "30d", "90d"]
default: "7d"
description: Time range for trend stats
responses:
"200":
description: Admin stats
@@ -1337,9 +1346,14 @@ components:
AdminStats:
type: object
properties:
newUsersLast7Days:
range:
type: string
enum: ["7d", "30d", "90d"]
rangeDays:
type: integer
newUsersPrev7Days:
newUsersInRange:
type: integer
newUsersPrevRange:
type: integer
activeServices:
type: integer
@@ -1369,9 +1383,9 @@ components:
required:
- date
- count
appOpensLast7Days:
appOpensInRange:
type: integer
appOpensPrev7Days:
appOpensPrevRange:
type: integer
servicesCreatedByDay:
type: array
@@ -1385,16 +1399,18 @@ components:
required:
- date
- count
servicesCreatedLast7Days:
servicesCreatedInRange:
type: integer
required:
- newUsersLast7Days
- newUsersPrev7Days
- range
- rangeDays
- newUsersInRange
- newUsersPrevRange
- activeServices
- inactiveServices
- signupsByDay
- appOpensByDay
- appOpensLast7Days
- appOpensPrev7Days
- appOpensInRange
- appOpensPrevRange
- servicesCreatedByDay
- servicesCreatedLast7Days
- servicesCreatedInRange