feat: add order quantity popup for item ordering in dashboard
This commit is contained in:
@@ -41,6 +41,9 @@ local selectedAmount = 1
|
|||||||
local amountOptions = {1, 4, 8, 16, 32, 64}
|
local amountOptions = {1, 4, 8, 16, 32, 64}
|
||||||
local searchQuery = ""
|
local searchQuery = ""
|
||||||
local showKeyboard = false
|
local showKeyboard = false
|
||||||
|
local orderPopupItem = nil
|
||||||
|
local orderPopupShort = nil
|
||||||
|
local orderPopupQty = 1
|
||||||
local smelterView = "status"
|
local smelterView = "status"
|
||||||
|
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
@@ -473,6 +476,117 @@ local function buildMainPage()
|
|||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
-- Order quantity popup (full-screen overlay; starts disabled)
|
||||||
|
orderPopup = UI.Window {
|
||||||
|
x = 1, y = 1, ex = -1, ey = -1,
|
||||||
|
backgroundColor = colors.black,
|
||||||
|
enable = function() end, -- toggled manually
|
||||||
|
draw = function(self)
|
||||||
|
self:clear(colors.black)
|
||||||
|
self._zones = {}
|
||||||
|
|
||||||
|
local dw = math.min(self.width - 2, 30)
|
||||||
|
local dh = 8
|
||||||
|
local dx = math.floor((self.width - dw) / 2) + 1
|
||||||
|
local dy = math.floor((self.height - dh) / 2) + 1
|
||||||
|
|
||||||
|
-- Title row (blue background)
|
||||||
|
local title = "Order: " .. (orderPopupShort or "?")
|
||||||
|
if #title > dw - 2 then title = title:sub(1, dw - 2) end
|
||||||
|
self:write(dx, dy, string.rep(" ", dw), colors.blue)
|
||||||
|
local titleX = dx + math.floor((dw - #title) / 2)
|
||||||
|
self:write(titleX, dy, title, colors.blue, colors.white)
|
||||||
|
|
||||||
|
-- Dialog body rows (gray background)
|
||||||
|
for row = 1, dh - 1 do
|
||||||
|
self:write(dx, dy + row, string.rep(" ", dw), colors.gray)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Quantity display (row 2)
|
||||||
|
local qtyStr = string.format("Quantity: %d", orderPopupQty)
|
||||||
|
local qtyX = dx + math.floor((dw - #qtyStr) / 2)
|
||||||
|
self:write(qtyX, dy + 2, qtyStr, colors.gray, colors.white)
|
||||||
|
|
||||||
|
-- Increment buttons (row 4): [-8] [-1] [+1] [+8]
|
||||||
|
local incBtns = {
|
||||||
|
{ label = " -8 ", delta = -8, bg = colors.red },
|
||||||
|
{ label = " -1 ", delta = -1, bg = colors.red },
|
||||||
|
{ label = " +1 ", delta = 1, bg = colors.green },
|
||||||
|
{ label = " +8 ", delta = 8, bg = colors.green },
|
||||||
|
}
|
||||||
|
local totalIncW = 0
|
||||||
|
for _, b in ipairs(incBtns) do totalIncW = totalIncW + #b.label end
|
||||||
|
totalIncW = totalIncW + (#incBtns - 1) * 2
|
||||||
|
local incX = dx + math.floor((dw - totalIncW) / 2)
|
||||||
|
local incRow = dy + 4
|
||||||
|
for _, b in ipairs(incBtns) do
|
||||||
|
self:write(incX, incRow, b.label, b.bg, colors.white)
|
||||||
|
table.insert(self._zones, {
|
||||||
|
x1 = incX, y1 = incRow,
|
||||||
|
x2 = incX + #b.label - 1, y2 = incRow,
|
||||||
|
action = "order_delta", data = b.delta,
|
||||||
|
})
|
||||||
|
incX = incX + #b.label + 2
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Preset buttons (row 5): [1] [4] [8] [16] [32] [64]
|
||||||
|
local presets = {1, 4, 8, 16, 32, 64}
|
||||||
|
local totalPreW = 0
|
||||||
|
for _, p in ipairs(presets) do totalPreW = totalPreW + #tostring(p) + 2 end
|
||||||
|
totalPreW = totalPreW + (#presets - 1)
|
||||||
|
local preX = dx + math.floor((dw - totalPreW) / 2)
|
||||||
|
local preRow = dy + 5
|
||||||
|
for _, p in ipairs(presets) do
|
||||||
|
local label = " " .. tostring(p) .. " "
|
||||||
|
local bg = (p == orderPopupQty) and colors.cyan or colors.lightGray
|
||||||
|
local fg = (p == orderPopupQty) and colors.white or colors.black
|
||||||
|
self:write(preX, preRow, label, bg, fg)
|
||||||
|
table.insert(self._zones, {
|
||||||
|
x1 = preX, y1 = preRow,
|
||||||
|
x2 = preX + #label - 1, y2 = preRow,
|
||||||
|
action = "order_set", data = p,
|
||||||
|
})
|
||||||
|
preX = preX + #label + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Action buttons (row 7): [Cancel] [Order]
|
||||||
|
local cancelLabel = " Cancel "
|
||||||
|
local orderLabel = " Order "
|
||||||
|
local actRow = dy + 7
|
||||||
|
local cancelX = dx + math.floor(dw / 4) - math.floor(#cancelLabel / 2)
|
||||||
|
local orderX = dx + math.floor(3 * dw / 4) - math.floor(#orderLabel / 2)
|
||||||
|
self:write(cancelX, actRow, cancelLabel, colors.red, colors.white)
|
||||||
|
table.insert(self._zones, {
|
||||||
|
x1 = cancelX, y1 = actRow,
|
||||||
|
x2 = cancelX + #cancelLabel - 1, y2 = actRow,
|
||||||
|
action = "order_cancel",
|
||||||
|
})
|
||||||
|
self:write(orderX, actRow, orderLabel, colors.lime, colors.white)
|
||||||
|
table.insert(self._zones, {
|
||||||
|
x1 = orderX, y1 = actRow,
|
||||||
|
x2 = orderX + #orderLabel - 1, y2 = actRow,
|
||||||
|
action = "order_confirm",
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
eventHandler = function(self, event)
|
||||||
|
if event.type == 'mouse_click' then
|
||||||
|
if self._zones then
|
||||||
|
for _, zone in ipairs(self._zones) do
|
||||||
|
if event.x >= zone.x1 and event.x <= zone.x2
|
||||||
|
and event.y >= zone.y1 and event.y <= zone.y2 then
|
||||||
|
self:emit({ type = zone.action, data = zone.data, element = self })
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Click outside dialog dismisses popup
|
||||||
|
self:emit({ type = 'order_cancel', element = self })
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return UI.Window.eventHandler(self, event)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
-- Notification overlay
|
-- Notification overlay
|
||||||
notification = UI.Notification {
|
notification = UI.Notification {
|
||||||
anchor = 'bottom',
|
anchor = 'bottom',
|
||||||
@@ -504,7 +618,7 @@ local function buildMainPage()
|
|||||||
searchQuery = searchQuery .. " "
|
searchQuery = searchQuery .. " "
|
||||||
end
|
end
|
||||||
D.refreshItemGrid()
|
D.refreshItemGrid()
|
||||||
self.searchRow:draw()
|
selfitem.total
|
||||||
self.footerBar:draw()
|
self.footerBar:draw()
|
||||||
self:sync()
|
self:sync()
|
||||||
return true
|
return true
|
||||||
@@ -534,14 +648,55 @@ local function buildMainPage()
|
|||||||
elseif event.type == 'grid_select' then
|
elseif event.type == 'grid_select' then
|
||||||
local row = event.selected
|
local row = event.selected
|
||||||
if row and row.name then
|
if row and row.name then
|
||||||
local short = shortName(row.name)
|
-- Hide keyboard if showing
|
||||||
state.statusMessage = string.format("Ordering %s x%d...", short, selectedAmount)
|
if showKeyboard then
|
||||||
|
showKeyboard = false
|
||||||
|
self.keyboard:disable()
|
||||||
|
end
|
||||||
|
-- Show order popup
|
||||||
|
orderPopupItem = row.name
|
||||||
|
orderPopupShort = shortName(row.name)
|
||||||
|
orderPopupQty = selectedAmount
|
||||||
|
UI.Window.enable(self.orderPopup)
|
||||||
|
self.orderPopup:raise()
|
||||||
|
self.orderPopup:draw()
|
||||||
|
self:sync()
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
|
||||||
|
elseif event.type == 'order_delta' then
|
||||||
|
orderPopupQty = math.max(1, math.min(999, orderPopupQty + event.data))
|
||||||
|
self.orderPopup:draw()
|
||||||
|
self:sync()
|
||||||
|
return true
|
||||||
|
|
||||||
|
elseif event.type == 'order_set' then
|
||||||
|
orderPopupQty = event.data
|
||||||
|
self.orderPopup:draw()
|
||||||
|
self:sync()
|
||||||
|
return true
|
||||||
|
|
||||||
|
elseif event.type == 'order_confirm' then
|
||||||
|
if orderPopupItem then
|
||||||
|
local short = shortName(orderPopupItem)
|
||||||
|
state.statusMessage = string.format("Ordering %s x%d...", short, orderPopupQty)
|
||||||
state.statusColor = colors.cyan
|
state.statusColor = colors.cyan
|
||||||
state.statusTimer = 10
|
state.statusTimer = 10
|
||||||
activity.dispensing = true
|
activity.dispensing = true
|
||||||
state.needsRedraw = true
|
state.needsRedraw = true
|
||||||
ops.orderItem(row.name, selectedAmount)
|
ops.orderItem(orderPopupItem, orderPopupQty)
|
||||||
end
|
end
|
||||||
|
self.orderPopup:disable()
|
||||||
|
orderPopupItem = nil
|
||||||
|
self:draw()
|
||||||
|
self:sync()
|
||||||
|
return true
|
||||||
|
|
||||||
|
elseif event.type == 'order_cancel' then
|
||||||
|
self.orderPopup:disable()
|
||||||
|
orderPopupItem = nil
|
||||||
|
self:draw()
|
||||||
|
self:sync()
|
||||||
return true
|
return true
|
||||||
|
|
||||||
elseif event.type == 'amount_select' then
|
elseif event.type == 'amount_select' then
|
||||||
|
|||||||
Reference in New Issue
Block a user