all repos — piggy @ 8a31a262f27c077d8a41170129e08c147f5404b9

Dead simple finance manager in Go, HTML and JS.

static/js/records-edit.js (view raw)

  1document.addEventListener('DOMContentLoaded', function () {
  2    handleID();
  3
  4    document.getElementById('save').addEventListener('click', saveRecord);
  5});
  6
  7let id;
  8
  9async function handleID() {
 10    id = Number(new URLSearchParams(window.location.search).get("id") ?? 0);
 11    const record = id === 0 ? null : await myFetch(`/api/records/${id}`);
 12
 13    document.getElementById("main-container").appendChild(loadRecord(record))
 14
 15    console.log(record);
 16}
 17
 18function loadRecord(record) {
 19    const div = document.createElement("div");
 20    div.setAttribute("data-type", "record");
 21    div.setAttribute("data-id", id);
 22    div.classList.add("record");
 23
 24    // record.type
 25    div.appendChild(newInputText("Type", record?.type, "record-type"));
 26
 27    // record.description
 28    div.appendChild(newInputText("Description", record?.description, "record-description"));
 29
 30    // record.done
 31    div.appendChild(newInputCheckbox("Done", record?.done, "record-done"));
 32
 33    // record.entries
 34    div.appendChild(loadEntries(record?.entries ?? [null], "record-entries"));
 35
 36    return div;
 37}
 38
 39function loadEntries(entries, name) {
 40    const div = document.createElement("div")
 41    div.className = name;
 42    for (const entry of entries) {
 43        div.appendChild(loadEntry(entry));
 44    }
 45    return div;
 46}
 47
 48function loadEntry(entry) {
 49    const div = document.createElement("div");
 50    div.setAttribute("data-type", "entry");
 51    div.setAttribute("data-id", entry?.id ?? 0);
 52    div.classList.add("entry");
 53
 54    // entry.bookmaker_id
 55    div.appendChild(newInputText("Bookmaker ID", entry?.bookmaker_id, "entry-bookmaker_id"))
 56
 57    // entry.account_id
 58    div.appendChild(newInputText("Account ID", entry?.account_id, "entry-account_id"))
 59
 60    // entry.amount
 61    div.appendChild(newInputText("Amount", entry?.amount, "entry-amount"))
 62
 63    // entry.refund
 64    div.appendChild(newInputText("Refund", entry?.refund, "entry-refund"))
 65
 66    // entry.bonus
 67    div.appendChild(newInputText("Bonus", entry?.bonus, "entry-bonus"))
 68
 69    // entry.commission
 70    div.appendChild(newInputText("Commission", entry?.commission, "entry-commission"))
 71
 72    // entry.sub_entries
 73    div.appendChild(loadSubEntries(entry?.sub_entries ?? [null], "entry-subentries"));
 74
 75    return div;
 76}
 77
 78function loadSubEntries(subEntries, name) {
 79    const div = document.createElement("div")
 80    div.className = name;
 81    for (const subEntry of subEntries) {
 82        div.appendChild(loadSubEntry(subEntry));
 83    }
 84    return div;
 85}
 86
 87function loadSubEntry(subEntry) {
 88    const div = document.createElement("div");
 89    div.setAttribute("data-type", "subentry");
 90    div.setAttribute("data-id", subEntry?.id ?? 0);
 91    div.classList.add("subentry");
 92
 93    // subentry.description
 94    div.appendChild(newInputText("Description", subEntry?.description, "subentry-description"));
 95    
 96    // subentry.odds
 97    div.appendChild(newInputText("Odds", subEntry?.odds, "subentry-odds"))
 98    
 99    // subentry.won
100    div.appendChild(newInputCheckbox("Won", subEntry?.won, "subentry-won"));
101    
102    // subentry.date
103    div.appendChild(newInputText("Date", subEntry?.date, "subentry-date"));
104
105    return div;
106}
107
108function getInputValueFromNode(node, name) {
109    const element = node.getElementsByClassName(name)[0];
110    return element.type === "checkbox" ? element.checked : element.value;
111}
112
113function buildRecordObject() {
114    const node = document.getElementsByClassName("record")[0];
115    return {
116        id: +node.getAttribute("data-id"),
117        type: getInputValueFromNode(node, "record-type"),
118        description: getInputValueFromNode(node, "record-description"),
119        done: getInputValueFromNode(node, "record-done"),
120        entries: buildEntriesObject(node.getElementsByClassName("record-entries")[0]),
121    }
122}
123
124function buildEntriesObject(entriesNode) {
125    const entriesNodes = entriesNode.getElementsByClassName("entry");
126    
127    const result = [];
128    for (const node of entriesNodes) {
129        result.push({
130            id: +node.getAttribute("data-id"),
131            bookmaker_id: +getInputValueFromNode(node, "entry-bookmaker_id"),
132            account_id: +getInputValueFromNode(node, "entry-account_id"),
133            amount: +getInputValueFromNode(node, "entry-amount"),
134            sub_entries: buildSubEntriesObject(node.getElementsByClassName("entry-subentries")[0]),
135        });
136    }
137    return result;
138}
139
140function buildSubEntriesObject(subEntriesNode) {
141    const subEntriesNodes = subEntriesNode.getElementsByClassName("subentry");
142    
143    const result = [];
144    for (const node of subEntriesNodes) {
145        result.push({
146            id: +node.getAttribute("data-id"),
147            description: getInputValueFromNode(node, "subentry-description"),
148            odds: +getInputValueFromNode(node, "subentry-odds"),
149            won: getInputValueFromNode(node, "subentry-won"),
150            date: getInputValueFromNode(node, "subentry-date"),
151        });
152    }
153    return result;
154}
155
156async function saveRecord() {
157    const result = await myFetchPOST("/api/records", buildRecordObject());
158    if (result) {
159        alert("Done");
160    }
161}