From 465331d6721cce6f39a9fd6eac7022d9ce27b734 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Mar 2026 20:42:18 +0000 Subject: [PATCH 1/3] Initial plan From 9c4a2e864c366ad8e27e47e741728bb6ee1a8490 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Mar 2026 20:45:33 +0000 Subject: [PATCH 2/3] refactor(template-search): export only tab preference factory Co-authored-by: marcuscastelo <27441558+marcuscastelo@users.noreply.github.com> Agent-Logs-Url: https://github.com/marcuscastelo/macroflows/sessions/b0157939-1dbd-407a-a1eb-2363c82780bc --- .../templateSearchTabPreference.ts | 25 +++++-- .../tests/templateSearchTabPreference.test.ts | 67 ++++++++++++------- .../search/components/TemplateSearchModal.tsx | 10 ++- 3 files changed, 67 insertions(+), 35 deletions(-) diff --git a/src/modules/template-search/infrastructure/templateSearchTabPreference.ts b/src/modules/template-search/infrastructure/templateSearchTabPreference.ts index c50665c19..31c5e92ad 100644 --- a/src/modules/template-search/infrastructure/templateSearchTabPreference.ts +++ b/src/modules/template-search/infrastructure/templateSearchTabPreference.ts @@ -12,10 +12,12 @@ import { const STORAGE_KEY = 'macroflows:template-search-tab' -/** - * Default tab to use when no preference is saved. - */ -export const DEFAULT_TAB: TemplateSearchTab = availableTabs.Todos.id +const DEFAULT_TAB: TemplateSearchTab = availableTabs.Todos.id + +type TemplateSearchTabPreference = { + loadTabPreference: () => TemplateSearchTab + saveTabPreference: (tab: TemplateSearchTab) => void +} /** * Checks if a value is a valid TemplateSearchTab. @@ -31,7 +33,7 @@ function isValidTab(value: string): value is TemplateSearchTab { * Loads the saved template search tab preference from localStorage. * @returns The saved tab preference, or the default tab if none is saved or invalid */ -export function loadTabPreference(): TemplateSearchTab { +function loadTabPreference(): TemplateSearchTab { try { const stored = localStorage.getItem(STORAGE_KEY) if (stored !== null && isValidTab(stored)) { @@ -47,7 +49,7 @@ export function loadTabPreference(): TemplateSearchTab { * Saves the template search tab preference to localStorage. * @param tab - The tab to save */ -export function saveTabPreference(tab: TemplateSearchTab): void { +function saveTabPreference(tab: TemplateSearchTab): void { try { // Don't persist the 'hidden' state if (tab !== 'hidden') { @@ -57,3 +59,14 @@ export function saveTabPreference(tab: TemplateSearchTab): void { // localStorage may not be available (SSR, private mode, etc.) } } + +/** + * Creates a localStorage-backed template search tab preference adapter. + * @returns An adapter with methods to load and save the selected tab + */ +export function createTemplateSearchTabPreference(): TemplateSearchTabPreference { + return { + loadTabPreference, + saveTabPreference, + } +} diff --git a/src/modules/template-search/infrastructure/tests/templateSearchTabPreference.test.ts b/src/modules/template-search/infrastructure/tests/templateSearchTabPreference.test.ts index 4b3455564..3774a2b40 100644 --- a/src/modules/template-search/infrastructure/tests/templateSearchTabPreference.test.ts +++ b/src/modules/template-search/infrastructure/tests/templateSearchTabPreference.test.ts @@ -31,9 +31,11 @@ describe('templateSearchTabPreference', () => { describe('loadTabPreference', () => { it('returns default tab when localStorage is empty', async () => { - const { loadTabPreference, DEFAULT_TAB } = + const { createTemplateSearchTabPreference } = await import('~/modules/template-search/infrastructure/templateSearchTabPreference') - expect(loadTabPreference()).toBe(DEFAULT_TAB) + const tabPreference = createTemplateSearchTabPreference() + + expect(tabPreference.loadTabPreference()).toBe(availableTabs.Todos.id) }) it('returns persisted tab from localStorage', async () => { @@ -41,9 +43,11 @@ describe('templateSearchTabPreference', () => { setMockLocalStorage() vi.resetModules() - const { loadTabPreference } = + const { createTemplateSearchTabPreference } = await import('~/modules/template-search/infrastructure/templateSearchTabPreference') - expect(loadTabPreference()).toBe(availableTabs.Favoritos.id) + const tabPreference = createTemplateSearchTabPreference() + + expect(tabPreference.loadTabPreference()).toBe(availableTabs.Favoritos.id) }) it('returns persisted Recentes tab from localStorage', async () => { @@ -51,9 +55,11 @@ describe('templateSearchTabPreference', () => { setMockLocalStorage() vi.resetModules() - const { loadTabPreference } = + const { createTemplateSearchTabPreference } = await import('~/modules/template-search/infrastructure/templateSearchTabPreference') - expect(loadTabPreference()).toBe(availableTabs.Recentes.id) + const tabPreference = createTemplateSearchTabPreference() + + expect(tabPreference.loadTabPreference()).toBe(availableTabs.Recentes.id) }) it('returns persisted Receitas tab from localStorage', async () => { @@ -61,9 +67,11 @@ describe('templateSearchTabPreference', () => { setMockLocalStorage() vi.resetModules() - const { loadTabPreference } = + const { createTemplateSearchTabPreference } = await import('~/modules/template-search/infrastructure/templateSearchTabPreference') - expect(loadTabPreference()).toBe(availableTabs.Receitas.id) + const tabPreference = createTemplateSearchTabPreference() + + expect(tabPreference.loadTabPreference()).toBe(availableTabs.Receitas.id) }) it('returns default tab for invalid stored value', async () => { @@ -71,27 +79,31 @@ describe('templateSearchTabPreference', () => { setMockLocalStorage() vi.resetModules() - const { loadTabPreference, DEFAULT_TAB } = + const { createTemplateSearchTabPreference } = await import('~/modules/template-search/infrastructure/templateSearchTabPreference') - expect(loadTabPreference()).toBe(DEFAULT_TAB) + const tabPreference = createTemplateSearchTabPreference() + + expect(tabPreference.loadTabPreference()).toBe(availableTabs.Todos.id) }) }) describe('saveTabPreference', () => { it('saves tab preference to localStorage', async () => { - const { saveTabPreference } = + const { createTemplateSearchTabPreference } = await import('~/modules/template-search/infrastructure/templateSearchTabPreference') + const tabPreference = createTemplateSearchTabPreference() - saveTabPreference(availableTabs.Favoritos.id) + tabPreference.saveTabPreference(availableTabs.Favoritos.id) expect(localStorageMock[STORAGE_KEY]).toBe(availableTabs.Favoritos.id) }) it('does not persist hidden tab state', async () => { - const { saveTabPreference } = + const { createTemplateSearchTabPreference } = await import('~/modules/template-search/infrastructure/templateSearchTabPreference') + const tabPreference = createTemplateSearchTabPreference() - saveTabPreference('hidden') + tabPreference.saveTabPreference('hidden') expect(localStorageMock[STORAGE_KEY]).toBeUndefined() }) @@ -101,10 +113,11 @@ describe('templateSearchTabPreference', () => { setMockLocalStorage() vi.resetModules() - const { saveTabPreference } = + const { createTemplateSearchTabPreference } = await import('~/modules/template-search/infrastructure/templateSearchTabPreference') + const tabPreference = createTemplateSearchTabPreference() - saveTabPreference(availableTabs.Recentes.id) + tabPreference.saveTabPreference(availableTabs.Recentes.id) expect(localStorageMock[STORAGE_KEY]).toBe(availableTabs.Recentes.id) }) @@ -112,27 +125,35 @@ describe('templateSearchTabPreference', () => { describe('round-trip persistence', () => { it('can save and load tab preference', async () => { - const { saveTabPreference } = + const { createTemplateSearchTabPreference } = await import('~/modules/template-search/infrastructure/templateSearchTabPreference') + const tabPreference = createTemplateSearchTabPreference() // Save a preference - saveTabPreference(availableTabs.Receitas.id) + tabPreference.saveTabPreference(availableTabs.Receitas.id) // Re-import to get fresh module state vi.resetModules() const freshModule = await import('~/modules/template-search/infrastructure/templateSearchTabPreference') + const freshTabPreference = freshModule.createTemplateSearchTabPreference() // Load should return the saved preference - expect(freshModule.loadTabPreference()).toBe(availableTabs.Receitas.id) + expect(freshTabPreference.loadTabPreference()).toBe( + availableTabs.Receitas.id, + ) }) }) - describe('DEFAULT_TAB', () => { - it('is the Todos tab', async () => { - const { DEFAULT_TAB } = + describe('createTemplateSearchTabPreference', () => { + it('returns load and save methods', async () => { + const { createTemplateSearchTabPreference } = await import('~/modules/template-search/infrastructure/templateSearchTabPreference') - expect(DEFAULT_TAB).toBe(availableTabs.Todos.id) + + const tabPreference = createTemplateSearchTabPreference() + + expect(typeof tabPreference.loadTabPreference).toBe('function') + expect(typeof tabPreference.saveTabPreference).toBe('function') }) }) }) diff --git a/src/sections/search/components/TemplateSearchModal.tsx b/src/sections/search/components/TemplateSearchModal.tsx index 8e023c6c4..ada594dab 100644 --- a/src/sections/search/components/TemplateSearchModal.tsx +++ b/src/sections/search/components/TemplateSearchModal.tsx @@ -13,10 +13,7 @@ import { import { type Template } from '~/modules/diet/template/domain/template' import { isTemplateRecipe } from '~/modules/diet/template/domain/template' import { type TemplateItem } from '~/modules/diet/template-item/domain/templateItem' -import { - loadTabPreference, - saveTabPreference, -} from '~/modules/template-search/infrastructure/templateSearchTabPreference' +import { createTemplateSearchTabPreference } from '~/modules/template-search/infrastructure/templateSearchTabPreference' import { showError, showSuccess, @@ -206,12 +203,13 @@ export function TemplateSearch(props: { onEANModal: () => void }) { const templateSearchState = useContainer().templateSearchState() + const templateSearchTabPreference = createTemplateSearchTabPreference() // TODO: Determine if user is on desktop or mobile to set autofocus const isDesktop = false // Load persisted tab preference on mount (only once) onMount(() => { - const persistedTab = loadTabPreference() + const persistedTab = templateSearchTabPreference.loadTabPreference() templateSearchState.setTemplateSearchTab(persistedTab) }) @@ -228,7 +226,7 @@ export function TemplateSearch(props: { : tabOrUpdater templateSearchState.setTemplateSearchTab(newTab) - saveTabPreference(newTab) + templateSearchTabPreference.saveTabPreference(newTab) } return ( From 5a9808557b1c91f96d794a563350b25434f511d8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Mar 2026 20:49:14 +0000 Subject: [PATCH 3/3] refactor(template-search): reuse tab preference adapter Co-authored-by: marcuscastelo <27441558+marcuscastelo@users.noreply.github.com> Agent-Logs-Url: https://github.com/marcuscastelo/macroflows/sessions/b0157939-1dbd-407a-a1eb-2363c82780bc --- src/sections/search/components/TemplateSearchModal.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sections/search/components/TemplateSearchModal.tsx b/src/sections/search/components/TemplateSearchModal.tsx index ada594dab..2d8505270 100644 --- a/src/sections/search/components/TemplateSearchModal.tsx +++ b/src/sections/search/components/TemplateSearchModal.tsx @@ -36,6 +36,8 @@ import { } from '~/shared/modal/helpers/modalHelpers' import { logging } from '~/shared/utils/logging' +const templateSearchTabPreference = createTemplateSearchTabPreference() + export type TemplateSearchModalProps = { targetName: string onNewItem?: (item: Item, originalAddedItem: TemplateItem) => void @@ -203,7 +205,6 @@ export function TemplateSearch(props: { onEANModal: () => void }) { const templateSearchState = useContainer().templateSearchState() - const templateSearchTabPreference = createTemplateSearchTabPreference() // TODO: Determine if user is on desktop or mobile to set autofocus const isDesktop = false