From 9e2d5663efbb69216441870082afd728fa56412b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 2 Aug 2026 21:20:17 +0000 Subject: [PATCH] =?UTF-8?q?refactor(campanha):=20B133=20simplify=20?= =?UTF-8?q?=E2=80=94=20extract=20useActiveMunicipalitySavedFilter=20hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Francisco Solla --- .../MunicipalityListPageChrome.tsx | 21 ++----------------- .../shared/useMunicipalitySavedFilters.ts | 21 +++++++++++++++++++ .../shell/MunicipalityNavSavedFilters.tsx | 21 ++++++------------- 3 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/components/campaign/municipality/MunicipalityListPageChrome.tsx b/src/components/campaign/municipality/MunicipalityListPageChrome.tsx index e1860d69..005dce95 100644 --- a/src/components/campaign/municipality/MunicipalityListPageChrome.tsx +++ b/src/components/campaign/municipality/MunicipalityListPageChrome.tsx @@ -1,32 +1,15 @@ 'use client' -import { usePathname, useSearchParams } from 'next/navigation' -import { useMemo } from 'react' - -import { useMunicipalitySavedFilters } from '@/components/campaign/shared/useMunicipalitySavedFilters' +import { useActiveMunicipalitySavedFilter } from '@/components/campaign/shared/useMunicipalitySavedFilters' import { SetCampaignPageChrome } from '@/components/campaign/shell/CampaignPageChromeContext' import { campaignPageChromeCatalog } from '@/lib/campaignPageChrome' -import { isSameListHref } from '@/lib/listQueryMatch' - -/** A page is a position inside a recorte, not part of it (B18). */ -const IGNORED_PARAMS = ['page'] /** * When the current URL matches a saved municipality filter, the filter name * becomes the page subtitle (B133) — the bar keeps chips as the editable recorte. */ export const MunicipalityListPageChrome = () => { - const savedFilters = useMunicipalitySavedFilters() - const pathname = usePathname() - const searchParams = useSearchParams() - - const activeFilter = useMemo(() => { - const query = searchParams.toString() - const currentHref = query ? `${pathname}?${query}` : pathname - return savedFilters.find((entry) => - isSameListHref(currentHref, entry.href, IGNORED_PARAMS), - ) - }, [pathname, searchParams, savedFilters]) + const activeFilter = useActiveMunicipalitySavedFilter() if (!activeFilter) return null diff --git a/src/components/campaign/shared/useMunicipalitySavedFilters.ts b/src/components/campaign/shared/useMunicipalitySavedFilters.ts index 0738b2f9..0783a1a0 100644 --- a/src/components/campaign/shared/useMunicipalitySavedFilters.ts +++ b/src/components/campaign/shared/useMunicipalitySavedFilters.ts @@ -1,13 +1,19 @@ 'use client' +import { usePathname, useSearchParams } from 'next/navigation' +import { useMemo } from 'react' import { useSyncExternalStore } from 'react' +import { isSameListHref } from '@/lib/listQueryMatch' import { listMunicipalitySavedFilters, subscribeMunicipalitySavedFilters, type MunicipalitySavedFilter, } from '@/utilities/municipality/municipalitySavedFilters' +/** A page is a position inside a recorte, not part of it (B18). */ +export const MUNICIPALITY_SAVED_FILTER_IGNORED_PARAMS = ['page'] as const + /** * Stable reference for the render that has no `localStorage` to read. Returning * a fresh `[]` here is the classic `useSyncExternalStore` render loop. @@ -26,3 +32,18 @@ export const useMunicipalitySavedFilters = (): readonly MunicipalitySavedFilter[ listMunicipalitySavedFilters, () => NO_SAVED_FILTERS, ) + +/** The saved filter whose href matches the current list URL, if any (B18/B133). */ +export const useActiveMunicipalitySavedFilter = (): MunicipalitySavedFilter | undefined => { + const savedFilters = useMunicipalitySavedFilters() + const pathname = usePathname() + const searchParams = useSearchParams() + + return useMemo(() => { + const query = searchParams.toString() + const currentHref = query ? `${pathname}?${query}` : pathname + return savedFilters.find((entry) => + isSameListHref(currentHref, entry.href, MUNICIPALITY_SAVED_FILTER_IGNORED_PARAMS), + ) + }, [pathname, searchParams, savedFilters]) +} diff --git a/src/components/campaign/shell/MunicipalityNavSavedFilters.tsx b/src/components/campaign/shell/MunicipalityNavSavedFilters.tsx index ea2e8dc6..af7ebebe 100644 --- a/src/components/campaign/shell/MunicipalityNavSavedFilters.tsx +++ b/src/components/campaign/shell/MunicipalityNavSavedFilters.tsx @@ -2,26 +2,24 @@ import { Trash2Icon } from 'lucide-react' import Link from 'next/link' -import { usePathname, useSearchParams } from 'next/navigation' import { toast } from 'sonner' -import { useMunicipalitySavedFilters } from '@/components/campaign/shared/useMunicipalitySavedFilters' +import { + useActiveMunicipalitySavedFilter, + useMunicipalitySavedFilters, +} from '@/components/campaign/shared/useMunicipalitySavedFilters' import { SidebarMenuAction, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, } from '@/components/ui/Sidebar' -import { isSameListHref } from '@/lib/listQueryMatch' import { removeMunicipalitySavedFilter, saveMunicipalitySavedFilter, type MunicipalitySavedFilter, } from '@/utilities/municipality/municipalitySavedFilters' -/** A page is a position inside a recorte, not part of it. */ -const IGNORED_PARAMS = ['page'] - /** * The saved filters of `/campanha/municipios` (B18), hung under that nav item. * @@ -31,14 +29,7 @@ const IGNORED_PARAMS = ['page'] */ export const MunicipalityNavSavedFilters = ({ onNavigate }: { onNavigate: () => void }) => { const savedFilters = useMunicipalitySavedFilters() - const pathname = usePathname() - const searchParams = useSearchParams() - - const query = searchParams.toString() - const currentHref = query ? `${pathname}?${query}` : pathname - const activeHref = savedFilters.find((entry) => - isSameListHref(currentHref, entry.href, IGNORED_PARAMS), - )?.href + const activeFilter = useActiveMunicipalitySavedFilter() if (!savedFilters.length) return null @@ -75,7 +66,7 @@ export const MunicipalityNavSavedFilters = ({ onNavigate }: { onNavigate: () => return ( {savedFilters.map((entry) => { - const isActive = entry.href === activeHref + const isActive = entry.href === activeFilter?.href return (