const pantryForm = document.getElementById('ingredient-form'); const pantryList = document.getElementById('pantry-list'); const filterList = document.getElementById('filter-list'); const recipesList = document.getElementById('recipes-list'); const clearPantryButton = document.getElementById('clear-pantry'); const barcodeForm = document.getElementById('barcode-form'); const barcodeMessage = document.getElementById('barcode-message'); const recipeTemplate = document.getElementById('recipe-template'); const STORAGE_KEYS = { pantry: 'pantry-tracker-pantry', filters: 'pantry-tracker-filters', }; const barcodeCatalog = { '0123456789012': { name: 'eggs', unit: 'pcs' }, '1234567890123': { name: 'flour', unit: 'g' }, '2345678901234': { name: 'soy sauce', unit: 'ml' }, '3456789012345': { name: 'milk', unit: 'ml' }, '4567890123456': { name: 'rice', unit: 'g' }, '5678901234567': { name: 'butter', unit: 'g' }, '6789012345678': { name: 'sugar', unit: 'g' }, '7890123456789': { name: 'pasta', unit: 'g' }, '8901234567890': { name: 'tomato', unit: 'pcs' }, '9012345678901': { name: 'onion', unit: 'pcs' }, }; const recipes = [ { name: 'Fried Egg on Toast', instructions: 'Cook an egg and serve with toast. Add salt and pepper to taste.', ingredients: [ { name: 'eggs', quantity: 1, unit: 'pcs' }, { name: 'flour', quantity: 30, unit: 'g' } ] }, { name: 'Pancakes', instructions: 'Mix flour, milk, and eggs into batter. Fry spoonfuls until golden.', ingredients: [ { name: 'flour', quantity: 150, unit: 'g' }, { name: 'eggs', quantity: 2, unit: 'pcs' }, { name: 'milk', quantity: 200, unit: 'ml' } ] }, { name: 'Soy Sauce Rice', instructions: 'Cook rice, then stir in soy sauce and optional vegetables.', ingredients: [ { name: 'rice', quantity: 200, unit: 'g' }, { name: 'soy sauce', quantity: 20, unit: 'ml' } ] }, { name: 'Tomato Pasta', instructions: 'Cook pasta and toss with chopped tomato and butter.', ingredients: [ { name: 'pasta', quantity: 120, unit: 'g' }, { name: 'tomato', quantity: 2, unit: 'pcs' }, { name: 'butter', quantity: 20, unit: 'g' } ] }, { name: 'Omelette', instructions: 'Whisk eggs, cook gently, and fold in butter.', ingredients: [ { name: 'eggs', quantity: 3, unit: 'pcs' }, { name: 'butter', quantity: 15, unit: 'g' } ] } ]; function loadPantry() { const raw = localStorage.getItem(STORAGE_KEYS.pantry); return raw ? JSON.parse(raw) : {}; } function savePantry(pantry) { localStorage.setItem(STORAGE_KEYS.pantry, JSON.stringify(pantry)); } function loadFilters() { const raw = localStorage.getItem(STORAGE_KEYS.filters); return raw ? JSON.parse(raw) : {}; } function saveFilters(filters) { localStorage.setItem(STORAGE_KEYS.filters, JSON.stringify(filters)); } function normalizeName(name) { return name.trim().toLowerCase(); } function updatePantryList() { const pantry = loadPantry(); pantryList.innerHTML = ''; const keys = Object.keys(pantry).sort(); if (keys.length === 0) { pantryList.innerHTML = '

Your pantry is empty. Add ingredients or scan a barcode.

'; return; } keys.forEach((key) => { const item = pantry[key]; const card = document.createElement('div'); card.className = 'pantry-item'; const info = document.createElement('div'); info.className = 'pantry-item-info'; info.innerHTML = `${item.name}${item.quantity} ${item.unit}`; const actions = document.createElement('div'); actions.innerHTML = ``; card.append(info, actions); pantryList.append(card); }); } function updateFilterList() { const pantry = loadPantry(); const filters = loadFilters(); filterList.innerHTML = ''; const keys = Object.keys(pantry).sort(); if (keys.length === 0) { filterList.innerHTML = '

Add pantry items first to filter recipes.

'; return; } keys.forEach((key) => { const item = pantry[key]; const id = `filter-${key}`; const row = document.createElement('div'); row.className = 'filter-item'; row.innerHTML = `
${item.quantity} ${item.unit} available
`; filterList.append(row); }); } function canMakeRecipe(recipe, pantry, filters) { const missing = []; for (const required of recipe.ingredients) { const pantryItem = pantry[normalizeName(required.name)]; if (!pantryItem) { missing.push(required.name); continue; } if (filters[pantryItem.name] === false) { missing.push(`${required.name} (excluded)`); continue; } if (pantryItem.unit !== required.unit || pantryItem.quantity < required.quantity) { missing.push(required.name); } } return { canMake: missing.length === 0, missing }; } function updateRecipes() { const pantry = loadPantry(); const filters = loadFilters(); recipesList.innerHTML = ''; recipes.forEach((recipe) => { const { canMake, missing } = canMakeRecipe(recipe, pantry, filters); const clone = recipeTemplate.content.cloneNode(true); const card = clone.querySelector('article'); const name = clone.querySelector('.recipe-name'); const status = clone.querySelector('.recipe-status'); const ingredientList = clone.querySelector('.recipe-ingredients'); const instructions = clone.querySelector('.recipe-instructions'); const button = clone.querySelector('.use-recipe'); name.textContent = recipe.name; status.textContent = canMake ? 'Ready to make with current pantry.' : `Missing: ${missing.join(', ')}`; instructions.textContent = recipe.instructions; recipe.ingredients.forEach((item) => { const li = document.createElement('li'); li.textContent = `${item.name}: ${item.quantity} ${item.unit}`; ingredientList.append(li); }); button.disabled = !canMake; button.addEventListener('click', () => handleUseRecipe(recipe)); recipesList.append(clone); }); } function handleUseRecipe(recipe) { const pantry = loadPantry(); recipe.ingredients.forEach((item) => { const key = normalizeName(item.name); const pantryItem = pantry[key]; if (!pantryItem) return; pantryItem.quantity = Math.max(0, pantryItem.quantity - item.quantity); if (pantryItem.quantity === 0) { delete pantry[key]; } }); savePantry(pantry); updatePantryList(); updateFilterList(); updateRecipes(); } function notifyBarcode(message, type = 'info') { barcodeMessage.textContent = message; barcodeMessage.style.color = type === 'error' ? '#b91c1c' : '#1d4ed8'; barcodeMessage.style.background = type === 'error' ? '#fee2e2' : '#eff6ff'; } function addOrUpdatePantry(name, quantity, unit) { const pantry = loadPantry(); const key = normalizeName(name); if (!pantry[key]) { pantry[key] = { name: key, quantity: 0, unit }; } const item = pantry[key]; if (item.unit !== unit) { item.unit = unit; } item.quantity = Math.max(0, item.quantity + quantity); if (item.quantity === 0) { delete pantry[key]; } savePantry(pantry); updatePantryList(); updateFilterList(); updateRecipes(); } pantryForm.addEventListener('submit', (event) => { event.preventDefault(); const name = event.target.name.value; const quantity = Number(event.target.quantity.value); const unit = event.target.unit.value; addOrUpdatePantry(name, quantity, unit); event.target.reset(); }); barcodeForm.addEventListener('submit', (event) => { event.preventDefault(); const rawCode = event.target.barcode.value.trim(); const quantity = Number(event.target.quantity.value); const unit = event.target.unit.value; if (!barcodeCatalog[rawCode]) { notifyBarcode('Barcode not recognized. Enter a known barcode or add manually.', 'error'); return; } const item = barcodeCatalog[rawCode]; addOrUpdatePantry(item.name, quantity, unit || item.unit); notifyBarcode(`Added ${quantity} ${unit} of ${item.name} to your pantry.`); event.target.reset(); }); clearPantryButton.addEventListener('click', () => { if (!confirm('Remove all pantry items?')) { return; } localStorage.removeItem(STORAGE_KEYS.pantry); localStorage.removeItem(STORAGE_KEYS.filters); updatePantryList(); updateFilterList(); updateRecipes(); }); filterList.addEventListener('change', (event) => { if (event.target.matches('input[type="checkbox"]')) { const name = event.target.dataset.name; const filters = loadFilters(); filters[name] = event.target.checked; saveFilters(filters); updateRecipes(); } }); pantryList.addEventListener('click', (event) => { if (!event.target.matches('.remove-item')) return; const name = event.target.dataset.name; const pantry = loadPantry(); delete pantry[normalizeName(name)]; savePantry(pantry); updatePantryList(); updateFilterList(); updateRecipes(); }); function initialize() { updatePantryList(); updateFilterList(); updateRecipes(); } initialize();