Add DashboardFilterBar and move global filters to top of dashboard

- Create DashboardFilterBar component with time-range and origin-filter
  toggle-button groups in a single card row (Stage 7, Tasks 7.1–7.3)
- Integrate filter bar below ServerStatusBar in DashboardPage; remove
  filter toolbars from the Ban List section header (Task 7.2)
- Add 6 tests covering rendering, active-state reflection, and callbacks
- tsc --noEmit, eslint, npm run build, npm test all pass (27/27 tests)
This commit is contained in:
2026-03-11 19:05:52 +01:00
parent 0a73c49d01
commit 2f602e45f7
4 changed files with 458 additions and 53 deletions

View File

@@ -7,23 +7,17 @@
*/
import { useState } from "react";
import {
Text,
ToggleButton,
Toolbar,
makeStyles,
tokens,
} from "@fluentui/react-components";
import { ChartStateWrapper } from "../components/ChartStateWrapper";
import { Text, makeStyles, tokens } from "@fluentui/react-components";
import { BanTable } from "../components/BanTable";
import { BanTrendChart } from "../components/BanTrendChart";
import { ChartStateWrapper } from "../components/ChartStateWrapper";
import { DashboardFilterBar } from "../components/DashboardFilterBar";
import { JailDistributionChart } from "../components/JailDistributionChart";
import { ServerStatusBar } from "../components/ServerStatusBar";
import { TopCountriesBarChart } from "../components/TopCountriesBarChart";
import { TopCountriesPieChart } from "../components/TopCountriesPieChart";
import { useDashboardCountryData } from "../hooks/useDashboardCountryData";
import type { BanOriginFilter, TimeRange } from "../types/ban";
import { BAN_ORIGIN_FILTER_LABELS, TIME_RANGE_LABELS } from "../types/ban";
// ---------------------------------------------------------------------------
@@ -82,16 +76,6 @@ const useStyles = makeStyles({
},
});
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
/** Ordered time-range presets for the toolbar. */
const TIME_RANGES: TimeRange[] = ["24h", "7d", "30d", "365d"];
/** Ordered origin filter options for the toolbar. */
const ORIGIN_FILTERS: BanOriginFilter[] = ["all", "blocklist", "selfblock"];
// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------
@@ -117,6 +101,16 @@ export function DashboardPage(): React.JSX.Element {
{/* ------------------------------------------------------------------ */}
<ServerStatusBar />
{/* ------------------------------------------------------------------ */}
{/* Global filter bar */}
{/* ------------------------------------------------------------------ */}
<DashboardFilterBar
timeRange={timeRange}
onTimeRangeChange={setTimeRange}
originFilter={originFilter}
onOriginFilterChange={setOriginFilter}
/>
{/* ------------------------------------------------------------------ */}
{/* Ban Trend section */}
{/* ------------------------------------------------------------------ */}
@@ -188,40 +182,6 @@ export function DashboardPage(): React.JSX.Element {
<Text as="h2" size={500} weight="semibold">
Ban List
</Text>
{/* Time-range selector */}
<Toolbar aria-label="Time range" size="small">
{TIME_RANGES.map((r) => (
<ToggleButton
key={r}
size="small"
checked={timeRange === r}
onClick={() => {
setTimeRange(r);
}}
aria-pressed={timeRange === r}
>
{TIME_RANGE_LABELS[r]}
</ToggleButton>
))}
</Toolbar>
{/* Origin filter */}
<Toolbar aria-label="Origin filter" size="small">
{ORIGIN_FILTERS.map((f) => (
<ToggleButton
key={f}
size="small"
checked={originFilter === f}
onClick={() => {
setOriginFilter(f);
}}
aria-pressed={originFilter === f}
>
{BAN_ORIGIN_FILTER_LABELS[f]}
</ToggleButton>
))}
</Toolbar>
</div>
{/* Ban table */}