Boersendchcker update
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
.bc-app {
|
.bc-page {
|
||||||
--bc-accent: var(--brand-accent);
|
--bc-accent: var(--brand-accent);
|
||||||
--bc-accent-strong: var(--brand-accent-2);
|
--bc-accent-strong: var(--brand-accent-2);
|
||||||
--bc-ink: var(--text);
|
--bc-ink: var(--text);
|
||||||
@@ -12,73 +12,9 @@
|
|||||||
color: var(--bc-text);
|
color: var(--bc-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bc-grid-bg {
|
.bc-page {
|
||||||
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 {
|
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 16px;
|
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 {
|
.bc-text {
|
||||||
@@ -86,10 +22,23 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bc-hero-controls {
|
.bc-section-head {
|
||||||
display: grid;
|
display: flex;
|
||||||
gap: 12px;
|
align-items: start;
|
||||||
justify-items: stretch;
|
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,
|
.bc-form-card,
|
||||||
@@ -128,10 +77,10 @@
|
|||||||
|
|
||||||
.bc-button,
|
.bc-button,
|
||||||
.bc-tabs a,
|
.bc-tabs a,
|
||||||
.bc-app button,
|
.bc-page button,
|
||||||
.bc-app input,
|
.bc-page input,
|
||||||
.bc-app select,
|
.bc-page select,
|
||||||
.bc-app textarea {
|
.bc-page textarea {
|
||||||
font: inherit;
|
font: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,14 +301,14 @@
|
|||||||
background: rgba(255,255,255,0.04);
|
background: rgba(255,255,255,0.04);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bc-app .setup-field {
|
.bc-page .setup-field {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bc-app input,
|
.bc-page input,
|
||||||
.bc-app select,
|
.bc-page select,
|
||||||
.bc-app textarea {
|
.bc-page textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid var(--bc-line);
|
border: 1px solid var(--bc-line);
|
||||||
border-radius: 14px;
|
border-radius: 14px;
|
||||||
@@ -368,16 +317,16 @@
|
|||||||
color: var(--bc-text);
|
color: var(--bc-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bc-app input::placeholder,
|
.bc-page input::placeholder,
|
||||||
.bc-app textarea::placeholder {
|
.bc-page textarea::placeholder {
|
||||||
color: color-mix(in srgb, var(--bc-muted) 70%, transparent);
|
color: color-mix(in srgb, var(--bc-muted) 70%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bc-app a {
|
.bc-page a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bc-app .muted {
|
.bc-page .muted {
|
||||||
color: var(--bc-muted);
|
color: var(--bc-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,7 +115,13 @@
|
|||||||
}
|
}
|
||||||
currentPayload = payload;
|
currentPayload = payload;
|
||||||
renderChart(pointsForRange(payload, activeRange));
|
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) {
|
} catch (error) {
|
||||||
currentPayload = null;
|
currentPayload = null;
|
||||||
chartShell.innerHTML = `<div class="muted">${error.message}</div>`;
|
chartShell.innerHTML = `<div class="muted">${error.message}</div>`;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"title": "Boersenchecker",
|
"title": "Boersenchecker",
|
||||||
"description": "Depotverwaltung fuer Aktien, Kaufdaten, Kursverlauf und Waehrungsumrechnung.",
|
"description": "Depotverwaltung fuer Aktien, Kaufdaten, Kursverlauf und Waehrungsumrechnung.",
|
||||||
"actions": [
|
"actions": [
|
||||||
{ "label": "Zur Startseite", "href": "/", "variant": "ghost" },
|
{ "label": "Nexus Übersicht", "href": "/", "variant": "ghost" },
|
||||||
{ "label": "Setup", "href": "/modules/setup/boersenchecker", "variant": "secondary" }
|
{ "label": "Setup", "href": "/modules/setup/boersenchecker", "variant": "secondary" }
|
||||||
],
|
],
|
||||||
"tabs": [
|
"tabs": [
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ $pdo = module_fn('boersenchecker', 'pdo');
|
|||||||
module_fn('boersenchecker', 'ensure_schema');
|
module_fn('boersenchecker', 'ensure_schema');
|
||||||
$instrumentTable = module_fn('boersenchecker', 'table', 'instruments');
|
$instrumentTable = module_fn('boersenchecker', 'table', 'instruments');
|
||||||
$positionTable = module_fn('boersenchecker', 'table', 'positions');
|
$positionTable = module_fn('boersenchecker', 'table', 'positions');
|
||||||
|
$quoteTable = module_fn('boersenchecker', 'table', 'quotes');
|
||||||
|
|
||||||
$stmt = $pdo->prepare(
|
$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
|
FROM ' . $instrumentTable . ' i
|
||||||
INNER JOIN ' . $positionTable . ' p ON p.instrument_id = i.id
|
INNER JOIN ' . $positionTable . ' p ON p.instrument_id = i.id
|
||||||
WHERE i.id = :id AND p.owner_sub = :owner_sub
|
WHERE i.id = :id AND p.owner_sub = :owner_sub
|
||||||
@@ -37,12 +38,93 @@ if (!is_array($instrument)) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$symbol = strtoupper(trim((string) ($instrument['symbol'] ?? '')));
|
$quoteStmt = $pdo->prepare(
|
||||||
if ($symbol === '') {
|
'SELECT id, price, currency, quoted_at, source, created_at
|
||||||
echo json_encode(['ok' => false, 'message' => 'Fuer diese Aktie ist kein Symbol hinterlegt.'], JSON_UNESCAPED_UNICODE);
|
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;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = module_fn('boersenchecker', 'alpha_vantage_fetch_chart_series', $symbol);
|
$dailyMap = [];
|
||||||
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
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;
|
exit;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,7 @@
|
|||||||
<?= module_shell_header('boersenchecker', [
|
<?= module_shell_header('boersenchecker', [
|
||||||
'title' => 'Depot-Ueberblick',
|
'title' => 'Depot-Ueberblick',
|
||||||
]) ?>
|
]) ?>
|
||||||
<div class="bc-app">
|
<div class="bc-page" data-bc-home data-chart-endpoint="<?= e($chartEndpoint) ?>">
|
||||||
<div class="bc-grid-bg">
|
|
||||||
<div class="bc-shell bc-stack module-flow" 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 {
|
<script type="application/json" data-bc-instruments-json><?= json_encode(array_map(static function (array $position): array {
|
||||||
return [
|
return [
|
||||||
'instrument_id' => (int) ($position['instrument_id'] ?? 0),
|
'instrument_id' => (int) ($position['instrument_id'] ?? 0),
|
||||||
@@ -14,15 +12,15 @@
|
|||||||
}, $positions), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?></script>
|
}, $positions), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?></script>
|
||||||
|
|
||||||
<?php if ($error): ?>
|
<?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): ?>
|
<?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 endif; ?>
|
||||||
|
|
||||||
<section class="module-box">
|
<section class="section-box">
|
||||||
<div class="module-box-head">
|
<div class="bc-section-head">
|
||||||
<div>
|
<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>
|
<p>Depotauswahl, Aktienfokus und aktueller Kursabruf in einem Bereich.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,31 +74,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="module-box-grid module-box-grid--stats">
|
<div class="bc-overview-grid">
|
||||||
<section class="module-box-soft bc-stat">
|
<section class="card-box bc-stat">
|
||||||
<div class="bc-field-label">Positionen</div>
|
<div class="bc-field-label">Positionen</div>
|
||||||
<div class="bc-stat-value"><?= e((string) ($summary['positions'] ?? 0)) ?></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>
|
<div class="bc-text" style="margin-top:6px;">Aktien im aktuell gewaehlten Depot</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="module-box-soft bc-stat">
|
<section class="card-box bc-stat">
|
||||||
<div class="bc-field-label">Investiert</div>
|
<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-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>
|
<div class="bc-text" style="margin-top:6px;">In Berichtswahrung bewertet</div>
|
||||||
</section>
|
</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-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-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>
|
<div class="bc-text" style="margin-top:6px;">Basierend auf dem letzten gespeicherten Kurs</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="module-box-soft bc-stat">
|
<section class="card-box bc-stat">
|
||||||
<div class="bc-field-label">Performance</div>
|
<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-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>
|
<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>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="module-box-grid module-box-grid--panels">
|
<div class="bc-card-grid">
|
||||||
<section class="module-box-soft">
|
<section class="card-box">
|
||||||
<div class="bc-field-label">Bester Wert</div>
|
<div class="bc-field-label">Bester Wert</div>
|
||||||
<?php if (!empty($summary['best'])): ?>
|
<?php if (!empty($summary['best'])): ?>
|
||||||
<div class="bc-stat-value"><?= e((string) $summary['best']['instrument_name']) ?></div>
|
<div class="bc-stat-value"><?= e((string) $summary['best']['instrument_name']) ?></div>
|
||||||
@@ -110,7 +108,7 @@
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="module-box-soft">
|
<section class="card-box">
|
||||||
<div class="bc-field-label">Schwaechster Wert</div>
|
<div class="bc-field-label">Schwaechster Wert</div>
|
||||||
<?php if (!empty($summary['worst'])): ?>
|
<?php if (!empty($summary['worst'])): ?>
|
||||||
<div class="bc-stat-value"><?= e((string) $summary['worst']['instrument_name']) ?></div>
|
<div class="bc-stat-value"><?= e((string) $summary['worst']['instrument_name']) ?></div>
|
||||||
@@ -121,7 +119,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<?php foreach (array_slice($positions, 0, 2) as $position): ?>
|
<?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-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-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>
|
<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; ?>
|
<?php endforeach; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="module-box">
|
<section class="section-box">
|
||||||
<div class="module-box-head">
|
<div class="bc-section-head">
|
||||||
<div>
|
<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>
|
<p>Schlusskurse ueber mehrere Zeitfenster fuer das aktuell gewaehlte Instrument.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -161,14 +159,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="module-box-table">
|
<section class="section-box">
|
||||||
<div class="module-box-head">
|
<div class="bc-section-head">
|
||||||
<div>
|
<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>
|
<p>Stueckzahl, Kaufdaten, letzter Kurs und Performance auf einen Blick.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="module-box-copy">
|
<div class="bc-section-copy">
|
||||||
<?php if ($positions === []): ?>
|
<?php if ($positions === []): ?>
|
||||||
<div class="bc-text" style="padding:0 0 18px;">Keine Aktien im ausgewaehlten Depot.</div>
|
<div class="bc-text" style="padding:0 0 18px;">Keine Aktien im ausgewaehlten Depot.</div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
@@ -207,7 +205,5 @@
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<?= module_shell_footer() ?>
|
<?= module_shell_footer() ?>
|
||||||
|
|||||||
@@ -1,192 +1,187 @@
|
|||||||
<?= module_shell_header('boersenchecker', [
|
<?= module_shell_header('boersenchecker', [
|
||||||
'title' => 'Aktienverwaltung',
|
'title' => 'Aktienverwaltung',
|
||||||
]) ?>
|
]) ?>
|
||||||
<div class="bc-app">
|
<div class="bc-page">
|
||||||
<div class="bc-grid-bg">
|
<?php if ($error): ?>
|
||||||
<div class="bc-shell bc-stack module-flow">
|
<section class="section-box"><div class="bc-alert bc-alert--error"><?= e($error) ?></div></section>
|
||||||
|
<?php elseif ($notice): ?>
|
||||||
|
<section class="section-box"><div class="bc-alert bc-alert--success"><?= e($notice) ?></div></section>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if ($error): ?>
|
<div class="bc-card-grid">
|
||||||
<div class="bc-alert bc-alert--error"><?= e($error) ?></div>
|
<section class="section-box">
|
||||||
<?php elseif ($notice): ?>
|
<div class="bc-section-head">
|
||||||
<div class="bc-alert bc-alert--success"><?= e($notice) ?></div>
|
<div>
|
||||||
<?php endif; ?>
|
<h2 class="bc-section-title">Aktie waehlen</h2>
|
||||||
|
<p>Systemweit vorhandene Aktie aus allen Depots auswaehlen.</p>
|
||||||
<div class="module-box-grid module-box-grid--panels">
|
</div>
|
||||||
<section class="module-box">
|
|
||||||
<div class="module-box-head">
|
|
||||||
<div>
|
|
||||||
<h2 class="module-box-title">Aktie waehlen</h2>
|
|
||||||
<p>Systemweit vorhandene Aktie aus allen Depots auswaehlen.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<form method="get" style="margin-top:16px;">
|
|
||||||
<label class="setup-field muted">
|
|
||||||
<span>Aktien aller Depots</span>
|
|
||||||
<select name="instrument_id" onchange="this.form.submit()">
|
|
||||||
<?php foreach ($instruments as $instrument): ?>
|
|
||||||
<option value="<?= e((string) $instrument['id']) ?>" <?= (string) $selectedInstrumentId === (string) $instrument['id'] ? 'selected' : '' ?>>
|
|
||||||
<?= e((string) $instrument['name']) ?><?= !empty($instrument['symbol']) ? ' (' . e((string) $instrument['symbol']) . ')' : '' ?>
|
|
||||||
</option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</form>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="module-box-table">
|
|
||||||
<div class="module-box-head">
|
|
||||||
<div>
|
|
||||||
<h2 class="module-box-title">Wertpapiersuche</h2>
|
|
||||||
<p>Alpha-Vantage-Suchergebnisse finden und direkt fuer die Aktie uebernehmen.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="module-box-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) ?>">
|
|
||||||
<label class="setup-field muted" style="margin:0; min-width:260px; flex:1;">
|
|
||||||
<span>Suchbegriff</span>
|
|
||||||
<input type="text" name="search_keywords" value="<?= e($searchKeywords) ?>" placeholder="z.B. Apple, AAPL, Allianz" required>
|
|
||||||
</label>
|
|
||||||
<button class="bc-button bc-button--primary" type="submit">Suchen</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<?php if ($searchResults !== []): ?>
|
|
||||||
<table class="bc-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Symbol</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Region</th>
|
|
||||||
<th>Waehrung</th>
|
|
||||||
<th>Aktion</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($searchResults as $result): ?>
|
|
||||||
<tr>
|
|
||||||
<td><strong><?= e((string) ($result['symbol'] ?? '')) ?></strong></td>
|
|
||||||
<td><?= e((string) ($result['name'] ?? '')) ?></td>
|
|
||||||
<td><?= e((string) ($result['region'] ?? '')) ?></td>
|
|
||||||
<td><?= e((string) ($result['currency'] ?? '')) ?></td>
|
|
||||||
<td>
|
|
||||||
<a class="bc-button bc-button--secondary" href="/module/boersenchecker/aktienverwaltung?instrument_id=<?= e((string) $selectedInstrumentId) ?>&symbol_candidate=<?= urlencode((string) ($result['symbol'] ?? '')) ?>&instrument_name_candidate=<?= urlencode((string) ($result['name'] ?? '')) ?>&isin_candidate=<?= urlencode((string) ($result['isin'] ?? '')) ?>&market_candidate=<?= urlencode((string) ($result['region'] ?? '')) ?>"e_currency_candidate=<?= urlencode((string) ($result['currency'] ?? '')) ?>">
|
|
||||||
Uebernehmen
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="module-box-copy">
|
|
||||||
<div class="muted">Noch keine Symbolsuche ausgefuehrt.</div>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</section>
|
|
||||||
</div>
|
</div>
|
||||||
|
<form method="get" style="margin-top:16px;">
|
||||||
|
<label class="setup-field muted">
|
||||||
|
<span>Aktien aller Depots</span>
|
||||||
|
<select name="instrument_id" onchange="this.form.submit()">
|
||||||
|
<?php foreach ($instruments as $instrument): ?>
|
||||||
|
<option value="<?= e((string) $instrument['id']) ?>" <?= (string) $selectedInstrumentId === (string) $instrument['id'] ? 'selected' : '' ?>>
|
||||||
|
<?= e((string) $instrument['name']) ?><?= !empty($instrument['symbol']) ? ' (' . e((string) $instrument['symbol']) . ')' : '' ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="module-box">
|
<section class="section-box">
|
||||||
<div class="module-box-head">
|
<div class="bc-section-head">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="module-box-title">Aktie bearbeiten</h2>
|
<h2 class="bc-section-title">Wertpapiersuche</h2>
|
||||||
<p>Stammdaten, Markt und Kurswaehrung zentral fuer die Aktie pflegen.</p>
|
<p>Alpha-Vantage-Suchergebnisse finden und direkt fuer die Aktie uebernehmen.</p>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<?php if (!$selectedInstrument || empty($selectedInstrument['id'])): ?>
|
</div>
|
||||||
<div class="muted" style="margin-top:16px;">Keine Aktie vorhanden.</div>
|
<div class="bc-section-copy">
|
||||||
<?php else: ?>
|
<form method="post" style="margin-top:16px; display:flex; gap:10px; flex-wrap:wrap; align-items:end;">
|
||||||
<form method="post" style="margin-top:16px; display:grid; gap:12px;">
|
<input type="hidden" name="action" value="search_symbol">
|
||||||
<input type="hidden" name="action" value="save_instrument">
|
<input type="hidden" name="instrument_id" value="<?= e((string) $selectedInstrumentId) ?>">
|
||||||
<input type="hidden" name="instrument_id" value="<?= e((string) ($selectedInstrument['id'] ?? 0)) ?>">
|
<label class="setup-field muted" style="margin:0; min-width:260px; flex:1;">
|
||||||
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
|
<span>Suchbegriff</span>
|
||||||
<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>
|
<input type="text" name="search_keywords" value="<?= e($searchKeywords) ?>" placeholder="z.B. Apple, AAPL, Allianz" required>
|
||||||
<label class="setup-field muted"><span>Symbol</span><input type="text" name="symbol" value="<?= e((string) (($selectedInstrument['symbol'] ?? '') ?: ($_GET['symbol_candidate'] ?? ''))) ?>"></label>
|
</label>
|
||||||
<label class="setup-field muted"><span>ISIN</span><input type="text" name="isin" value="<?= e((string) ($selectedInstrument['isin'] ?? '')) ?>"></label>
|
<button class="bc-button bc-button--primary" type="submit">Suchen</button>
|
||||||
<label class="setup-field muted"><span>WKN</span><input type="text" name="wkn" value="<?= e((string) ($selectedInstrument['wkn'] ?? '')) ?>"></label>
|
</form>
|
||||||
<label class="setup-field muted"><span>Markt</span><input type="text" name="market" value="<?= e((string) (($selectedInstrument['market'] ?? '') ?: ($_GET['market_candidate'] ?? ''))) ?>"></label>
|
</div>
|
||||||
<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>
|
<?php if ($searchResults !== []): ?>
|
||||||
</div>
|
<table class="bc-table">
|
||||||
<div class="bc-actions">
|
<thead>
|
||||||
<button class="bc-button bc-button--primary" type="submit">Aktie speichern</button>
|
<tr>
|
||||||
</div>
|
<th>Symbol</th>
|
||||||
</form>
|
<th>Name</th>
|
||||||
<form method="post" style="margin-top:12px;">
|
<th>Region</th>
|
||||||
<input type="hidden" name="action" value="refresh_market_data_instrument">
|
<th>Waehrung</th>
|
||||||
<input type="hidden" name="instrument_id" value="<?= e((string) ($selectedInstrument['id'] ?? 0)) ?>">
|
<th>Aktion</th>
|
||||||
<button class="bc-button bc-button--secondary" type="submit">Aktuellen API-Kurs abrufen</button>
|
</tr>
|
||||||
</form>
|
</thead>
|
||||||
<?php endif; ?>
|
<tbody>
|
||||||
</section>
|
<?php foreach ($searchResults as $result): ?>
|
||||||
|
|
||||||
<section class="module-box">
|
|
||||||
<div class="module-box-head">
|
|
||||||
<div>
|
|
||||||
<h2 class="module-box-title">Manuellen Kurs eingeben</h2>
|
|
||||||
<p>Einzelne Kurse mit Zeitstempel und Quelle fuer die ausgewaehlte Aktie speichern.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php if (!$selectedInstrument || empty($selectedInstrument['id'])): ?>
|
|
||||||
<div class="muted" style="margin-top:16px;">Keine Aktie vorhanden.</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<form method="post" style="margin-top:16px; display:grid; gap:12px;">
|
|
||||||
<input type="hidden" name="action" value="save_quote">
|
|
||||||
<input type="hidden" name="instrument_id" value="<?= e((string) ($selectedInstrument['id'] ?? 0)) ?>">
|
|
||||||
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
|
|
||||||
<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((string) ($selectedInstrument['quote_currency'] ?? $defaultReportCurrency)) ?>" required></label>
|
|
||||||
<label class="setup-field muted"><span>Zeitpunkt</span><input type="datetime-local" name="quoted_at" value="<?= e($localNowInputValue) ?>" required></label>
|
|
||||||
<label class="setup-field muted"><span>Quelle</span><input type="text" name="quote_source" value="manual"></label>
|
|
||||||
</div>
|
|
||||||
<div class="bc-actions">
|
|
||||||
<button class="bc-button bc-button--primary" type="submit">Kurs speichern</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<?php endif; ?>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="module-box-table">
|
|
||||||
<div class="module-box-head">
|
|
||||||
<div>
|
|
||||||
<h2 class="module-box-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="muted">Keine Kursdaten vorhanden.</div>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<table class="bc-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Zeitpunkt</th>
|
<td><strong><?= e((string) ($result['symbol'] ?? '')) ?></strong></td>
|
||||||
<th>Kurs</th>
|
<td><?= e((string) ($result['name'] ?? '')) ?></td>
|
||||||
<th>Quelle</th>
|
<td><?= e((string) ($result['region'] ?? '')) ?></td>
|
||||||
<th>Aktion</th>
|
<td><?= e((string) ($result['currency'] ?? '')) ?></td>
|
||||||
|
<td>
|
||||||
|
<a class="bc-button bc-button--secondary" href="/module/boersenchecker/aktienverwaltung?instrument_id=<?= e((string) $selectedInstrumentId) ?>&symbol_candidate=<?= urlencode((string) ($result['symbol'] ?? '')) ?>&instrument_name_candidate=<?= urlencode((string) ($result['name'] ?? '')) ?>&isin_candidate=<?= urlencode((string) ($result['isin'] ?? '')) ?>&market_candidate=<?= urlencode((string) ($result['region'] ?? '')) ?>"e_currency_candidate=<?= urlencode((string) ($result['currency'] ?? '')) ?>">
|
||||||
|
Uebernehmen
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
<?php endforeach; ?>
|
||||||
<tbody>
|
</tbody>
|
||||||
<?php foreach ($quotes as $quote): ?>
|
</table>
|
||||||
<tr>
|
<?php else: ?>
|
||||||
<td><?= e($fmtDateTime((string) $quote['quoted_at'], (string) ($quote['source'] ?? ''))) ?></td>
|
<div class="bc-section-copy">
|
||||||
<td><?= e(number_format((float) $quote['price'], 4, ',', '.')) ?> <?= e((string) $quote['currency']) ?></td>
|
<div class="muted">Noch keine Symbolsuche ausgefuehrt.</div>
|
||||||
<td><?= e((string) $quote['source']) ?></td>
|
</div>
|
||||||
<td>
|
<?php endif; ?>
|
||||||
<form method="post" onsubmit="return confirm('Kurseintrag wirklich loeschen?')">
|
</section>
|
||||||
<input type="hidden" name="action" value="delete_quote">
|
|
||||||
<input type="hidden" name="instrument_id" value="<?= e((string) $selectedInstrumentId) ?>">
|
|
||||||
<input type="hidden" name="quote_id" value="<?= e((string) $quote['id']) ?>">
|
|
||||||
<button class="bc-button bc-button--secondary" type="submit">Loeschen</button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<?php endif; ?>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<section class="section-box">
|
||||||
|
<div class="bc-section-head">
|
||||||
|
<div>
|
||||||
|
<h2 class="bc-section-title">Aktie bearbeiten</h2>
|
||||||
|
<p>Stammdaten, Markt und Kurswaehrung zentral fuer die Aktie pflegen.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php if (!$selectedInstrument || empty($selectedInstrument['id'])): ?>
|
||||||
|
<div class="muted" style="margin-top:16px;">Keine Aktie vorhanden.</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<form method="post" style="margin-top:16px; display:grid; gap:12px;">
|
||||||
|
<input type="hidden" name="action" value="save_instrument">
|
||||||
|
<input type="hidden" name="instrument_id" value="<?= e((string) ($selectedInstrument['id'] ?? 0)) ?>">
|
||||||
|
<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>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>
|
||||||
|
<div class="bc-actions">
|
||||||
|
<button class="bc-button bc-button--primary" type="submit">Aktie speichern</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form method="post" style="margin-top:12px;">
|
||||||
|
<input type="hidden" name="action" value="refresh_market_data_instrument">
|
||||||
|
<input type="hidden" name="instrument_id" value="<?= e((string) ($selectedInstrument['id'] ?? 0)) ?>">
|
||||||
|
<button class="bc-button bc-button--secondary" type="submit">Aktuellen API-Kurs abrufen</button>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section-box">
|
||||||
|
<div class="bc-section-head">
|
||||||
|
<div>
|
||||||
|
<h2 class="bc-section-title">Manuellen Kurs eingeben</h2>
|
||||||
|
<p>Einzelne Kurse mit Zeitstempel und Quelle fuer die ausgewaehlte Aktie speichern.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php if (!$selectedInstrument || empty($selectedInstrument['id'])): ?>
|
||||||
|
<div class="muted" style="margin-top:16px;">Keine Aktie vorhanden.</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<form method="post" style="margin-top:16px; display:grid; gap:12px;">
|
||||||
|
<input type="hidden" name="action" value="save_quote">
|
||||||
|
<input type="hidden" name="instrument_id" value="<?= e((string) ($selectedInstrument['id'] ?? 0)) ?>">
|
||||||
|
<div class="grid" style="grid-template-columns:repeat(auto-fit, minmax(180px, 1fr)); gap:10px;">
|
||||||
|
<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((string) ($selectedInstrument['quote_currency'] ?? $defaultReportCurrency)) ?>" required></label>
|
||||||
|
<label class="setup-field muted"><span>Zeitpunkt</span><input type="datetime-local" name="quoted_at" value="<?= e($localNowInputValue) ?>" required></label>
|
||||||
|
<label class="setup-field muted"><span>Quelle</span><input type="text" name="quote_source" value="manual"></label>
|
||||||
|
</div>
|
||||||
|
<div class="bc-actions">
|
||||||
|
<button class="bc-button bc-button--primary" type="submit">Kurs speichern</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section-box">
|
||||||
|
<div class="bc-section-head">
|
||||||
|
<div>
|
||||||
|
<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="bc-section-copy">
|
||||||
|
<div class="muted">Keine Kursdaten vorhanden.</div>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<table class="bc-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Zeitpunkt</th>
|
||||||
|
<th>Kurs</th>
|
||||||
|
<th>Quelle</th>
|
||||||
|
<th>Aktion</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($quotes as $quote): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?= e($fmtDateTime((string) $quote['quoted_at'], (string) ($quote['source'] ?? ''))) ?></td>
|
||||||
|
<td><?= e(number_format((float) $quote['price'], 4, ',', '.')) ?> <?= e((string) $quote['currency']) ?></td>
|
||||||
|
<td><?= e((string) $quote['source']) ?></td>
|
||||||
|
<td>
|
||||||
|
<form method="post" onsubmit="return confirm('Kurseintrag wirklich loeschen?')">
|
||||||
|
<input type="hidden" name="action" value="delete_quote">
|
||||||
|
<input type="hidden" name="instrument_id" value="<?= e((string) $selectedInstrumentId) ?>">
|
||||||
|
<input type="hidden" name="quote_id" value="<?= e((string) $quote['id']) ?>">
|
||||||
|
<button class="bc-button bc-button--secondary" type="submit">Loeschen</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<?php endif; ?>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<?= module_shell_footer() ?>
|
<?= module_shell_footer() ?>
|
||||||
|
|||||||
Reference in New Issue
Block a user