From 4f694850e6d54164de90ea48bc7550282a0d992e Mon Sep 17 00:00:00 2001 From: John Mizerek Date: Tue, 30 Dec 2025 14:40:53 -0800 Subject: [PATCH] Fix KDS nested modifier display with breadcrumb paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- kds/kds.js | 104 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 19 deletions(-) diff --git a/kds/kds.js b/kds/kds.js index 7a046d4..f0d1528 100644 --- a/kds/kds.js +++ b/kds/kds.js @@ -100,8 +100,13 @@ function startAutoRefresh() { async function loadOrders() { if (!config.businessId) return; + console.log('[loadOrders] Fetching with BusinessID:', config.businessId, 'ServicePointID:', config.servicePointId); + 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', headers: { 'Content-Type': 'application/json', @@ -112,13 +117,20 @@ async function loadOrders() { }) }); + console.log('[loadOrders] Response status:', response.status); const data = await response.json(); + console.log('[loadOrders] Response data:', data); if (data.OK) { orders = data.ORDERS || []; + console.log('[loadOrders] Orders received:', orders.length); + if (orders.length > 0) { + console.log('[loadOrders] First order LineItems:', orders[0].LineItems); + } renderOrders(); updateStatus(true, `${orders.length} active orders`); } else { + console.error('[loadOrders] API returned OK=false:', data); updateStatus(false, `Error: ${data.MESSAGE || data.ERROR}`); } } catch (error) { @@ -203,6 +215,11 @@ function renderOrder(order) { function renderLineItem(item, allItems) { 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 `
@@ -210,11 +227,7 @@ function renderLineItem(item, allItems) {
×${item.OrderLineItemQuantity}
- ${modifiers.length > 0 ? ` -
- ${modifiers.map(mod => renderModifier(mod, allItems)).join('')} -
- ` : ''} + ${modifiers.length > 0 ? renderAllModifiers(modifiers, allItems) : ''} ${item.OrderLineItemRemark ? `
Note: ${escapeHtml(item.OrderLineItemRemark)}
@@ -223,20 +236,73 @@ function renderLineItem(item, allItems) { `; } -// Render modifier (recursive for nested modifiers) -function renderModifier(modifier, allItems) { - const subModifiers = allItems.filter(mod => mod.OrderLineItemParentOrderLineItemID === modifier.OrderLineItemID); +// Render all modifiers (flattened, no nested wrappers) +function renderAllModifiers(modifiers, allItems) { + let html = '
'; - return ` -
- + ${escapeHtml(modifier.ItemName)} - ${subModifiers.length > 0 ? ` -
- ${subModifiers.map(sub => renderModifier(sub, allItems)).join('')} -
- ` : ''} -
- `; + // Build path for each leaf modifier + function getModifierPath(mod) { + const path = []; + let current = mod; + + // Walk up the tree to build the path + while (current) { + path.unshift(current.ItemName); + 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 += `
+ ${escapeHtml(displayText)}
`; + }); + + html += '
'; + 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 = `
+ ${escapeHtml(modifier.ItemName)}
`; + + // 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