all repos — piggy @ 1a0ce761ef68d0800a69ebff7968d2c655aba6f3

Dead simple finance manager in Go, HTML and JS.

static/js/common.js (view raw)

  1document.addEventListener('DOMContentLoaded', function () {
  2    const navObject = document.getElementsByTagName("nav")[0];
  3    for (const page of navPages) {
  4        const a = document.createElement("a");
  5        a.innerText = page.name;
  6        a.href = page.href;
  7        navObject.appendChild(a)
  8    }
  9});
 10
 11// Global constants
 12const navPages = [
 13    { name: "Home", href: "/" },
 14    { name: "Bookmakers", href: "/bookmakers" },
 15    { name: "Accounts", href: "/accounts" },
 16    { name: "Records", href: "/records" },
 17];
 18
 19const currency = "€";
 20const locale = "it-IT";
 21
 22// Cell formatters
 23function formatValue(v) {
 24    return (v / 100).toFixed(2);
 25}
 26
 27function formatCash(v) {
 28    if (v === 0) return "-";
 29    return `${v > 0 ? "+" : ""}${formatValue(v)}${currency}`;
 30}
 31
 32function formatPercentage(v) {
 33    if (v === 0) return "-";
 34    return formatValue(v) + "%";
 35}
 36
 37function formatDate(dateString) {
 38    return (new Date(dateString)).toLocaleString(locale);
 39}
 40
 41function formatBoolean(value, id) {
 42    const input = document.createElement("input");
 43    input.type = "checkbox";
 44    if (value) input.setAttribute("checked", "");
 45    input.disabled = true;
 46    //input.setAttribute("data-id", id);
 47    //input.onchange = undefined;
 48    return input.outerHTML;
 49}
 50
 51// Input components
 52function newInputText(label, value, name) {
 53    const l = document.createElement("label");
 54    const input = document.createElement("input");
 55    input.className = name;
 56    input.type = "text";
 57    input.placeholder = label;
 58    input.value = value ?? "";
 59    l.innerHTML += label + "<br />";
 60    l.appendChild(input);
 61    return l;
 62}
 63
 64function newInputCheckbox(label, value, name) {
 65    const l = document.createElement("label");
 66    const input = document.createElement("input");
 67    input.className = name;
 68    input.type = "checkbox";
 69    if (value) input.setAttribute("checked", "");
 70    l.appendChild(input);
 71    l.innerHTML += label;
 72    return l;
 73}
 74
 75// Functions
 76function getQueryStringID() {
 77    return Number(new URLSearchParams(window.location.search).get("id") ?? 0);
 78}
 79
 80async function myConfirm(f, id) {
 81    if (confirm("Are you sure?")) return await f(id);
 82    return false;
 83}
 84
 85async function handleFetchResult(res) {
 86    if (!res.ok) {
 87        console.error(await res.text())
 88        return
 89    }
 90
 91    return await res.json();
 92}
 93
 94async function myFetch(url) {
 95    res = await fetch(url);
 96    return await handleFetchResult(res);
 97}
 98
 99async function myFetchPOST(url, body) {
100    const res = await fetch(url, {
101        method: 'POST',
102        headers: { 'Content-Type': 'application/json' },
103        body: body ? JSON.stringify(body) : undefined,
104    });
105    return await handleFetchResult(res);
106}
107
108async function myFetchDELETE(url) {
109    const res = await fetch(url, { method: 'DELETE' });
110    return await handleFetchResult(res);
111}
112
113// API calls
114async function getBookmakers() {
115    return await myFetch('/api/bookmakers');
116}
117
118async function getBookmaker(id) {
119    return await myFetch(`/api/bookmakers/${id}`);
120}
121
122async function saveBookmaker(payload) {
123    return await myFetchPOST("/api/bookmakers", payload);
124}
125
126async function deleteBookmaker(id) {
127    return await myFetchDELETE(`/api/bookmakers/${id}`);
128}
129
130
131async function getAccounts() {
132    return await myFetch('/api/accounts');
133}
134
135async function getAccount(id) {
136    return await myFetch(`/api/accounts/${id}`);
137}
138
139async function saveAccount(payload) {
140    return await myFetchPOST("/api/accounts", payload);
141}
142
143async function deleteAccount(id) {
144    return await myFetchDELETE(`/api/accounts/${id}`);
145}
146
147
148async function getRecords() {
149    return await myFetch('/api/records');
150}
151
152async function getRecord(id) {
153    return await myFetch(`/api/records/${id}`);
154}
155
156async function saveRecord(payload) {
157    return await myFetchPOST("/api/records", payload);
158}
159
160async function deleteRecord(id) {
161    return await myFetchDELETE(`/api/records/${id}`);
162}