Boersendchcker update
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
.bc-app {
|
||||
.bc-page {
|
||||
--bc-accent: var(--brand-accent);
|
||||
--bc-accent-strong: var(--brand-accent-2);
|
||||
--bc-ink: var(--text);
|
||||
@@ -12,73 +12,9 @@
|
||||
color: var(--bc-text);
|
||||
}
|
||||
|
||||
.bc-grid-bg {
|
||||
position: relative;
|
||||
padding: 0 0 8px;
|
||||
}
|
||||
|
||||
.bc-grid-bg::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
background:
|
||||
radial-gradient(circle at top right, color-mix(in srgb, var(--brand-accent-2) 10%, transparent), transparent 28%),
|
||||
radial-gradient(circle at bottom left, color-mix(in srgb, var(--brand-accent-3) 10%, transparent), transparent 30%),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0));
|
||||
}
|
||||
|
||||
.bc-shell {
|
||||
position: relative;
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.bc-stack {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.bc-hero {
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
padding: 28px;
|
||||
border-radius: 28px;
|
||||
background:
|
||||
radial-gradient(circle at top right, rgba(94, 234, 212, 0.18), transparent 28%),
|
||||
radial-gradient(circle at bottom left, rgba(121, 215, 255, 0.14), transparent 32%),
|
||||
linear-gradient(145deg, rgba(15, 23, 42, 0.9), rgba(15, 23, 42, 0.78));
|
||||
border: 1px solid var(--bc-line);
|
||||
box-shadow: 0 18px 40px rgba(2, 6, 23, 0.22);
|
||||
}
|
||||
|
||||
.bc-hero-top {
|
||||
.bc-page {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
grid-template-columns: minmax(0, 1.6fr) minmax(240px, 0.7fr);
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.bc-hero-copy {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.bc-eyebrow {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
width: fit-content;
|
||||
padding: 8px 12px;
|
||||
border-radius: 999px;
|
||||
background: color-mix(in srgb, var(--bc-accent) 18%, transparent);
|
||||
border: 1px solid color-mix(in srgb, var(--bc-accent) 28%, transparent);
|
||||
color: var(--bc-text);
|
||||
font-size: 0.86rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.bc-title {
|
||||
margin: 0;
|
||||
font-size: clamp(2rem, 3vw, 2.8rem);
|
||||
line-height: 1.05;
|
||||
}
|
||||
|
||||
.bc-text {
|
||||
@@ -86,10 +22,23 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.bc-hero-controls {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
justify-items: stretch;
|
||||
.bc-section-head {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.bc-section-title {
|
||||
margin: 0;
|
||||
font-size: 1.45rem;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.bc-section-head p,
|
||||
.bc-section-copy {
|
||||
color: var(--bc-muted);
|
||||
margin: 8px 0 0;
|
||||
}
|
||||
|
||||
.bc-form-card,
|
||||
@@ -128,10 +77,10 @@
|
||||
|
||||
.bc-button,
|
||||
.bc-tabs a,
|
||||
.bc-app button,
|
||||
.bc-app input,
|
||||
.bc-app select,
|
||||
.bc-app textarea {
|
||||
.bc-page button,
|
||||
.bc-page input,
|
||||
.bc-page select,
|
||||
.bc-page textarea {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
@@ -352,14 +301,14 @@
|
||||
background: rgba(255,255,255,0.04);
|
||||
}
|
||||
|
||||
.bc-app .setup-field {
|
||||
.bc-page .setup-field {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.bc-app input,
|
||||
.bc-app select,
|
||||
.bc-app textarea {
|
||||
.bc-page input,
|
||||
.bc-page select,
|
||||
.bc-page textarea {
|
||||
width: 100%;
|
||||
border: 1px solid var(--bc-line);
|
||||
border-radius: 14px;
|
||||
@@ -368,16 +317,16 @@
|
||||
color: var(--bc-text);
|
||||
}
|
||||
|
||||
.bc-app input::placeholder,
|
||||
.bc-app textarea::placeholder {
|
||||
.bc-page input::placeholder,
|
||||
.bc-page textarea::placeholder {
|
||||
color: color-mix(in srgb, var(--bc-muted) 70%, transparent);
|
||||
}
|
||||
|
||||
.bc-app a {
|
||||
.bc-page a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.bc-app .muted {
|
||||
.bc-page .muted {
|
||||
color: var(--bc-muted);
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,13 @@
|
||||
}
|
||||
currentPayload = payload;
|
||||
renderChart(pointsForRange(payload, activeRange));
|
||||
if (statusNode) statusNode.textContent = `Quelle: Alpha Vantage | Symbol ${payload.symbol || ''}`;
|
||||
if (statusNode) {
|
||||
const sourceLabel = payload.source_label || payload.source || 'Lokale Kurshistorie';
|
||||
const instrumentRef = payload.symbol || payload.isin || '';
|
||||
statusNode.textContent = instrumentRef
|
||||
? `Quelle: ${sourceLabel} | ${instrumentRef}`
|
||||
: `Quelle: ${sourceLabel}`;
|
||||
}
|
||||
} catch (error) {
|
||||
currentPayload = null;
|
||||
chartShell.innerHTML = `<div class="muted">${error.message}</div>`;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"title": "Boersenchecker",
|
||||
"description": "Depotverwaltung fuer Aktien, Kaufdaten, Kursverlauf und Waehrungsumrechnung.",
|
||||
"actions": [
|
||||
{ "label": "Zur Startseite", "href": "/", "variant": "ghost" },
|
||||
{ "label": "Nexus Übersicht", "href": "/", "variant": "ghost" },
|
||||
{ "label": "Setup", "href": "/modules/setup/boersenchecker", "variant": "secondary" }
|
||||
],
|
||||
"tabs": [
|
||||
|
||||
@@ -17,9 +17,10 @@ $pdo = module_fn('boersenchecker', 'pdo');
|
||||
module_fn('boersenchecker', 'ensure_schema');
|
||||
$instrumentTable = module_fn('boersenchecker', 'table', 'instruments');
|
||||
$positionTable = module_fn('boersenchecker', 'table', 'positions');
|
||||
$quoteTable = module_fn('boersenchecker', 'table', 'quotes');
|
||||
|
||||
$stmt = $pdo->prepare(
|
||||
'SELECT i.id, i.name, i.symbol, i.isin
|
||||
'SELECT i.id, i.name, i.symbol, i.isin, i.quote_currency
|
||||
FROM ' . $instrumentTable . ' i
|
||||
INNER JOIN ' . $positionTable . ' p ON p.instrument_id = i.id
|
||||
WHERE i.id = :id AND p.owner_sub = :owner_sub
|
||||
@@ -37,12 +38,93 @@ if (!is_array($instrument)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$symbol = strtoupper(trim((string) ($instrument['symbol'] ?? '')));
|
||||
if ($symbol === '') {
|
||||
echo json_encode(['ok' => false, 'message' => 'Fuer diese Aktie ist kein Symbol hinterlegt.'], JSON_UNESCAPED_UNICODE);
|
||||
$quoteStmt = $pdo->prepare(
|
||||
'SELECT id, price, currency, quoted_at, source, created_at
|
||||
FROM ' . $quoteTable . '
|
||||
WHERE instrument_id = :instrument_id
|
||||
ORDER BY quoted_at ASC, created_at ASC, id ASC'
|
||||
);
|
||||
$quoteStmt->execute([
|
||||
'instrument_id' => $instrumentId,
|
||||
]);
|
||||
$quotes = $quoteStmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
|
||||
|
||||
if ($quotes === []) {
|
||||
echo json_encode([
|
||||
'ok' => false,
|
||||
'message' => 'Keine lokalen Kursdaten fuer diese Aktie vorhanden.',
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
|
||||
$result = module_fn('boersenchecker', 'alpha_vantage_fetch_chart_series', $symbol);
|
||||
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
$dailyMap = [];
|
||||
foreach ($quotes as $quote) {
|
||||
$localDate = trim((string) module_fn(
|
||||
'boersenchecker',
|
||||
'format_datetime_for_display',
|
||||
(string) ($quote['quoted_at'] ?? ''),
|
||||
(string) ($quote['source'] ?? ''),
|
||||
'Y-m-d'
|
||||
));
|
||||
$localDateTime = trim((string) module_fn(
|
||||
'boersenchecker',
|
||||
'format_datetime_for_display',
|
||||
(string) ($quote['quoted_at'] ?? ''),
|
||||
(string) ($quote['source'] ?? ''),
|
||||
'Y-m-d H:i:s'
|
||||
));
|
||||
if ($localDate === '' || !is_numeric($quote['price'] ?? null)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$point = [
|
||||
'date' => $localDate,
|
||||
'close' => (float) $quote['price'],
|
||||
'currency' => strtoupper(trim((string) ($quote['currency'] ?? ''))),
|
||||
'quoted_at' => $localDateTime,
|
||||
'source' => (string) ($quote['source'] ?? ''),
|
||||
];
|
||||
|
||||
if (!isset($dailyMap[$localDate]) || strcmp($localDateTime, (string) ($dailyMap[$localDate]['quoted_at'] ?? '')) >= 0) {
|
||||
$dailyMap[$localDate] = $point;
|
||||
}
|
||||
}
|
||||
|
||||
$daily = array_values($dailyMap);
|
||||
usort($daily, static fn (array $left, array $right): int => strcmp((string) $left['date'], (string) $right['date']));
|
||||
|
||||
if ($daily === []) {
|
||||
echo json_encode([
|
||||
'ok' => false,
|
||||
'message' => 'Keine gueltigen lokalen Schlusskurse fuer diese Aktie vorhanden.',
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
|
||||
$aggregate = static function (array $points, string $format): array {
|
||||
$result = [];
|
||||
$timezone = new DateTimeZone('Europe/Berlin');
|
||||
foreach ($points as $point) {
|
||||
$date = DateTimeImmutable::createFromFormat('Y-m-d', (string) ($point['date'] ?? ''), $timezone);
|
||||
if (!$date instanceof DateTimeImmutable) {
|
||||
continue;
|
||||
}
|
||||
$bucket = $date->format($format);
|
||||
$result[$bucket] = $point;
|
||||
}
|
||||
return array_values($result);
|
||||
};
|
||||
|
||||
echo json_encode([
|
||||
'ok' => true,
|
||||
'symbol' => strtoupper(trim((string) ($instrument['symbol'] ?? ''))),
|
||||
'isin' => strtoupper(trim((string) ($instrument['isin'] ?? ''))),
|
||||
'instrument_name' => (string) ($instrument['name'] ?? ''),
|
||||
'currency' => strtoupper(trim((string) ($instrument['quote_currency'] ?? ''))),
|
||||
'daily' => $daily,
|
||||
'weekly' => $aggregate($daily, 'o-W'),
|
||||
'monthly' => $aggregate($daily, 'Y-m'),
|
||||
'source' => 'database:quotes',
|
||||
'source_label' => 'Lokale Kurshistorie',
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
exit;
|
||||
|
||||
@@ -2,21 +2,18 @@
|
||||
<?= module_shell_header('boersenchecker', [
|
||||
'title' => 'Depotverwaltung',
|
||||
]) ?>
|
||||
<div class="bc-app">
|
||||
<div class="bc-grid-bg">
|
||||
<div class="bc-shell bc-stack module-flow">
|
||||
|
||||
<div class="bc-page">
|
||||
<?php if ($error): ?>
|
||||
<div class="bc-alert bc-alert--error"><?= e($error) ?></div>
|
||||
<section class="section-box"><div class="bc-alert bc-alert--error"><?= e($error) ?></div></section>
|
||||
<?php elseif ($notice): ?>
|
||||
<div class="bc-alert bc-alert--success"><?= e($notice) ?></div>
|
||||
<section class="section-box"><div class="bc-alert bc-alert--success"><?= e($notice) ?></div></section>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($isAdmin): ?>
|
||||
<section class="module-box">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Benutzer-Scope</h2>
|
||||
<h2 class="bc-section-title">Benutzer-Scope</h2>
|
||||
<p>Depots anderer Benutzer sind nur fuer `appadmin` sichtbar und bearbeitbar.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -36,11 +33,11 @@
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="module-box-grid module-box-grid--panels">
|
||||
<section class="module-box">
|
||||
<div class="module-box-head">
|
||||
<div class="bc-card-grid">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title"><?= $editPortfolio ? 'Depot bearbeiten' : 'Neues Depot' ?></h2>
|
||||
<h2 class="bc-section-title"><?= $editPortfolio ? 'Depot bearbeiten' : 'Neues Depot' ?></h2>
|
||||
<p>Stammdaten und Berichtswahrung fuer ein Depot pflegen.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -69,10 +66,10 @@
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="module-box">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">API / FX</h2>
|
||||
<h2 class="bc-section-title">API / FX</h2>
|
||||
<p>Kurs- und Waehrungsdaten zentral aktualisieren.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -110,10 +107,10 @@
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="module-box">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title"><?= $editPosition ? 'Position bearbeiten' : 'Neue Position' ?></h2>
|
||||
<h2 class="bc-section-title"><?= $editPosition ? 'Position bearbeiten' : 'Neue Position' ?></h2>
|
||||
<p>Aktienpositionen fuer ein Depot mit Kaufdaten und Kurswaehrung verwalten.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -198,14 +195,14 @@
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<section class="module-box-table">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Wertpapiersuche</h2>
|
||||
<h2 class="bc-section-title">Wertpapiersuche</h2>
|
||||
<p>Alpha-Vantage-Suchergebnisse pruefen und Daten direkt ins Positionsformular uebernehmen.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="module-box-copy">
|
||||
<div class="bc-section-copy">
|
||||
<form method="post" style="margin-top:16px; 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) ?>">
|
||||
@@ -216,7 +213,6 @@
|
||||
<button class="bc-button bc-button--primary" type="submit">Suchen</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php if ($symbolSearchResults !== []): ?>
|
||||
<table class="bc-table">
|
||||
<thead>
|
||||
@@ -249,16 +245,16 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<div class="module-box-copy">
|
||||
<div class="bc-section-copy">
|
||||
<div class="muted">Noch keine Symbolsuche ausgefuehrt.</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<section class="module-box">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Manuellen Kurs erfassen</h2>
|
||||
<h2 class="bc-section-title">Manuellen Kurs erfassen</h2>
|
||||
<p>Kurse mit Uhrzeit und Quelle direkt in die Historie schreiben.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -304,23 +300,23 @@
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<section class="module-box">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Depots</h2>
|
||||
<h2 class="bc-section-title">Depots</h2>
|
||||
<p>Uebersicht aller Depots mit Kennzahlen und Schnellaktionen.</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($portfolios === []): ?>
|
||||
<div class="muted" style="margin-top:16px;">Noch keine Depots vorhanden.</div>
|
||||
<?php else: ?>
|
||||
<div class="module-box-grid module-box-grid--panels" style="margin-top:16px;">
|
||||
<div class="bc-card-grid" style="margin-top:16px;">
|
||||
<?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];
|
||||
?>
|
||||
<section class="module-box-soft">
|
||||
<section class="card-box">
|
||||
<div style="display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap;">
|
||||
<div>
|
||||
<strong><?= e((string) $portfolio['name']) ?></strong>
|
||||
@@ -359,15 +355,15 @@
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<section class="module-box-table">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Positionen</h2>
|
||||
<h2 class="bc-section-title">Positionen</h2>
|
||||
<p>Alle Positionen mit Kaufdaten, letztem Kurs und aktuellen Werten.</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($positions === []): ?>
|
||||
<div class="module-box-copy">
|
||||
<div class="bc-section-copy">
|
||||
<div class="muted">Noch keine Positionen vorhanden.</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
@@ -451,20 +447,20 @@
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<section class="module-box">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Kursverlauf</h2>
|
||||
<h2 class="bc-section-title">Kursverlauf</h2>
|
||||
<p>Historische Kurse pro Aktie mit Zeitstempel und Quelle.</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($instrumentList === []): ?>
|
||||
<div class="muted" style="margin-top:16px;">Noch keine Kursdaten vorhanden.</div>
|
||||
<?php else: ?>
|
||||
<div class="module-box-grid module-box-grid--panels" style="margin-top:16px;">
|
||||
<div class="bc-card-grid" style="margin-top:16px;">
|
||||
<?php foreach ($instrumentList as $instrumentId => $instrument): ?>
|
||||
<?php $history = array_slice($quoteHistory[$instrumentId] ?? [], 0, 10); ?>
|
||||
<section class="module-box-soft">
|
||||
<section class="card-box">
|
||||
<div style="display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap;">
|
||||
<div>
|
||||
<strong><?= e((string) $instrument['name']) ?></strong>
|
||||
@@ -513,6 +509,4 @@
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?= module_shell_footer() ?>
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<?= module_shell_header('boersenchecker', [
|
||||
'title' => 'Depot-Ueberblick',
|
||||
]) ?>
|
||||
<div class="bc-app">
|
||||
<div class="bc-grid-bg">
|
||||
<div class="bc-shell bc-stack module-flow" data-bc-home data-chart-endpoint="<?= e($chartEndpoint) ?>">
|
||||
<div class="bc-page" data-bc-home data-chart-endpoint="<?= e($chartEndpoint) ?>">
|
||||
<script type="application/json" data-bc-instruments-json><?= json_encode(array_map(static function (array $position): array {
|
||||
return [
|
||||
'instrument_id' => (int) ($position['instrument_id'] ?? 0),
|
||||
@@ -14,15 +12,15 @@
|
||||
}, $positions), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?></script>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="bc-alert bc-alert--error"><?= e($error) ?></div>
|
||||
<section class="section-box"><div class="bc-alert bc-alert--error"><?= e($error) ?></div></section>
|
||||
<?php elseif ($notice): ?>
|
||||
<div class="bc-alert bc-alert--success"><?= e($notice) ?></div>
|
||||
<section class="section-box"><div class="bc-alert bc-alert--success"><?= e($notice) ?></div></section>
|
||||
<?php endif; ?>
|
||||
|
||||
<section class="module-box">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Marktueberblick</h2>
|
||||
<h2 class="bc-section-title">Marktueberblick</h2>
|
||||
<p>Depotauswahl, Aktienfokus und aktueller Kursabruf in einem Bereich.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -76,31 +74,31 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="module-box-grid module-box-grid--stats">
|
||||
<section class="module-box-soft bc-stat">
|
||||
<div class="bc-overview-grid">
|
||||
<section class="card-box bc-stat">
|
||||
<div class="bc-field-label">Positionen</div>
|
||||
<div class="bc-stat-value"><?= e((string) ($summary['positions'] ?? 0)) ?></div>
|
||||
<div class="bc-text" style="margin-top:6px;">Aktien im aktuell gewaehlten Depot</div>
|
||||
</section>
|
||||
<section class="module-box-soft bc-stat">
|
||||
<section class="card-box bc-stat">
|
||||
<div class="bc-field-label">Investiert</div>
|
||||
<div class="bc-stat-value"><?= isset($summary['invested']) && $summary['invested'] !== null ? e(number_format((float) $summary['invested'], 2, ',', '.')) . ' ' . e($defaultReportCurrency) : 'n/a' ?></div>
|
||||
<div class="bc-text" style="margin-top:6px;">In Berichtswahrung bewertet</div>
|
||||
</section>
|
||||
<section class="module-box-soft bc-stat">
|
||||
<section class="card-box bc-stat">
|
||||
<div class="bc-field-label">Aktueller Wert</div>
|
||||
<div class="bc-stat-value"><?= isset($summary['current']) && $summary['current'] !== null ? e(number_format((float) $summary['current'], 2, ',', '.')) . ' ' . e($defaultReportCurrency) : 'n/a' ?></div>
|
||||
<div class="bc-text" style="margin-top:6px;">Basierend auf dem letzten gespeicherten Kurs</div>
|
||||
</section>
|
||||
<section class="module-box-soft bc-stat">
|
||||
<section class="card-box bc-stat">
|
||||
<div class="bc-field-label">Performance</div>
|
||||
<div class="bc-stat-value"><?= isset($summary['gain']) && $summary['gain'] !== null ? e(number_format((float) $summary['gain'], 2, ',', '.')) . ' ' . e($defaultReportCurrency) : 'n/a' ?></div>
|
||||
<div class="bc-text" style="margin-top:6px;"><?= !empty($summary['best']['instrument_name']) ? 'Top-Wert: ' . e((string) $summary['best']['instrument_name']) : 'Noch keine Vergleichsdaten' ?></div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="module-box-grid module-box-grid--panels">
|
||||
<section class="module-box-soft">
|
||||
<div class="bc-card-grid">
|
||||
<section class="card-box">
|
||||
<div class="bc-field-label">Bester Wert</div>
|
||||
<?php if (!empty($summary['best'])): ?>
|
||||
<div class="bc-stat-value"><?= e((string) $summary['best']['instrument_name']) ?></div>
|
||||
@@ -110,7 +108,7 @@
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<section class="module-box-soft">
|
||||
<section class="card-box">
|
||||
<div class="bc-field-label">Schwaechster Wert</div>
|
||||
<?php if (!empty($summary['worst'])): ?>
|
||||
<div class="bc-stat-value"><?= e((string) $summary['worst']['instrument_name']) ?></div>
|
||||
@@ -121,7 +119,7 @@
|
||||
</section>
|
||||
|
||||
<?php foreach (array_slice($positions, 0, 2) as $position): ?>
|
||||
<section class="module-box-soft bc-stat">
|
||||
<section class="card-box bc-stat">
|
||||
<div class="bc-field-label"><?= e((string) $position['instrument_name']) ?></div>
|
||||
<div class="bc-stat-value"><?= $position['latest_price'] !== null ? e(number_format((float) $position['latest_price'], 2, ',', '.')) . ' ' . e((string) $position['latest_currency']) : 'n/a' ?></div>
|
||||
<div class="bc-text" style="margin-top:6px;"><?= e((string) (($position['latest_quoted_at'] ?? '') !== '' ? $fmtDateTime((string) $position['latest_quoted_at'], (string) ($position['latest_source'] ?? '')) : 'kein Kurs')) ?></div>
|
||||
@@ -129,10 +127,10 @@
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<section class="module-box">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Kursverlauf</h2>
|
||||
<h2 class="bc-section-title">Kursverlauf</h2>
|
||||
<p>Schlusskurse ueber mehrere Zeitfenster fuer das aktuell gewaehlte Instrument.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -161,14 +159,14 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="module-box-table">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Aktien im Depot</h2>
|
||||
<h2 class="bc-section-title">Aktien im Depot</h2>
|
||||
<p>Stueckzahl, Kaufdaten, letzter Kurs und Performance auf einen Blick.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="module-box-copy">
|
||||
<div class="bc-section-copy">
|
||||
<?php if ($positions === []): ?>
|
||||
<div class="bc-text" style="padding:0 0 18px;">Keine Aktien im ausgewaehlten Depot.</div>
|
||||
<?php else: ?>
|
||||
@@ -208,6 +206,4 @@
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?= module_shell_footer() ?>
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
<?= module_shell_header('boersenchecker', [
|
||||
'title' => 'Aktienverwaltung',
|
||||
]) ?>
|
||||
<div class="bc-app">
|
||||
<div class="bc-grid-bg">
|
||||
<div class="bc-shell bc-stack module-flow">
|
||||
|
||||
<div class="bc-page">
|
||||
<?php if ($error): ?>
|
||||
<div class="bc-alert bc-alert--error"><?= e($error) ?></div>
|
||||
<section class="section-box"><div class="bc-alert bc-alert--error"><?= e($error) ?></div></section>
|
||||
<?php elseif ($notice): ?>
|
||||
<div class="bc-alert bc-alert--success"><?= e($notice) ?></div>
|
||||
<section class="section-box"><div class="bc-alert bc-alert--success"><?= e($notice) ?></div></section>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="module-box-grid module-box-grid--panels">
|
||||
<section class="module-box">
|
||||
<div class="module-box-head">
|
||||
<div class="bc-card-grid">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Aktie waehlen</h2>
|
||||
<h2 class="bc-section-title">Aktie waehlen</h2>
|
||||
<p>Systemweit vorhandene Aktie aus allen Depots auswaehlen.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -33,14 +30,14 @@
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="module-box-table">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Wertpapiersuche</h2>
|
||||
<h2 class="bc-section-title">Wertpapiersuche</h2>
|
||||
<p>Alpha-Vantage-Suchergebnisse finden und direkt fuer die Aktie uebernehmen.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="module-box-copy">
|
||||
<div class="bc-section-copy">
|
||||
<form method="post" style="margin-top:16px; display:flex; gap:10px; flex-wrap:wrap; align-items:end;">
|
||||
<input type="hidden" name="action" value="search_symbol">
|
||||
<input type="hidden" name="instrument_id" value="<?= e((string) $selectedInstrumentId) ?>">
|
||||
@@ -79,17 +76,17 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<div class="module-box-copy">
|
||||
<div class="bc-section-copy">
|
||||
<div class="muted">Noch keine Symbolsuche ausgefuehrt.</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="module-box">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Aktie bearbeiten</h2>
|
||||
<h2 class="bc-section-title">Aktie bearbeiten</h2>
|
||||
<p>Stammdaten, Markt und Kurswaehrung zentral fuer die Aktie pflegen.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -102,8 +99,8 @@
|
||||
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
|
||||
<label class="setup-field muted"><span>Name</span><input type="text" name="instrument_name" value="<?= e((string) (($selectedInstrument['name'] ?? '') ?: ($_GET['instrument_name_candidate'] ?? ''))) ?>" required></label>
|
||||
<label class="setup-field muted"><span>Symbol</span><input type="text" name="symbol" value="<?= e((string) (($selectedInstrument['symbol'] ?? '') ?: ($_GET['symbol_candidate'] ?? ''))) ?>"></label>
|
||||
<label class="setup-field muted"><span>ISIN</span><input type="text" name="isin" value="<?= e((string) ($selectedInstrument['isin'] ?? '')) ?>"></label>
|
||||
<label class="setup-field muted"><span>WKN</span><input type="text" name="wkn" value="<?= e((string) ($selectedInstrument['wkn'] ?? '')) ?>"></label>
|
||||
<label class="setup-field muted"><span>ISIN</span><input type="text" name="isin" value="<?= e((string) $selectedInstrument['isin'] ?? '') ?>"></label>
|
||||
<label class="setup-field muted"><span>WKN</span><input type="text" name="wkn" value="<?= e((string) $selectedInstrument['wkn'] ?? '') ?>"></label>
|
||||
<label class="setup-field muted"><span>Markt</span><input type="text" name="market" value="<?= e((string) (($selectedInstrument['market'] ?? '') ?: ($_GET['market_candidate'] ?? ''))) ?>"></label>
|
||||
<label class="setup-field muted"><span>Kurswaehrung</span><input type="text" name="quote_currency" value="<?= e((string) (($selectedInstrument['quote_currency'] ?? $defaultReportCurrency) ?: ($_GET['quote_currency_candidate'] ?? $defaultReportCurrency))) ?>"></label>
|
||||
</div>
|
||||
@@ -119,10 +116,10 @@
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<section class="module-box">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Manuellen Kurs eingeben</h2>
|
||||
<h2 class="bc-section-title">Manuellen Kurs eingeben</h2>
|
||||
<p>Einzelne Kurse mit Zeitstempel und Quelle fuer die ausgewaehlte Aktie speichern.</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -145,15 +142,15 @@
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<section class="module-box-table">
|
||||
<div class="module-box-head">
|
||||
<section class="section-box">
|
||||
<div class="bc-section-head">
|
||||
<div>
|
||||
<h2 class="module-box-title">Kursverlauf</h2>
|
||||
<h2 class="bc-section-title">Kursverlauf</h2>
|
||||
<p>Gespeicherte Kursdaten der ausgewaehlten Aktie mit Quelle und Loeschoption.</p>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($quotes === []): ?>
|
||||
<div class="module-box-copy">
|
||||
<div class="bc-section-copy">
|
||||
<div class="muted">Keine Kursdaten vorhanden.</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
@@ -187,6 +184,4 @@
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?= module_shell_footer() ?>
|
||||
|
||||
Reference in New Issue
Block a user