From 4d4a034efc02d9da18f9f3df0e3e547c99360879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 21 May 2026 12:42:17 +0200 Subject: [PATCH] refactor(compare-toggle): migrate to queryKeys.dashboardWidgets factory The compare-toggle component still declared three bare-literal `["user", "dashboardWidgets"]` queryKeys for read, onMutate cancel/set, onError rollback and onSettled invalidation. Migrate every call site to the central `queryKeys.dashboardWidgets()` factory so a future rename or shape evolution only touches one file. Extend the W-RSC factory-bypass walker to cover `src/components/comparison/` so any future regression in this directory gets caught by CI. Closes UX H1 from the v1.4.40 QA round. --- src/components/comparison/compare-toggle.tsx | 20 +++++++++++--------- src/lib/__tests__/query-keys.test.ts | 1 + 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/components/comparison/compare-toggle.tsx b/src/components/comparison/compare-toggle.tsx index c9e39ccb0..cb9e52f60 100644 --- a/src/components/comparison/compare-toggle.tsx +++ b/src/components/comparison/compare-toggle.tsx @@ -3,6 +3,7 @@ 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, @@ -26,7 +27,7 @@ export function CompareToggle({ className }: { className?: string }) { const queryClient = useQueryClient(); const { data: layoutData } = useQuery({ - queryKey: ["user", "dashboardWidgets"], + queryKey: queryKeys.dashboardWidgets(), queryFn: async () => { const res = await fetch("/api/dashboard/widgets"); if (!res.ok) throw new Error("failed"); @@ -52,15 +53,14 @@ export function CompareToggle({ className }: { className?: string }) { }, onMutate: async (next) => { await queryClient.cancelQueries({ - queryKey: ["user", "dashboardWidgets"], + queryKey: queryKeys.dashboardWidgets(), }); - const prev = queryClient.getQueryData([ - "user", - "dashboardWidgets", - ]); + const prev = queryClient.getQueryData( + queryKeys.dashboardWidgets(), + ); if (prev) { queryClient.setQueryData( - ["user", "dashboardWidgets"], + queryKeys.dashboardWidgets(), { ...prev, comparisonBaseline: next }, ); } @@ -68,11 +68,13 @@ export function CompareToggle({ className }: { className?: string }) { }, onError: (_err, _next, ctx) => { if (ctx?.prev) { - queryClient.setQueryData(["user", "dashboardWidgets"], ctx.prev); + queryClient.setQueryData(queryKeys.dashboardWidgets(), ctx.prev); } }, onSettled: () => { - queryClient.invalidateQueries({ queryKey: ["user", "dashboardWidgets"] }); + queryClient.invalidateQueries({ + queryKey: queryKeys.dashboardWidgets(), + }); }, }); diff --git a/src/lib/__tests__/query-keys.test.ts b/src/lib/__tests__/query-keys.test.ts index 4f0002b48..4d25e19b7 100644 --- a/src/lib/__tests__/query-keys.test.ts +++ b/src/lib/__tests__/query-keys.test.ts @@ -172,6 +172,7 @@ describe("queryKey factory enforcement", () => { // guard's scope until a follow-up wave routes those keys. const guardedRoots = [ join(repoRoot, "src", "components", "charts"), + join(repoRoot, "src", "components", "comparison"), join(repoRoot, "src", "app", "page.tsx"), join(repoRoot, "src", "hooks", "use-auth.ts"), ];