diff --git a/ticketmachine.lua b/ticketmachine.lua index fff32ef..3c28274 100644 --- a/ticketmachine.lua +++ b/ticketmachine.lua @@ -1440,8 +1440,8 @@ local function showHome() local cx = math.floor((w - btnW) / 2) + 1 addButton(cx, y-4, 'NEW', btnW, btnH, {colors.green, colors.white}, function() resetTicketFlow() - stopAudio(); playAudioFile('Audio/welcome.wav'); waitAudioComplete() - state.page = 'departure' + stopAudio() + state.page = 'new_menu' end) addButton(cx, y, 'SINGLE', btnW, btnH, {colors.blue, colors.white}, function() resetTicketFlow() @@ -1452,34 +1452,48 @@ local function showHome() resetCardFlow('open') stopAudio(); state.page = 'card_home' end) - addButton(cx, y+8, 'ONLINE', btnW, btnH, {colors.cyan, colors.white}, function() - resetTicketFlow() - stopAudio(); state.page = 'online' - end) else local cx = math.floor((w - btnW) / 2) + 1 addButton(x1, y-2, 'NEW', btnW, btnH, {colors.green, colors.white}, function() resetTicketFlow() - stopAudio(); playAudioFile('Audio/welcome.wav'); waitAudioComplete() - state.page = 'departure' + stopAudio() + state.page = 'new_menu' end) addButton(x2, y-2, 'SINGLE', btnW, btnH, {colors.blue, colors.white}, function() resetTicketFlow() stopAudio(); playAudioFile('Audio/welcome.wav'); waitAudioComplete() state.page = 'single_segment' end) - addButton(x1, y+2, 'CARD', btnW, btnH, {colors.orange, colors.white}, function() + addButton(cx, y+2, 'CARD', btnW, btnH, {colors.orange, colors.white}, function() resetCardFlow('open') stopAudio(); state.page = 'card_home' end) - addButton(x2, y+2, 'ONLINE', btnW, btnH, {colors.cyan, colors.white}, function() - resetTicketFlow() - stopAudio(); state.page = 'online' - end) end waitButtons() end +local function showNewMenu() + while state.page == 'new_menu' do + drawHeader('Ticket Service', 'Buy ticket or redeem voucher') + Buttons = {} + local btnW, btnH = 16, 3 + local cx = math.floor((w - btnW) / 2) + 1 + local y = math.floor(h / 2) - 3 + addButton(cx, y, 'BUY TICKET', btnW, btnH, {colors.green, colors.white}, function() + resetTicketFlow() + stopAudio(); playAudioFile('Audio/welcome.wav'); waitAudioComplete() + state.page = 'departure' + end) + addButton(cx, y + 4, 'REDEEM CODE', btnW, btnH, {colors.cyan, colors.white}, function() + resetTicketFlow() + stopAudio() + state.page = 'online' + end) + addButton(2, h-3, '<-back', 8, 3, {colors.black, colors.red}, function() state.page = 'home' end) + waitButtons() + end +end + local function showCardHome() while state.page == 'card_home' do drawHeader('IC Card Service', 'Open card or redeem online order') @@ -1643,9 +1657,24 @@ local function showCardOnlineRedeem() {'Z','X','C','V','B','N','M'} } + local function clearLine(y) + termDev.setBackgroundColor(colors.black) + termDev.setCursorPos(1, y) + termDev.write(string.rep(' ', w)) + end + + local function renderInput() + local placeholder = code .. string.rep('_', math.max(0, 5-#code)) + clearLine(4) + clearLine(5) + centerText(4, '[' .. placeholder .. ']', colors.yellow) + if msg and #msg > 0 then centerText(5, msg, msgCol) end + end + local function submitCode() if #code ~= 5 then msg, msgCol = 'Need 5 chars', colors.red + renderInput() return end local res = fetchJSON(API_BASE .. '/public/ic-cards/orders/' .. code) @@ -1654,17 +1683,20 @@ local function showCardOnlineRedeem() end if not (res and res.ok) then msg, msgCol = 'Voucher Invalid', colors.red + renderInput() return end local d = res.data or res local cardStatus = tostring(d.status or ''):lower() if d.consumed or (cardStatus ~= '' and cardStatus ~= 'pending_pickup' and isCardOrderLike(d)) then msg, msgCol = 'Already Used!', colors.red + renderInput() return end local cardOrder = buildCardOrderState(d, code) if not cardOrder then msg, msgCol = 'Not a card order', colors.red + renderInput() return end resetCardFlow('redeem') @@ -1682,10 +1714,7 @@ local function showCardOnlineRedeem() end while state.page == 'card_online' do - local placeholder = code .. string.rep('_', math.max(0, 5-#code)) drawHeader('Redeem IC Card', 'Type 5 chars then OK') - centerText(4, '[' .. placeholder .. ']', colors.yellow) - if msg and #msg > 0 then centerText(5, msg, msgCol) end Buttons = {} local keyW, keyH = (w < 44 and 2 or 3), 2 local kbW = 10 * (keyW + 1) @@ -1694,26 +1723,46 @@ local function showCardOnlineRedeem() local y, x = sY + (rIdx-1) * (keyH + 1), sX + (rIdx-1) for _, ch in ipairs(row) do addButton(x, y, ch, keyW, keyH, {colors.black, colors.white}, function() - if #code < 5 then code = code .. ch end + if #code < 5 then + code = code .. ch + msg = '' + renderInput() + end end) x = x + keyW + 1 end end addButton(2, h-3, '<-back', 8, 3, {colors.black, colors.red}, function() state.page = 'card_home' end) - addButton(w-31, h-3, 'BKSP', 8, 3, {colors.black, colors.red}, function() code = code:sub(1, -2) end) - addButton(w-21, h-3, 'CLEAR', 8, 3, {colors.black, colors.red}, function() code = '' end) - addButton(w-11, h-3, 'OK', 10, 3, {colors.black, colors.green}, submitCode) - local ev, p1, p2, p3 = os.pullEvent() - if ev == 'mouse_click' or ev == 'monitor_touch' then - for _, b in ipairs(Buttons) do - if inRect(b, p2, p3) then clickSound(); if b.onClick then b.onClick() end; break end - end - elseif ev == 'char' and #code < 5 then - code = code .. tostring(p1 or ''):upper() - elseif ev == 'key' and p1 == keys.backspace then + addButton(w-31, h-3, 'BKSP', 8, 3, {colors.black, colors.red}, function() code = code:sub(1, -2) - elseif ev == 'key' and (p1 == keys.enter or p1 == keys.numPadEnter) then - submitCode() + msg = '' + renderInput() + end) + addButton(w-21, h-3, 'CLEAR', 8, 3, {colors.black, colors.red}, function() + code = '' + msg = '' + renderInput() + end) + addButton(w-11, h-3, 'OK', 10, 3, {colors.black, colors.green}, submitCode) + renderInput() + while state.page == 'card_online' do + local ev, p1, p2, p3 = os.pullEvent() + if ev == 'mouse_click' or ev == 'monitor_touch' then + for _, b in ipairs(Buttons) do + if inRect(b, p2, p3) then clickSound(); if b.onClick then b.onClick() end; break end + end + elseif ev == 'char' and #code < 5 then + code = code .. tostring(p1 or ''):upper() + msg = '' + renderInput() + elseif ev == 'key' and p1 == keys.backspace then + code = code:sub(1, -2) + msg = '' + renderInput() + elseif ev == 'key' and (p1 == keys.enter or p1 == keys.numPadEnter) then + submitCode() + elseif ev == 'config_updated' then + end end end end @@ -2531,6 +2580,20 @@ local function showOnlineVoucher() {'Z','X','C','V','B','N','M'} } + local function clearLine(y) + termDev.setBackgroundColor(colors.black) + termDev.setCursorPos(1, y) + termDev.write(string.rep(' ', w)) + end + + local function renderInput() + local placeholder = code .. string.rep('_', math.max(0, 5-#code)) + clearLine(4) + clearLine(5) + centerText(4, '[' .. placeholder .. ']', colors.yellow) + if msg and #msg > 0 then centerText(5, msg, msgCol) end + end + local function submitCode() if #code == 5 then local res = fetchJSON(API_BASE .. '/public/orders/' .. code) @@ -2540,6 +2603,7 @@ local function showOnlineVoucher() -- Check if already consumed if d.consumed then msg, msgCol = 'Already Used!', colors.red + renderInput() return end @@ -2553,15 +2617,16 @@ local function showOnlineVoucher() state.page = 'order' else msg, msgCol = 'Voucher Invalid', colors.red + renderInput() end + else + msg, msgCol = 'Need 5 chars', colors.red + renderInput() end end while state.page == 'online' do - local placeholder = code .. string.rep('_', math.max(0, 5-#code)) drawHeader('Enter Voucher', 'Type 5 chars then OK') - centerText(4, '[' .. placeholder .. ']', colors.yellow) - if msg and #msg > 0 then centerText(5, msg, msgCol) end Buttons = {} local keyW, keyH = (w < 44 and 2 or 3), 2 @@ -2571,7 +2636,13 @@ local function showOnlineVoucher() for rIdx, row in ipairs(rows) do local y, x = sY + (rIdx-1) * (keyH + 1), sX + (rIdx-1) for _, ch in ipairs(row) do - addButton(x, y, ch, keyW, keyH, {colors.black, colors.white}, function() if #code < 5 then code = code .. ch end end) + addButton(x, y, ch, keyW, keyH, {colors.black, colors.white}, function() + if #code < 5 then + code = code .. ch + msg = '' + renderInput() + end + end) x = x + keyW + 1 end end @@ -2581,27 +2652,47 @@ local function showOnlineVoucher() local gap = 2 local total = bw + gap + cw + gap + ow local ax = math.floor((w - total) / 2) + 1 + local smallMode = false if ax < 1 then + smallMode = true bw, cw, ow = 6, 6, 6 - total = bw + 1 + cw + 1 + ow + gap = 1 + total = bw + gap + cw + gap + ow ax = math.floor((w - total) / 2) + 1 - addButton(math.max(1, ax), actY, 'BKSP', bw, 3, {colors.black, colors.red}, function() code = code:sub(1, -2) end) - addButton(math.max(1, ax) + bw + 1, actY, 'CLEAR', cw, 3, {colors.black, colors.red}, function() code = '' end) - addButton(math.max(1, ax) + bw + 1 + cw + 1, actY, 'OK', ow, 3, {colors.black, colors.green}, submitCode) - else - addButton(ax, actY, 'Backspace', bw, 3, {colors.black, colors.red}, function() code = code:sub(1, -2) end) - addButton(ax + bw + gap, actY, 'Clear', cw, 3, {colors.black, colors.red}, function() code = '' end) - addButton(ax + bw + gap + cw + gap, actY, 'OK', ow, 3, {colors.black, colors.green}, submitCode) end + local bx = math.max(1, ax) + addButton(bx, actY, smallMode and 'BKSP' or 'Backspace', bw, 3, {colors.black, colors.red}, function() + code = code:sub(1, -2) + msg = '' + renderInput() + end) + addButton(bx + bw + gap, actY, smallMode and 'CLEAR' or 'Clear', cw, 3, {colors.black, colors.red}, function() + code = '' + msg = '' + renderInput() + end) + addButton(bx + bw + gap + cw + gap, actY, 'OK', ow, 3, {colors.black, colors.green}, submitCode) addButton(2, h-3, '<-back', 8, 3, {colors.black, colors.red}, function() state.page = 'home' end) - - local ev, p1, p2, p3 = os.pullEvent() - if ev == 'mouse_click' or ev == 'monitor_touch' then - for _, b in ipairs(Buttons) do if inRect(b, p2, p3) then clickSound(); if b.onClick then b.onClick() end; break end end - elseif ev == 'char' and #code < 5 then code = code .. p1:upper() - elseif ev == 'key' and p1 == keys.backspace then code = code:sub(1, -2) - elseif ev == 'key' and (p1 == keys.enter or p1 == keys.numPadEnter) then submitCode() - elseif ev == 'config_updated' then + + renderInput() + while state.page == 'online' do + local ev, p1, p2, p3 = os.pullEvent() + if ev == 'mouse_click' or ev == 'monitor_touch' then + for _, b in ipairs(Buttons) do + if inRect(b, p2, p3) then clickSound(); if b.onClick then b.onClick() end; break end + end + elseif ev == 'char' and #code < 5 then + code = code .. tostring(p1 or ''):upper() + msg = '' + renderInput() + elseif ev == 'key' and p1 == keys.backspace then + code = code:sub(1, -2) + msg = '' + renderInput() + elseif ev == 'key' and (p1 == keys.enter or p1 == keys.numPadEnter) then + submitCode() + elseif ev == 'config_updated' then + end end end end @@ -2612,6 +2703,7 @@ end local function mainPageLoop() while true do if state.page == 'home' then showHome() + elseif state.page == 'new_menu' then showNewMenu() elseif state.page == 'single_segment' then showSingleSegmentSelection() elseif state.page == 'card_home' then showCardHome() elseif state.page == 'card_name' then showCardNameInput()