97 lines
5.4 KiB
HTML
97 lines
5.4 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}Recurring Rules{% endblock %}
|
||
{% block page_title %}Recurring Transactions{% endblock %}
|
||
|
||
{% block topbar_actions %}
|
||
<form method="POST" action="{{ url_for('settings.recurring_run') }}" class="d-inline">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||
<button type="submit" class="btn btn-sm btn-outline-secondary me-1" style="font-size:12px;" title="Process all due rules now">
|
||
<i class="bi bi-play-fill me-1"></i>Run Now
|
||
</button>
|
||
</form>
|
||
<a href="{{ url_for('settings.recurring_new') }}" class="btn btn-sm btn-primary" style="font-size:12px;"><i class="bi bi-plus-lg me-1"></i>New Rule</a>
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="row g-3">
|
||
<div class="col-12 col-lg-7">
|
||
<div class="pcard p-0">
|
||
<div class="px-4 py-3" style="border-bottom:1px solid var(--border);">
|
||
<span class="pcard-title mb-0">Rules ({{ rules | length }})</span>
|
||
</div>
|
||
{% if rules %}
|
||
<table class="pfm-table">
|
||
<thead>
|
||
<tr>
|
||
<th style="padding-left:20px;">Name</th>
|
||
<th>Frequency</th>
|
||
<th class="text-end">Amount</th>
|
||
<th class="text-end">Next Run</th>
|
||
<th class="text-end" style="padding-right:20px;"></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for rule in rules %}
|
||
<tr style="{% if not rule.is_active %}opacity:.5;{% endif %}">
|
||
<td style="padding-left:20px;">
|
||
<div style="font-size:13px;font-weight:500;">{{ rule.name }}</div>
|
||
<div style="font-size:11px;color:var(--muted);">{{ rule.description }}</div>
|
||
</td>
|
||
<td>
|
||
<span class="badge" style="font-size:11px;background:#f1f5f9;color:var(--muted);">{{ rule.frequency | title }}</span>
|
||
<span class="badge ms-1 {% if rule.transaction_type == 'income' %}badge-income{% else %}badge-expense{% endif %}" style="font-size:11px;">{{ rule.transaction_type | title }}</span>
|
||
</td>
|
||
<td class="text-end mono {% if rule.transaction_type == 'income' %}text-income{% else %}text-expense{% endif %}" style="font-size:13px;font-weight:500;">{{ rule.amount | currency }}</td>
|
||
<td class="text-end" style="font-size:12px;color:var(--muted);white-space:nowrap;">
|
||
{{ rule.next_run.strftime('%b %d') if rule.next_run else '—' }}
|
||
</td>
|
||
<td class="text-end" style="padding-right:20px;white-space:nowrap;">
|
||
<a href="{{ url_for('settings.recurring_edit', id=rule.id) }}" class="btn btn-sm btn-outline-secondary" style="font-size:11px;padding:2px 7px;">Edit</a>
|
||
<form method="POST" action="{{ url_for('settings.recurring_toggle', id=rule.id) }}" style="display:inline;">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||
<button type="submit" class="btn btn-sm btn-outline-secondary ms-1" style="font-size:11px;padding:2px 7px;">
|
||
{% if rule.is_active %}Pause{% else %}Enable{% endif %}
|
||
</button>
|
||
</form>
|
||
<form method="POST" action="{{ url_for('settings.recurring_delete', id=rule.id) }}" style="display:inline;" onsubmit="return confirm('Delete this rule?')">
|
||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||
<button type="submit" class="btn btn-sm btn-outline-danger ms-1" style="font-size:11px;padding:2px 7px;">×</button>
|
||
</form>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% else %}
|
||
<div class="text-center py-5">
|
||
<i class="bi bi-repeat text-muted" style="font-size:2.5rem;"></i>
|
||
<p class="text-muted small mt-2 mb-2">No recurring rules yet.</p>
|
||
<a href="{{ url_for('settings.recurring_new') }}" class="btn btn-sm btn-primary">Create First Rule</a>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-12 col-lg-5">
|
||
<div class="pcard">
|
||
<div class="pcard-title mb-3">Upcoming (30 days)</div>
|
||
{% if upcoming %}
|
||
{% for item in upcoming[:15] %}
|
||
<div class="d-flex justify-content-between align-items-center py-2" style="border-bottom:1px solid var(--border);">
|
||
<div>
|
||
<div style="font-size:13px;">{{ item.description }}</div>
|
||
<div style="font-size:11px;color:var(--muted);">{{ item.date.strftime('%b %d, %Y') }}</div>
|
||
</div>
|
||
<span class="mono {% if item.type == 'income' %}text-income{% else %}text-expense{% endif %}" style="font-size:13px;font-weight:500;">
|
||
{% if item.type == 'income' %}+{% else %}-{% endif %}{{ item.amount | currency }}
|
||
</span>
|
||
</div>
|
||
{% endfor %}
|
||
{% else %}
|
||
<p class="text-muted small">No upcoming recurring transactions.</p>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|