diff --git a/portal/menu-builder.html b/portal/menu-builder.html index 329907d..6ff6a4e 100644 --- a/portal/menu-builder.html +++ b/portal/menu-builder.html @@ -2122,6 +2122,209 @@ } }, + // Find modifier/option and its parent array + findModifierWithParent(modifierId) { + for (const cat of this.menu.categories) { + for (const item of cat.items) { + // Check if it's a top-level modifier + const idx = item.modifiers.findIndex(m => m.id === modifierId); + if (idx !== -1) { + return { array: item.modifiers, index: idx, parentId: item.id, isItem: true }; + } + // Check nested + const nested = this.findNestedModifierWithParent(item.modifiers, modifierId); + if (nested) return nested; + } + } + return null; + }, + + findNestedModifierWithParent(modifiers, modifierId) { + for (const mod of modifiers) { + if (mod.options && mod.options.length > 0) { + const idx = mod.options.findIndex(o => o.id === modifierId); + if (idx !== -1) { + return { array: mod.options, index: idx, parentId: mod.id, isItem: false }; + } + const nested = this.findNestedModifierWithParent(mod.options, modifierId); + if (nested) return nested; + } + } + return null; + }, + + // Get the parent array for a parentId (item or modifier) + getParentModifiersArray(parentId) { + for (const cat of this.menu.categories) { + for (const item of cat.items) { + if (item.id === parentId) { + return item.modifiers; + } + const found = this.findOptionRecursive(item.modifiers, parentId); + if (found) { + if (!found.options) found.options = []; + return found.options; + } + } + } + return null; + }, + + // Deep clone a modifier with new IDs + cloneModifierDeep(mod) { + const clone = JSON.parse(JSON.stringify(mod)); + clone.id = this.generateId(); + clone.dbId = null; // Will get new dbId on save + if (clone.options && clone.options.length > 0) { + clone.options = clone.options.map(opt => this.cloneModifierDeep(opt)); + } + return clone; + }, + + // Reorder modifier within same parent + reorderModifier(draggedId, targetId, parentId, position) { + this.saveState(); + const parentArray = this.getParentModifiersArray(parentId); + if (!parentArray) return; + + const draggedIdx = parentArray.findIndex(m => m.id === draggedId); + const targetIdx = parentArray.findIndex(m => m.id === targetId); + if (draggedIdx === -1 || targetIdx === -1) return; + + // Remove dragged + const [dragged] = parentArray.splice(draggedIdx, 1); + + // Find new target index (may have shifted) + let newTargetIdx = parentArray.findIndex(m => m.id === targetId); + if (position === 'after') newTargetIdx++; + + // Insert at new position + parentArray.splice(newTargetIdx, 0, dragged); + + // Update sort orders + parentArray.forEach((m, i) => m.sortOrder = i); + + this.render(); + this.toast('Modifier reordered', 'success'); + }, + + // Move modifier from one parent to another + moveModifier(draggedId, fromParentId, targetModId, toParentId, position) { + this.saveState(); + const fromArray = this.getParentModifiersArray(fromParentId); + const toArray = this.getParentModifiersArray(toParentId); + if (!fromArray || !toArray) return; + + const draggedIdx = fromArray.findIndex(m => m.id === draggedId); + if (draggedIdx === -1) return; + + // Remove from source + const [dragged] = fromArray.splice(draggedIdx, 1); + + // Find target position in destination + const targetIdx = toArray.findIndex(m => m.id === targetModId); + let insertIdx = targetIdx === -1 ? toArray.length : targetIdx; + if (position === 'after') insertIdx++; + + // Insert at new position + toArray.splice(insertIdx, 0, dragged); + + // Update sort orders in both arrays + fromArray.forEach((m, i) => m.sortOrder = i); + toArray.forEach((m, i) => m.sortOrder = i); + + this.render(); + this.toast('Modifier moved', 'success'); + }, + + // Copy modifier to position relative to another modifier + copyModifier(draggedId, fromParentId, targetModId, toParentId, position) { + this.saveState(); + const fromArray = this.getParentModifiersArray(fromParentId); + const toArray = this.getParentModifiersArray(toParentId); + if (!fromArray || !toArray) return; + + const dragged = fromArray.find(m => m.id === draggedId); + if (!dragged) return; + + // Clone with new IDs + const clone = this.cloneModifierDeep(dragged); + + // Find target position + const targetIdx = toArray.findIndex(m => m.id === targetModId); + let insertIdx = targetIdx === -1 ? toArray.length : targetIdx; + if (position === 'after') insertIdx++; + + // Insert clone + toArray.splice(insertIdx, 0, clone); + + // Update sort orders + toArray.forEach((m, i) => m.sortOrder = i); + + this.render(); + this.toast('Modifier copied', 'success'); + }, + + // Move modifier to an item (as top-level modifier) + moveModifierToItem(draggedId, fromParentId, toItemId) { + this.saveState(); + const fromArray = this.getParentModifiersArray(fromParentId); + if (!fromArray) return; + + // Find target item + let targetItem = null; + for (const cat of this.menu.categories) { + targetItem = cat.items.find(i => i.id === toItemId); + if (targetItem) break; + } + if (!targetItem) return; + + const draggedIdx = fromArray.findIndex(m => m.id === draggedId); + if (draggedIdx === -1) return; + + // Remove from source + const [dragged] = fromArray.splice(draggedIdx, 1); + + // Add to target item's modifiers + dragged.sortOrder = targetItem.modifiers.length; + targetItem.modifiers.push(dragged); + + // Update sort orders + fromArray.forEach((m, i) => m.sortOrder = i); + + this.render(); + this.toast('Modifier moved to item', 'success'); + }, + + // Copy modifier to an item (as top-level modifier) + copyModifierToItem(draggedId, fromParentId, toItemId) { + this.saveState(); + const fromArray = this.getParentModifiersArray(fromParentId); + if (!fromArray) return; + + // Find target item + let targetItem = null; + for (const cat of this.menu.categories) { + targetItem = cat.items.find(i => i.id === toItemId); + if (targetItem) break; + } + if (!targetItem) return; + + const dragged = fromArray.find(m => m.id === draggedId); + if (!dragged) return; + + // Clone with new IDs + const clone = this.cloneModifierDeep(dragged); + clone.sortOrder = targetItem.modifiers.length; + + // Add to target item + targetItem.modifiers.push(clone); + + this.render(); + this.toast('Modifier copied to item', 'success'); + }, + + // Update category // Update category updateCategory(categoryId, field, value) { this.saveState(); @@ -2756,7 +2959,9 @@ const hasOptions = mod.options && mod.options.length > 0; const modExpanded = this.expandedModifierIds.has(mod.id); return ` -
${hasOptions ? ` @@ -2765,11 +2970,14 @@
- ` : ` -