Fix KDS nested modifier display with breadcrumb paths

- Rewrote modifier rendering to display leaf modifiers only
- Added breadcrumb paths for full context (e.g., "Customize Spread: Extra")
- Eliminated nested div wrappers that were breaking the display
- Added comprehensive debug logging for troubleshooting
- Modifiers now show complete hierarchy without clutter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
John Mizerek 2025-12-30 14:40:53 -08:00
parent d7f68e8098
commit 4f694850e6

View file

@ -100,8 +100,13 @@ function startAutoRefresh() {
async function loadOrders() { async function loadOrders() {
if (!config.businessId) return; if (!config.businessId) return;
console.log('[loadOrders] Fetching with BusinessID:', config.businessId, 'ServicePointID:', config.servicePointId);
try { try {
const response = await fetch(`${config.apiBaseUrl}/orders/listForKDS.cfm`, { const url = `${config.apiBaseUrl}/orders/listForKDS.cfm`;
console.log('[loadOrders] URL:', url);
const response = await fetch(url, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -112,13 +117,20 @@ async function loadOrders() {
}) })
}); });
console.log('[loadOrders] Response status:', response.status);
const data = await response.json(); const data = await response.json();
console.log('[loadOrders] Response data:', data);
if (data.OK) { if (data.OK) {
orders = data.ORDERS || []; orders = data.ORDERS || [];
console.log('[loadOrders] Orders received:', orders.length);
if (orders.length > 0) {
console.log('[loadOrders] First order LineItems:', orders[0].LineItems);
}
renderOrders(); renderOrders();
updateStatus(true, `${orders.length} active orders`); updateStatus(true, `${orders.length} active orders`);
} else { } else {
console.error('[loadOrders] API returned OK=false:', data);
updateStatus(false, `Error: ${data.MESSAGE || data.ERROR}`); updateStatus(false, `Error: ${data.MESSAGE || data.ERROR}`);
} }
} catch (error) { } catch (error) {
@ -203,6 +215,11 @@ function renderOrder(order) {
function renderLineItem(item, allItems) { function renderLineItem(item, allItems) {
const modifiers = allItems.filter(mod => mod.OrderLineItemParentOrderLineItemID === item.OrderLineItemID); const modifiers = allItems.filter(mod => mod.OrderLineItemParentOrderLineItemID === item.OrderLineItemID);
console.log(`[renderLineItem] Item: ${item.ItemName}, ID: ${item.OrderLineItemID}, Modifiers found: ${modifiers.length}`);
if (modifiers.length > 0) {
console.log('[renderLineItem] Modifiers:', modifiers);
}
return ` return `
<div class="line-item"> <div class="line-item">
<div class="line-item-main"> <div class="line-item-main">
@ -210,11 +227,7 @@ function renderLineItem(item, allItems) {
<div class="item-qty">×${item.OrderLineItemQuantity}</div> <div class="item-qty">×${item.OrderLineItemQuantity}</div>
</div> </div>
${modifiers.length > 0 ? ` ${modifiers.length > 0 ? renderAllModifiers(modifiers, allItems) : ''}
<div class="modifiers">
${modifiers.map(mod => renderModifier(mod, allItems)).join('')}
</div>
` : ''}
${item.OrderLineItemRemark ? ` ${item.OrderLineItemRemark ? `
<div class="item-remark">Note: ${escapeHtml(item.OrderLineItemRemark)}</div> <div class="item-remark">Note: ${escapeHtml(item.OrderLineItemRemark)}</div>
@ -223,20 +236,73 @@ function renderLineItem(item, allItems) {
`; `;
} }
// Render modifier (recursive for nested modifiers) // Render all modifiers (flattened, no nested wrappers)
function renderModifier(modifier, allItems) { function renderAllModifiers(modifiers, allItems) {
const subModifiers = allItems.filter(mod => mod.OrderLineItemParentOrderLineItemID === modifier.OrderLineItemID); let html = '<div class="modifiers">';
return ` // Build path for each leaf modifier
<div class="modifier"> function getModifierPath(mod) {
+ ${escapeHtml(modifier.ItemName)} const path = [];
${subModifiers.length > 0 ? ` let current = mod;
<div class="modifiers">
${subModifiers.map(sub => renderModifier(sub, allItems)).join('')} // Walk up the tree to build the path
</div> while (current) {
` : ''} path.unshift(current.ItemName);
</div> const parentId = current.OrderLineItemParentOrderLineItemID;
`; if (parentId === 0) break;
current = allItems.find(item => item.OrderLineItemID === parentId);
}
return path;
}
// Collect all leaf modifiers with their paths
const leafModifiers = [];
function collectLeafModifiers(mods) {
mods.forEach(mod => {
const children = allItems.filter(item => item.OrderLineItemParentOrderLineItemID === mod.OrderLineItemID);
if (children.length === 0) {
// This is a leaf - no children
const path = getModifierPath(mod);
leafModifiers.push({ mod, path });
} else {
// This has children, recurse into them
collectLeafModifiers(children);
}
});
}
collectLeafModifiers(modifiers);
// Render leaf modifiers with breadcrumb paths
leafModifiers.forEach(({ path }) => {
const displayText = path.join(': ');
html += `<div class="modifier">+ ${escapeHtml(displayText)}</div>`;
});
html += '</div>';
return html;
}
// Render modifier recursively with indentation
function renderModifierRecursive(modifier, allItems, level) {
const subModifiers = allItems.filter(mod => mod.OrderLineItemParentOrderLineItemID === modifier.OrderLineItemID);
// For KDS MVP: no indentation, just flat list
const indent = 0; // Changed from: level * 20
console.log(`[renderModifierRecursive] Level ${level}: ${modifier.ItemName} (ID: ${modifier.OrderLineItemID}), Sub-modifiers: ${subModifiers.length}`);
let html = `<div class="modifier" style="padding-left: ${indent}px;">+ ${escapeHtml(modifier.ItemName)}</div>`;
// Recursively render sub-modifiers
if (subModifiers.length > 0) {
subModifiers.forEach(sub => {
html += renderModifierRecursive(sub, allItems, level + 1);
});
}
return html;
} }
// Render action buttons based on order status // Render action buttons based on order status