469 lines
25 KiB
PHP
469 lines
25 KiB
PHP
<?php $ownerQuery = $isAdmin ? '?owner_sub=' . urlencode((string) $ownerSub) : ''; ?>
|
|
<div class="card">
|
|
<div class="pill">Boersenchecker</div>
|
|
<h1 style="margin-top:.75rem;">Depotverwaltung</h1>
|
|
<p class="muted">
|
|
Depots, Positionen und manuelle Kursverlaeufe. Die Waehrungsumrechnung nutzt, sofern verfuegbar,
|
|
die bestehende FX-Logik des Mining-Checkers weiter.
|
|
</p>
|
|
|
|
<?php if ($error): ?>
|
|
<div class="card" style="margin-top:1rem; border-color:#ffb4a8; background:#fff5f3; color:#7a2114;">
|
|
<?= e($error) ?>
|
|
</div>
|
|
<?php elseif ($notice): ?>
|
|
<div class="card" style="margin-top:1rem; border-color:var(--accent-2);">
|
|
<?= e($notice) ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($isAdmin): ?>
|
|
<div class="card" style="margin-top:1rem; background:var(--panel-2);">
|
|
<strong>Benutzer-Scope</strong>
|
|
<form method="get" style="margin-top:.75rem; display:flex; gap:10px; flex-wrap:wrap; align-items:end;">
|
|
<label class="setup-field muted" style="margin:0; min-width:260px;">
|
|
<span>Depots von Benutzer</span>
|
|
<select name="owner_sub">
|
|
<?php foreach ($availableOwners as $owner): ?>
|
|
<option value="<?= e((string) $owner['sub']) ?>" <?= (string) $ownerSub === (string) $owner['sub'] ? 'selected' : '' ?>>
|
|
<?= e((string) $owner['label']) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
<button class="cta-button" type="submit">Anzeigen</button>
|
|
</form>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="grid" style="margin-top:1rem;">
|
|
<div class="card" style="background:var(--panel-2);">
|
|
<strong><?= $editPortfolio ? 'Depot bearbeiten' : 'Neues Depot' ?></strong>
|
|
<form method="post" style="margin-top:.75rem; display:grid; gap:10px;">
|
|
<input type="hidden" name="action" value="save_portfolio">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<input type="hidden" name="portfolio_id" value="<?= e((string) ($editPortfolio['id'] ?? '0')) ?>">
|
|
<label class="setup-field muted">
|
|
<span>Depotname</span>
|
|
<input type="text" name="portfolio_name" value="<?= e((string) ($editPortfolio['name'] ?? '')) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Berichtswahrung</span>
|
|
<input type="text" name="portfolio_base_currency" value="<?= e((string) ($editPortfolio['base_currency'] ?? $defaultReportCurrency)) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Notizen</span>
|
|
<textarea name="portfolio_notes" rows="3"><?= e((string) ($editPortfolio['notes'] ?? '')) ?></textarea>
|
|
</label>
|
|
<div style="display:flex; gap:10px; flex-wrap:wrap;">
|
|
<button class="cta-button" type="submit">Depot speichern</button>
|
|
<?php if ($editPortfolio): ?>
|
|
<a class="nav-link" href="/module/boersenchecker/depotverwaltung<?= e($ownerQuery) ?>">Abbrechen</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="card" style="background:var(--panel-2);">
|
|
<strong>API / FX</strong>
|
|
<p class="muted" style="margin-top:.75rem;">
|
|
Die Umrechnung liest gespeicherte FX-Daten aus dem Mining-Checker. Eine Aktualisierung wird nur manuell
|
|
angestossen und respektiert die dortige Max-Age-Logik.
|
|
</p>
|
|
<p class="muted" style="margin-top:.75rem;">
|
|
Aktienkurse werden ueber Alpha Vantage anhand des hinterlegten API-Symbols / Tickers pro Aktie abgerufen.
|
|
</p>
|
|
<div style="display:flex; gap:10px; flex-wrap:wrap; margin-top:1rem;">
|
|
<form method="post">
|
|
<input type="hidden" name="action" value="refresh_fx">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<button class="cta-button" type="submit">FX-Daten aktualisieren</button>
|
|
</form>
|
|
<form method="post">
|
|
<input type="hidden" name="action" value="refresh_alpha_vantage_all">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<button class="nav-link" type="submit">Alle API-Kurse abrufen</button>
|
|
</form>
|
|
</div>
|
|
<div class="muted" style="margin-top:.75rem;">
|
|
Alpha Vantage Mindestabstand: <?= e((string) $alphaMinIntervalMinutes) ?> Min.
|
|
</div>
|
|
<div class="muted" style="margin-top:.35rem;">
|
|
API-Key und Timeout werden ueber <a class="nav-link" href="/modules/setup/boersenchecker">Modul-Setup</a> gepflegt.
|
|
</div>
|
|
<div class="muted" style="margin-top:.75rem;">
|
|
Standard-Berichtswahrung: <?= e($defaultReportCurrency) ?> · Max. Alter: <?= e((string) $fxMaxAgeHours) ?>h
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card" style="margin-top:1rem; background:var(--panel-2);">
|
|
<strong><?= $editPosition ? 'Position bearbeiten' : 'Neue Position' ?></strong>
|
|
<?php if ($portfolios === []): ?>
|
|
<div class="muted" style="margin-top:.75rem;">Bitte zuerst ein Depot anlegen.</div>
|
|
<?php else: ?>
|
|
<form method="post" style="margin-top:.75rem; display:grid; gap:10px;">
|
|
<input type="hidden" name="action" value="save_position">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<input type="hidden" name="position_id" value="<?= e((string) ($editPosition['id'] ?? '0')) ?>">
|
|
<input type="hidden" name="instrument_id" value="<?= e((string) ($editPosition['instrument_id'] ?? '0')) ?>">
|
|
<label class="setup-field muted">
|
|
<span>Depot</span>
|
|
<select name="portfolio_id" required>
|
|
<option value="">Bitte waehlen</option>
|
|
<?php foreach ($portfolios as $portfolio): ?>
|
|
<option value="<?= e((string) $portfolio['id']) ?>" <?= (string) ($editPosition['portfolio_id'] ?? '') === (string) $portfolio['id'] ? 'selected' : '' ?>>
|
|
<?= e((string) $portfolio['name']) ?> (<?= e((string) $portfolio['base_currency']) ?>)
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
|
|
<label class="setup-field muted">
|
|
<span>Aktienname</span>
|
|
<input type="text" name="instrument_name" value="<?= e((string) ($editPosition['instrument_name'] ?? '')) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>API-Symbol / Ticker</span>
|
|
<input type="text" name="symbol" value="<?= e((string) ($editPosition['symbol'] ?? '')) ?>" placeholder="z.B. AAPL oder MBG.DE">
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>ISIN</span>
|
|
<input type="text" name="isin" value="<?= e((string) ($editPosition['isin'] ?? '')) ?>">
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>WKN</span>
|
|
<input type="text" name="wkn" value="<?= e((string) ($editPosition['wkn'] ?? '')) ?>">
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Boerse / Markt</span>
|
|
<input type="text" name="market" value="<?= e((string) ($editPosition['market'] ?? '')) ?>">
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Kurswaehrung</span>
|
|
<input type="text" name="quote_currency" value="<?= e((string) ($editPosition['quote_currency'] ?? $defaultReportCurrency)) ?>" required>
|
|
</label>
|
|
</div>
|
|
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
|
|
<label class="setup-field muted">
|
|
<span>Stueckzahl</span>
|
|
<input type="number" name="quantity" min="0" step="0.000001" value="<?= e((string) ($editPosition['quantity'] ?? '')) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Kaufpreis</span>
|
|
<input type="number" name="purchase_price" min="0" step="0.00000001" value="<?= e((string) ($editPosition['purchase_price'] ?? '')) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Kaufwaehrung</span>
|
|
<input type="text" name="purchase_currency" value="<?= e((string) ($editPosition['purchase_currency'] ?? $defaultReportCurrency)) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Kaufdatum</span>
|
|
<input type="date" name="purchase_date" value="<?= e((string) ($editPosition['purchase_date'] ?? date('Y-m-d'))) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Gebuehren</span>
|
|
<input type="number" name="fees" min="0" step="0.00000001" value="<?= e((string) ($editPosition['fees'] ?? '')) ?>">
|
|
</label>
|
|
</div>
|
|
<label class="setup-field muted">
|
|
<span>Notizen</span>
|
|
<textarea name="position_notes" rows="3"><?= e((string) ($editPosition['notes'] ?? '')) ?></textarea>
|
|
</label>
|
|
<div style="display:flex; gap:10px; flex-wrap:wrap;">
|
|
<button class="cta-button" type="submit">Position speichern</button>
|
|
<?php if ($editPosition): ?>
|
|
<a class="nav-link" href="/module/boersenchecker/depotverwaltung<?= e($ownerQuery) ?>">Abbrechen</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</form>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="card" style="margin-top:1rem; background:var(--panel-2);">
|
|
<strong>API-Symbol suchen</strong>
|
|
<p class="muted" style="margin-top:.75rem;">
|
|
Suche nach Firma oder Ticker ueber den Alpha-Vantage-`SYMBOL_SEARCH`-Endpoint und uebernimm einen Treffer direkt ins Positionsformular.
|
|
</p>
|
|
<form method="post" style="margin-top:.75rem; display:flex; gap:10px; flex-wrap:wrap; align-items:end;">
|
|
<input type="hidden" name="action" value="search_symbol">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<label class="setup-field muted" style="margin:0; min-width:260px; flex:1;">
|
|
<span>Suchbegriff</span>
|
|
<input type="text" name="search_keywords" value="<?= e($symbolSearchKeywords) ?>" placeholder="z.B. Mercedes, AAPL, Allianz" required>
|
|
</label>
|
|
<button class="cta-button" type="submit">Suchen</button>
|
|
</form>
|
|
|
|
<?php if ($symbolSearchResults !== []): ?>
|
|
<div style="overflow:auto; margin-top:1rem;">
|
|
<table style="width:100%; border-collapse:collapse;">
|
|
<thead>
|
|
<tr style="text-align:left; border-bottom:1px solid var(--border);">
|
|
<th style="padding:8px;">Symbol</th>
|
|
<th style="padding:8px;">Name</th>
|
|
<th style="padding:8px;">Typ</th>
|
|
<th style="padding:8px;">Region</th>
|
|
<th style="padding:8px;">Waehrung</th>
|
|
<th style="padding:8px;">Match</th>
|
|
<th style="padding:8px;">Aktion</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($symbolSearchResults as $result): ?>
|
|
<tr style="border-bottom:1px solid var(--border); vertical-align:top;">
|
|
<td style="padding:8px;"><strong><?= e((string) ($result['symbol'] ?? '')) ?></strong></td>
|
|
<td style="padding:8px;"><?= e((string) ($result['name'] ?? '')) ?></td>
|
|
<td style="padding:8px;"><?= e((string) ($result['type'] ?? '')) ?></td>
|
|
<td style="padding:8px;"><?= e((string) ($result['region'] ?? '')) ?></td>
|
|
<td style="padding:8px;"><?= e((string) ($result['currency'] ?? '')) ?></td>
|
|
<td style="padding:8px;"><?= e((string) ($result['match_score'] ?? '')) ?></td>
|
|
<td style="padding:8px;">
|
|
<a class="nav-link" href="/module/boersenchecker/depotverwaltung?owner_sub=<?= urlencode((string) $ownerSub) ?>&symbol_candidate=<?= urlencode((string) ($result['symbol'] ?? '')) ?>&instrument_name_candidate=<?= urlencode((string) ($result['name'] ?? '')) ?>&market_candidate=<?= urlencode((string) ($result['region'] ?? '')) ?>"e_currency_candidate=<?= urlencode((string) ($result['currency'] ?? '')) ?>">
|
|
In Formular uebernehmen
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="card" style="margin-top:1rem; background:var(--panel-2);">
|
|
<strong>Manuellen Kurs erfassen</strong>
|
|
<?php if ($instrumentList === []): ?>
|
|
<div class="muted" style="margin-top:.75rem;">Sobald Positionen vorhanden sind, koennen hier Kurse mit Uhrzeit gespeichert werden.</div>
|
|
<?php else: ?>
|
|
<form method="post" style="margin-top:.75rem; display:grid; gap:10px;">
|
|
<input type="hidden" name="action" value="save_quote">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
|
|
<label class="setup-field muted">
|
|
<span>Aktie</span>
|
|
<select name="quote_instrument_id" required>
|
|
<option value="">Bitte waehlen</option>
|
|
<?php foreach ($instrumentList as $instrument): ?>
|
|
<option value="<?= e((string) $instrument['id']) ?>" <?= $selectedInstrumentForQuote === (int) $instrument['id'] ? 'selected' : '' ?>>
|
|
<?= e((string) $instrument['name']) ?><?= $instrument['symbol'] !== '' ? ' (' . e((string) $instrument['symbol']) . ')' : '' ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Kurs</span>
|
|
<input type="number" name="quote_price" min="0" step="0.00000001" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Waehrung</span>
|
|
<input type="text" name="quote_currency" value="<?= e($selectedInstrumentQuoteCurrency) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Zeitpunkt</span>
|
|
<input type="datetime-local" name="quoted_at" value="<?= e(date('Y-m-d\TH:i')) ?>" required>
|
|
</label>
|
|
<label class="setup-field muted">
|
|
<span>Quelle</span>
|
|
<input type="text" name="quote_source" value="manual">
|
|
</label>
|
|
</div>
|
|
<div>
|
|
<button class="cta-button" type="submit">Kurs speichern</button>
|
|
</div>
|
|
</form>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div style="margin-top:1rem;" class="grid">
|
|
<?php if ($portfolios === []): ?>
|
|
<div class="card">
|
|
<div class="muted">Noch keine Depots vorhanden.</div>
|
|
</div>
|
|
<?php else: ?>
|
|
<?php foreach ($portfolios as $portfolio): ?>
|
|
<?php
|
|
$portfolioId = (int) $portfolio['id'];
|
|
$stats = $portfolioStats[$portfolioId] ?? ['positions' => 0, 'invested' => 0.0, 'current' => 0.0, 'gain' => null, 'has_invested' => false, 'has_current' => false];
|
|
?>
|
|
<div class="card" style="background:var(--panel-2);">
|
|
<div style="display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap;">
|
|
<div>
|
|
<strong><?= e((string) $portfolio['name']) ?></strong>
|
|
<div class="muted"><?= e((string) $portfolio['base_currency']) ?> · <?= e((string) $stats['positions']) ?> Position(en)</div>
|
|
</div>
|
|
<div style="display:flex; gap:10px; flex-wrap:wrap;">
|
|
<a class="nav-link" href="/module/boersenchecker/depotverwaltung?owner_sub=<?= urlencode((string) $ownerSub) ?>&edit_portfolio=<?= e((string) $portfolioId) ?>">Bearbeiten</a>
|
|
<form method="post" onsubmit="return confirm('Depot wirklich loeschen?')">
|
|
<input type="hidden" name="action" value="delete_portfolio">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<input type="hidden" name="portfolio_id" value="<?= e((string) $portfolioId) ?>">
|
|
<button class="nav-link" type="submit">Loeschen</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<?php if (!empty($portfolio['notes'])): ?>
|
|
<div class="muted" style="margin-top:.65rem;"><?= e((string) $portfolio['notes']) ?></div>
|
|
<?php endif; ?>
|
|
<div class="grid" style="margin-top:1rem; grid-template-columns:repeat(auto-fit, minmax(140px, 1fr)); gap:10px;">
|
|
<div class="card">
|
|
<div class="muted">Investiert</div>
|
|
<strong><?= $stats['has_invested'] ? e($fmtNumber((float) $stats['invested'])) . ' ' . e((string) $portfolio['base_currency']) : 'n/a' ?></strong>
|
|
</div>
|
|
<div class="card">
|
|
<div class="muted">Aktuell</div>
|
|
<strong><?= $stats['has_current'] ? e($fmtNumber((float) $stats['current'])) . ' ' . e((string) $portfolio['base_currency']) : 'n/a' ?></strong>
|
|
</div>
|
|
<div class="card">
|
|
<div class="muted">Gewinn / Verlust</div>
|
|
<strong><?= $stats['gain'] !== null ? e($fmtNumber((float) $stats['gain'])) . ' ' . e((string) $portfolio['base_currency']) : 'n/a' ?></strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="card" style="margin-top:1rem;">
|
|
<strong>Positionen</strong>
|
|
<?php if ($positions === []): ?>
|
|
<div class="muted" style="margin-top:.75rem;">Noch keine Positionen vorhanden.</div>
|
|
<?php else: ?>
|
|
<div style="overflow:auto; margin-top:.75rem;">
|
|
<table style="width:100%; border-collapse:collapse;">
|
|
<thead>
|
|
<tr style="text-align:left; border-bottom:1px solid var(--border);">
|
|
<th style="padding:8px;">Depot</th>
|
|
<th style="padding:8px;">Aktie</th>
|
|
<th style="padding:8px;">ISIN / WKN</th>
|
|
<th style="padding:8px;">Stueck</th>
|
|
<th style="padding:8px;">Kauf</th>
|
|
<th style="padding:8px;">Letzter Kurs</th>
|
|
<th style="padding:8px;">Wert</th>
|
|
<th style="padding:8px;">Delta</th>
|
|
<th style="padding:8px;">Aktion</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($positions as $position): ?>
|
|
<tr style="border-bottom:1px solid var(--border); vertical-align:top;">
|
|
<td style="padding:8px;"><?= e((string) ($portfolioById[(int) $position['portfolio_id']]['name'] ?? '')) ?></td>
|
|
<td style="padding:8px;">
|
|
<strong><?= e((string) $position['instrument_name']) ?></strong>
|
|
<?php if (!empty($position['symbol'])): ?>
|
|
<div class="muted"><?= e((string) $position['symbol']) ?></div>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td style="padding:8px;">
|
|
<?= e((string) ($position['isin'] ?: '-')) ?>
|
|
<div class="muted"><?= e((string) ($position['wkn'] ?: '-')) ?></div>
|
|
</td>
|
|
<td style="padding:8px;"><?= e($fmtNumber((float) $position['quantity'], 6)) ?></td>
|
|
<td style="padding:8px;">
|
|
<?= e($fmtNumber((float) $position['purchase_price'], 4)) ?> <?= e((string) $position['purchase_currency']) ?>
|
|
<div class="muted"><?= e((string) $position['purchase_date']) ?></div>
|
|
</td>
|
|
<td style="padding:8px;">
|
|
<?php if ($position['latest_price'] !== null): ?>
|
|
<?= e($fmtNumber((float) $position['latest_price'], 4)) ?> <?= e((string) $position['latest_currency']) ?>
|
|
<div class="muted"><?= e((string) $position['latest_quoted_at']) ?></div>
|
|
<?php else: ?>
|
|
<span class="muted">kein Kurs</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td style="padding:8px;">
|
|
<?php if ($position['current_total_base'] !== null): ?>
|
|
<?= e($fmtNumber((float) $position['current_total_base'])) ?> <?= e((string) $position['base_currency']) ?>
|
|
<?php else: ?>
|
|
<span class="muted">n/a</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td style="padding:8px;">
|
|
<?php if ($position['gain_base'] !== null): ?>
|
|
<?= e($fmtNumber((float) $position['gain_base'])) ?> <?= e((string) $position['base_currency']) ?>
|
|
<?php else: ?>
|
|
<span class="muted">n/a</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td style="padding:8px;">
|
|
<div style="display:flex; gap:8px; flex-wrap:wrap;">
|
|
<a class="nav-link" href="/module/boersenchecker/depotverwaltung?owner_sub=<?= urlencode((string) $ownerSub) ?>&edit_position=<?= e((string) $position['id']) ?>">Bearbeiten</a>
|
|
<a class="nav-link" href="/module/boersenchecker/depotverwaltung?owner_sub=<?= urlencode((string) $ownerSub) ?>&instrument_id=<?= e((string) $position['instrument_id']) ?>">Kurs erfassen</a>
|
|
<form method="post">
|
|
<input type="hidden" name="action" value="refresh_alpha_vantage_position">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<input type="hidden" name="position_id" value="<?= e((string) $position['id']) ?>">
|
|
<button class="nav-link" type="submit">API-Kurs</button>
|
|
</form>
|
|
<form method="post" onsubmit="return confirm('Position wirklich loeschen?')">
|
|
<input type="hidden" name="action" value="delete_position">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<input type="hidden" name="position_id" value="<?= e((string) $position['id']) ?>">
|
|
<button class="nav-link" type="submit">Loeschen</button>
|
|
</form>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="card" style="margin-top:1rem;">
|
|
<strong>Kursverlauf</strong>
|
|
<?php if ($instrumentList === []): ?>
|
|
<div class="muted" style="margin-top:.75rem;">Noch keine Kursdaten vorhanden.</div>
|
|
<?php else: ?>
|
|
<?php foreach ($instrumentList as $instrumentId => $instrument): ?>
|
|
<?php $history = array_slice($quoteHistory[$instrumentId] ?? [], 0, 10); ?>
|
|
<div class="card" style="margin-top:1rem; background:var(--panel-2);">
|
|
<div style="display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap;">
|
|
<div>
|
|
<strong><?= e((string) $instrument['name']) ?></strong>
|
|
<div class="muted">
|
|
<?= e((string) ($instrument['symbol'] ?: '-')) ?> · <?= e((string) ($instrument['isin'] ?: '-')) ?>
|
|
</div>
|
|
</div>
|
|
<a class="nav-link" href="/module/boersenchecker/depotverwaltung?owner_sub=<?= urlencode((string) $ownerSub) ?>&instrument_id=<?= e((string) $instrumentId) ?>">Neuen Kurs erfassen</a>
|
|
</div>
|
|
<?php if ($history === []): ?>
|
|
<div class="muted" style="margin-top:.75rem;">Noch keine historischen Kurse vorhanden.</div>
|
|
<?php else: ?>
|
|
<div style="overflow:auto; margin-top:.75rem;">
|
|
<table style="width:100%; border-collapse:collapse;">
|
|
<thead>
|
|
<tr style="text-align:left; border-bottom:1px solid var(--border);">
|
|
<th style="padding:8px;">Zeitpunkt</th>
|
|
<th style="padding:8px;">Kurs</th>
|
|
<th style="padding:8px;">Quelle</th>
|
|
<th style="padding:8px;">Aktion</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($history as $quote): ?>
|
|
<tr style="border-bottom:1px solid var(--border);">
|
|
<td style="padding:8px;"><?= e((string) $quote['quoted_at']) ?></td>
|
|
<td style="padding:8px;"><?= e($fmtNumber((float) $quote['price'], 4)) ?> <?= e((string) $quote['currency']) ?></td>
|
|
<td style="padding:8px;"><?= e((string) $quote['source']) ?></td>
|
|
<td style="padding:8px;">
|
|
<form method="post" onsubmit="return confirm('Kurseintrag wirklich loeschen?')">
|
|
<input type="hidden" name="action" value="delete_quote">
|
|
<input type="hidden" name="owner_sub" value="<?= e((string) $ownerSub) ?>">
|
|
<input type="hidden" name="quote_id" value="<?= e((string) $quote['id']) ?>">
|
|
<button class="nav-link" type="submit">Loeschen</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|