diff --git a/strichliste.lua b/strichliste.lua index 927a08a..4e941b9 100755 --- a/strichliste.lua +++ b/strichliste.lua @@ -41,13 +41,22 @@ local stylesheet = [[ .amount-neg { color: red; } nav h2 { display: inline-block } .notif { padding: 0.5em; margin: 0.5em; background-color: #ddd; } + .notif.error { background-color: #faa; } .notif p { margin: 5px; } form.box { border: 2px solid grey; padding: 0.5em; margin: 0.5em; display: inline-block; } form h3 { margin: 5px; } ]] +-- local script = io.open("main.js"):read("a") local script = [[ - + document.addEventListener("keypress", ev => { + if (!(document.activeElement instanceof HTMLInputElement)) { + if (ev.code.startsWith("Digit")) + document.forms.buy_product.product.value += ev.code.substring(5) + if (ev.code == "Enter") + document.forms.buy_product.submit() + } + }) ]] local function respond(status, title, body) @@ -55,6 +64,7 @@ local function respond(status, title, body) print("Content-Type: text/html") print("") print(string.format([[ + %s @@ -88,6 +98,13 @@ local function form_data() return parse_query(io.read()) end +local function format_duration(t) + if t > 86400 then return string.format("%d days", t / 86400) end + if t > 3600 then return string.format("%d hours", t / 3600) end + if t > 60 then return string.format("%d minutes", t / 60) end + return string.format("%d seconds", t) +end + local function read_log() local log = io.open("log", "r") if log == nil then @@ -126,54 +143,65 @@ local function balances() end return users end +local function last_txns() + local users = {} + for time, username, _, _ in read_log() do + users[username] = time + end + return users +end -local function r_user() - if path == nil then - return respond_error("no path") - end - local username = urldecode(path:sub(2)) - if username == nil or username:match("^([%w_ -]+)$") == nil then - return respond_error("username invalid") - end - local notif = nil - if method == "POST" then - local data = form_data() - local amount = nil - local comment = "" - if data.barcode then - for p_barcode, p_amount, p_name in read_products() do - if p_barcode == data.barcode then - amount = p_amount - comment = p_name - end +local function error_box(message) + return string.format([[

Error: %s

]], message) +end + +local function r_user_post(username) + local data = form_data() + local amount = nil + local comment = "" + if data.product then + for p_barcode, p_amount, p_name in read_products() do + if p_barcode == data.product then + amount = p_amount + comment = p_name end - else - amount = tonumber(data.amount) - comment = data.comment or "" end if amount == nil then - return respond_error("amount invalid") + return error_box("unknown product") end - if comment:match("^[%w_ -]*$") == nil then - return respond_error("comment invalid") - end - local log = io.open("log", "a+") - if log == nil then - return respond_error("failed to open log") - end - local time = os.time() - log:write(string.format("%d,%s,%d,%s\n", time, username, amount, comment)) - log:flush() - log:close() - notif = string.format( - "

Transaction successful: %.02f€ (%s)

", - amount >= 0 and "pos" or "neg", amount / 100, escape(comment) - ) + else + amount = tonumber(data.amount) + comment = data.comment or "" end + if amount == nil then + return error_box("amount invalid") + end + if comment:match("^[%w_ -]*$") == nil then + return error_box("comment invalid") + end + local log = io.open("log", "a+") + if log == nil then + return error_box("failed to open log") + end + local time = os.time() + log:write(string.format("%d,%s,%d,%s\n", time, username, amount, comment)) + log:flush() + log:close() + return string.format( + "

Transaction successful: %.02f€ (%s)

", + amount >= 0 and "pos" or "neg", amount / 100, escape(comment) + ) +end +local function r_user(username) + local notif = nil + if method == "POST" then + notif = r_user_post(username) + end return respond(200, username, function() print(string.format("

%s

", username)) local balance = balances()[username] + local last_txn = last_txns()[username] local new_user = balance == nil balance = balance or 0 if new_user then @@ -181,11 +209,13 @@ local function r_user()

This user account does not exist yet. It will only be created after the first transaction.

]]) end - if notif then - print(notif) - end - print(string.format("

Current balance: %.02f€

", balance >= 0 and "pos" or "neg", - balance / 100)) + if notif then print(notif) end + print(string.format([[ +

Current balance: %.02f€

+ ]], balance >= 0 and "pos" or "neg", balance / 100)) + print(string.format([[ +

Last transaction added %s ago. View user log + ]], format_duration(os.time() - last_txn), username)) print([[

Create Transaction

@@ -195,6 +225,12 @@ local function r_user()
+
+

Buy Product

+ +
+ +
]]) print("
") for _, type in ipairs({ 1, -1 }) do @@ -214,14 +250,20 @@ local function r_user() end) end -local function r_log() +local function r_log(filter) return respond(200, "Log", function() print("") print("") for time, username, amount, comment in read_log() do - print(string.format("", time, - escape(username), - amount >= 0 and "pos" or "neg", amount / 100, escape(comment))) + if filter == nil or filter == username then + print(string.format( + "", + time, format_duration(os.time() - time), + escape(username), + amount >= 0 and "pos" or "neg", amount / 100, + escape(comment) + )) + end end print("
TimeUsernameAmountComment
%d%s%.02f€%s
%d (%s ago)%s%.02f€%s
") end) @@ -254,6 +296,17 @@ local function r_create_user() return redirect(string.format("/%s", urlencode(username))) end +local function extract_username() + if path == nil then + return respond_error("no path") + end + local username = urldecode(path:sub(2)) + if username == nil or username:match("^([%w_ -]+)$") == nil then + return nil + end + return username +end + if path == "/" then if query.log then return r_log() @@ -263,5 +316,12 @@ if path == "/" then return r_index() end else - return r_user() + local username = extract_username() + if username == nil then + return respond_error("username invalid") + elseif query.log then + return r_log(username) + else + return r_user(username) + end end