Files
nexus/modules/fx-rates/pages/currencies.php
Lars Gebhardt-Kusche 6d59d94273
All checks were successful
Deploy / deploy-staging (push) Successful in 5s
Deploy / deploy-production (push) Has been skipped
asfsfd
2026-05-02 03:24:16 +02:00

272 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
require_once dirname(__DIR__) . '/bootstrap.php';
$assets = app()->assets();
if ($assets) {
$assets->addStyle('/module/fx-rates/asset?file=fx-rates.css');
$assets->addScript('/module/fx-rates/asset?file=fx-rates-currencies.js', 'footer', true);
}
$settings = module_fn('fx-rates', 'settings');
$service = module_fn('fx-rates', 'service');
$notice = trim((string) ($_GET['notice'] ?? ''));
$error = trim((string) ($_GET['error'] ?? ''));
if (strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET')) === 'POST') {
try {
$action = trim((string) ($_POST['fx_action'] ?? ''));
if ($action === 'save_selection') {
$payload = [
'display_base_currency' => (string) ($_POST['display_base_currency'] ?? ''),
'preferred_currencies' => $_POST['preferred_currencies'] ?? [],
];
$saved = module_fn('fx-rates', 'save_runtime_settings', $payload);
$params = ['notice' => 'Waehrungs-Auswahl gespeichert.'];
if (is_array($saved) && !empty($saved['display_base_currency'])) {
$params['base'] = (string) $saved['display_base_currency'];
}
redirect('/module/fx-rates/currencies?' . http_build_query($params));
}
if ($action === 'sync_catalog') {
$result = module_fn('fx-rates', 'run_setup_action', 'sync_currency_catalog');
redirect('/module/fx-rates/currencies?' . http_build_query([
'notice' => sprintf('Waehrungskatalog synchronisiert. %d Waehrungen verarbeitet.', (int) ($result['synced_count'] ?? 0)),
]));
}
if ($action === 'refresh_rates') {
$result = $service->refreshLatestRates(null, (string) ($settings['default_base_currency'] ?? ''), 'manual');
redirect('/module/fx-rates/currencies?' . http_build_query([
'notice' => sprintf('Alle Wechselkurse aktualisiert. %d Werte gespeichert.', (int) ($result['updated_count'] ?? 0)),
]));
}
} catch (\Throwable $exception) {
redirect('/module/fx-rates/currencies?' . http_build_query([
'error' => $exception->getMessage() !== '' ? $exception->getMessage() : 'Aktion konnte nicht ausgefuehrt werden.',
]));
}
}
$catalog = is_array($settings['currency_catalog'] ?? null) ? $settings['currency_catalog'] : [];
$preferredCurrencies = is_array($settings['preferred_currencies'] ?? null) ? $settings['preferred_currencies'] : [];
$savedDisplayBaseCurrency = strtoupper(trim((string) ($settings['display_base_currency'] ?? $settings['default_base_currency'] ?? 'EUR')));
$requestedDisplayBaseCurrency = strtoupper(trim((string) ($_GET['base'] ?? '')));
$latest = $service->latestStatus();
$recentFetches = $service->recentFetches(15);
$currencies = [];
foreach ($catalog as $item) {
if (!is_array($item)) {
continue;
}
$code = strtoupper(trim((string) ($item['code'] ?? '')));
$name = trim((string) ($item['name'] ?? ''));
if ($code === '' || $name === '') {
continue;
}
$currencies[] = [
'code' => $code,
'name' => $name,
];
}
$cryptoCodes = array_fill_keys([
'ADA', 'ARB', 'BNB', 'BTC', 'DAI', 'DOGE', 'DOT', 'ETH', 'LINK', 'LTC',
'SOL', 'USDC', 'USDT', 'XAG', 'XAU', 'XRP',
], true);
$fiatCount = 0;
$cryptoCount = 0;
foreach ($currencies as $currency) {
if (isset($cryptoCodes[$currency['code']])) {
$cryptoCount++;
} else {
$fiatCount++;
}
}
$catalogCodes = [];
foreach ($currencies as $currency) {
$catalogCodes[(string) $currency['code']] = true;
}
$displayBaseCurrency = $requestedDisplayBaseCurrency !== '' ? $requestedDisplayBaseCurrency : $savedDisplayBaseCurrency;
if ($displayBaseCurrency === '' || (!isset($catalogCodes[$displayBaseCurrency]) && $preferredCurrencies !== [])) {
$displayBaseCurrency = $savedDisplayBaseCurrency !== '' ? $savedDisplayBaseCurrency : (string) ($preferredCurrencies[0] ?? 'EUR');
}
$tableCurrencies = [];
foreach ([$displayBaseCurrency, ...$preferredCurrencies] as $currency) {
$currency = strtoupper(trim((string) $currency));
if ($currency !== '' && !in_array($currency, $tableCurrencies, true)) {
$tableCurrencies[] = $currency;
}
}
$currencyPageData = json_encode([
'currencies' => $currencies,
'preferred_currencies' => array_values(array_unique(array_map(static fn (mixed $code): string => strtoupper(trim((string) $code)), $preferredCurrencies))),
'display_base_currency' => $displayBaseCurrency,
'saved_display_base_currency' => $savedDisplayBaseCurrency,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$tabs = [
['label' => 'Ueberblick', 'href' => '/module/fx-rates'],
['label' => 'Waehrungen', 'href' => '/module/fx-rates/currencies', 'active' => true],
];
?>
<?= module_shell_header('fx-rates', [
'title' => 'Waehrungskurse',
'tabs' => $tabs,
'actions' => [
['label' => 'Setup', 'href' => '/modules/setup/fx-rates', 'variant' => 'secondary', 'size' => 'sm'],
],
]) ?>
<div id="fx-rates-currencies" data-page='<?= e(is_string($currencyPageData) ? $currencyPageData : '{}') ?>'>
<div class="fx-stack">
<div class="fx-card">
<?php if ($notice !== ''): ?>
<div class="fx-message is-success"><?= e($notice) ?></div>
<?php elseif ($error !== ''): ?>
<div class="fx-message is-error"><?= e($error) ?></div>
<?php endif; ?>
<h2>Waehrungs-Update</h2>
<p>Auswahl wird in den FX-Rates-Einstellungen gespeichert und steht damit auf Handy und Desktop gleich zur Verfuegung.</p>
<div class="fx-action-row">
<form method="post">
<input type="hidden" name="fx_action" value="refresh_rates">
<button type="submit" class="fx-button fx-button--accent">Alle Wechselkurse aktualisieren</button>
</form>
<form method="post">
<input type="hidden" name="fx_action" value="sync_catalog">
<button type="submit" class="fx-button fx-button--ghost">Waehrungskatalog sync</button>
</form>
</div>
<div class="fx-mini-grid">
<div class="fx-mini-card">
<div class="fx-mini-label">Fiat</div>
<div><?= e((string) $fiatCount) ?> Waehrungen</div>
</div>
<div class="fx-mini-card">
<div class="fx-mini-label">Krypto</div>
<div><?= e((string) $cryptoCount) ?> Waehrungen</div>
</div>
</div>
<div class="fx-field-label">Bevorzugte Waehrungen fuer Anzeige</div>
<div class="fx-currency-selection-row">
<div class="fx-token-list fx-token-list--inline" data-fx-token-list></div>
<div class="fx-currency-search">
<input type="text" class="fx-input" value="" placeholder="Waehrung hinzufuegen: EUR, USD, DOGE oder Euro" autocomplete="off" data-fx-search-input>
</div>
</div>
<div class="fx-suggestion-list" data-fx-suggestions></div>
<div class="fx-field fx-currency-search">
<label class="fx-field-label" for="fx-display-base-select">Darstellung auf Basis von</label>
<select id="fx-display-base-select" class="fx-select" data-fx-display-base-select></select>
</div>
<div class="fx-save-row">
<form method="post">
<input type="hidden" name="fx_action" value="save_selection">
<input type="hidden" name="display_base_currency" value="<?= e($displayBaseCurrency) ?>" data-fx-display-base-hidden>
<div data-fx-hidden-preferred></div>
<button type="submit" class="fx-button fx-button--ghost">Auswahl speichern</button>
</form>
</div>
</div>
<div class="fx-card">
<div class="fx-card-head">
<div>
<h2>Letzte 15 Kurs-Uploads</h2>
<p>Zeigt die zuletzt gespeicherten Wechselkurse aus der Datenbank.</p>
</div>
<div class="fx-card-meta">
<div><strong>Anzeige-Basis:</strong> <?= e($displayBaseCurrency) ?></div>
<div><strong>Letzter Abruf:</strong> <?= e((string) ($latest['fetched_at_display'] ?? $latest['fetched_at'] ?? 'noch keiner')) ?></div>
</div>
</div>
<div class="fx-table-wrap">
<table class="fx-table">
<thead>
<tr>
<th>Zeit</th>
<?php foreach ($tableCurrencies as $currency): ?>
<th><?= e((string) $currency) ?></th>
<?php endforeach; ?>
</tr>
</thead>
<tbody>
<?php if ($recentFetches === []): ?>
<tr><td colspan="<?= 1 + count($tableCurrencies) ?>">Noch keine Abrufe vorhanden.</td></tr>
<?php else: ?>
<?php foreach ($recentFetches as $fetch): ?>
<?php
$fetchBaseCurrency = strtoupper(trim((string) ($fetch['base_currency'] ?? '')));
$snapshot = $service->snapshotByFetchId((int) ($fetch['id'] ?? 0), $fetchBaseCurrency, $tableCurrencies);
$originalRates = is_array($snapshot['rates'] ?? null) ? $snapshot['rates'] : [];
$displayBaseRate = $displayBaseCurrency === $fetchBaseCurrency
? 1.0
: (is_numeric($originalRates[$displayBaseCurrency] ?? null) ? (float) $originalRates[$displayBaseCurrency] : null);
$tableRates = [];
foreach ($tableCurrencies as $currency) {
$currency = strtoupper(trim((string) $currency));
if ($currency === '') {
continue;
}
if ($currency === $displayBaseCurrency) {
$tableRates[$currency] = 1.0;
continue;
}
if ($displayBaseRate === null || $displayBaseRate <= 0) {
$tableRates[$currency] = null;
continue;
}
if ($currency === $fetchBaseCurrency) {
$tableRates[$currency] = 1 / $displayBaseRate;
continue;
}
$rawRate = $originalRates[$currency] ?? null;
$tableRates[$currency] = is_numeric($rawRate) ? ((float) $rawRate / $displayBaseRate) : null;
}
$infoTitle = sprintf(
'Basis: %s | Provider: %s | Ausloeser: %s',
(string) ($fetch['base_currency'] ?? '-'),
(string) ($fetch['provider'] ?? '-'),
(string) ($fetch['trigger_source_label'] ?? $fetch['trigger_source'] ?? '-')
);
?>
<tr>
<td>
<div class="fx-history-date">
<span><?= e((string) ($fetch['fetched_at_display'] ?? $fetch['fetched_at'] ?? '')) ?></span>
<button
type="button"
class="fx-info-button"
title="<?= e($infoTitle) ?>"
aria-label="<?= e('Abrufinfo fuer ' . (string) ($fetch['fetched_at_display'] ?? $fetch['fetched_at'] ?? '')) ?>"
>i</button>
</div>
</td>
<?php foreach ($tableCurrencies as $currency): ?>
<?php $value = $tableRates[(string) $currency] ?? null; ?>
<td><?= is_numeric($value) ? e(number_format((float) $value, 8, ',', '')) : '' ?></td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?= module_shell_footer() ?>