fix: image upload (add extension field) + ingredient groups

- Fix Mealie image upload 422: send required `extension` field in form data
- Parse ingredient groups from mindmegette (multiple div.ingredients
  containers with strong.ingredients-group titles)
- Show group headers in UI with dashed-border accent input
- Pass group markers through to Mealie as title-only ingredient entries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-24 08:44:34 +01:00
parent cb669f1861
commit c235d5caa7
3 changed files with 76 additions and 11 deletions
+55 -8
View File
@@ -52,6 +52,31 @@
line-height: 1;
flex-shrink: 0;
}
.ingredient-group {
display: flex;
gap: 0.5rem;
align-items: center;
margin: 0.8rem 0 0.3rem;
}
.ingredient-group input {
margin-bottom: 0;
flex: 1;
font-weight: 600;
color: var(--accent);
border-style: dashed;
}
.ingredient-group button {
background: var(--danger);
border: none;
color: #fff;
width: 28px;
height: 28px;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
line-height: 1;
flex-shrink: 0;
}
.instruction-row {
display: flex;
gap: 0.5rem;
@@ -144,7 +169,10 @@
<span class="col-extra">Megjegyzés</span>
</div>
<div id="ingredientsList"></div>
<button class="add-btn mt-1 mb-2" onclick="addIngredient({})">+ Hozzávaló hozzáadása</button>
<div class="flex gap-1 mt-1 mb-2">
<button class="add-btn" onclick="addIngredient({})">+ Hozzávaló</button>
<button class="add-btn" onclick="addIngredientGroup('')">+ Csoport</button>
</div>
<!-- Instructions -->
<label>Elkészítés</label>
@@ -236,6 +264,11 @@ function populatePreview(r) {
function addIngredient(item) {
if (typeof item === 'string') item = { food: item };
// Group header marker
if (item.group !== undefined && item.food === undefined) {
addIngredientGroup(item.group);
return;
}
const list = document.getElementById('ingredientsList');
const row = document.createElement('div');
row.className = 'ingredient-row';
@@ -247,6 +280,15 @@ function addIngredient(item) {
list.appendChild(row);
}
function addIngredientGroup(name) {
const list = document.getElementById('ingredientsList');
const row = document.createElement('div');
row.className = 'ingredient-group';
row.innerHTML = '<input type="text" class="ing-group-name" placeholder="Csoport neve" value="' + escHtml(name || '') + '">'
+ '<button onclick="this.parentElement.remove()">✕</button>';
list.appendChild(row);
}
function addInstruction(value) {
const list = document.getElementById('instructionsList');
const idx = list.children.length + 1;
@@ -271,13 +313,18 @@ function renumberInstructions() {
function gatherRecipe() {
const ingredients = [];
document.querySelectorAll('#ingredientsList .ingredient-row').forEach(row => {
const qty = row.querySelector('.ing-qty').value.trim();
const unit = row.querySelector('.ing-unit').value.trim();
const food = row.querySelector('.ing-food').value.trim();
const extra = row.querySelector('.ing-extra').value.trim();
if (food || qty) {
ingredients.push({ quantity: qty, unit: unit, food: food, extra: extra });
document.querySelectorAll('#ingredientsList > div').forEach(el => {
if (el.classList.contains('ingredient-group')) {
const name = el.querySelector('.ing-group-name').value.trim();
if (name) ingredients.push({ group: name });
} else if (el.classList.contains('ingredient-row')) {
const qty = el.querySelector('.ing-qty').value.trim();
const unit = el.querySelector('.ing-unit').value.trim();
const food = el.querySelector('.ing-food').value.trim();
const extra = el.querySelector('.ing-extra').value.trim();
if (food || qty) {
ingredients.push({ quantity: qty, unit: unit, food: food, extra: extra });
}
}
});