06/02 Optimize app

This commit is contained in:
2026-06-02 16:20:36 -04:00
parent 8536988b1a
commit de948156b9
7 changed files with 175 additions and 23 deletions
+5 -5
View File
@@ -90,16 +90,16 @@
<div class="d-flex gap-2 mt-3">
<a href="{{ url_for('transactions.transfer', to_account_id=acct.id, description='Credit Card Payment — ' ~ acct.name) }}"
class="btn btn-sm flex-fill btn-danger" style="font-size:12px;">
<i class="bi bi-send me-1"></i>Pay Card
<i class="bi bi-send me-1"></i>Pay
</a>
<a href="{{ url_for('accounts.payments', id=acct.id) }}"
class="btn btn-sm flex-fill btn-outline-secondary" style="font-size:12px;">
<i class="bi bi-clock-history me-1"></i>Payments
</a>
<a href="{{ url_for('transactions.index', tab='expense', account_id=acct.id) }}"
class="btn btn-sm flex-fill btn-outline-secondary" style="font-size:12px;">
<i class="bi bi-list-ul me-1"></i>Charges
</a>
<a href="{{ url_for('transactions.new', type='expense') }}"
class="btn btn-sm" style="font-size:12px;background:#f1f5f9;color:#475569;border:none;" title="Add Charge">
<i class="bi bi-plus-lg"></i>
</a>
</div>
{% else %}
<div class="d-flex gap-2 mt-3">
+111
View File
@@ -0,0 +1,111 @@
{% extends "base.html" %}
{% block title %}Payments — {{ account.name }}{% endblock %}
{% block page_title %}Card Payments{% endblock %}
{% block topbar_actions %}
<a href="{{ url_for('transactions.transfer', to_account_id=account.id, description='Credit Card Payment — ' ~ account.name) }}"
class="btn btn-sm btn-danger" style="font-size:12px;">
<i class="bi bi-send"></i><span class="btn-label ms-1">Pay Card</span>
</a>
{% endblock %}
{% block content %}
<!-- Account header -->
<div class="pcard mb-3" style="border-left: 4px solid {{ account.color }};">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2">
<div class="d-flex align-items-center gap-2">
<div style="width:36px;height:36px;border-radius:9px;background:{{ account.color }}22;color:{{ account.color }};display:flex;align-items:center;justify-content:center;font-size:18px;">
<i class="bi {{ account.icon }}"></i>
</div>
<div>
<div style="font-weight:600;font-size:14px;">{{ account.name }}</div>
<div style="font-size:11px;color:var(--muted);">Payment History</div>
</div>
</div>
<div class="d-flex gap-3">
<div style="text-align:right;">
<div style="font-size:10px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.04em;">Paid This Month</div>
<div class="mono text-income" style="font-size:18px;font-weight:700;">+{{ paid_this_month | currency }}</div>
</div>
<div style="text-align:right;">
{% set owed = [0, -account.balance] | max %}
<div style="font-size:10px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.04em;">Still Owed</div>
<div class="mono {% if owed > 0 %}text-expense{% endif %}" style="font-size:18px;font-weight:700;{% if owed == 0 %}color:#10b981;{% endif %}">
{% if owed > 0 %}-{% endif %}{{ owed | currency }}
</div>
</div>
</div>
</div>
</div>
<!-- Back link -->
<div class="mb-2">
<a href="{{ url_for('accounts.index', tab='credit') }}" class="btn btn-sm btn-outline-secondary" style="font-size:12px;">
<i class="bi bi-arrow-left me-1"></i>Back to Accounts
</a>
<a href="{{ url_for('transactions.index', tab='expense', account_id=account.id) }}" class="btn btn-sm btn-outline-secondary ms-1" style="font-size:12px;">
<i class="bi bi-list-ul me-1"></i>View Charges
</a>
</div>
{% if payments %}
<div class="pcard p-0">
<table class="pfm-table">
<thead>
<tr>
<th style="padding-left:20px;">Date</th>
<th>Description</th>
<th class="d-mob-none">From Account</th>
<th class="text-end" style="padding-right:20px;">Amount Paid</th>
</tr>
</thead>
<tbody>
{% for txn in payments %}
<tr>
<td style="padding-left:20px;font-size:12px;color:var(--muted);white-space:nowrap;">
{{ txn.date.strftime('%b %d, %Y') }}
</td>
<td>
<div style="font-size:13px;font-weight:500;">{{ txn.description }}</div>
{% if txn.notes %}<div style="font-size:11px;color:var(--muted);">{{ txn.notes | truncate(60) }}</div>{% endif %}
</td>
<td class="d-mob-none" style="font-size:12px;color:var(--muted);">
{{ txn.account.name if txn.account else '—' }}
</td>
<td class="text-end mono text-income" style="font-size:13px;font-weight:600;padding-right:20px;">
+{{ txn.amount | currency }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if pagination.pages > 1 %}
<div class="d-flex justify-content-between align-items-center px-4 py-3" style="border-top:1px solid var(--border);font-size:12px;color:var(--muted);">
<span>{{ ((pagination.page-1)*30)+1 }}{{ [pagination.page*30, pagination.total]|min }} of {{ pagination.total }}</span>
<div class="d-flex gap-1">
{% if pagination.has_prev %}
<a href="{{ url_for('accounts.payments', id=account.id, page=pagination.prev_num) }}" class="btn btn-sm btn-outline-secondary" style="font-size:11px;">← Prev</a>
{% endif %}
{% if pagination.has_next %}
<a href="{{ url_for('accounts.payments', id=account.id, page=pagination.next_num) }}" class="btn btn-sm btn-outline-secondary" style="font-size:11px;">Next →</a>
{% endif %}
</div>
</div>
{% endif %}
</div>
{% else %}
<div class="pcard text-center py-5">
<i class="bi bi-send text-muted" style="font-size:3rem;opacity:.4;"></i>
<p class="fw-semibold mt-3 mb-1">No payments recorded yet</p>
<p class="text-muted small mb-3">Use "Pay Card" to record a payment from your checking or savings account.</p>
<a href="{{ url_for('transactions.transfer', to_account_id=account.id, description='Credit Card Payment — ' ~ account.name) }}"
class="btn btn-sm btn-danger">
<i class="bi bi-send me-1"></i>Record First Payment
</a>
</div>
{% endif %}
{% endblock %}
+13 -3
View File
@@ -165,12 +165,22 @@
.pcard { padding: 14px; }
.stat-card { padding: 14px 16px; }
.stat-card .stat-value { font-size: 20px; }
/* Tables: scroll horizontally on small screens.
Targets both manual .table-wrap and the common .pcard.p-0 pattern. */
/* Tables: scroll horizontally on small screens */
.table-wrap, .pcard.p-0 { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.pfm-table { min-width: 560px; }
.pfm-table { min-width: 580px; }
/* Hide low-priority columns */
.d-mob-none { display: none !important; }
/* Topbar title: truncate so action buttons always fit */
.tb-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* Flash: stretch full width */
.flash-wrap { left: 8px; right: 8px; max-width: none; }
}
/* Extra-small screens: hide button label text, keep icons */
@media (max-width: 575px) {
#main { padding: 10px; }
.pcard { padding: 12px; }
.btn-label { display: none; }
.tb-right .btn { padding-left: 8px; padding-right: 8px; }
}
.sb-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.4); z-index: 1039; }
.sb-overlay.on { display: block; }
+6 -6
View File
@@ -11,21 +11,21 @@
{% block topbar_actions %}
<div class="d-flex align-items-center gap-1">
<a href="?period=this_month" class="btn btn-sm btn-outline-secondary period-btn {% if period=='this_month' %}active{% endif %}" style="font-size:12px;">This Month</a>
<a href="?period=last_month" class="btn btn-sm btn-outline-secondary period-btn {% if period=='last_month' %}active{% endif %}" style="font-size:12px;">Last Month</a>
<button class="btn btn-sm btn-outline-secondary period-btn {% if period=='custom' %}active{% endif %}" style="font-size:12px;" data-bs-toggle="modal" data-bs-target="#customModal">Custom</button>
<a href="?period=this_month" class="btn btn-sm btn-outline-secondary period-btn {% if period=='this_month' %}active{% endif %}" style="font-size:12px;"><i class="bi bi-calendar-check"></i><span class="btn-label ms-1">This Month</span></a>
<a href="?period=last_month" class="btn btn-sm btn-outline-secondary period-btn {% if period=='last_month' %}active{% endif %}" style="font-size:12px;"><i class="bi bi-calendar"></i><span class="btn-label ms-1">Last Month</span></a>
<button class="btn btn-sm btn-outline-secondary period-btn {% if period=='custom' %}active{% endif %}" style="font-size:12px;" data-bs-toggle="modal" data-bs-target="#customModal"><i class="bi bi-calendar-range"></i><span class="btn-label ms-1">Custom</span></button>
</div>
{% endblock %}
{% block content %}
<div class="d-flex align-items-center justify-content-between mb-4">
<div class="d-flex align-items-start align-items-sm-center justify-content-between flex-wrap gap-2 mb-4">
<div>
<h5 class="mb-0 fw-semibold">{{ period_label }}</h5>
<small class="text-muted">{{ date_from.strftime('%b %d') }} {{ date_to.strftime('%b %d, %Y') }}</small>
</div>
<div class="d-flex gap-2">
<a href="{{ url_for('transactions.new', type='income') }}" class="btn btn-sm" style="background:#d1fae5;color:#065f46;font-size:12px;"><i class="bi bi-plus-lg me-1"></i>Income</a>
<a href="{{ url_for('transactions.new', type='expense') }}" class="btn btn-sm" style="background:#fee2e2;color:#991b1b;font-size:12px;"><i class="bi bi-plus-lg me-1"></i>Expense</a>
<a href="{{ url_for('transactions.new', type='income') }}" class="btn btn-sm" style="background:#d1fae5;color:#065f46;font-size:12px;"><i class="bi bi-plus-lg"></i><span class="btn-label ms-1">Income</span></a>
<a href="{{ url_for('transactions.new', type='expense') }}" class="btn btn-sm" style="background:#fee2e2;color:#991b1b;font-size:12px;"><i class="bi bi-dash-lg"></i><span class="btn-label ms-1">Expense</span></a>
</div>
</div>
+2 -2
View File
@@ -152,7 +152,7 @@
<tr>
<th style="padding-left:20px;">Asset</th>
<th class="text-end">Price</th>
<th class="text-end">1D Chg</th>
<th class="text-end d-mob-none">1D Chg</th>
<th class="text-end">Value</th>
<th class="text-end" style="padding-right:8px;">P&amp;L</th>
<th style="width:36px;"></th>
@@ -184,7 +184,7 @@
<span class="text-muted" style="font-size:12px;"></span>
{% endif %}
</td>
<td class="text-end" id="chg-{{ inv.id }}">
<td class="text-end d-mob-none" id="chg-{{ inv.id }}">
{% if inv.ticker %}
<span class="chg-badge chg-loading"></span>
{% else %}
+7 -7
View File
@@ -3,9 +3,9 @@
{% block page_title %}Transactions{% endblock %}
{% block topbar_actions %}
<a href="{{ url_for('transactions.new', type='income') }}" class="btn btn-sm" style="background:#d1fae5;color:#065f46;font-size:12px;"><i class="bi bi-plus-lg me-1"></i>Income</a>
<a href="{{ url_for('transactions.new', type='expense') }}" class="btn btn-sm ms-1" style="background:#fee2e2;color:#991b1b;font-size:12px;"><i class="bi bi-plus-lg me-1"></i>Expense</a>
<a href="{{ url_for('transactions.transfer') }}" class="btn btn-sm btn-outline-secondary ms-1" style="font-size:12px;"><i class="bi bi-arrow-left-right me-1"></i>Transfer</a>
<a href="{{ url_for('transactions.new', type='income') }}" class="btn btn-sm" style="background:#d1fae5;color:#065f46;font-size:12px;"><i class="bi bi-plus-lg"></i><span class="btn-label ms-1">Income</span></a>
<a href="{{ url_for('transactions.new', type='expense') }}" class="btn btn-sm ms-1" style="background:#fee2e2;color:#991b1b;font-size:12px;"><i class="bi bi-dash-lg"></i><span class="btn-label ms-1">Expense</span></a>
<a href="{{ url_for('transactions.transfer') }}" class="btn btn-sm btn-outline-secondary ms-1" style="font-size:12px;"><i class="bi bi-arrow-left-right"></i><span class="btn-label ms-1">Transfer</span></a>
{% endblock %}
{% block content %}
@@ -68,8 +68,8 @@
<tr>
<th style="padding-left:20px;">Date</th>
<th>Description</th>
<th>Category</th>
<th>Account</th>
<th class="d-mob-none">Category</th>
<th class="d-mob-none">Account</th>
<th class="text-end">Amount</th>
<th class="text-end" style="padding-right:20px;">Actions</th>
</tr>
@@ -82,14 +82,14 @@
<div style="font-size:13px;font-weight:500;">{{ txn.description }}</div>
{% if txn.notes %}<div style="font-size:11px;color:var(--muted);">{{ txn.notes | truncate(60) }}</div>{% endif %}
</td>
<td>
<td class="d-mob-none">
{% if txn.category %}
<span style="font-size:12px;white-space:nowrap;">
<i class="bi {{ txn.category.icon }}" style="color:{{ txn.category.color }};"></i> {{ txn.category.name }}
</span>
{% else %}<span class="text-muted" style="font-size:12px;"></span>{% endif %}
</td>
<td style="font-size:12px;color:var(--muted);">{{ txn.account.name if txn.account else '—' }}</td>
<td class="d-mob-none" style="font-size:12px;color:var(--muted);">{{ txn.account.name if txn.account else '—' }}</td>
<td class="text-end mono {% if txn.transaction_type=='income' %}text-income{% else %}text-expense{% endif %}" style="font-size:13px;font-weight:600;white-space:nowrap;">
{% if txn.transaction_type=='income' %}+{% else %}-{% endif %}{{ txn.amount | currency }}
</td>