06/05 Optimize app
This commit is contained in:
+11
-1
@@ -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') }}"
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -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;">
|
||||
|
||||
@@ -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 & 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) }}"
|
||||
|
||||
Reference in New Issue
Block a user