dsasd
All checks were successful
Deploy / deploy-staging (push) Successful in 5s
Deploy / deploy-production (push) Has been skipped

This commit is contained in:
2026-05-09 01:34:41 +02:00
parent 693086029d
commit de99f21332
3 changed files with 106 additions and 42 deletions

View File

@@ -667,9 +667,34 @@
]);
}
function miningCheckerViewFromHref(href) {
try {
const url = new URL(href, window.location.origin);
if (url.pathname !== '/module/mining-checker') {
return null;
}
return url.searchParams.get('view') || 'overview';
} catch (err) {
return null;
}
}
function syncMiningCheckerTabButtons(activeTab) {
const buttons = Array.from(document.querySelectorAll('.module-tabs a[href*="/module/mining-checker"]'));
for (const button of buttons) {
const tab = miningCheckerViewFromHref(button.getAttribute('href') || '');
if (!tab) {
continue;
}
const isActive = tab === activeTab;
button.classList.toggle('module-button--tab-active', isActive);
button.classList.toggle('module-button--tab', !isActive);
}
}
function App() {
const [projectKey, setProjectKey] = useState(initialProjectKey);
const [activeTab] = useState(initialActiveTab);
const [activeTab, setActiveTab] = useState(initialActiveTab);
const [payload, setPayload] = useState(() => normalizeBootstrap(null, initialProjectKey));
const [dashboardData, setDashboardData] = useState({});
const [loading, setLoading] = useState(true);
@@ -1159,14 +1184,46 @@
useEffect(() => {
loadBootstrap(projectKey);
}, [projectKey]);
}, [projectKey, activeTab]);
useEffect(() => {
if (activeTab === 'settings') {
loadSchemaStatus(projectKey);
loadModuleAuth();
syncMiningCheckerTabButtons(activeTab);
function handleNavigationClick(event) {
const link = event.target instanceof Element
? event.target.closest('.module-tabs a[href*="/module/mining-checker"]')
: null;
if (!link) {
return;
}
const nextTab = miningCheckerViewFromHref(link.getAttribute('href') || '');
if (!nextTab || nextTab === activeTab) {
return;
}
event.preventDefault();
window.history.pushState({ miningCheckerView: nextTab }, '', `/module/mining-checker?view=${encodeURIComponent(nextTab)}`);
setActiveTab(nextTab);
}
}, [activeTab, projectKey]);
function handlePopState() {
const nextTab = miningCheckerViewFromHref(window.location.href) || 'overview';
setActiveTab(nextTab);
}
document.addEventListener('click', handleNavigationClick);
window.addEventListener('popstate', handlePopState);
return () => {
document.removeEventListener('click', handleNavigationClick);
window.removeEventListener('popstate', handlePopState);
};
}, [activeTab]);
useEffect(() => {
loadSchemaStatus(projectKey);
loadModuleAuth();
}, [projectKey]);
useEffect(() => {
async function loadSavedDashboards() {
@@ -1937,8 +1994,8 @@
h('div', { key: 'shell', className: 'mc-shell mc-stack' }, [
error ? h('div', { key: 'error', className: 'mc-alert mc-alert--error' }, error) : null,
message ? h('div', { key: 'message', className: 'mc-alert mc-alert--success' }, message) : null,
loading ? h('div', { key: 'loading', className: 'mc-empty' }, 'Lade Mining-Checker Daten …') : null,
payload ? renderTab() : null,
loading ? h('div', { key: 'loading', className: 'mc-alert mc-alert--warning' }, 'Mining-Checker Daten werden aktualisiert …') : null,
renderTab(),
]),
]);
@@ -2077,10 +2134,41 @@
}
if (activeTab === 'measurements') {
return h('div', { className: 'mc-main-grid' }, [
h('div', { className: 'mc-stack' }, [
]),
panel('Mining-History', 'Die letzten 10 Mining-Uploads inkl. Performance-Werten und OCR-Metadaten.', h('div', { className: 'mc-table-shell' }, [
h('table', { key: 'table', className: 'mc-table' }, [
h('thead', { key: 'thead' }, h('tr', null, [
'Zeit', 'Coins', 'Kurs', 'Quelle', perDayLabel, 'Trend', 'Notiz', 'Aktion'
].map((label) => h('th', { key: label }, label)))),
h('tbody', { key: 'tbody' },
measurements.slice(-10).reverse().map((row) => h('tr', { key: row.id }, [
h('td', { key: 'measured' }, fmtDate(row.measured_at)),
h('td', { key: 'coins' }, `${fmtNumber(row.coins_total, 6)} ${row.coin_currency || currentCoinCurrency}`),
h('td', { key: 'price' }, row.price_per_coin ? `${fmtNumber(row.price_per_coin, 6)} ${row.price_currency}` : 'n/a'),
h('td', { key: 'source' }, row.source),
h('td', { key: 'rate' }, fmtNumber(row.doge_per_day_interval, 4)),
h('td', { key: 'trend' }, row.trend_label),
h('td', { key: 'note' }, row.note || row.ocr_flags.join(', ') || '—'),
h('td', { key: 'action' }, h('button', {
type: 'button',
className: 'mc-button mc-button--ghost',
onClick: () => deleteMeasurement(row.id),
disabled: saving,
}, 'Loeschen')),
]))
),
]),
])),
]);
}
if (activeTab === 'upload') {
return h('div', { className: 'mc-main-grid' }, [
h('div', { className: 'mc-stack' }, [
renderSharedOcrPanel(),
panel('Messpunkt manuell erfassen', 'Direkte Eingabe eines einzelnen Messpunkts mit serverseitiger Validierung.', h('form', {
panel('Mining manuell erfassen', 'Direkte Eingabe eines einzelnen Mining-Messpunkts mit serverseitiger Validierung.', h('form', {
className: 'mc-form',
onSubmit: function (event) {
event.preventDefault();
@@ -2098,7 +2186,7 @@
disabled: saving,
}, saving ? 'Speichert …' : 'Messpunkt speichern'),
])),
panel('Import per Copy & Paste', 'Mehrere historische Messpunkte auf einmal einfuegen. Doppelte Eintraege werden ignoriert.', h('form', {
panel('Mining-Import per Copy & Paste', 'Mehrere historische Mining-Messpunkte auf einmal einfuegen. Doppelte Eintraege werden ignoriert.', h('form', {
className: 'mc-form',
onSubmit: submitMeasurementImport,
}, [
@@ -2158,37 +2246,12 @@
]),
]) : null,
]),
panel('Messhistorie', 'Die letzten 10 Uploads inkl. Performance-Werten und OCR-Metadaten.', h('div', { className: 'mc-table-shell' }, [
h('table', { key: 'table', className: 'mc-table' }, [
h('thead', { key: 'thead' }, h('tr', null, [
'Zeit', 'Coins', 'Kurs', 'Quelle', perDayLabel, 'Trend', 'Notiz', 'Aktion'
].map((label) => h('th', { key: label }, label)))),
h('tbody', { key: 'tbody' },
measurements.slice(-10).reverse().map((row) => h('tr', { key: row.id }, [
h('td', { key: 'measured' }, fmtDate(row.measured_at)),
h('td', { key: 'coins' }, `${fmtNumber(row.coins_total, 6)} ${row.coin_currency || currentCoinCurrency}`),
h('td', { key: 'price' }, row.price_per_coin ? `${fmtNumber(row.price_per_coin, 6)} ${row.price_currency}` : 'n/a'),
h('td', { key: 'source' }, row.source),
h('td', { key: 'rate' }, fmtNumber(row.doge_per_day_interval, 4)),
h('td', { key: 'trend' }, row.trend_label),
h('td', { key: 'note' }, row.note || row.ocr_flags.join(', ') || '—'),
h('td', { key: 'action' }, h('button', {
type: 'button',
className: 'mc-button mc-button--ghost',
onClick: () => deleteMeasurement(row.id),
disabled: saving,
}, 'Loeschen')),
]))
),
]),
])),
]);
}
if (activeTab === 'wallet') {
return h('div', { className: 'mc-main-grid' }, [
h('div', { className: 'mc-stack' }, [
renderSharedOcrPanel(),
panel('Wallet-Historie', `Erkannte Wallet-Snapshots. Fuer Reinvestitionen ist aktuell ${currentSettings.crypto_currency || 'DOGE'} entscheidend.`, h('div', { className: 'mc-table-shell' }, [
h('table', { key: 'wallet-table', className: 'mc-table' }, [
h('thead', { key: 'thead' }, h('tr', null, [