all repos — piggy @ e82c0fc1e0a153fffa9de1c390f9d0cc4cee487d

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
 22const flatpickrOptions = {
 23    enableTime: true,
 24    time_24hr: true,
 25    dateFormat: "Z",
 26};
 27
 28// Cell formatters
 29function formatValue(v) {
 30    if (v === undefined) return 0;
 31    return (v / 100).toFixed(2);
 32}
 33
 34function restoreValue(v) {
 35    return Number(v) * 100;
 36}
 37
 38function formatCash(v) {
 39    if (v === 0) return "-";
 40    return `${v > 0 ? "+" : ""}${formatValue(v)}${currency}`;
 41}
 42
 43function formatPercentage(v) {
 44    if (v === 0) return "-";
 45    return formatValue(v) + "%";
 46}
 47
 48function formatDate(dateString) {
 49    return (new Date(dateString)).toLocaleString(locale);
 50}
 51
 52function formatBoolean(value, id) {
 53    const input = document.createElement("input");
 54    input.type = "checkbox";
 55    if (value) input.setAttribute("checked", "");
 56    input.disabled = true;
 57    //input.setAttribute("data-id", id);
 58    //input.onchange = undefined;
 59    return input.outerHTML;
 60}
 61
 62// Input components
 63function newInputText(label, value, name) {
 64    const l = document.createElement("label");
 65    const input = document.createElement("input");
 66    input.className = name;
 67    input.type = "text";
 68    input.placeholder = label;
 69    input.value = value ?? "";
 70    l.innerHTML += label + "<br />";
 71    l.appendChild(input);
 72    return l;
 73}
 74
 75function newInputCheckbox(label, value, name) {
 76    const l = document.createElement("label");
 77    const input = document.createElement("input");
 78    input.className = name;
 79    input.type = "checkbox";
 80    if (value) input.setAttribute("checked", "");
 81    l.appendChild(input);
 82    l.innerHTML += label;
 83    return l;
 84}
 85
 86function newInputDate(label, value, name) {
 87    const l = document.createElement("label");
 88    const input = document.createElement("input");
 89    input.className = name;
 90    input.placeholder = label;
 91    input.value = value ?? "";
 92    flatpickr(input, flatpickrOptions);
 93    l.innerHTML += label + "<br />";
 94    l.appendChild(input);
 95    return l;
 96}
 97
 98// Functions
 99function getQueryStringID() {
100    return Number(new URLSearchParams(window.location.search).get("id") ?? 0);
101}
102
103async function myConfirm(f, id) {
104    if (confirm("Are you sure?")) return await f(id);
105    return false;
106}
107
108async function handleFetchResult(res) {
109    if (!res.ok) {
110        console.error(await res.text())
111        return
112    }
113
114    return await res.json();
115}
116
117async function myFetch(url) {
118    res = await fetch(url);
119    return await handleFetchResult(res);
120}
121
122async function myFetchPOST(url, body) {
123    const res = await fetch(url, {
124        method: 'POST',
125        headers: { 'Content-Type': 'application/json' },
126        body: body ? JSON.stringify(body) : undefined,
127    });
128    return await handleFetchResult(res);
129}
130
131async function myFetchDELETE(url) {
132    const res = await fetch(url, { method: 'DELETE' });
133    return await handleFetchResult(res);
134}
135
136// API calls
137async function getBookmakers() {
138    return await myFetch('/api/bookmakers');
139}
140
141async function getBookmaker(id) {
142    return await myFetch(`/api/bookmakers/${id}`);
143}
144
145async function saveBookmaker(payload) {
146    return await myFetchPOST("/api/bookmakers", payload);
147}
148
149async function deleteBookmaker(id) {
150    return await myFetchDELETE(`/api/bookmakers/${id}`);
151}
152
153
154async function getAccounts() {
155    return await myFetch('/api/accounts');
156}
157
158async function getAccount(id) {
159    return await myFetch(`/api/accounts/${id}`);
160}
161
162async function saveAccount(payload) {
163    return await myFetchPOST("/api/accounts", payload);
164}
165
166async function deleteAccount(id) {
167    return await myFetchDELETE(`/api/accounts/${id}`);
168}
169
170
171async function getRecords() {
172    return await myFetch('/api/records');
173}
174
175async function getRecord(id) {
176    return await myFetch(`/api/records/${id}`);
177}
178
179async function saveRecord(payload) {
180    return await myFetchPOST("/api/records", payload);
181}
182
183async function deleteRecord(id) {
184    return await myFetchDELETE(`/api/records/${id}`);
185}