KDS: per-station line item filtering with expand toggle
Backend returns all line items for every order (removes station filter from sub-query). Frontend filters by station, showing only relevant items by default. An expand toggle reveals other stations' items dimmed at 35% opacity for full order context. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c65cd8242b
commit
94b5bbbce1
3 changed files with 77 additions and 56 deletions
|
|
@ -110,57 +110,28 @@
|
|||
<cfset orders = []>
|
||||
|
||||
<cfloop query="qOrders">
|
||||
<!--- Get line items for this order --->
|
||||
<!--- If filtering by station, only show items for that station (plus modifiers) --->
|
||||
<cfif StationID GT 0>
|
||||
<cfset qLineItems = queryTimed("
|
||||
SELECT
|
||||
oli.ID,
|
||||
oli.ParentOrderLineItemID,
|
||||
oli.ItemID,
|
||||
oli.Price,
|
||||
oli.Quantity,
|
||||
oli.Remark,
|
||||
oli.IsDeleted,
|
||||
i.Name,
|
||||
i.ParentItemID,
|
||||
i.IsCheckedByDefault,
|
||||
i.StationID,
|
||||
parent.Name AS ItemParentName
|
||||
FROM OrderLineItems oli
|
||||
INNER JOIN Items i ON i.ID = oli.ItemID
|
||||
LEFT JOIN Items parent ON parent.ID = i.ParentItemID
|
||||
WHERE oli.OrderID = ?
|
||||
AND oli.IsDeleted = b'0'
|
||||
AND (i.StationID = ? OR i.StationID = 0 OR i.StationID IS NULL OR oli.ParentOrderLineItemID > 0)
|
||||
ORDER BY oli.ID
|
||||
", [
|
||||
{ value = qOrders.ID, cfsqltype = "cf_sql_integer" },
|
||||
{ value = StationID, cfsqltype = "cf_sql_integer" }
|
||||
], { datasource = "payfrit" })>
|
||||
<cfelse>
|
||||
<cfset qLineItems = queryTimed("
|
||||
SELECT
|
||||
oli.ID,
|
||||
oli.ParentOrderLineItemID,
|
||||
oli.ItemID,
|
||||
oli.Price,
|
||||
oli.Quantity,
|
||||
oli.Remark,
|
||||
oli.IsDeleted,
|
||||
i.Name,
|
||||
i.ParentItemID,
|
||||
i.IsCheckedByDefault,
|
||||
i.StationID,
|
||||
parent.Name AS ItemParentName
|
||||
FROM OrderLineItems oli
|
||||
INNER JOIN Items i ON i.ID = oli.ItemID
|
||||
LEFT JOIN Items parent ON parent.ID = i.ParentItemID
|
||||
WHERE oli.OrderID = ?
|
||||
AND oli.IsDeleted = b'0'
|
||||
ORDER BY oli.ID
|
||||
", [ { value = qOrders.ID, cfsqltype = "cf_sql_integer" } ], { datasource = "payfrit" })>
|
||||
</cfif>
|
||||
<!--- Get all line items for this order (frontend handles station filtering) --->
|
||||
<cfset qLineItems = queryTimed("
|
||||
SELECT
|
||||
oli.ID,
|
||||
oli.ParentOrderLineItemID,
|
||||
oli.ItemID,
|
||||
oli.Price,
|
||||
oli.Quantity,
|
||||
oli.Remark,
|
||||
oli.IsDeleted,
|
||||
i.Name,
|
||||
i.ParentItemID,
|
||||
i.IsCheckedByDefault,
|
||||
i.StationID,
|
||||
parent.Name AS ItemParentName
|
||||
FROM OrderLineItems oli
|
||||
INNER JOIN Items i ON i.ID = oli.ItemID
|
||||
LEFT JOIN Items parent ON parent.ID = i.ParentItemID
|
||||
WHERE oli.OrderID = ?
|
||||
AND oli.IsDeleted = b'0'
|
||||
ORDER BY oli.ID
|
||||
", [ { value = qOrders.ID, cfsqltype = "cf_sql_integer" } ], { datasource = "payfrit" })>
|
||||
|
||||
<cfset lineItems = []>
|
||||
<cfloop query="qLineItems">
|
||||
|
|
|
|||
|
|
@ -79,6 +79,13 @@
|
|||
.station-btn.all-stations:hover { border-color: #3b82f6; background: #001a2a; }
|
||||
.station-btn svg { width: 24px; height: 24px; opacity: 0.5; }
|
||||
.station-name-display { font-size: 11px; color: #555; margin-left: 8px; text-transform: uppercase; letter-spacing: 1px; }
|
||||
|
||||
/* Expand toggle */
|
||||
.expand-toggle { background: none; border: 1px solid #333; color: #555; padding: 4px 10px; border-radius: 4px; font-size: 11px; cursor: pointer; margin-bottom: 10px; width: 100%; transition: all 0.2s; }
|
||||
.expand-toggle:hover { border-color: #555; color: #888; }
|
||||
|
||||
/* Other-station items (dimmed) */
|
||||
.line-item.other-station { opacity: 0.35; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -109,6 +116,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script src="kds.js?v=5"></script>
|
||||
<script src="kds.js?v=6"></script>
|
||||
</body>
|
||||
</html>
|
||||
51
kds/kds.js
51
kds/kds.js
|
|
@ -12,6 +12,7 @@ let config = {
|
|||
let orders = [];
|
||||
let stations = [];
|
||||
let refreshTimer = null;
|
||||
let expandedOrders = new Set();
|
||||
|
||||
// Status ID mapping
|
||||
const STATUS = { NEW: 1, PREPARING: 2, READY: 3, COMPLETED: 4 };
|
||||
|
|
@ -283,12 +284,52 @@ function renderOrders() {
|
|||
grid.innerHTML = orders.map(order => renderOrder(order)).join('');
|
||||
}
|
||||
|
||||
// Check if a root item belongs to the current station
|
||||
function isStationItem(item) {
|
||||
if (!config.stationId || config.stationId === 0) return true;
|
||||
const sid = parseInt(item.StationID) || 0;
|
||||
return sid === config.stationId || sid === 0;
|
||||
}
|
||||
|
||||
// Toggle expand/collapse for an order
|
||||
function toggleExpand(orderId) {
|
||||
if (expandedOrders.has(orderId)) {
|
||||
expandedOrders.delete(orderId);
|
||||
} else {
|
||||
expandedOrders.add(orderId);
|
||||
}
|
||||
renderOrders();
|
||||
}
|
||||
|
||||
// Render single order card
|
||||
function renderOrder(order) {
|
||||
const statusClass = getStatusClass(order.StatusID);
|
||||
const elapsedTime = getElapsedTime(order.SubmittedOn);
|
||||
const timeClass = getTimeClass(elapsedTime);
|
||||
const rootItems = order.LineItems.filter(item => item.ParentOrderLineItemID === 0);
|
||||
const allRootItems = order.LineItems.filter(item => item.ParentOrderLineItemID === 0);
|
||||
const isFiltering = config.stationId && config.stationId > 0;
|
||||
const isExpanded = expandedOrders.has(order.OrderID);
|
||||
|
||||
// Split into station items and other-station items
|
||||
const stationItems = isFiltering ? allRootItems.filter(i => isStationItem(i)) : allRootItems;
|
||||
const otherItems = isFiltering ? allRootItems.filter(i => !isStationItem(i)) : [];
|
||||
const hasOtherItems = otherItems.length > 0;
|
||||
|
||||
// Build expand toggle button
|
||||
let expandToggle = '';
|
||||
if (isFiltering && hasOtherItems) {
|
||||
if (isExpanded) {
|
||||
expandToggle = `<button class="expand-toggle" onclick="toggleExpand(${order.OrderID})">Hide ${otherItems.length} other item${otherItems.length > 1 ? 's' : ''}</button>`;
|
||||
} else {
|
||||
expandToggle = `<button class="expand-toggle" onclick="toggleExpand(${order.OrderID})">Show ${otherItems.length} other item${otherItems.length > 1 ? 's' : ''}</button>`;
|
||||
}
|
||||
}
|
||||
|
||||
// Render line items: station items always, other items only when expanded
|
||||
let lineItemsHtml = stationItems.map(item => renderLineItem(item, order.LineItems, false)).join('');
|
||||
if (isExpanded && hasOtherItems) {
|
||||
lineItemsHtml += otherItems.map(item => renderLineItem(item, order.LineItems, true)).join('');
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="order-card ${statusClass}">
|
||||
|
|
@ -309,8 +350,9 @@ function renderOrder(order) {
|
|||
${order.Remarks ? `<div class="order-remarks">Note: ${escapeHtml(order.Remarks)}</div>` : ''}
|
||||
|
||||
<div class="line-items">
|
||||
${rootItems.map(item => renderLineItem(item, order.LineItems)).join('')}
|
||||
${lineItemsHtml}
|
||||
</div>
|
||||
${expandToggle}
|
||||
|
||||
<div class="action-buttons">
|
||||
${renderActionButtons(order)}
|
||||
|
|
@ -320,11 +362,12 @@ function renderOrder(order) {
|
|||
}
|
||||
|
||||
// Render line item with modifiers
|
||||
function renderLineItem(item, allItems) {
|
||||
function renderLineItem(item, allItems, isOtherStation = false) {
|
||||
const modifiers = allItems.filter(mod => mod.ParentOrderLineItemID === item.OrderLineItemID);
|
||||
console.log(`Item: ${item.Name} (ID: ${item.OrderLineItemID}) has ${modifiers.length} direct modifiers:`, modifiers.map(m => m.Name));
|
||||
const otherClass = isOtherStation ? ' other-station' : '';
|
||||
return `
|
||||
<div class="line-item">
|
||||
<div class="line-item${otherClass}">
|
||||
<div class="line-item-main">
|
||||
<div class="item-name">${escapeHtml(item.Name)}</div>
|
||||
<div class="item-qty">x${item.Quantity}</div>
|
||||
|
|
|
|||
Reference in a new issue