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

This commit is contained in:
2026-05-09 01:47:22 +02:00
parent de99f21332
commit c6642c0ef5
5 changed files with 302 additions and 40 deletions

View File

@@ -2134,9 +2134,7 @@
}
if (activeTab === 'measurements') {
return h('div', { className: 'mc-main-grid' }, [
h('div', { className: 'mc-stack' }, [
]),
return 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, [
@@ -2165,8 +2163,8 @@
}
if (activeTab === 'upload') {
return h('div', { className: 'mc-main-grid' }, [
h('div', { className: 'mc-stack' }, [
return h('div', { className: 'mc-stack' }, [
h('div', { className: 'mc-two-col' }, [
renderSharedOcrPanel(),
panel('Mining manuell erfassen', 'Direkte Eingabe eines einzelnen Mining-Messpunkts mit serverseitiger Validierung.', h('form', {
className: 'mc-form',
@@ -2186,28 +2184,6 @@
disabled: saving,
}, saving ? 'Speichert …' : 'Messpunkt speichern'),
])),
panel('Mining-Import per Copy & Paste', 'Mehrere historische Mining-Messpunkte auf einmal einfuegen. Doppelte Eintraege werden ignoriert.', h('form', {
className: 'mc-form',
onSubmit: submitMeasurementImport,
}, [
h('div', { className: 'mc-inline-row' }, [
h('button', {
key: 'help',
type: 'button',
className: 'mc-button mc-button--ghost',
onClick: () => setImportHelpOpen(true),
}, 'Import-Hilfe'),
]),
displayField('Format', 'DD.MM.YYYY HH:MM | Coins | Kurs | Waehrung | Notiz'),
textareaField('Importdaten', importForm.rows_text, (value) => setImportForm({ ...importForm, rows_text: value })),
selectField('Standard-Waehrung', importForm.default_currency, [''].concat(selectableCurrencies.map((currency) => currency.code)), (value) => setImportForm({ ...importForm, default_currency: value })),
selectField('Import-Quelle', importForm.source, ['manual', 'seed_import'], (value) => setImportForm({ ...importForm, source: value })),
h('button', {
type: 'submit',
className: 'mc-button mc-button--secondary',
disabled: saving,
}, saving ? 'Importiert …' : 'Import ausfuehren'),
])),
importHelpOpen ? h('div', { className: 'mc-modal-backdrop', onClick: () => setImportHelpOpen(false) }, [
h('div', {
key: 'modal',
@@ -2246,16 +2222,56 @@
]),
]) : null,
]),
panel('Mining-Import per Copy & Paste', 'Mehrere historische Mining-Messpunkte auf einmal einfuegen. Doppelte Eintraege werden ignoriert.', h('form', {
className: 'mc-form',
onSubmit: submitMeasurementImport,
}, [
h('div', { className: 'mc-inline-row' }, [
h('button', {
key: 'help',
type: 'button',
className: 'mc-button mc-button--ghost',
onClick: () => setImportHelpOpen(true),
}, 'Import-Hilfe'),
]),
displayField('Format', 'DD.MM.YYYY HH:MM | Coins | Kurs | Waehrung | Notiz'),
textareaField('Importdaten', importForm.rows_text, (value) => setImportForm({ ...importForm, rows_text: value })),
selectField('Standard-Waehrung', importForm.default_currency, [''].concat(selectableCurrencies.map((currency) => currency.code)), (value) => setImportForm({ ...importForm, default_currency: value })),
selectField('Import-Quelle', importForm.source, ['manual', 'seed_import'], (value) => setImportForm({ ...importForm, source: value })),
h('button', {
type: 'submit',
className: 'mc-button mc-button--secondary',
disabled: saving,
}, saving ? 'Importiert …' : 'Import ausfuehren'),
])),
]);
}
if (activeTab === 'wallet') {
return h('div', { className: 'mc-main-grid' }, [
h('div', { className: 'mc-stack' }, [
panel('Wallet-Historie', `Erkannte Wallet-Snapshots. Fuer Reinvestitionen ist aktuell ${currentSettings.crypto_currency || 'DOGE'} entscheidend.`, h('div', { className: 'mc-table-shell' }, [
const latestWalletSnapshot = currentWalletSnapshots.length ? currentWalletSnapshots[0] : null;
const latestWalletAssets = latestWalletSnapshot && latestWalletSnapshot.balances_json && typeof latestWalletSnapshot.balances_json === 'object'
? Object.entries(latestWalletSnapshot.balances_json)
: [];
return h('div', { className: 'mc-stack' }, [
panel('Wallet-Bestaende', 'Der letzte Wallet-Snapshot zeigt alle erkannten Assets separat.', latestWalletAssets.length
? h('div', { className: 'mc-asset-grid' }, latestWalletAssets.map(([code, asset]) => {
const balance = asset && typeof asset === 'object' ? asset.balance : asset;
const priceAmount = asset && typeof asset === 'object' ? asset.price_amount : null;
const priceCurrency = asset && typeof asset === 'object' ? asset.price_currency : null;
return h('div', { key: code, className: 'mc-display-field mc-asset-card' }, [
h('div', { key: 'code', className: 'mc-field-label' }, code),
h('div', { key: 'balance', className: 'mc-asset-balance' }, `${fmtNumber(balance, 8)} ${code}`),
h('div', { key: 'price', className: 'mc-text' }, priceAmount !== null && priceAmount !== undefined
? `1 ${code} = ${fmtNumber(priceAmount, 6)} ${priceCurrency || ''}`.trim()
: 'Kein Screenshot-Kurs erkannt'),
]);
}))
: h('div', { className: 'mc-empty' }, 'Noch keine Wallet-Assets erkannt.')),
panel('Wallet-Historie', 'Erkannte Wallet-Snapshots mit allen aus dem Screenshot gelesenen Assets.', h('div', { className: 'mc-table-shell' }, [
h('table', { key: 'wallet-table', className: 'mc-table' }, [
h('thead', { key: 'thead' }, h('tr', null, [
'Zeit', 'Mining-Waehrung', 'Bestand', 'Gesamtwert', 'Quelle', 'Assets'
'Zeit', 'Mining-Waehrung', 'Mining-Bestand', 'Quelle', 'Assets'
].map((label) => h('th', { key: label }, label)))),
h('tbody', { key: 'tbody' },
currentWalletSnapshots.length
@@ -2263,20 +2279,24 @@
h('td', { key: 'measured' }, fmtDate(row.measured_at)),
h('td', { key: 'currency' }, row.wallet_currency || currentSettings.crypto_currency || 'DOGE'),
h('td', { key: 'balance' }, row.wallet_balance !== null && row.wallet_balance !== undefined ? `${fmtNumber(row.wallet_balance, 8)} ${row.wallet_currency || ''}`.trim() : 'n/a'),
h('td', { key: 'value' }, row.total_value_amount !== null && row.total_value_amount !== undefined ? `${fmtNumber(row.total_value_amount, 4)} ${row.total_value_currency || ''}`.trim() : 'n/a'),
h('td', { key: 'source' }, row.source || 'manual'),
h('td', { key: 'assets' }, Object.entries(row.balances_json || {}).slice(0, 6).map(([code, asset]) => {
h('td', { key: 'assets' }, h('div', { className: 'mc-asset-list' }, Object.entries(row.balances_json || {}).map(([code, asset]) => {
const balance = asset && typeof asset === 'object' ? asset.balance : asset;
const priceAmount = asset && typeof asset === 'object' ? asset.price_amount : null;
const priceCurrency = asset && typeof asset === 'object' ? asset.price_currency : null;
return `${fmtNumber(balance, 8)} ${code}${priceAmount ? ` @ ${fmtNumber(priceAmount, 6)} ${priceCurrency || ''}`.trim() : ''}`;
}).join(' · ') || 'n/a'),
return h('div', { key: code, className: 'mc-asset-row' }, [
h('strong', { key: 'code' }, code),
h('span', { key: 'balance' }, `${fmtNumber(balance, 8)} ${code}`),
priceAmount !== null && priceAmount !== undefined
? h('span', { key: 'price', className: 'mc-text' }, `1 ${code} = ${fmtNumber(priceAmount, 6)} ${priceCurrency || ''}`.trim())
: null,
]);
}))),
]))
: [h('tr', { key: 'empty' }, h('td', { colSpan: 6 }, 'Noch keine Wallet-Snapshots gespeichert.'))]
: [h('tr', { key: 'empty' }, h('td', { colSpan: 5 }, 'Noch keine Wallet-Snapshots gespeichert.'))]
),
]),
])),
]),
]);
}