209 lines
7.7 KiB
HTML
209 lines
7.7 KiB
HTML
<html>
|
|
<header>
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/dark.css">
|
|
<style>
|
|
input[type="text"] {
|
|
border: 1px solid black;
|
|
}
|
|
</style>
|
|
<script>
|
|
function http(method, remote, callback, body) {
|
|
var xmlhttp = new XMLHttpRequest();
|
|
xmlhttp.onreadystatechange = function() {
|
|
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
|
|
callback(xmlhttp.responseText, xmlhttp.status)
|
|
}
|
|
};
|
|
xmlhttp.open(method, remote, true);
|
|
if (typeof body == "undefined") {
|
|
body = null
|
|
}
|
|
xmlhttp.send(body);
|
|
}
|
|
|
|
function callback(responseBody, responseStatus) {
|
|
}
|
|
//var f = String(window.location).split("/transactions.html")[1]
|
|
//if (!f) {
|
|
// f = "/ledger.dat"
|
|
//}
|
|
//f = "." + f
|
|
|
|
function init() {
|
|
const zeroPad = (num, places) => String(num).padStart(places, '0')
|
|
var d = new Date()
|
|
d.setMonth(d.getMonth()-6)
|
|
const replacement = `${d.getFullYear()}-${zeroPad(d.getMonth(), 2)}`
|
|
var iframe = document.getElementsByTagName("iframe")[0]
|
|
iframe.src = iframe.src.replace("YYYY-MM", replacement)
|
|
|
|
load()
|
|
}
|
|
|
|
function load() {
|
|
http("GET", "/api/transactions" /*?f="+f*/, (body, status) => {
|
|
var d = JSON.parse(body)
|
|
console.log("loading", d)
|
|
loadBalances(d.balances)
|
|
loadTransactions(d.transactions)
|
|
})
|
|
}
|
|
|
|
function loadBalances(balances) {
|
|
console.log("loading balances", balances)
|
|
var result = `<table>`
|
|
for (var k in balances) {
|
|
result += `<tr style="display: flex; flex-direction: row; width: 100%; justify-content: space-between;"><td>${k}</td><td>${Math.floor(balances[k]["$"])}</td></tr>`
|
|
}
|
|
result += `</table>`
|
|
document.getElementById("bal").innerHTML = result
|
|
}
|
|
|
|
function loadTransactions(transactions) {
|
|
transactions.reverse()
|
|
console.log(transactions[0])
|
|
|
|
var result = `<table>`
|
|
for (var t of transactions) {
|
|
result += `<tr transaction='${btoa(JSON.stringify(t))}' style="cursor: crosshair;" onclick="stageEdit(this); return false;">`
|
|
result += ` <td style="width: 6em;">${t[0].Date}</td>`
|
|
result += ` <td style="width: 10em;">${t[0].Description}</td>`
|
|
result += ` <td><table style="margin: 0;">`
|
|
for (var delta of t) {
|
|
result += ` <tr>`
|
|
result += ` <td><span style="font-variant: petite-caps;">${delta.Name.split(":")[0]}</span><span style="opacity: 0.6;"> :${delta.Name.split(":").slice(1, 100).join(":")}</span></td>`
|
|
result += ` <td style="text-align: right; width: 2em;">${delta.Payee ? delta.Currency : ""}</td>`
|
|
result += ` <td style="text-align: right; width: 5em;">${delta.Payee ? delta.Value : ""}</td>`
|
|
result += ` </tr>`
|
|
}
|
|
result += ` </table></td>`
|
|
result += `</tr>`
|
|
}
|
|
result += `</table>`
|
|
|
|
document.getElementById("reg").innerHTML = result
|
|
}
|
|
|
|
function stageEdit(row) {
|
|
const xactionJSON = atob(row.attributes.transaction.value)
|
|
const xaction = JSON.parse(xactionJSON)
|
|
console.log(xaction)
|
|
|
|
row.attributes.onclick = ""
|
|
row.onclick = ""
|
|
row.style = ""
|
|
console.log(row)
|
|
|
|
var result = `<td colspan="3">`
|
|
result += `<form method="modal">`
|
|
result += ` <div>`
|
|
result += ` <label for="date">Date</label>`
|
|
result += ` <input type="text" name="date" value='${xaction[0].Date}' style="width: 100%;"/>`
|
|
result += ` </div>`
|
|
result += ` <div>`
|
|
result += ` <label for="description">Description</label>`
|
|
result += ` <input type="text" name="description" value='${xaction[0].Description}' style="width: 100%;"/>`
|
|
result += ` </div>`
|
|
|
|
for (var i in xaction) {
|
|
var delta = xaction[i]
|
|
result += `<hr>`
|
|
result += `<div style="display: flex; flex-direction: row; width: 100%; margin-top: 1em;">`
|
|
result += ` <div style="flex-grow: 1; margin-left: 1em; margin-right: 1em;">`
|
|
result += ` <label for="name${i}">Name${i}</label>`
|
|
result += ` <input type="text" name="name${i}" value='${delta.Name}' style="width: 100%;"/>`
|
|
result += ` </div>`
|
|
result += ` <div style="margin-left: 1em; margin-right: 1em;">`
|
|
result += ` <label for="value${i}">Value${i}</label>`
|
|
result += ` <input type="text" name="value${i}" value='${delta.Value}' style="width: 100%;"/>`
|
|
result += ` </div>`
|
|
result += ` <input type="button" name="submit${i}" value="Submit${i}" onclick="submitEdit(this); return false;" delta="${btoa(JSON.stringify(delta))}"/>`
|
|
result += `</div>`
|
|
}
|
|
|
|
result += `</form`
|
|
result += `</td>`
|
|
|
|
row.innerHTML = result
|
|
}
|
|
|
|
function submitEdit(btn) {
|
|
const old = JSON.parse(atob(btn.attributes.delta.value))
|
|
const now = JSON.parse(atob(btn.attributes.delta.value))
|
|
|
|
const idx = btn.name.split("submit")[1]
|
|
const form = btn.parentElement.parentElement
|
|
|
|
now.Value = form[`value${idx}`].value
|
|
now.Name = form[`name${idx}`].value
|
|
now.Description = form[`description`].value
|
|
now.Date = form[`date`].value
|
|
|
|
if (JSON.stringify(old) === JSON.stringify(now)) {
|
|
return
|
|
}
|
|
|
|
http("PUT", "/api/amend", (body, status) => {
|
|
if (status != 200)
|
|
throw(`Unexpected status ${status}: ${body}`)
|
|
load()
|
|
}, {
|
|
old: old,
|
|
now: now,
|
|
})
|
|
}
|
|
|
|
function stage(who, contributesToHouse) {
|
|
var d = new Date()
|
|
const zeroPad = (num, places) => String(num).padStart(places, '0')
|
|
const today = `${d.getFullYear()}-${zeroPad(1+d.getMonth(), 2)}-${zeroPad(d.getDate(), 2)}`
|
|
|
|
var who_currency = who.split(":").at(-1).toUpperCase()
|
|
|
|
var benefactor = who
|
|
var benefactor_value = `-0.00 ${who_currency}`
|
|
var beneficiary = "AssetAccount:Chase:5876"
|
|
var beneficiary_value = `$0.00`
|
|
if (!contributesToHouse) {
|
|
beneficiary_value = `$-0.00`
|
|
benefactor_value = `0.00 ${who_currency}`
|
|
}
|
|
|
|
console.log(`@${today} ${benefactor} gave to ${beneficiary}`)
|
|
}
|
|
</script>
|
|
</header>
|
|
<body onload="init();" style="">
|
|
<h2>Moolah2</h2>
|
|
<details open>
|
|
<summary>Balance</summary>
|
|
<div id="bal">
|
|
</div>
|
|
<details>
|
|
<summary><i>Look at this graph</i></summary>
|
|
<iframe style="background: white; width: 100%;" src="/api/reg?x=y&mode=reg&likeName=Withdrawal:[0123]&chart=stack&predictionMonths=6&prediction=autoContributions=&bpi=true&zoomStart=YYYY-MM"></iframe>
|
|
</details>
|
|
</details>
|
|
<details open style="display: none;">
|
|
<summary>Edit</summary>
|
|
<div style="display:flex; flex-direction:row; width:100%; justify-content:space-between;">
|
|
<div>
|
|
<input type="button" onclick="stage('AssetAccount:Zach', true)" value="Stage Zach's Payment"/>
|
|
<input type="button" onclick="stage('AssetAccount:Zach', false)" value="Stage Zach's Charge"/>
|
|
</div>
|
|
<div>
|
|
<input type="button" onclick="stage('AssetAccount:Bel', true)" value="Stage Bel's Payment"/>
|
|
<input type="button" onclick="stage('AssetAccount:Bel', false)" value="Stage Bel's Charge"/>
|
|
</div>
|
|
</div>
|
|
</details>
|
|
<details open>
|
|
<summary>Register</summary>
|
|
<div id="reg">
|
|
</div>
|
|
</details>
|
|
</body>
|
|
<footer>
|
|
</footer>
|
|
</html>
|