var gui = require('gui'); var fs = require('fs'); const { waitForAddAccountWindow } = require('./waitForAddAccountWindow'); const { waitForDataEntryWindow } = require('./waitForDataEntryWindow'); const { waitForCloseAccountWindow } = require('./waitForCloseAccountWindow'); const { getAccounts, toListViewEntries, getSummation } = require('./utils'); const { waitForChartWindow } = require('./waitForChartWindow'); function mainWindow(projectData) { var rh = 14; var sp = 4; var y = sp; let internalProjectData = projectData; let invalidate = false; let gadgets = []; const cycleId = 1; const listViewId = 2; const balanceId = 3; const addButtonId = 4; cols = 56; gadgets.push({ kind: 'cycle', id: cycleId, left: sp, top: y, width: 120, height: rh, border: false, items: getAccounts(internalProjectData), value: 0 }); gadgets.push({ kind: 'button', id: addButtonId, left: -(sp + 80), top: y, width: 80, label: "+Transfer", height: rh }); gadgets.push({ kind: 'listview', id: listViewId, left: sp, top: y + rh + sp, width: 500 - sp - sp, height: 186, items: toListViewEntries(internalProjectData[0].entries, cols), value: 0 }); gadgets.push({ kind: 'text', id: balanceId, label: 'Balance:', left: 100, top: -(sp + rh), width: 400 - sp, height: rh, value: getSummation(internalProjectData[0].entries).toFixed(2) }); let win = gui.createWindow({ title: 'Budget', width: 500, height: 14 + 4 + 4 + 200 + 4, left: 20, top: 15, gadgets: gadgets, }); /* Set up menu bar */ gui.setMenu(win, [ { title: 'Project', items: [ { label: 'New', id: 101, key: 'N' }, { label: 'Open...', id: 102, key: 'O' }, { label: 'Save...', id: 103, key: 'S' }, { label: '---' }, { label: 'Quit', id: 199, key: 'Q' } ] }, { title: 'Accounts', items: [ { label: "Add...", id: 104, key: 'A' }, { label: "Close...", id: 105, key: 'C' } ] }, { title: 'Charts', items: [ { label: "---" }, { label: "New", id: 106 } ] } ]); let currentAccountIndex = 0; let updateView = (accountIndex, data) => { if (accountIndex != null) { gui.set(win, cycleId, getAccounts(data)); gui.set(win, cycleId, accountIndex); } else { accountIndex = gui.get(win, cycleId); } // sort data[accountIndex].entries = data[accountIndex].entries.sort((a, b) => a.date - b.date); gui.set(win, 2, toListViewEntries(data[accountIndex].entries, cols)); gui.set(win, 3, getSummation(data[accountIndex].entries).toFixed(2)); } let doNew = () => { return [ { name: "Current", entries: [] } ]; } let doOpen = () => { var r = gui.fileRequest({ title: 'Open File', pattern: '#?.json' }); if (r) { return JSON.parse(fs.readFileSync(r.file)); } } let doSave = () => { var r = gui.fileRequest({ title: 'Save File', pattern: '#?.json', save: true }); if (r) { fs.writeFileSync(r.file, JSON.stringify(internalProjectData)); } } gui.setMenuItem(win, 105, { disabled: internalProjectData.length <= 1 }); while (!invalidate) { var evt = gui.waitEvent(win); if (!evt) continue; if (evt.type === 'close') { invalidate = true; internalProjectData = null; } if (evt.type === 'menu') { if (evt.id === 101) { internalProjectData = doNew(); updateView(0, internalProjectData); } else if (evt.id === 102) { internalProjectData = doOpen(); updateView(0, internalProjectData); } else if (evt.id === 103) { doSave(); } else if (evt.id === 104) { let indexOfNewAccount = waitForAddAccountWindow(internalProjectData); if (indexOfNewAccount > -1) { currentAccountIndex = indexOfNewAccount; } updateView(currentAccountIndex, internalProjectData); } else if (evt.id === 105) { if (internalProjectData.length > 1) { const rValue = waitForCloseAccountWindow(internalProjectData, internalProjectData[currentAccountIndex]); if (rValue === -1) { internalProjectData.splice(currentAccountIndex, 1); updateView(0, internalProjectData); } } else { gui.alert("Cannot close last remaining Account"); } } else if (evt.id === 106) { waitForChartWindow(projectData[currentAccountIndex]); } else if (evt.id === 199) { invalidate = true; internalProjectData = null; } } if (evt.type === 'gadgetup') { if (evt.id === cycleId) { currentAccountIndex = evt.code; updateView(null, internalProjectData); } else if (evt.id === listViewId) { let selectedEntry = evt.code; const entry = waitForDataEntryWindow(internalProjectData[currentAccountIndex].entries[evt.code], internalProjectData); if (entry != null) { console.log(entry); if (entry === -1) { console.log(selectedEntry); internalProjectData[currentAccountIndex].entries.splice(selectedEntry, 1); } else { internalProjectData[currentAccountIndex].entries[selectedEntry] = entry; } if (entry.targetAccount) { const targetAccount = internalProjectData.find(d => d.name === entry.targetAccount); if (targetAccount) { targetAccount.entries.push({ date: entry.date, subject: "(" + internalProjectData[currentAccountIndex].name + ")" + entry.subject, amount: -entry.amount }); } } updateView(currentAccountIndex, internalProjectData); } } else if (evt.id === addButtonId) { const entry = waitForDataEntryWindow(null, internalProjectData); if (entry != null) { internalProjectData[currentAccountIndex].entries.push(entry); if (entry.targetAccount) { const targetAccount = internalProjectData.find(d => d.name === entry.targetAccount); if (targetAccount) { targetAccount.entries.push({ date: entry.date, subject: "(" + internalProjectData[currentAccountIndex].name + ")" + entry.subject, amount: -entry.amount }); } } updateView(currentAccountIndex, internalProjectData); } } } }; gui.closeWindow(win); } let projectData = [ { "name": "Current", "entries": [ { "date": 1704067200000, "subject": "Salary", "amount": 2182.15000000000009 }, { "date": 1704153600000, "subject": "(Savings) Initial Deposit", "targetAccount": "Current", "amount": -500 }, { "date": 1704240000000, "subject": "Rent", "amount": -800 }, { "date": 1704326400000, "subject": "Groceries", "amount": -24.19 }] }, { "name": "Savings", "entries": [ { "date": 1704153600000, "subject": "Initial Deposit", "amount": 500 }] } ]; exports.projectData = projectData; mainWindow(projectData);