Add BanTrendChart component and useBanTrend hook

- Add BanTrendBucket / BanTrendResponse interfaces to types/ban.ts
- Add dashboardBansTrend endpoint constant to api/endpoints.ts
- Add fetchBanTrend() to api/dashboard.ts
- Create useBanTrend hook with abort-safe data fetching
- Create BanTrendChart: AreaChart with gradient fill, dynamic
  X-axis labels per range, custom tooltip, loading/error/empty states
- tsc --noEmit and ESLint pass with zero warnings
This commit is contained in:
2026-03-11 16:48:49 +01:00
parent 9242b4709a
commit 259ff17eba
6 changed files with 416 additions and 2 deletions

View File

@@ -6,7 +6,12 @@
import { get } from "./client";
import { ENDPOINTS } from "./endpoints";
import type { DashboardBanListResponse, TimeRange, BanOriginFilter } from "../types/ban";
import type {
BanTrendResponse,
BanOriginFilter,
DashboardBanListResponse,
TimeRange,
} from "../types/ban";
import type { ServerStatusResponse } from "../types/server";
/**
@@ -48,3 +53,22 @@ export async function fetchBans(
return get<DashboardBanListResponse>(`${ENDPOINTS.dashboardBans}?${params.toString()}`);
}
/**
* Fetch ban counts grouped into equal-width time buckets for the trend chart.
*
* @param range - Time-range preset: `"24h"`, `"7d"`, `"30d"`, or `"365d"`.
* @param origin - Origin filter: `"blocklist"`, `"selfblock"`, or `"all"`
* (default `"all"`, which omits the parameter entirely).
* @returns {@link BanTrendResponse} with the ordered bucket list.
* @throws {ApiError} When the server returns a non-2xx status.
*/
export async function fetchBanTrend(
range: TimeRange,
origin: BanOriginFilter = "all",
): Promise<BanTrendResponse> {
const params = new URLSearchParams({ range });
if (origin !== "all") {
params.set("origin", origin);
}
return get<BanTrendResponse>(`${ENDPOINTS.dashboardBansTrend}?${params.toString()}`);
}

View File

@@ -30,6 +30,7 @@ export const ENDPOINTS = {
dashboardStatus: "/dashboard/status",
dashboardBans: "/dashboard/bans",
dashboardBansByCountry: "/dashboard/bans/by-country",
dashboardBansTrend: "/dashboard/bans/trend",
// -------------------------------------------------------------------------
// Jails