Add shopping list tab with auto-generation from planner
- New ShoppingList.js view with category-grouped items - Check item = auto-transfer to pantry - "Generate shortfalls" button computes weekly needs vs pantry stock - Badge on shopping tab icon shows unchecked item count - Bottom dock expanded to 5 columns for new tab Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,6 +42,12 @@ export function getBottomNavHTML() {
|
||||
<i class="fas fa-warehouse" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="nav-slot" style="position:relative;">
|
||||
<button type="button" data-tab="shopping" id="nav-shopping" class="nav-tab" aria-label="Zakupy">
|
||||
<i class="fas fa-cart-shopping" aria-hidden="true"></i>
|
||||
</button>
|
||||
<span id="nav-shopping-badge" class="hidden absolute -top-0.5 -right-0.5 min-w-[16px] h-4 rounded-full flex items-center justify-center text-[9px] font-bold leading-none px-1" style="background:rgb(var(--accent-rgb)); color:#1a1a1a;"></span>
|
||||
</div>
|
||||
<div class="nav-slot">
|
||||
<button type="button" id="nav-theme-toggle" class="nav-action" aria-label="${isDark ? 'Włącz jasny motyw' : 'Włącz ciemny motyw'}" title="${isDark ? 'Jasny motyw' : 'Ciemny motyw'}">
|
||||
<i class="${isDark ? 'fas fa-sun' : 'fas fa-moon'}" aria-hidden="true"></i>
|
||||
@@ -52,24 +58,29 @@ export function getBottomNavHTML() {
|
||||
`;
|
||||
}
|
||||
|
||||
export function setupBottomNav({ refreshPantry } = {}) {
|
||||
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 || !nav) return;
|
||||
if (!main || !planner || !pantry || !shopping || !nav) return;
|
||||
|
||||
const TABS = ['recipes', 'planner', 'pantry', 'shopping'];
|
||||
|
||||
const apply = (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');
|
||||
|
||||
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 (id === 'recipes' || id === 'planner' || id === 'pantry') {
|
||||
if (TABS.includes(id)) {
|
||||
const isActive = id === tab;
|
||||
btn.classList.toggle('is-active', isActive);
|
||||
if (isActive) btn.setAttribute('aria-current', 'page');
|
||||
@@ -82,7 +93,7 @@ export function setupBottomNav({ refreshPantry } = {}) {
|
||||
const btn = e.target.closest('.nav-tab[data-tab]');
|
||||
if (!btn || btn.hasAttribute('disabled')) return;
|
||||
const tab = btn.getAttribute('data-tab');
|
||||
if (tab === 'recipes' || tab === 'planner' || tab === 'pantry') apply(tab);
|
||||
if (TABS.includes(tab)) apply(tab);
|
||||
});
|
||||
|
||||
setupThemeToggle();
|
||||
|
||||
Reference in New Issue
Block a user