127.0.0.1:8000 budget / master src / js / pages / transactions_and_credit_cards.js
master

Tree @master (Download .tar.gz)

transactions_and_credit_cards.js @masterraw · history · blame

const api = require('../utils/api');
const utils = require('../utils');
const chart = require('./chart_and_messages');
const list_row = require('../ui/list_row');
const ui = require('../ui/common');
const $ = require('jquery');
const modal = require('../utils/modal');

// We don't want to hit the API any time we are loading new data
let cached_credit_cards = {};

const one_hour = 3600000; // 1000 * 60 * 60
// Idk maybe I'll leave the page open for days at a time
// TODO: use same time logic as in service time util for daily actions
utils.setIntervalAndTriggerImmediate(function () {
    const today = new Date();
    let month = today.getMonth() + 1;
    let day = today.getDate();
    let year = today.getFullYear();
    if (month < 10)
        month = '0' + month;
    if (day < 10)
        day = '0' + day;
    $("#transaction-date").attr('max', year + '-' + month + '-' + day);
    $("#transaction-date").val(year + '-' + month + '-' + day);
}, one_hour);

api.on_submit("/budget/transaction", [
    $("#create-transaction"), $("#edit-transaction")
], {
    value: x => -Math.abs(utils.round(parseFloat(x), 2))
}, [
    ["value", "Money spent must be provided"], // value=0 will be accounted for here
    ["value", "Money spent must be a number", value => !isNaN(value)],
    ["credit_card", "Invalid Credit Card", credit_card => cached_credit_cards[credit_card]],
    ["date", "Transaction Date must be provided"],
    ["date", "Transaction Date must be in YYYY-MM-DD format", utils.validate.iso_date]
], async function () {
    modal.close();
    await chart.refresh();
    await populate_ui_with_data();
});

$("#delete-transaction").on("click", async function () {
    const id = $("#edit-transaction").find('[name="id"]').val();
    await api.delete('/budget/transaction/' + id);
    ui.show_banner({
        message: `Transaction ${id} deleted`
    });
    modal.close();
    await chart.refresh();
    await populate_ui_with_data();
});

api.on_submit("/budget/credit-card", [
    $("#create-credit-card"), $("#edit-credit-card")
], {
    billing_day: x => parseInt(x),
    statement_day: x => parseInt(x)
}, [
    ["name", "Credit Card must have a name"],
    ["billing_day", "Invalid billing date", utils.validate.day],
    ["statement_day", "Invalid statement date", utils.validate.day]
], async function () {
    modal.create();
    await chart.refresh();
    await get_credit_cards();
    await populate_ui_with_data();
});

$("#delete-credit-card").on("click", async function () {
    const id = $("#edit-credit-card").find('[name="id"]').val();
    await api.delete('/budget/credit-card/' + id);
    ui.show_banner({
        message: `Credit Card ${id} deleted`
    });
    modal.close();
    await chart.refresh();
    await get_credit_cards();
    await populate_ui_with_data();
});

const billing_day_fields = ui.get_inputs(["#create-credit-card", "#edit-credit-card"], "billing_day");
const statement_day_fields = ui.get_inputs(["#create-credit-card", "#edit-credit-card"], "statement_day");
billing_day_fields.forEach(function ($billing_day_field) {
    ui.generate_day_options($billing_day_field);
});
statement_day_fields.forEach(function ($statement_day_field) {
    ui.generate_day_options($statement_day_field);
});

get_credit_cards().then(populate_ui_with_data);

async function get_credit_cards() {
    $("#credit-cards-list").empty();

    const {
        credit_cards
    } = await api.get('/budget/credit_cards');

    const credit_card_fields = ui.get_inputs(
        ["#create-transaction", "#edit-transaction", "#set-statement-override"],
        "credit_card"
    );

    for (const credit_card of credit_cards) {
        cached_credit_cards[credit_card.id] = {
            name: credit_card.name,
            date: credit_card.date
        };
        let text = `monthly on the ${utils.format_day(credit_card.billing_day)}`;
        list_row.create("credit-cards", {
            title: `${credit_card.name}:`,
            text
        }).on('click', function () {
            ui.prefill_inputs("#edit-credit-card", credit_card);
            modal.create('edit-credit-card-modal');
        });

        credit_card_fields.map(function ($input) {
            $input.append($('<option>', {
                value: credit_card.id,
                text: credit_card.name
            }));
        })
    }

    credit_card_fields.map(function ($input) {
        $input.append($('<option>', {
            value: 0,
            text: "Other"
        }));
    });
}

async function populate_ui_with_data() {
    $("#transactions-list").empty();

    const {
        transactions
    } = await api.get("/budget/transactions");

    const today = new Date();
    let add_separator = false;

    for (const transaction of transactions) {
        const action = transaction.value > 0 ? "credited" : "charged";
        let text = `$${Math.abs(transaction.value).toFixed(2)} ${action}`
        if (transaction.credit_card) {
            text += ` to ${cached_credit_cards[transaction.credit_card].name}`
        }
        text += ` on ${transaction.date}`;
        if (transaction.description) {
            text += ` (${transaction.description})`;
        }
        list_row.create("transactions", {
            text
        }).on('click', function () {
            ui.prefill_inputs("#edit-transaction", transaction);
            modal.create('edit-transaction-modal');
        });

        if (new Date(transaction.date) > today) {
            add_separator = true;
        } else if (add_separator) {
            $(`#transactions-list`).append($('<div>', {
                class: "list-separator",
            }));
            add_separator = false;
        }
    }
}

populate_statements_list();

async function populate_statements_list() {
    $("#credit-cards-statements-list").empty();

    const {
        credit_card_statements
    } = await api.get('/budget/credit_cards/statements');

    const today = new Date();
    let add_separator = false;

    for (const credit_card_statement of credit_card_statements) {
        list_row.create("credit-card-statements", {
            title: `${credit_card_statement.name}:`,
            text: `${(-credit_card_statement.value).toFixed(2)} on ${credit_card_statement.date}`
        }).on('click', function () {
            ui.prefill_inputs("#edit-credit-card-statement", credit_card_statement);
            modal.create('edit-credit-card-statement-modal');
        });

        if (new Date(credit_card_statement.date) > today) {
            add_separator = true;
        } else if (add_separator) {
            $(`#credit-card-statements-list`).append($('<div>', {
                class: "list-separator",
            }));
            add_separator = false;
        }
    }
}