Files
2026-04-30 08:02:03 +02:00

138 lines
5.2 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Portfolio — Samantha Friis</title>
<link href="https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Fraunces:ital,wght@0,300;0,400;0,600;1,300;1,400&display=swap" rel="stylesheet"/>
<link rel="stylesheet" href="/styles/main">
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
</head>
<body>
<div class="container">
<header>
<a href="/" class="back">← back,</a>
<a href="/login" class="back"> login</a>
<p class="tag">// portfolio</p>
<h1>Investment<br/><span>Portfolio</span></h1>
<p class="header-sub">Equity positions &nbsp;·&nbsp; Personal research</p>
</header>
<!-- Health bar: polls every 60s, shows error on failure -->
<div class="status-bar"
hx-get="/health/fragment"
hx-trigger="load, every 60s"
hx-target="this"
hx-swap="innerHTML"
hx-on::response-error="this.innerHTML = '<span class=\'status-dot error\'></span><span>backend unreachable</span><span class=\'status-spacer\'></span><button class=\'refresh-btn\' hx-get=\'/health/fragment\' hx-target=\'closest .status-bar\' hx-swap=\'innerHTML\' onclick=\'htmx.process(this)\'>↺ retry</button>'"
hx-on::send-error="this.innerHTML = '<span class=\'status-dot error\'></span><span>failed to connect</span><span class=\'status-spacer\'></span><button class=\'refresh-btn\' hx-get=\'/health/fragment\' hx-target=\'closest .status-bar\' hx-swap=\'innerHTML\' onclick=\'htmx.process(this)\'>↺ retry</button>'">
<span class="status-dot loading"></span>
<span>connecting to backend…</span>
<span class="status-spacer"></span>
<button class="refresh-btn"
hx-get="/health/fragment"
hx-target="closest .status-bar"
hx-swap="innerHTML">↺ refresh</button>
</div>
<!-- Summary cards -->
<div class="cards"
hx-get="/summary/fragment"
hx-trigger="load"
hx-swap="outerHTML">
<div class="card"><p class="card-label">Positions</p><p class="card-value dim"></p></div>
<div class="card"><p class="card-label">Total Shares</p><p class="card-value dim"></p></div>
<div class="card"><p class="card-label">Total Trades</p><p class="card-value dim"></p></div>
<div class="card"><p class="card-label">Currencies</p><p class="card-value dim"></p></div>
</div>
<!-- Positions table -->
<p class="section-label">// <span>positions</span></p>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Symbol</th><th>Currency</th><th>Shares</th>
<th>Cost Basis</th><th>Weight</th>
</tr>
</thead>
<tbody hx-get="/positions/fragment"
hx-trigger="load"
hx-swap="innerHTML">
<tr class="state-row"><td colspan="5">loading…</td></tr>
</tbody>
</table>
</div>
<!-- Companies table -->
<p class="section-label">// <span>companies</span> — tracked universe</p>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Symbol</th><th>Currency</th><th>Price</th>
<th>Shares Outstanding</th><th>Market Cap</th>
</tr>
</thead>
<tbody hx-get="/company/fragment"
hx-trigger="load"
hx-swap="innerHTML">
<tr class="state-row"><td colspan="5">loading…</td></tr>
</tbody>
</table>
</div>
<!-- Trades accordion: lazy-loads on open -->
<div class="trades-section">
<button class="trades-toggle"
aria-expanded="false"
onclick="this.setAttribute('aria-expanded', this.getAttribute('aria-expanded')==='true'?'false':'true'); this.nextElementSibling.classList.toggle('open')">
<span class="toggle-label">// <span>trade history</span> — all executed orders</span>
<span class="toggle-icon"></span>
</button>
<div class="trades-body" id="tradesAccordion">
<div class="trades-inner">
<!-- Filter buttons swap only the tbody -->
<div class="trades-filter" id="tradeFilters">
<button class="filter-btn active"
hx-get="/trade/fragment"
hx-target="#tradesBody"
hx-swap="innerHTML">All</button>
</div>
<p class="trades-count"
hx-get="/trade/count"
hx-trigger="load from:#tradesAccordion"
hx-swap="innerHTML"></p>
<div class="trades-table-wrap">
<table class="trades-table">
<thead>
<tr>
<th>Symbol</th><th>Asset</th><th>Currency</th>
<th>Date</th><th>Dir</th><th>Qty</th><th>Price</th>
</tr>
</thead>
<tbody id="tradesBody"
hx-get="/trade/fragment"
hx-trigger="revealed"
hx-swap="innerHTML">
<tr class="state-row"><td colspan="7">expand to load trades</td></tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<footer>
<a href="mailto:me@samantha42.xyz">me@samantha42.xyz</a>
<p class="footer-copy">&copy; 2026 — All rights reserved</p>
</footer>
</div>
</body>
</html>