Initial commit — Moon Household Budget

This commit is contained in:
Bonna
2026-06-06 14:22:57 -05:00
commit fa3c030b36
44 changed files with 10860 additions and 0 deletions

225
templates/net_worth.html Normal file
View File

@@ -0,0 +1,225 @@
{% extends "base.html" %}
{% block content %}
<div class="page-header">
<h1>Net Worth</h1>
<span class="muted" style="font-size:0.85rem;">Assets minus Liabilities</span>
</div>
<!-- Big Net Worth Number -->
<div class="net-worth-hero {% if net_worth >= 0 %}net-worth-positive{% else %}net-worth-negative{% endif %}">
<div class="net-worth-label">Current Net Worth</div>
<div class="net-worth-number">${{ net_worth | money }}</div>
<div class="net-worth-sub">
<span>Assets: <strong>${{ total_assets | money }}</strong></span>
<span style="margin:0 0.75rem;opacity:0.5;"></span>
<span>Debts: <strong>${{ total_debts | money }}</strong></span>
</div>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:1.5rem;margin-top:1.5rem;">
<!-- ASSETS COLUMN -->
<div>
<h2 style="margin-bottom:1rem;color:var(--accent);">Assets</h2>
<!-- Cash & Accounts -->
<div class="budget-section">
<div class="budget-section-header" style="border-left-color:#7AB87A;">
<h3>Cash & Bank Accounts</h3>
<span class="muted" style="font-size:0.82rem;">${{ total_cash | money }}</span>
</div>
<table class="budget-table">
<thead><tr><th>Account</th><th>Owner</th><th>Balance</th><th></th></tr></thead>
<tbody>
{% for acc in accounts %}
<tr>
<td>{{ acc.name }}</td>
<td><span class="owner-tag" style="background:{{ owner_colors.get(acc.owner,'#ddd') }};font-size:0.72rem;">{{ acc.owner }}</span></td>
<td class="amount">
<input type="number" step="0.01" class="budget-input"
value="{{ acc.balance }}"
onchange="updateAccount('{{ acc.id }}', this.value)"
style="width:110px;">
</td>
<td>
<form method="POST" action="/net-worth/account/delete/{{ acc.id }}" style="display:inline;">
<button type="submit" class="debt-delete-btn" onclick="return confirm('Remove this account?')"></button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr class="total-row">
<td colspan="2">Total Cash</td>
<td class="amount">${{ total_cash | money }}</td>
<td></td>
</tr>
</tfoot>
</table>
<!-- Add Account -->
<details style="margin-top:0.75rem;">
<summary class="btn btn-ghost" style="display:inline-block;cursor:pointer;font-size:0.82rem;">+ Add Account</summary>
<form method="POST" action="/net-worth/account/add" style="display:flex;gap:0.5rem;flex-wrap:wrap;margin-top:0.75rem;align-items:flex-end;">
<div class="form-group" style="margin:0;">
<label style="font-size:0.78rem;">Account Name</label>
<input type="text" name="name" placeholder="e.g. WestConsin Checking" class="budget-input" required>
</div>
<div class="form-group" style="margin:0;">
<label style="font-size:0.78rem;">Owner</label>
<select name="owner" class="budget-input">
<option value="Bonna">Bonna</option>
<option value="Tony">Tony</option>
<option value="Both">Both</option>
</select>
</div>
<div class="form-group" style="margin:0;">
<label style="font-size:0.78rem;">Balance</label>
<input type="number" step="0.01" name="balance" placeholder="0.00" class="budget-input" style="width:110px;">
</div>
<button type="submit" class="btn btn-primary" style="align-self:flex-end;">Add</button>
</form>
</details>
</div>
<!-- Sinking Funds -->
<div class="budget-section" style="margin-top:1rem;">
<div class="budget-section-header" style="border-left-color:#C5BBA0;">
<h3>Sinking Funds</h3>
<a href="{{ url_for('sinking_view') }}" class="edit-link">manage</a>
<span class="muted" style="font-size:0.82rem;">${{ total_sinking | money }}</span>
</div>
<table class="budget-table">
<tbody>
{% for f in sinking_funds %}
<tr>
<td>{{ f.name }}</td>
<td class="amount">${{ (f.balance or 0) | money }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr class="total-row">
<td>Total</td>
<td class="amount">${{ total_sinking | money }}</td>
</tr>
</tfoot>
</table>
</div>
<!-- Vehicles -->
{% if personal_cars %}
<div class="budget-section" style="margin-top:1rem;">
<div class="budget-section-header" style="border-left-color:#D4A96A;">
<h3>Vehicles</h3>
<a href="{{ url_for('assets_view') }}" class="edit-link">manage</a>
<span class="muted" style="font-size:0.82rem;">${{ total_vehicles | money }}</span>
</div>
<table class="budget-table">
<tbody>
{% for car in personal_cars %}
<tr>
<td>{{ car.display_name }}</td>
<td><span class="owner-tag" style="background:{{ owner_colors.get(car.owner,'#ddd') }};font-size:0.72rem;">{{ car.owner }}</span></td>
<td class="amount">
{% if car.estimated_value %}
${{ car.estimated_value | float | money }}
{% else %}
<span class="muted">no value set</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr class="total-row">
<td colspan="2">Total</td>
<td class="amount">${{ total_vehicles | money }}</td>
</tr>
</tfoot>
</table>
</div>
{% endif %}
<!-- Other Assets -->
{% if other_assets %}
<div class="budget-section" style="margin-top:1rem;">
<div class="budget-section-header" style="border-left-color:#A08CC5;">
<h3>Other Assets</h3>
<a href="{{ url_for('assets_view') }}" class="edit-link">manage</a>
<span class="muted" style="font-size:0.82rem;">${{ total_other_assets | money }}</span>
</div>
<table class="budget-table">
<tbody>
{% for a in other_assets %}
<tr>
<td>{{ a.name }}</td>
<td class="muted" style="font-size:0.8rem;">{{ a.category }}</td>
<td class="amount">${{ a.value | float | money }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr class="total-row">
<td colspan="2">Total</td>
<td class="amount">${{ total_other_assets | money }}</td>
</tr>
</tfoot>
</table>
</div>
{% endif %}
</div><!-- end assets column -->
<!-- LIABILITIES COLUMN -->
<div>
<h2 style="margin-bottom:1rem;color:#C57A7A;">Liabilities (Debts)</h2>
{% for cat in debt_categories %}
{% set cat_debts = debts_by_cat[cat] %}
{% if cat_debts %}
<div class="budget-section" style="margin-top:{% if loop.first %}0{% else %}1rem{% endif %};">
<div class="budget-section-header" style="border-left-color:#C57A7A;">
<h3>{{ cat }}</h3>
<span class="muted" style="font-size:0.82rem;">${{ debt_cat_totals[cat] | money }}</span>
</div>
<table class="budget-table">
<tbody>
{% for d in cat_debts %}
<tr>
<td>{{ d.name }}</td>
<td><span class="owner-tag" style="background:{{ owner_colors.get(d.owner,'#ddd') }};font-size:0.72rem;">{{ d.owner }}</span></td>
<td class="amount">${{ d.current_balance | float | money }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr class="total-row">
<td colspan="2">Subtotal</td>
<td class="amount">${{ debt_cat_totals[cat] | money }}</td>
</tr>
</tfoot>
</table>
</div>
{% endif %}
{% endfor %}
<div class="leftover-bar" style="margin-top:1rem;">
<span>Total Debt</span>
<span style="font-size:1.1rem;font-weight:700;color:#C57A7A;">${{ total_debts | money }}</span>
</div>
</div><!-- end liabilities column -->
</div>
<script>
function updateAccount(id, value) {
fetch('/net-worth/account/update/' + id, {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({balance: value})
}).then(() => location.reload());
}
</script>
{% endblock %}