From 19d8aeda3a2f317a8a1003ab86da2841fb57badd Mon Sep 17 00:00:00 2001 From: ZProger Date: Sun, 30 Aug 2026 04:52:33 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20allocation=20view=20as=20a=20real=20tabl?= =?UTF-8?q?e=20(color=20=C2=B7=20ticker,=20%,=20amount)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the flex-based list (coin logo + full name + ticker suffix, prone to truncation and misaligned columns) with an actual : a color swatch + ticker, percent, and amount as three real columns that align natively instead of fighting flexbox for it. Full coin name is still available via a title tooltip. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01855PiW5Wd8n4aRW4n9kByY --- .../crypto/CryptoAllocationBody.tsx | 69 ++++++++----------- 1 file changed, 30 insertions(+), 39 deletions(-) diff --git a/frontend/src/components/crypto/CryptoAllocationBody.tsx b/frontend/src/components/crypto/CryptoAllocationBody.tsx index 67dc3dc..73ff61e 100644 --- a/frontend/src/components/crypto/CryptoAllocationBody.tsx +++ b/frontend/src/components/crypto/CryptoAllocationBody.tsx @@ -1,4 +1,3 @@ -import { Bitcoin } from "lucide-react"; import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip } from "recharts"; import { formatCurrency, maskAmount } from "@/lib/format"; import { useTranslation } from "@/lib/i18n"; @@ -31,7 +30,6 @@ interface Slice { key: string; name: string; symbol: string | null; - thumbUrl: string | null; amount: number; color: string; } @@ -39,7 +37,7 @@ interface Slice { function buildSlices(holdings: CryptoHolding[]): Slice[] { const priced = holdings .filter((h) => h.value !== null && Number(h.value) > 0) - .map((h) => ({ key: String(h.asset_id), name: h.name, symbol: h.symbol, thumbUrl: h.thumb_url, amount: Number(h.value) })) + .map((h) => ({ key: String(h.asset_id), name: h.name, symbol: h.symbol, amount: Number(h.value) })) .sort((a, b) => b.amount - a.amount); const top = priced.slice(0, MAX_SLICES).map((item, index) => ({ ...item, color: SERIES_COLORS[index] })); @@ -47,7 +45,7 @@ function buildSlices(holdings: CryptoHolding[]): Slice[] { if (rest.length === 0) return top; const otherTotal = rest.reduce((sum, item) => sum + item.amount, 0); - return [...top, { key: "other", name: "Other", symbol: null, thumbUrl: null, amount: otherTotal, color: OTHER_COLOR }]; + return [...top, { key: "other", name: "Other", symbol: null, amount: otherTotal, color: OTHER_COLOR }]; } function DonutTooltip({ @@ -73,11 +71,13 @@ function DonutTooltip({ ); } -/** The "Allocation" tab's content inside CryptoOverviewCard — a donut (part- - * to-whole across few categories is exactly the case a donut is fine for) - * plus a list that also carries the $ amount, which the donut/legend alone - * can't — the user explicitly wants both percent and sum per coin, not just - * percent the way CoinMarketCap's own version shows it. */ +/** The "Allocation" tab's content inside CryptoOverviewCard — a donut + * (part-to-whole across few categories is exactly the case a donut is fine + * for) plus a compact table: a color swatch identifying the ticker, its + * share, and the amount. A real
, not a flex row list — table + * columns size to their own content and align natively, so this can't + * stretch across whatever space is left next to the donut the way a + * flex-1 row did. */ export function CryptoAllocationBody({ holdings, isLoading, hidden }: CryptoAllocationBodyProps) { const { t } = useTranslation(); @@ -93,7 +93,7 @@ export function CryptoAllocationBody({ holdings, isLoading, hidden }: CryptoAllo const donutData = slices.map((slice) => ({ ...slice, percent: (slice.amount / total) * 100 })); return ( -
+
@@ -117,35 +117,26 @@ export function CryptoAllocationBody({ holdings, isLoading, hidden }: CryptoAllo
- {/* Capped width, not flex-1 — otherwise with few/short coin names the - row stretches across whatever's left of the card and the percent/ - amount columns end up stranded far from the coin they describe. */} -
    - {donutData.map((slice) => ( -
  • - {slice.thumbUrl ? ( - - ) : ( - - - - )} - - {slice.key === "other" ? t("crypto.allocation.other") : slice.name} - {slice.symbol && · {slice.symbol}} - - - {slice.percent.toFixed(1)}% - - - {maskAmount(formatCurrency(slice.amount), hidden)} - -
  • - ))} -
+
+ + {donutData.map((slice) => ( + + + + + + ))} + +
+ + + + {slice.key === "other" ? t("crypto.allocation.other") : slice.symbol} + + + + {slice.percent.toFixed(1)}% + {maskAmount(formatCurrency(slice.amount), hidden)}
); }