Add Show Modifiers toggle to menu builder outline view
Adds button in the outline modal to toggle modifier group display under each item. Each group shows a + to expand into full options with prices. Useful for debugging modifier assignments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9000fc91fe
commit
2d3634693b
1 changed files with 90 additions and 27 deletions
|
|
@ -3391,15 +3391,14 @@
|
|||
// Show outline modal - full menu in hierarchical text format
|
||||
showOutlineModal() {
|
||||
document.getElementById('modalTitle').textContent = 'Menu Outline';
|
||||
this._outlineShowMods = false;
|
||||
|
||||
let outline = '';
|
||||
const categories = this.menu.categories || [];
|
||||
|
||||
if (categories.length === 0) {
|
||||
outline = '<div style="color: var(--gray-500); text-align: center; padding: 40px;">No menu items yet</div>';
|
||||
} else {
|
||||
outline = '<div class="menu-outline">';
|
||||
const buildOutline = () => {
|
||||
const categories = this.menu.categories || [];
|
||||
if (categories.length === 0)
|
||||
return '<div style="color: var(--gray-500); text-align: center; padding: 40px;">No menu items yet</div>';
|
||||
|
||||
let outline = '<div class="menu-outline">';
|
||||
const topLevel = categories.filter(c => !c.parentCategoryId || c.parentCategoryId === 0);
|
||||
const getSubcats = (parent) => categories.filter(c =>
|
||||
c.parentCategoryId === parent.id || (parent.dbId && c.parentCategoryDbId === parent.dbId)
|
||||
|
|
@ -3410,7 +3409,9 @@
|
|||
for (const item of (items || [])) {
|
||||
const itemPrice = item.price ? `$${parseFloat(item.price).toFixed(2)}` : '';
|
||||
html += `<div class="outline-item" style="padding-left: ${indentLevel * 20}px;">${this.escapeHtml(item.name)}${itemPrice ? ' <span class="outline-price">' + itemPrice + '</span>' : ''}</div>`;
|
||||
html += this.renderOutlineModifiers(item.modifiers || [], indentLevel + 1);
|
||||
if (this._outlineShowMods) {
|
||||
html += this.renderOutlineModifierGroups(item.modifiers || [], indentLevel + 1);
|
||||
}
|
||||
}
|
||||
return html;
|
||||
};
|
||||
|
|
@ -3418,24 +3419,37 @@
|
|||
for (const cat of topLevel) {
|
||||
outline += `<div class="outline-category">${this.escapeHtml(cat.name)}</div>`;
|
||||
outline += renderOutlineItems(cat.items, 1);
|
||||
|
||||
const subcats = getSubcats(cat);
|
||||
for (const subcat of subcats) {
|
||||
outline += `<div class="outline-subcategory">${this.escapeHtml(subcat.name)}</div>`;
|
||||
outline += renderOutlineItems(subcat.items, 2);
|
||||
}
|
||||
}
|
||||
|
||||
outline += '</div>';
|
||||
}
|
||||
return outline;
|
||||
};
|
||||
|
||||
document.getElementById('modalBody').innerHTML = `
|
||||
<style>
|
||||
const render = () => {
|
||||
const btnLabel = this._outlineShowMods ? 'Hide Modifiers' : 'Show Modifiers';
|
||||
document.getElementById('modalBody').innerHTML = `
|
||||
<div style="margin-bottom: 12px;">
|
||||
<button class="outline-mods-btn" onclick="MenuBuilder.toggleOutlineMods()">${btnLabel}</button>
|
||||
</div>
|
||||
${buildOutline()}
|
||||
`;
|
||||
};
|
||||
|
||||
// Inject styles once
|
||||
document.getElementById('modalBody').innerHTML = '';
|
||||
if (!document.getElementById('outlineStyles')) {
|
||||
const style = document.createElement('style');
|
||||
style.id = 'outlineStyles';
|
||||
style.textContent = `
|
||||
.menu-outline {
|
||||
font-family: monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
max-height: 60vh;
|
||||
max-height: 55vh;
|
||||
overflow-y: auto;
|
||||
padding: 16px;
|
||||
background: var(--bg-secondary);
|
||||
|
|
@ -3449,9 +3463,7 @@
|
|||
margin-bottom: 4px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.outline-category:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
.outline-category:first-child { margin-top: 0; }
|
||||
.outline-subcategory {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
|
|
@ -3464,21 +3476,72 @@
|
|||
padding-left: 20px;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
.outline-modifier {
|
||||
.outline-modifier { color: var(--text-muted); }
|
||||
.outline-price { color: var(--success); }
|
||||
.outline-modifier .outline-price { color: var(--warning); }
|
||||
.outline-mods-btn {
|
||||
padding: 6px 14px;
|
||||
font-size: 13px;
|
||||
border: 1px solid var(--border-color, #ccc);
|
||||
border-radius: 6px;
|
||||
background: var(--bg-primary, #fff);
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
}
|
||||
.outline-mods-btn:hover { background: var(--bg-secondary, #f5f5f5); }
|
||||
.outline-mod-group {
|
||||
padding-left: 20px;
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
.outline-price {
|
||||
color: var(--success);
|
||||
}
|
||||
.outline-modifier .outline-price {
|
||||
color: var(--warning);
|
||||
}
|
||||
</style>
|
||||
${outline}
|
||||
`;
|
||||
.outline-mod-group:hover { color: var(--text-secondary); }
|
||||
.outline-mod-expand { display: inline-block; width: 14px; font-size: 11px; color: var(--text-muted); }
|
||||
.outline-mod-opts { display: none; }
|
||||
.outline-mod-opts.open { display: block; }
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
this._outlineRender = render;
|
||||
render();
|
||||
this.showModal();
|
||||
},
|
||||
|
||||
toggleOutlineMods() {
|
||||
this._outlineShowMods = !this._outlineShowMods;
|
||||
if (this._outlineRender) this._outlineRender();
|
||||
},
|
||||
|
||||
// Render first-level modifier groups with expandable options
|
||||
renderOutlineModifierGroups(modifiers, depth) {
|
||||
if (!modifiers || modifiers.length === 0) return '';
|
||||
let html = '';
|
||||
const pad = depth * 20;
|
||||
for (let i = 0; i < modifiers.length; i++) {
|
||||
const mod = modifiers[i];
|
||||
const modPrice = mod.price ? `+$${parseFloat(mod.price).toFixed(2)}` : '';
|
||||
const opts = mod.options || [];
|
||||
const uid = 'om_' + Math.random().toString(36).substring(2, 8);
|
||||
const countLabel = opts.length ? ` (${opts.length})` : '';
|
||||
|
||||
if (opts.length > 0) {
|
||||
html += `<div class="outline-mod-group" style="padding-left: ${pad}px;" onclick="var el=document.getElementById('${uid}');el.classList.toggle('open');this.querySelector('.outline-mod-expand').textContent=el.classList.contains('open')?'−':'+'">`;
|
||||
html += `<span class="outline-mod-expand">+</span> ${this.escapeHtml(mod.name)}${modPrice ? ' <span class="outline-price">' + modPrice + '</span>' : ''}${countLabel}`;
|
||||
html += `</div>`;
|
||||
html += `<div id="${uid}" class="outline-mod-opts">`;
|
||||
for (const opt of opts) {
|
||||
const optPrice = opt.price ? `+$${parseFloat(opt.price).toFixed(2)}` : '';
|
||||
html += `<div class="outline-modifier" style="padding-left: ${(depth + 1) * 20}px;">${this.escapeHtml(opt.name)}${optPrice ? ' <span class="outline-price">' + optPrice + '</span>' : ''}</div>`;
|
||||
}
|
||||
html += `</div>`;
|
||||
} else {
|
||||
html += `<div class="outline-modifier" style="padding-left: ${pad}px;">${this.escapeHtml(mod.name)}${modPrice ? ' <span class="outline-price">' + modPrice + '</span>' : ''}</div>`;
|
||||
}
|
||||
}
|
||||
return html;
|
||||
},
|
||||
|
||||
// Helper to render modifiers recursively for outline
|
||||
renderOutlineModifiers(modifiers, depth) {
|
||||
if (!modifiers || modifiers.length === 0) return '';
|
||||
|
|
|
|||
Reference in a new issue