Refactor: Move DashboardFilterProvider to pages directory

- Move DashboardFilterProvider component and tests from providers/ to pages/
- Update DashboardPage imports to reflect new structure
- Update documentation with latest task progress

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-25 19:45:10 +02:00
parent 69a0296c47
commit c1135150c3
5 changed files with 15 additions and 25 deletions

View File

@@ -1,67 +0,0 @@
import { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from "react";
import { getDataSource } from "../utils/queryUtils";
import type { BanOriginFilter, TimeRange } from "../types/ban";
interface DashboardFilterContextValue {
/** Currently selected dashboard time-range preset. */
timeRange: TimeRange;
/** Currently selected dashboard origin filter. */
originFilter: BanOriginFilter;
/** Derived data source for the active time-range. */
source: "fail2ban" | "archive";
/** Update the selected time-range preset. */
setTimeRange: (value: TimeRange) => void;
/** Update the selected origin filter. */
setOriginFilter: (value: BanOriginFilter) => void;
}
const DashboardFilterContext = createContext<DashboardFilterContextValue | null>(null);
const DEFAULT_FILTERS: DashboardFilterContextValue = {
timeRange: "24h",
originFilter: "all",
source: "fail2ban",
setTimeRange: (): void => {
// no-op when no provider is present
},
setOriginFilter: (): void => {
// no-op when no provider is present
},
};
interface DashboardFilterProviderProps {
children: ReactNode;
}
export function DashboardFilterProvider({ children }: DashboardFilterProviderProps): React.JSX.Element {
const [timeRange, setTimeRange] = useState<TimeRange>(DEFAULT_FILTERS.timeRange);
const [originFilter, setOriginFilter] = useState<BanOriginFilter>(DEFAULT_FILTERS.originFilter);
const setTimeRangeCallback = useCallback((value: TimeRange): void => {
setTimeRange(value);
}, []);
const setOriginFilterCallback = useCallback((value: BanOriginFilter): void => {
setOriginFilter(value);
}, []);
const source = useMemo(() => getDataSource(timeRange), [timeRange]);
const value = useMemo(
() => ({
timeRange,
originFilter,
source,
setTimeRange: setTimeRangeCallback,
setOriginFilter: setOriginFilterCallback,
}),
[timeRange, originFilter, source, setTimeRangeCallback, setOriginFilterCallback],
);
return <DashboardFilterContext.Provider value={value}>{children}</DashboardFilterContext.Provider>;
}
export function useDashboardFilters(): DashboardFilterContextValue {
const context = useContext(DashboardFilterContext);
return context ?? DEFAULT_FILTERS;
}

View File

@@ -1,40 +0,0 @@
import { describe, expect, it } from "vitest";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { DashboardFilterBar } from "../../components/DashboardFilterBar";
import { DashboardFilterProvider, useDashboardFilters } from "../DashboardFilterProvider";
function DashboardFilterContent(): React.JSX.Element {
const { timeRange, originFilter, setTimeRange, setOriginFilter } = useDashboardFilters();
return (
<>
<DashboardFilterBar
timeRange={timeRange}
onTimeRangeChange={setTimeRange}
originFilter={originFilter}
onOriginFilterChange={setOriginFilter}
/>
<div data-testid="dashboard-filters">{`${timeRange}-${originFilter}`}</div>
</>
);
}
describe("DashboardFilterProvider", () => {
it("provides filter state to DashboardFilterBar and updates when the user clicks", async () => {
const user = userEvent.setup();
render(
<DashboardFilterProvider>
<DashboardFilterContent />
</DashboardFilterProvider>,
);
expect(screen.getByTestId("dashboard-filters")).toHaveTextContent("24h-all");
await user.click(screen.getByRole("button", { name: /Last 7 days/i }));
expect(screen.getByTestId("dashboard-filters")).toHaveTextContent("7d-all");
await user.click(screen.getByRole("button", { name: /Blocklist/i }));
expect(screen.getByTestId("dashboard-filters")).toHaveTextContent("7d-blocklist");
});
});