Files
Personal-Finance-Management/app/templates/goals/index.html
T
2026-05-31 16:18:37 -04:00

143 lines
7.9 KiB
HTML

{% extends "base.html" %}
{% block title %}Goals{% endblock %}
{% block page_title %}Goals & Savings{% endblock %}
{% block extra_css %}
.goal-card { border-radius: 12px; border: 1px solid var(--border); background: var(--card-bg); padding: 18px 20px; }
.goal-progress { height: 10px; background: #f1f5f9; border-radius: 5px; overflow: hidden; margin: 10px 0 6px; }
.goal-progress-fill { height: 100%; border-radius: 5px; transition: width .6s ease; }
{% endblock %}
{% block topbar_actions %}
<a href="{{ url_for('goals.new') }}" class="btn btn-sm btn-primary" style="font-size:12px;"><i class="bi bi-plus-lg me-1"></i>New Goal</a>
{% endblock %}
{% block content %}
<!-- Emergency Fund -->
{% if emergency and emergency.avg_monthly_expense > 0 %}
<div class="pcard mb-4" style="border-left:4px solid #f59e0b;">
<div class="d-flex justify-content-between align-items-start mb-2">
<div>
<span style="font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.07em;color:#92400e;">Emergency Fund</span>
<div style="font-size:13px;color:var(--muted);margin-top:2px;">Based on avg monthly expense of <span class="mono">{{ emergency.avg_monthly_expense | currency }}</span></div>
</div>
<span class="mono fw-bold" style="font-size:18px;color:{% if emergency.months_covered >= 6 %}#10b981{% elif emergency.months_covered >= 3 %}#f59e0b{% else %}#ef4444{% endif %};">
{{ emergency.months_covered }}mo
</span>
</div>
<div class="row g-3">
<div class="col-6">
<div style="font-size:11px;color:var(--muted);margin-bottom:4px;">3-Month Target: <span class="mono">{{ emergency.target_3mo | currency }}</span></div>
<div style="height:6px;background:#f1f5f9;border-radius:3px;"><div style="height:6px;border-radius:3px;background:#f59e0b;width:{{ emergency.pct_3mo }}%;"></div></div>
<small class="text-muted" style="font-size:10px;">{{ emergency.pct_3mo }}%</small>
</div>
<div class="col-6">
<div style="font-size:11px;color:var(--muted);margin-bottom:4px;">6-Month Target: <span class="mono">{{ emergency.target_6mo | currency }}</span></div>
<div style="height:6px;background:#f1f5f9;border-radius:3px;"><div style="height:6px;border-radius:3px;background:#10b981;width:{{ emergency.pct_6mo }}%;"></div></div>
<small class="text-muted" style="font-size:10px;">{{ emergency.pct_6mo }}%</small>
</div>
</div>
<div style="font-size:12px;margin-top:8px;color:var(--muted);">
Liquid assets: <span class="mono text-income">{{ emergency.liquid_assets | currency }}</span>
</div>
</div>
{% endif %}
<!-- Active Goals -->
{% if active_goals %}
<div class="row g-3 mb-4">
{% for goal in active_goals %}
<div class="col-12 col-md-6 col-xl-4">
<div class="goal-card" style="border-left: 4px solid {{ goal.color }};">
<div class="d-flex justify-content-between align-items-start">
<div class="d-flex align-items-center gap-2">
<div style="width:36px;height:36px;border-radius:9px;background:{{ goal.color }}22;color:{{ goal.color }};display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0;">
<i class="bi {{ goal.icon }}"></i>
</div>
<div>
<div style="font-size:14px;font-weight:600;">{{ goal.name }}</div>
{% if goal.target_date %}
<div style="font-size:11px;color:var(--muted);">By {{ goal.target_date.strftime('%b %d, %Y') }}</div>
{% endif %}
</div>
</div>
<div class="dropdown">
<button class="btn btn-sm" style="background:none;border:none;color:var(--muted);padding:2px 6px;" data-bs-toggle="dropdown"><i class="bi bi-three-dots"></i></button>
<ul class="dropdown-menu dropdown-menu-end" style="font-size:13px;">
<li><a class="dropdown-item" href="{{ url_for('goals.contribute', id=goal.id) }}"><i class="bi bi-plus-circle me-2"></i>Add Contribution</a></li>
<li><a class="dropdown-item" href="{{ url_for('goals.contributions', id=goal.id) }}"><i class="bi bi-clock-history me-2"></i>History</a></li>
<li><a class="dropdown-item" href="{{ url_for('goals.edit', id=goal.id) }}"><i class="bi bi-pencil me-2"></i>Edit</a></li>
<li><hr class="dropdown-divider"></li>
<li>
<form method="POST" action="{{ url_for('goals.delete', id=goal.id) }}" onsubmit="return confirm('Delete this goal?')">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<button type="submit" class="dropdown-item text-danger"><i class="bi bi-trash me-2"></i>Delete</button>
</form>
</li>
</ul>
</div>
</div>
<div class="goal-progress">
<div class="goal-progress-fill" style="width:{{ goal.progress_percent }}%;background:{{ goal.color }};"></div>
</div>
<div class="d-flex justify-content-between align-items-center">
<span class="mono" style="font-size:13px;font-weight:600;color:{{ goal.color }};">{{ goal.current_amount | currency }}</span>
<span class="text-muted mono" style="font-size:12px;">/ {{ goal.target_amount | currency }}</span>
</div>
<div class="d-flex justify-content-between align-items-center mt-2">
<small class="text-muted">{{ goal.progress_percent }}% complete</small>
{% if projections[goal.id] %}
<small class="text-muted"><i class="bi bi-calendar-check me-1"></i>~{{ projections[goal.id].strftime('%b %Y') }}</small>
{% endif %}
</div>
{% if goal.description %}
<div style="font-size:12px;color:var(--muted);margin-top:8px;">{{ goal.description | truncate(80) }}</div>
{% endif %}
<a href="{{ url_for('goals.contribute', id=goal.id) }}" class="btn btn-sm w-100 mt-3" style="background:{{ goal.color }}22;color:{{ goal.color }};border:1px solid {{ goal.color }}44;font-size:12px;">
<i class="bi bi-plus-lg me-1"></i>Add Contribution
</a>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="pcard text-center py-5 mb-4">
<i class="bi bi-bullseye text-muted" style="font-size:3rem;"></i>
<h5 class="mt-3 mb-1">No active goals</h5>
<p class="text-muted small mb-3">Set savings goals and track your progress.</p>
<a href="{{ url_for('goals.new') }}" class="btn btn-primary btn-sm">Create First Goal</a>
</div>
{% endif %}
<!-- Completed Goals -->
{% if completed_goals %}
<div class="pcard">
<div class="pcard-title mb-3">Completed Goals 🎉</div>
<table class="pfm-table">
<thead><tr><th>Goal</th><th>Target</th><th>Completed</th></tr></thead>
<tbody>
{% for goal in completed_goals %}
<tr>
<td>
<div class="d-flex align-items-center gap-2">
<div style="width:26px;height:26px;border-radius:6px;background:{{ goal.color }}22;color:{{ goal.color }};display:flex;align-items:center;justify-content:center;font-size:13px;">
<i class="bi {{ goal.icon }}"></i>
</div>
<span style="font-size:13px;">{{ goal.name }}</span>
</div>
</td>
<td><span class="mono" style="font-size:13px;">{{ goal.target_amount | currency }}</span></td>
<td style="font-size:12px;color:var(--muted);">{{ goal.completed_at.strftime('%b %d, %Y') if goal.completed_at else '—' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
{% endblock %}