120 lines
5.6 KiB
HTML
120 lines
5.6 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Overview{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="section-panel">
|
|
<div class="d-flex flex-column flex-lg-row justify-content-between align-items-lg-end gap-3">
|
|
<div>
|
|
<h1 class="h2 mb-2">Portfolio Overview</h1>
|
|
<p class="text-secondary mb-0">Latest synced account balances and historical portfolio value.</p>
|
|
</div>
|
|
<div class="text-lg-end">
|
|
<div class="metric-label">Accounts</div>
|
|
<div class="metric-value">{{ accounts|length }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-4 mb-4">
|
|
<div class="col-12 col-lg-8">
|
|
<section class="section-panel h-100">
|
|
<div class="d-flex justify-content-between align-items-start mb-3">
|
|
<div>
|
|
<h2 class="h5 mb-1">Portfolio Value Over Time</h2>
|
|
<p class="text-secondary mb-0">Running total based on the latest known balance for each account at every sync.</p>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex justify-content-between align-items-end gap-3 flex-wrap mb-3">
|
|
{% if latest_portfolio_point %}
|
|
<div class="text-end">
|
|
<div class="metric-label">Latest Total</div>
|
|
<div class="fw-semibold fs-5">${{ latest_portfolio_point.display_value }}</div>
|
|
</div>
|
|
{% endif %}
|
|
<form method="get" class="range-form">
|
|
<label for="portfolio-range" class="metric-label mb-0">Range</label>
|
|
<select id="portfolio-range" name="range" class="form-select form-select-sm range-select" onchange="this.form.submit()">
|
|
{% for value, label in date_range_options %}
|
|
<option value="{{ value }}"{% if selected_range == value %} selected{% endif %}>{{ label }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</form>
|
|
</div>
|
|
|
|
{% if portfolio_timeline %}
|
|
<div class="chart-frame">
|
|
<div class="chart-axis chart-axis-top">
|
|
<span>${{ portfolio_chart.max_label }}</span>
|
|
<span>Change shown on hover</span>
|
|
</div>
|
|
<svg class="chart-svg" viewBox="0 0 100 100" preserveAspectRatio="none" role="img" aria-label="Portfolio value over time">
|
|
<line class="chart-baseline" x1="0" y1="100" x2="100" y2="100"></line>
|
|
<path class="chart-line" d="{{ portfolio_chart.path }}"></path>
|
|
{% for point in portfolio_chart.points %}
|
|
<circle class="chart-point" cx="{{ point.x }}" cy="{{ point.y }}" r="2.2">
|
|
<title>{{ point.label }} | ${{ point.display_value }} | {{ point.change_display }}</title>
|
|
</circle>
|
|
{% endfor %}
|
|
</svg>
|
|
<div class="chart-axis chart-axis-bottom">
|
|
<span>{{ portfolio_chart.start_label }}</span>
|
|
<span>${{ portfolio_chart.min_label }}</span>
|
|
<span>{{ portfolio_chart.end_label }}</span>
|
|
</div>
|
|
</div>
|
|
{% else %}
|
|
<p class="text-secondary mb-0">Run a brokerage sync to start building a portfolio history.</p>
|
|
{% endif %}
|
|
</section>
|
|
</div>
|
|
<div class="col-12 col-lg-4">
|
|
<section class="section-panel h-100">
|
|
<h2 class="h5 mb-3">Recent Sync Points</h2>
|
|
{% if portfolio_timeline %}
|
|
<div class="list-group list-group-flush timeline-list">
|
|
{% for point in portfolio_timeline %}
|
|
<div class="list-group-item">
|
|
<div class="d-flex justify-content-between gap-3">
|
|
<span class="text-secondary">{{ point.label }}</span>
|
|
<strong>${{ point.display_value }}</strong>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% else %}
|
|
<p class="text-secondary mb-0">No historical snapshots yet.</p>
|
|
{% endif %}
|
|
</section>
|
|
</div>
|
|
</div>
|
|
|
|
<section class="section-panel">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<h2 class="h5 mb-0">Accounts</h2>
|
|
<span class="text-secondary small">Click an account to view holdings and its value history.</span>
|
|
</div>
|
|
|
|
<div class="list-group">
|
|
{% for account in accounts %}
|
|
<a href="portfolio/{{ account.id }}" class="list-group-item list-group-item-action">
|
|
<div class="row align-items-center">
|
|
<div class="col-12 col-md-8">
|
|
<h3 class="h6 mb-1">{{ account.name }}</h3>
|
|
<div class="text-secondary small">{{ account.provider|default:"manual" }}{% if account.number %} • {{ account.number }}{% endif %}</div>
|
|
</div>
|
|
<div class="col-12 col-md-4 text-md-end mt-2 mt-md-0">
|
|
<strong>${{ account.balance }}</strong>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
{% empty %}
|
|
<div class="list-group-item">
|
|
<p class="text-secondary mb-0">No accounts yet. Run a brokerage sync to populate this view.</p>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</section>
|
|
|
|
{% endblock %}
|