diff --git a/assets/css/custom.css b/assets/css/custom.css index ae9a54b..4e3b297 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -294,6 +294,43 @@ footer { padding: 20px 24px; } +/* Recipe Card Selection */ +.recipe-selection-card { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + border: 2px solid transparent; +} + +.recipe-selection-card.selected { + border-color: var(--brand-primary); + box-shadow: 0 15px 45px rgba(45, 106, 79, 0.15); + background-color: #F7FAF9; +} + +.recipe-selection-card .select-recipe:checked { + background-color: var(--brand-primary); + border-color: var(--brand-primary); +} + +.recipe-controls { + border: 1px solid #EAEAEA; + transition: all 0.3s ease; +} + +.recipe-selection-card.selected .recipe-controls { + background-color: #ffffff !important; + border-color: var(--brand-primary); +} + +.recipe-selection-card .form-check-input { + width: 1.5em; + height: 1.5em; +} + +.recipe-selection-card .form-check-label { + cursor: pointer; + user-select: none; +} + /* Category Label */ .recipe-category-label { background-color: #E9F5EF; diff --git a/assets/js/main.js b/assets/js/main.js index 40a60e3..3a2bf09 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -5,6 +5,7 @@ const app = { confirmedRecipeProducts: [], checkedItems: [], additionalProducts: [], + selectedRecipeIds: [], user: null }, api: { @@ -18,6 +19,7 @@ const app = { app.state.checkedItems = data.user.shopping_list.checkedItems || []; app.state.additionalProducts = data.user.shopping_list.additionalProducts || []; app.state.confirmedRecipeProducts = data.user.shopping_list.confirmedRecipeProducts || []; + app.state.selectedRecipeIds = data.user.shopping_list.selectedRecipeIds || []; } } else { app.state.user = null; @@ -36,7 +38,8 @@ const app = { shopping_list: { checkedItems: app.state.checkedItems, additionalProducts: app.state.additionalProducts, - confirmedRecipeProducts: app.state.confirmedRecipeProducts + confirmedRecipeProducts: app.state.confirmedRecipeProducts, + selectedRecipeIds: app.state.selectedRecipeIds } }) }); @@ -141,9 +144,20 @@ const app = { }); const data = await response.json(); if (data.success) { + // Remove from selectedRecipeIds if present + const index = app.state.selectedRecipeIds.indexOf(id.toString()); + if (index > -1) { + app.state.selectedRecipeIds.splice(index, 1); + } + const indexNum = app.state.selectedRecipeIds.indexOf(Number(id)); + if (indexNum > -1) { + app.state.selectedRecipeIds.splice(indexNum, 1); + } + await app.api.getRecipes(); app.ui.renderRecipeCards(app.state.recipes); app.ui.updateShoppingList(); + app.api.saveShoppingList(); } else { alert('Failed to delete recipe: ' + data.error); } @@ -166,8 +180,10 @@ const app = { cardCol.setAttribute('data-id', recipe.id); cardCol.style.animationDelay = `${index * 0.1}s`; + const isSelected = app.state.selectedRecipeIds.includes(recipe.id.toString()) || app.state.selectedRecipeIds.includes(Number(recipe.id)); + const card = document.createElement('div'); - card.className = 'card h-100'; + card.className = `card h-100 recipe-selection-card ${isSelected ? 'selected' : ''}`; if (recipe.image_url) { const img = document.createElement('img'); @@ -183,10 +199,15 @@ const app = { const titleWrapper = document.createElement('div'); titleWrapper.className = 'd-flex justify-content-between align-items-start mb-2 gap-2'; - const title = document.createElement('h5'); - title.className = 'card-title mb-0'; - title.textContent = recipe.name; - titleWrapper.appendChild(title); + const selectionWrapper = document.createElement('div'); + selectionWrapper.className = 'form-check mb-0'; + selectionWrapper.innerHTML = ` + + + `; + titleWrapper.appendChild(selectionWrapper); if (recipe.category) { const categoryLabel = document.createElement('div'); @@ -199,19 +220,35 @@ const app = { } const text = document.createElement('p'); - text.className = 'card-text text-muted'; + text.className = 'card-text text-muted mb-3'; text.textContent = `${recipe.ingredients.length} ingredients`; + const controlsWrapper = document.createElement('div'); + controlsWrapper.className = 'recipe-controls mb-3 p-2 bg-light rounded'; + controlsWrapper.innerHTML = ` +