export function getBottomNavHTML() { return ` `; } export function setupBottomNav({ refreshPantry, refreshShoppingList } = {}) { const main = document.getElementById('main-view'); const planner = document.getElementById('planner-view'); const pantry = document.getElementById('pantry-view'); const shopping = document.getElementById('shopping-view'); const nav = document.getElementById('app-bottom-nav'); if (!main || !planner || !pantry || !shopping || !nav) return; const TABS = ['recipes', 'planner', 'pantry', 'shopping']; const COLLAPSED_TABS = new Set(); const EXTRA_CONTROL_SLOTS = { recipes: 2, pantry: 2, shopping: 1 }; const DOUBLE_COMPACT_TABS = new Set(['recipes', 'pantry']); const COLLAPSED_TAB_ICON = { recipes: 'fa-book-open', pantry: 'fa-warehouse' }; const COLLAPSED_TAB_LABEL = { recipes: 'Otwórz menu katalogu', pantry: 'Otwórz menu spiżarni' }; let isRecipeMenuOpen = false; let activeTab = 'planner'; let previousTab = 'planner'; let collapseTimer = null; const syncRecipeNavMetrics = () => { const rootFontSize = parseFloat(window.getComputedStyle(document.documentElement).fontSize) || 16; const navStyles = window.getComputedStyle(nav); const navPadLeft = parseFloat(navStyles.paddingLeft) || 0; const navPadRight = parseFloat(navStyles.paddingRight) || 0; const navContentWidth = nav.clientWidth - navPadLeft - navPadRight; const isCompact = window.matchMedia('(max-width: 380px)').matches; const dockInset = (isCompact ? 1.6 : 2.4) * rootFontSize; const dockMax = (isCompact ? 22.5 : 24.5) * rootFontSize; const dockWidth = Math.min(navContentWidth - dockInset, dockMax); if (dockWidth <= 0) return; const padLeft = (isCompact ? 0.38 : 0.42) * rootFontSize; const padRight = (isCompact ? 0.38 : 0.42) * rootFontSize; const columnGap = (isCompact ? 0.05 : 0.06) * rootFontSize; const dockLeft = navPadLeft + ((navContentWidth - dockWidth) / 2); const controlSize = (isCompact ? 2.95 : 3.05) * rootFontSize; const expandedDockHeight = controlSize; const controlGap = 0.5 * rootFontSize; const controlsLift = Math.max(0, (expandedDockHeight - controlSize) / 2); const collapsedDockWidth = controlSize; const collapsedSlotWidth = Math.max(32, collapsedDockWidth - padLeft - padRight); const controlCluster = controlSize + controlGap; const compactExtraWidth = (EXTRA_CONTROL_SLOTS[activeTab] || 0) * controlCluster; const filterLeft = dockLeft + dockWidth - controlSize; const searchButtonLeft = filterLeft - controlGap - controlSize; const searchRight = Math.max(16, nav.clientWidth - filterLeft + controlGap); nav.style.setProperty('--recipe-dock-width', `${dockWidth}px`); nav.style.setProperty('--recipe-collapsed-dock-width', `${collapsedDockWidth}px`); nav.style.setProperty('--recipe-toggle-size', `${collapsedSlotWidth}px`); nav.style.setProperty('--nav-compact-extra-width', `${compactExtraWidth}px`); nav.style.setProperty('--nav-compact-translate-x', `${compactExtraWidth * -0.5}px`); document.documentElement.style.setProperty('--recipe-dock-width', `${dockWidth}px`); document.documentElement.style.setProperty('--catalog-menu-left', `${dockLeft}px`); document.documentElement.style.setProperty('--catalog-menu-width', `${collapsedDockWidth}px`); document.documentElement.style.setProperty('--catalog-filter-left', `${filterLeft}px`); document.documentElement.style.setProperty('--catalog-search-btn-left', `${searchButtonLeft}px`); document.documentElement.style.setProperty('--catalog-search-right', `${searchRight}px`); document.documentElement.style.setProperty('--recipe-control-size', `${controlSize}px`); document.documentElement.style.setProperty('--recipe-controls-lift', `${controlsLift}px`); }; const updateToggleForTab = (tab) => { const icon = document.getElementById('recipe-nav-toggle-icon'); const button = document.getElementById('recipe-nav-toggle'); const nextIcon = COLLAPSED_TAB_ICON[tab]; if (icon && nextIcon) { icon.className = `fas ${nextIcon}`; } if (button && COLLAPSED_TAB_LABEL[tab]) { button.setAttribute('aria-label', COLLAPSED_TAB_LABEL[tab]); } }; const setRecipeMenuOpen = (open) => { syncRecipeNavMetrics(); window.clearTimeout(collapseTimer); isRecipeMenuOpen = open; nav.classList.remove('is-nav-collapsing'); nav.classList.toggle('is-nav-menu-open', open); document.documentElement.classList.toggle('is-nav-menu-open', open); document.getElementById('recipe-nav-toggle')?.setAttribute('aria-expanded', open ? 'true' : 'false'); }; const apply = (tab) => { const wasCollapsedTab = COLLAPSED_TABS.has(previousTab); const isCollapsedTab = COLLAPSED_TABS.has(tab); const isCompactTab = (EXTRA_CONTROL_SLOTS[tab] || 0) > 0; const isDoubleCompact = DOUBLE_COMPACT_TABS.has(tab); main.classList.toggle('hidden', tab !== 'recipes'); planner.classList.toggle('hidden', tab !== 'planner'); pantry.classList.toggle('hidden', tab !== 'pantry'); shopping.classList.toggle('hidden', tab !== 'shopping'); nav.classList.toggle('is-collapsed-tab', isCollapsedTab); nav.classList.toggle('is-compact-tab', isCompactTab); nav.classList.toggle('is-double-compact', isDoubleCompact); activeTab = tab; updateToggleForTab(tab); syncRecipeNavMetrics(); setRecipeMenuOpen(false); if (isCollapsedTab && (!wasCollapsedTab || tab !== previousTab)) { nav.classList.add('is-nav-menu-open', 'is-nav-collapsing'); document.documentElement.classList.add('is-nav-menu-open'); document.getElementById('recipe-nav-toggle')?.setAttribute('aria-expanded', 'false'); requestAnimationFrame(() => { requestAnimationFrame(() => { requestAnimationFrame(() => { nav.classList.remove('is-nav-menu-open'); document.documentElement.classList.remove('is-nav-menu-open'); collapseTimer = window.setTimeout(() => { nav.classList.remove('is-nav-collapsing'); }, 500); }); }); }); } if (tab === 'pantry' && typeof refreshPantry === 'function') refreshPantry(); if (tab === 'shopping' && typeof refreshShoppingList === 'function') refreshShoppingList(); nav.querySelectorAll('.nav-tab[data-tab]').forEach((btn) => { const id = btn.getAttribute('data-tab'); if (btn.hasAttribute('disabled')) return; if (TABS.includes(id)) { const isActive = id === tab; btn.classList.toggle('is-active', isActive); if (isActive) btn.setAttribute('aria-current', 'page'); else btn.removeAttribute('aria-current'); } }); window.dispatchEvent(new CustomEvent('app-tab-change', { detail: { tab } })); previousTab = tab; }; nav.addEventListener('click', (e) => { const toggle = e.target.closest('#recipe-nav-toggle'); if (toggle) { e.stopPropagation(); setRecipeMenuOpen(!isRecipeMenuOpen); window.closeRecipeSearch?.(); window.closePantrySearch?.(); window.closePantryFilter?.(); window.closeShoppingCalendar?.(); window.closeShoppingBoughtPopup?.(); window.closeFilters?.(); return; } const btn = e.target.closest('.nav-tab[data-tab]'); if (!btn || btn.hasAttribute('disabled')) return; const tab = btn.getAttribute('data-tab'); if (TABS.includes(tab)) apply(tab); }); document.addEventListener('click', (e) => { if (!isRecipeMenuOpen || !nav.classList.contains('is-collapsed-tab')) return; if (e.composedPath().includes(nav)) return; setRecipeMenuOpen(false); }); document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && isRecipeMenuOpen) setRecipeMenuOpen(false); }); window.addEventListener('resize', syncRecipeNavMetrics); apply('planner'); window.switchAppTab = (tab) => { if (TABS.includes(tab)) apply(tab); }; window.refreshStockViews = () => { if (typeof refreshPantry === 'function') refreshPantry(); }; }