06/03 Optimize codes, fix transactions import functions

This commit is contained in:
2026-06-03 10:44:36 -04:00
parent faacd4d91a
commit 3ce779ccfd
3 changed files with 79 additions and 10 deletions
+59 -6
View File
@@ -82,12 +82,24 @@
<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">
{% 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 class="d-mob-none" style="min-width:150px;">
<div class="d-flex align-items-center gap-1">
<i id="cat-icon-{{ txn.id }}"
class="bi {{ txn.category.icon if txn.category else 'bi-tag' }}"
style="font-size:12px;color:{{ txn.category.color if txn.category else '#94a3b8' }};flex-shrink:0;"></i>
<select class="cat-select"
data-txn-id="{{ txn.id }}"
title="Change category"
style="font-size:12px;border:1px solid transparent;border-radius:4px;background:transparent;padding:2px 4px;cursor:pointer;max-width:130px;color:var(--text);">
<option value="">— None —</option>
{% for cat in categories %}
<option value="{{ cat.id }}"
data-icon="{{ cat.icon }}"
data-color="{{ cat.color }}"
{% if txn.category_id == cat.id %}selected{% endif %}>{{ cat.name }}</option>
{% endfor %}
</select>
</div>
</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;">
@@ -141,3 +153,44 @@
{% endif %}
</div>
{% endblock %}
{% block extra_js %}
<style>
.cat-select:hover { border-color: var(--border) !important; background: #f8fafc !important; }
.cat-select:focus { outline: none; border-color: #3b82f6 !important; background: #fff !important; }
</style>
<script>
const CSRF = document.querySelector('meta[name="csrf-token"]').content;
document.querySelectorAll('.cat-select').forEach(sel => {
sel.addEventListener('change', function () {
const txnId = this.dataset.txnId;
const catId = this.value || null;
const opt = this.options[this.selectedIndex];
const icon = document.getElementById('cat-icon-' + txnId);
if (icon) {
icon.className = 'bi ' + (catId ? opt.dataset.icon : 'bi-tag');
icon.style.color = catId ? opt.dataset.color : '#94a3b8';
}
fetch(`/transactions/${txnId}/set-category`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': CSRF },
body: JSON.stringify({ category_id: catId ? parseInt(catId) : null }),
})
.then(r => r.json())
.then(data => {
if (data.ok) {
sel.style.color = '#10b981';
setTimeout(() => sel.style.color = '', 1500);
}
})
.catch(() => {
sel.style.color = '#ef4444';
setTimeout(() => sel.style.color = '', 2000);
});
});
});
</script>
{% endblock %}