Server
This commit is contained in:
@@ -1129,26 +1129,71 @@
|
||||
const selectableFiatCurrencies = preferredSelectableFiatCurrencies.length ? preferredSelectableFiatCurrencies : fiatCurrencies;
|
||||
const selectableCryptoCurrencies = preferredSelectableCryptoCurrencies.length ? preferredSelectableCryptoCurrencies : cryptoCurrencies;
|
||||
const selectedMinerScenario = scenarioMinerOffers.find((offer) => String(offer.id) === String(selectedMinerScenarioId)) || null;
|
||||
const activeMinerRows = currentPurchasedMiners.map((miner) => {
|
||||
const coverage = entryCoverageMeta(miner.purchased_at, miner.runtime_months, miner.auto_renew);
|
||||
const allMinerRows = currentPurchasedMiners.map((miner) => {
|
||||
const effectiveCurrency = String(miner.currency || '').toUpperCase();
|
||||
const paymentType = isCryptoCurrencyCode(effectiveCurrency) ? 'crypto' : 'fiat';
|
||||
const effectiveAutoRenew = paymentType === 'crypto' ? false : !!miner.auto_renew;
|
||||
const coverage = entryCoverageMeta(miner.purchased_at, miner.runtime_months, effectiveAutoRenew);
|
||||
const referenceCurrency = String(miner.reference_price_currency || '').toUpperCase();
|
||||
const referenceAmount = Number(miner.reference_price_amount);
|
||||
const hasFiatReference = referenceCurrency && !isCryptoCurrencyCode(referenceCurrency);
|
||||
const fallbackUsdReference = Number(miner.usd_reference_amount);
|
||||
let baseAmount = null;
|
||||
let baseCurrency = null;
|
||||
if (paymentType === 'crypto') {
|
||||
if (Number.isFinite(referenceAmount) && referenceAmount > 0 && hasFiatReference) {
|
||||
const convertedReference = referenceCurrency === reportCurrency
|
||||
? referenceAmount
|
||||
: convertCurrencyValue(referenceAmount, referenceCurrency, reportCurrency);
|
||||
if (Number.isFinite(convertedReference) && convertedReference > 0) {
|
||||
baseAmount = convertedReference;
|
||||
baseCurrency = reportCurrency;
|
||||
} else {
|
||||
baseAmount = referenceAmount;
|
||||
baseCurrency = referenceCurrency;
|
||||
}
|
||||
} else if (Number.isFinite(fallbackUsdReference) && fallbackUsdReference > 0) {
|
||||
const convertedUsd = reportCurrency === 'USD'
|
||||
? fallbackUsdReference
|
||||
: convertCurrencyValue(fallbackUsdReference, 'USD', reportCurrency);
|
||||
if (Number.isFinite(convertedUsd) && convertedUsd > 0) {
|
||||
baseAmount = convertedUsd;
|
||||
baseCurrency = reportCurrency;
|
||||
} else {
|
||||
baseAmount = fallbackUsdReference;
|
||||
baseCurrency = 'USD';
|
||||
}
|
||||
} else {
|
||||
const convertedEffective = convertCurrencyValue(miner.total_cost_amount, effectiveCurrency, reportCurrency);
|
||||
if (Number.isFinite(convertedEffective) && convertedEffective > 0) {
|
||||
baseAmount = convertedEffective;
|
||||
baseCurrency = reportCurrency;
|
||||
}
|
||||
}
|
||||
} else if (Number.isFinite(referenceAmount) && referenceAmount > 0 && hasFiatReference) {
|
||||
baseAmount = referenceAmount;
|
||||
baseCurrency = referenceCurrency;
|
||||
} else if (Number.isFinite(fallbackUsdReference) && fallbackUsdReference > 0) {
|
||||
baseAmount = fallbackUsdReference;
|
||||
baseCurrency = 'USD';
|
||||
}
|
||||
return {
|
||||
id: `purchase-${miner.id}`,
|
||||
source: 'miete',
|
||||
starts_at: miner.purchased_at,
|
||||
label: miner.label,
|
||||
runtime_months: miner.runtime_months,
|
||||
auto_renew: !!miner.auto_renew,
|
||||
auto_renew: effectiveAutoRenew,
|
||||
effective_amount: miner.total_cost_amount,
|
||||
effective_currency: miner.currency,
|
||||
base_amount: miner.reference_price_amount,
|
||||
base_currency: miner.reference_price_currency,
|
||||
base_amount: baseAmount,
|
||||
base_currency: baseCurrency,
|
||||
miner_id: miner.id,
|
||||
miner_offer_id: miner.miner_offer_id,
|
||||
payment_type: isCryptoCurrencyCode(effectiveCurrency) ? 'crypto' : 'fiat',
|
||||
payment_type: paymentType,
|
||||
is_active: miner.is_active !== false && coverage.isCovered,
|
||||
end_at: coverage.endAt,
|
||||
can_toggle_auto_renew: Number(miner.runtime_months) > 0,
|
||||
can_toggle_auto_renew: paymentType !== 'crypto' && Number(miner.runtime_months) > 0,
|
||||
toggle_resource: 'purchased-miners',
|
||||
toggle_id: miner.id,
|
||||
hashrate_text: formatHashrateWithBonus(miner.mining_speed_value, miner.mining_speed_unit, miner.bonus_speed_value, miner.bonus_speed_unit),
|
||||
@@ -1177,6 +1222,8 @@
|
||||
type_label: 'Manuell eingetragen',
|
||||
};
|
||||
})).sort((left, right) => String(right.starts_at || '').localeCompare(String(left.starts_at || '')));
|
||||
const activeMinerRows = allMinerRows.filter((row) => row.is_active);
|
||||
const inactiveMinerRows = allMinerRows.filter((row) => !row.is_active);
|
||||
|
||||
useEffect(() => {
|
||||
if (reportCurrencyOverride) {
|
||||
@@ -2745,8 +2792,8 @@
|
||||
const totalEarnedOverall = latest && latest.growth_since_baseline !== null && latest.growth_since_baseline !== undefined
|
||||
? Number(latest.growth_since_baseline)
|
||||
: null;
|
||||
const totalEarnedOverallFiat = latest && totalEarnedOverall !== null
|
||||
? convertMeasurementMoney(latest, totalEarnedOverall, reportCurrency)
|
||||
const totalEarnedOverallFiat = totalEarnedOverall !== null
|
||||
? convertCurrencyValue(totalEarnedOverall, currentCoinCurrency, reportCurrency)
|
||||
: null;
|
||||
const totalSpentOverallCurrentAsset = latest
|
||||
? convertMeasurementMoney(
|
||||
@@ -2755,8 +2802,8 @@
|
||||
currentCoinCurrency
|
||||
)
|
||||
: null;
|
||||
const totalSpentOverallFiat = latest && totalSpentOverallCurrentAsset !== null
|
||||
? convertMeasurementMoney(latest, totalSpentOverallCurrentAsset, reportCurrency)
|
||||
const totalSpentOverallFiat = totalSpentOverallCurrentAsset !== null
|
||||
? convertCurrencyValue(totalSpentOverallCurrentAsset, currentCoinCurrency, reportCurrency)
|
||||
: null;
|
||||
const spentByType = activeMinerRows.reduce((summary, row) => {
|
||||
const amount = Number(row?.effective_amount);
|
||||
@@ -3206,6 +3253,51 @@
|
||||
const scenarioInvestedCapital = selectedMinerScenario ? convertMeasurementMoney(latest, selectedMinerScenario.scenario_invested_capital, reportCurrency) : null;
|
||||
const scenarioOfferCost = selectedMinerScenario ? convertMeasurementMoney(latest, selectedMinerScenario.scenario_offer_cost, reportCurrency) : null;
|
||||
const scenarioBreakEvenRemaining = selectedMinerScenario ? convertMeasurementMoney(latest, selectedMinerScenario.scenario_break_even_remaining_amount, reportCurrency) : null;
|
||||
const renderMinerTable = (rows, emptyText) => (
|
||||
h('div', { className: 'mc-table-shell' }, [
|
||||
h('table', { key: 'table', className: 'mc-table' }, [
|
||||
h('thead', { key: 'head' }, h('tr', null, ['Label', 'Start', 'Laufzeit', 'Auto', 'Kosten', 'Waehrung', 'Aktiv', 'Aktion'].map((label) => h('th', { key: label }, label)))),
|
||||
h('tbody', { key: 'body' },
|
||||
rows.length
|
||||
? rows.map((row) => h('tr', { key: row.id }, [
|
||||
h('td', { key: 'label' }, [
|
||||
h('div', { key: 'main' }, row.label),
|
||||
h('div', { key: 'type', className: 'mc-kicker' }, row.type_label),
|
||||
]),
|
||||
h('td', { key: 'start' }, fmtDateTime(row.starts_at)),
|
||||
h('td', { key: 'runtime' }, [
|
||||
h('div', { key: 'months' }, `${row.runtime_months} Monate`),
|
||||
h('div', { key: 'hash', className: 'mc-kicker' }, row.hashrate_text),
|
||||
row.end_at ? h('div', { key: 'end', className: 'mc-kicker' }, `Ende ${fmtDate(row.end_at)}`) : null,
|
||||
]),
|
||||
h('td', { key: 'renew' }, row.payment_type === 'crypto' ? 'nein' : (row.auto_renew ? 'ja' : 'nein')),
|
||||
h('td', { key: 'cost' }, [
|
||||
h('div', { key: 'effective' }, fmtNumber(row.effective_amount, 6)),
|
||||
row.base_amount !== null && row.base_amount !== undefined && row.base_currency
|
||||
? h('div', { key: 'base', className: 'mc-kicker' }, `Basis ${fmtNumber(row.base_amount, 6)} ${row.base_currency}`)
|
||||
: null,
|
||||
]),
|
||||
h('td', { key: 'currency' }, [
|
||||
h('div', { key: 'currency-main' }, row.effective_currency),
|
||||
row.payment_type ? h('div', { key: 'currency-mode', className: 'mc-kicker' }, row.payment_type === 'crypto' ? 'Zahlung Krypto' : 'Zahlung FIAT') : null,
|
||||
]),
|
||||
h('td', { key: 'active' }, row.is_active ? 'ja' : 'nein'),
|
||||
h('td', { key: 'action' },
|
||||
row.can_toggle_auto_renew
|
||||
? h('button', {
|
||||
type: 'button',
|
||||
className: 'mc-button mc-button--ghost',
|
||||
onClick: () => toggleMinerAutoRenew(row),
|
||||
disabled: saving,
|
||||
}, row.auto_renew ? 'Verlaengerung aus' : 'Verlaengerung an')
|
||||
: '—'
|
||||
),
|
||||
]))
|
||||
: [h('tr', { key: 'empty' }, h('td', { colSpan: 8 }, emptyText))]
|
||||
),
|
||||
]),
|
||||
])
|
||||
);
|
||||
return h('div', { className: 'mc-stack' }, [
|
||||
panel('Aktive Miner', 'Alle bereits gemieteten oder manuell eingetragenen Miner in einer gemeinsamen Liste.', [
|
||||
h('div', { key: 'actions', className: 'mc-inline-row' }, [
|
||||
@@ -3240,49 +3332,10 @@
|
||||
disabled: !scenarioMinerOffers.length,
|
||||
}, 'Neuen Miner mieten'),
|
||||
]),
|
||||
h('div', { key: 'list', className: 'mc-table-shell' }, [
|
||||
h('table', { key: 'table', className: 'mc-table' }, [
|
||||
h('thead', { key: 'head' }, h('tr', null, ['Label', 'Start', 'Laufzeit', 'Auto', 'Kosten', 'Waehrung', 'Aktiv', 'Aktion'].map((label) => h('th', { key: label }, label)))),
|
||||
h('tbody', { key: 'body' },
|
||||
activeMinerRows.length
|
||||
? activeMinerRows.map((row) => h('tr', { key: row.id }, [
|
||||
h('td', { key: 'label' }, [
|
||||
h('div', { key: 'main' }, row.label),
|
||||
h('div', { key: 'type', className: 'mc-kicker' }, row.type_label),
|
||||
]),
|
||||
h('td', { key: 'start' }, fmtDateTime(row.starts_at)),
|
||||
h('td', { key: 'runtime' }, [
|
||||
h('div', { key: 'months' }, `${row.runtime_months} Monate`),
|
||||
h('div', { key: 'hash', className: 'mc-kicker' }, row.hashrate_text),
|
||||
row.end_at ? h('div', { key: 'end', className: 'mc-kicker' }, `Ende ${fmtDate(row.end_at)}`) : null,
|
||||
]),
|
||||
h('td', { key: 'renew' }, row.auto_renew ? 'ja' : 'nein'),
|
||||
h('td', { key: 'cost' }, [
|
||||
h('div', { key: 'effective' }, fmtNumber(row.effective_amount, 6)),
|
||||
row.base_amount !== null && row.base_amount !== undefined && row.base_currency
|
||||
? h('div', { key: 'base', className: 'mc-kicker' }, `Basis ${fmtNumber(row.base_amount, 6)} ${row.base_currency}`)
|
||||
: null,
|
||||
]),
|
||||
h('td', { key: 'currency' }, [
|
||||
h('div', { key: 'currency-main' }, row.effective_currency),
|
||||
row.payment_type ? h('div', { key: 'currency-mode', className: 'mc-kicker' }, row.payment_type === 'crypto' ? 'Zahlung Krypto' : 'Zahlung FIAT') : null,
|
||||
]),
|
||||
h('td', { key: 'active' }, row.is_active ? 'ja' : 'nein'),
|
||||
h('td', { key: 'action' },
|
||||
row.can_toggle_auto_renew
|
||||
? h('button', {
|
||||
type: 'button',
|
||||
className: 'mc-button mc-button--ghost',
|
||||
onClick: () => toggleMinerAutoRenew(row),
|
||||
disabled: saving,
|
||||
}, row.auto_renew ? 'Verlaengerung aus' : 'Verlaengerung an')
|
||||
: '—'
|
||||
),
|
||||
]))
|
||||
: [h('tr', { key: 'empty' }, h('td', { colSpan: 8 }, 'Noch keine Miner hinterlegt.'))]
|
||||
),
|
||||
]),
|
||||
]),
|
||||
renderMinerTable(activeMinerRows, 'Noch keine aktiven Miner hinterlegt.'),
|
||||
]),
|
||||
panel('Inaktive Miner', 'Abgelaufene oder deaktivierte Miner werden separat gefuehrt.', [
|
||||
renderMinerTable(inactiveMinerRows, 'Noch keine inaktiven Miner hinterlegt.'),
|
||||
]),
|
||||
panel('Miner-Angebote', selectedOfferType === 'crypto'
|
||||
? (currentWalletMiningBalance !== null
|
||||
|
||||
Reference in New Issue
Block a user