"use client"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useTranslations } from "@/lib/i18n/context"; import { cn } from "@/lib/utils"; import { queryKeys } from "@/lib/query-keys"; import { COMPARISON_BASELINES, resolveDashboardLayout, type ComparisonBaseline, type DashboardLayout, } from "@/lib/dashboard-layout"; import { apiGet, apiPut } from "@/lib/api/api-fetch"; /** * v1.4.16 phase D reconcile (CRITICAL C3) — on-surface comparison * toggle. Replaces the Settings-only Select buried 3 clicks deep with * a 3-segment control mounted next to the dashboard greeting and the * insights page hero. Persists via the same `/api/dashboard/widgets` * PUT the Settings page uses, so a flip on either surface updates the * other on next refetch. * * Hit area: each segment is `min-h-11` (44 px) per WCAG 2.5.5; pressed * state is the `default` button variant, idle is `outline`. */ export function CompareToggle({ className }: { className?: string }) { const { t } = useTranslations(); const queryClient = useQueryClient(); const { data: layoutData } = useQuery({ queryKey: queryKeys.dashboardWidgets(), queryFn: async () => { return apiGet("/api/dashboard/widgets"); }, }); const layout = layoutData ? resolveDashboardLayout(layoutData) : null; const value: ComparisonBaseline = layout?.comparisonBaseline ?? "none"; const mutation = useMutation({ mutationFn: async (next: ComparisonBaseline) => { if (!layout) throw new Error("layout-not-loaded"); const body: DashboardLayout = { ...layout, comparisonBaseline: next }; return apiPut("/api/dashboard/widgets", body); }, onMutate: async (next) => { await queryClient.cancelQueries({ queryKey: queryKeys.dashboardWidgets(), }); const prev = queryClient.getQueryData( queryKeys.dashboardWidgets(), ); if (prev) { queryClient.setQueryData( queryKeys.dashboardWidgets(), { ...prev, comparisonBaseline: next }, ); } return { prev }; }, onError: (_err, _next, ctx) => { if (ctx?.prev) { queryClient.setQueryData(queryKeys.dashboardWidgets(), ctx.prev); } }, onSettled: () => { queryClient.invalidateQueries({ queryKey: queryKeys.dashboardWidgets(), }); }, }); return (
{COMPARISON_BASELINES.map((option) => { const active = value === option; return ( ); })}
); }