From dc9421e08aecd0139df34ca1b5f779872e71bb30 Mon Sep 17 00:00:00 2001 From: ZProger Date: Sun, 30 Aug 2026 04:59:35 +0300 Subject: [PATCH] fix: Best/Worst Performer compared personal ROI, not coins against each other MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit best/worst were picked by profit_loss_percent (return since the user's own purchase price), so a coin bought cheap long ago could show as "best" without actually being the strongest mover right now. Switched to price_change_24h — the same market-price move already shown in the table's 24h% column — so the comparison is coins against each other by how they're actually performing today, independent of when/at what price each was bought. 24h was the user's explicit choice over 1h/7d. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01855PiW5Wd8n4aRW4n9kByY --- .../src/components/crypto/CryptoStatsRow.tsx | 18 ++++++++++++------ frontend/src/lib/i18n.ts | 4 ++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/crypto/CryptoStatsRow.tsx b/frontend/src/components/crypto/CryptoStatsRow.tsx index 9d78908..258ce9c 100644 --- a/frontend/src/components/crypto/CryptoStatsRow.tsx +++ b/frontend/src/components/crypto/CryptoStatsRow.tsx @@ -28,9 +28,15 @@ function computeTotals(holdings: CryptoHolding[]): Totals { for (const holding of holdings) { if (holding.value !== null) totalValue += Number(holding.value); if (holding.cost_basis !== null) totalCostBasis += Number(holding.cost_basis); - if (holding.profit_loss_percent === null) continue; - if (best === null || holding.profit_loss_percent > best.profit_loss_percent!) best = holding; - if (worst === null || holding.profit_loss_percent < worst.profit_loss_percent!) worst = holding; + // Best/Worst Performer compare coins against *each other* by market + // price move (24h % change), not against what the user personally paid + // — a coin someone bought yesterday at the top can still be "best + // performer" here if it's simply up the most of anything they hold + // today, independent of their own entry price/timing. + if (holding.price_change_24h === null) continue; + const change = Number(holding.price_change_24h); + if (best === null || change > Number(best.price_change_24h)) best = holding; + if (worst === null || change < Number(worst.price_change_24h)) worst = holding; } const totalProfitLoss = totalValue - totalCostBasis; @@ -52,14 +58,14 @@ function StatTile({ label, children }: { label: string; children: ReactNode }) { function PerformerTile({ label, holding }: { label: string; holding: CryptoHolding | null }) { const { t } = useTranslation(); - if (holding === null || holding.profit_loss_percent === null) { + if (holding === null || holding.price_change_24h === null) { return (

—

); } - const percent = holding.profit_loss_percent; + const percent = Number(holding.price_change_24h); const color = percent >= 0 ? "var(--success)" : "var(--danger)"; return ( @@ -75,7 +81,7 @@ function PerformerTile({ label, holding }: { label: string; holding: CryptoHoldi {percent >= 0 ? "+" : ""} {percent.toFixed(2)}%

-

{t("crypto.stats.since", { name: holding.name })}

+

{t("crypto.stats.change24h")}

); } diff --git a/frontend/src/lib/i18n.ts b/frontend/src/lib/i18n.ts index 68db599..369759e 100644 --- a/frontend/src/lib/i18n.ts +++ b/frontend/src/lib/i18n.ts @@ -158,7 +158,7 @@ const ru = { "crypto.stats.costBasisHint": "сумма покупок по факту", "crypto.stats.bestPerformer": "Лучший рост", "crypto.stats.worstPerformer": "Худшее падение", - "crypto.stats.since": "с момента покупки {{name}}", + "crypto.stats.change24h": "изменение цены за 24ч", "roi.calculator.title": "Калькулятор ROI", "roi.calculator.investmentLabel": "Сумма инвестиции", @@ -619,7 +619,7 @@ const en: Record = { "crypto.stats.costBasisHint": "actual amount spent buying", "crypto.stats.bestPerformer": "Best Performer", "crypto.stats.worstPerformer": "Worst Performer", - "crypto.stats.since": "since buying {{name}}", + "crypto.stats.change24h": "24h price change", "roi.calculator.title": "ROI Calculator", "roi.calculator.investmentLabel": "Investment amount",