Simpl-Resultat/src/components/reports/ViewModeToggle.tsx
le king fu 91430e994a
All checks were successful
PR Check / rust (push) Successful in 24m21s
PR Check / frontend (push) Successful in 2m12s
PR Check / rust (pull_request) Successful in 23m5s
PR Check / frontend (pull_request) Successful in 2m16s
refactor: remove pivot report, add sub-route skeletons and shared components (#69)
- Delete DynamicReport* components and pivot types (PivotConfig, PivotResult, PivotFieldId, etc.)
- Remove getDynamicReportData/getDynamicFilterValues from reportService
- Strip pivotConfig/pivotResult from useReports hook and ReportsPage
- Drop "dynamic" from ReportTab union
- Remove reports.pivot.* and reports.dynamic i18n keys in FR and EN
- Add skeletons for /reports/highlights, /trends, /compare, /category pages
- Register the 4 new sub-routes in App.tsx
- Add reports.hub, reports.viewMode, reports.empty, common.underConstruction keys
- New shared ContextMenu component with click-outside + Escape handling
- Refactor ChartContextMenu to compose generic ContextMenu
- New ViewModeToggle with localStorage persistence via storageKey
- New Sparkline (Recharts LineChart) for compact trends
- Unit tests for readViewMode helper

Fixes #69

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 14:25:38 -04:00

52 lines
1.8 KiB
TypeScript

import { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { BarChart3, Table } from "lucide-react";
export type ViewMode = "chart" | "table";
export interface ViewModeToggleProps {
value: ViewMode;
onChange: (mode: ViewMode) => void;
/** localStorage key used to persist the preference per section. */
storageKey?: string;
}
export function readViewMode(storageKey: string, fallback: ViewMode = "chart"): ViewMode {
if (typeof localStorage === "undefined") return fallback;
const saved = localStorage.getItem(storageKey);
return saved === "chart" || saved === "table" ? saved : fallback;
}
export default function ViewModeToggle({ value, onChange, storageKey }: ViewModeToggleProps) {
const { t } = useTranslation();
useEffect(() => {
if (storageKey) localStorage.setItem(storageKey, value);
}, [value, storageKey]);
const options: { mode: ViewMode; icon: React.ReactNode; label: string }[] = [
{ mode: "chart", icon: <BarChart3 size={14} />, label: t("reports.viewMode.chart") },
{ mode: "table", icon: <Table size={14} />, label: t("reports.viewMode.table") },
];
return (
<div className="inline-flex gap-1" role="group" aria-label={t("reports.viewMode.chart")}>
{options.map(({ mode, icon, label }) => (
<button
key={mode}
type="button"
onClick={() => onChange(mode)}
aria-pressed={value === mode}
className={`inline-flex items-center gap-1.5 px-3 py-2 rounded-lg text-sm font-medium transition-colors ${
value === mode
? "bg-[var(--primary)] text-white"
: "bg-[var(--card)] border border-[var(--border)] text-[var(--foreground)] hover:bg-[var(--muted)]"
}`}
>
{icon}
{label}
</button>
))}
</div>
);
}