06/05 Optimize app

This commit is contained in:
2026-06-05 15:51:57 -04:00
parent 458044201e
commit 025f3f8823
14 changed files with 425 additions and 64 deletions
+11 -1
View File
@@ -189,7 +189,13 @@
.btn-label { display: none; }
.tb-right .btn { padding-left: 8px; padding-right: 8px; }
.stat-card .stat-value { font-size: 16px; }
/* AI chat: shorter on small screens so it doesn't eat the whole viewport */
#chatMessages { height: 300px !important; }
/* Projection / combo charts: cap height so they're not giant on phones */
.proj-chart-wrap { height: 200px !important; }
}
/* table-wrap inside a regular (padded) pcard also needs overflow-x */
.pcard .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* Keyboard shortcut cheatsheet modal */
#kbd-modal .kbd-row { display: flex; align-items: center; justify-content: space-between; padding: 6px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
#kbd-modal .kbd-row:last-child { border: none; }
@@ -304,7 +310,11 @@
class="sb-link {% if request.blueprint == 'transactions' %}active{% endif %}"
>
<i class="bi bi-arrow-left-right"></i
><span class="lt">Transactions</span>
><span class="lt">Transactions
{% if plaid_review_count > 0 %}
<span style="margin-left:6px;background:#7c3aed;color:#fff;font-size:10px;font-weight:700;padding:1px 5px;border-radius:10px;line-height:1.4;">{{ plaid_review_count }}</span>
{% endif %}
</span>
</a>
<a
href="{{ url_for('transactions.new', type='income') }}"
+56
View File
@@ -362,6 +362,62 @@
</div>
</div>
<!-- Upcoming Bills -->
{% if upcoming_bills %}
<div class="pcard mt-3">
<div class="d-flex justify-content-between align-items-center mb-3">
<span class="pcard-title mb-0">Upcoming Bills <span style="font-size:11px;font-weight:400;color:var(--muted);">(next 14 days)</span></span>
<a href="{{ url_for('settings.recurring') }}" style="font-size:12px;color:#3b82f6;">Manage →</a>
</div>
<div class="table-wrap">
<table class="pfm-table">
<thead>
<tr>
<th style="padding-left:16px;">Rule</th>
<th class="d-mob-none">Frequency</th>
<th>Due</th>
<th class="text-end">Amount</th>
<th class="text-end d-mob-none" style="padding-right:16px;">Account</th>
</tr>
</thead>
<tbody>
{% for rule in upcoming_bills %}
<tr>
<td style="padding-left:16px;">
<div class="d-flex align-items-center gap-2">
{% if rule.category %}
<div style="width:26px;height:26px;border-radius:6px;background:{{ rule.category.color }}22;color:{{ rule.category.color }};display:flex;align-items:center;justify-content:center;font-size:12px;flex-shrink:0;">
<i class="bi {{ rule.category.icon }}"></i>
</div>
{% else %}
<div style="width:26px;height:26px;border-radius:6px;background:#f1f5f9;color:#94a3b8;display:flex;align-items:center;justify-content:center;font-size:12px;flex-shrink:0;">
<i class="bi bi-arrow-repeat"></i>
</div>
{% endif %}
<span style="font-size:13px;font-weight:500;">{{ rule.name }}</span>
</div>
</td>
<td class="d-mob-none" style="font-size:12px;color:var(--muted);">{{ rule.frequency | title }}</td>
<td>
{% set days_until = (rule.next_run - today).days %}
<span style="font-size:12px;" class="{% if days_until == 0 %}text-expense fw-semibold{% elif days_until <= 3 %}text-warning{% endif %}">
{% if days_until == 0 %}Today
{% elif days_until == 1 %}Tomorrow
{% else %}{{ rule.next_run.strftime('%b %d') }}{% endif %}
</span>
</td>
<td class="text-end mono {% if rule.transaction_type=='income' %}text-income{% else %}text-expense{% endif %}" style="font-size:13px;font-weight:600;">
{% if rule.transaction_type=='income' %}+{% else %}-{% endif %}{{ rule.amount | currency }}
</td>
<td class="text-end d-mob-none" style="font-size:12px;color:var(--muted);padding-right:16px;">{{ rule.account.name if rule.account else '—' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
<!-- Custom Range Modal -->
<div class="modal fade" id="customModal" tabindex="-1">
<div class="modal-dialog modal-sm">
+2
View File
@@ -118,6 +118,7 @@
{% if completed_goals %}
<div class="pcard">
<div class="pcard-title mb-3">Completed Goals 🎉</div>
<div class="table-wrap">
<table class="pfm-table">
<thead><tr><th>Goal</th><th>Target</th><th>Completed</th></tr></thead>
<tbody>
@@ -137,6 +138,7 @@
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
{% endblock %}
+11 -1
View File
@@ -78,6 +78,14 @@
</div>
{% else %}
<!-- Price alerts banner (populated by AJAX) -->
<div id="price-alert-banner" style="display:none;" class="alert d-flex align-items-start gap-2 mb-3" style="background:#fef3c7;border:1px solid #fcd34d;color:#78350f;font-size:13px;border-radius:8px;padding:10px 14px;">
<i class="bi bi-graph-up-arrow flex-shrink-0 mt-1" style="color:#d97706;"></i>
<div class="flex-grow-1" id="price-alert-text"></div>
<button type="button" onclick="document.getElementById('price-alert-banner').style.display='none';"
style="background:none;border:none;color:#92400e;cursor:pointer;font-size:16px;line-height:1;padding:0 4px;" title="Dismiss">×</button>
</div>
<!-- Summary cards -->
<div class="row g-3 mb-4">
<div class="col-6 col-xl-3">
@@ -134,7 +142,8 @@
{# ── Reusable holdings table macro ──────────────────────────────────────── #}
{% macro holdings_table(inv_list) %}
<table class="pfm-table">
<div class="table-wrap">
<table class="pfm-table wide">
<thead>
<tr>
<th style="padding-left:20px;">Asset</th>
@@ -219,6 +228,7 @@
{% endfor %}
</tbody>
</table>
</div>
{% endmacro %}
<!-- Chart + Allocation -->
+1 -1
View File
@@ -135,7 +135,7 @@
</div>
<!-- Chart -->
<div id="proj-chart-wrap" style="position:relative;height:200px;">
<div id="proj-chart-wrap" class="proj-chart-wrap" style="position:relative;height:200px;">
<canvas id="projChart"></canvas>
</div>
<div id="proj-loading" class="text-center py-4 text-muted" style="display:none;">
+10
View File
@@ -9,6 +9,16 @@
{% endblock %}
{% block content %}
{% if plaid_review_count > 0 %}
<div class="alert d-flex align-items-center gap-2 mb-3" style="background:#f5f3ff;border:1px solid #ddd6fe;color:#5b21b6;font-size:13px;border-radius:8px;padding:10px 14px;">
<i class="bi bi-cloud-download flex-shrink-0"></i>
<div class="flex-grow-1">
<strong>{{ plaid_review_count }} Plaid transaction{{ 's' if plaid_review_count != 1 else '' }}</strong>
imported via webhook without a category.
<a href="{{ url_for('transactions.index') }}" style="color:#7c3aed;font-weight:600;" class="ms-1">Review &amp; categorize →</a>
</div>
</div>
{% endif %}
<!-- Tabs -->
<div class="d-flex gap-1 mb-3">
<a href="{{ url_for('transactions.index', tab='expense', q=search, account_id=account_id, category_id=category_id, date_from=date_from, date_to=date_to) }}"