Reject invalid custom date ranges on /api/stats/admin with HTTP 400

Original task (Task #35): When the admin dashboard's custom range
receives a malformed or missing date (e.g. ?range=custom&from=foo),
the API silently fell back to the 7-day window instead of returning
an error. This masked client bugs and confused admins.

Changes:
- artifacts/api-server/src/routes/stats.ts:
  - Refactored the custom-range branch so range=custom now always
    validates from/to. Returns 400 with a helpful, specific message
    when:
      * from or to is missing
      * from or to is not a valid YYYY-MM-DD UTC date
      * from is after to (existing behavior, message clarified)
  - Removed the silent `if (range === "custom") range = "7d"` fallback.
- lib/api-spec/openapi.yaml:
  - Documented the 400 ErrorResponse on getAdminStats so the generated
    clients know about this failure mode.
- Regenerated @workspace/api-client-react and @workspace/api-zod via
  `pnpm --filter @workspace/api-spec run codegen`.
- artifacts/teaboy-os/src/pages/admin.tsx:
  - Captured `error` from useGetAdminStats (with retry: false) and
    surface a translated, role="alert" panel beneath the range
    controls when the API returns an error, including the server's
    error message. The frontend already guards against client-side
    invalid input via isCustomValid, so this primarily covers any
    remaining edge cases (stale querystring, race conditions).
- Added admin.dashboard.customRange.loadError translations in
  en.json and ar.json.

Verified with `pnpm -w run typecheck` (passes for libs and all
artifacts). Manual curl confirmed the route is wired (auth gate
returns 401 first, as expected).
This commit is contained in:
Riyadh
2026-04-21 09:01:03 +00:00
parent 77843e3540
commit e8cb2b836d
6 changed files with 50 additions and 11 deletions
+3 -3
View File
@@ -4068,7 +4068,7 @@ export const getGetAdminStatsQueryKey = (params?: GetAdminStatsParams) => {
export const getGetAdminStatsQueryOptions = <
TData = Awaited<ReturnType<typeof getAdminStats>>,
TError = ErrorType<unknown>,
TError = ErrorType<ErrorResponse>,
>(
params?: GetAdminStatsParams,
options?: {
@@ -4098,7 +4098,7 @@ export const getGetAdminStatsQueryOptions = <
export type GetAdminStatsQueryResult = NonNullable<
Awaited<ReturnType<typeof getAdminStats>>
>;
export type GetAdminStatsQueryError = ErrorType<unknown>;
export type GetAdminStatsQueryError = ErrorType<ErrorResponse>;
/**
* @summary Get admin dashboard trend stats
@@ -4106,7 +4106,7 @@ export type GetAdminStatsQueryError = ErrorType<unknown>;
export function useGetAdminStats<
TData = Awaited<ReturnType<typeof getAdminStats>>,
TError = ErrorType<unknown>,
TError = ErrorType<ErrorResponse>,
>(
params?: GetAdminStatsParams,
options?: {