From 87dff8bfa7f6cbc7e612719811ceb4f7993aae16 Mon Sep 17 00:00:00 2001 From: ayuriel Date: Mon, 16 Feb 2026 12:51:56 +0900 Subject: [PATCH] feat: show stock names as primary display in portfolio card, detail, and rebalance pages --- frontend/src/app/portfolio/[id]/page.tsx | 10 +++---- .../src/app/portfolio/[id]/rebalance/page.tsx | 26 +++++++++++++++---- frontend/src/app/portfolio/page.tsx | 1 + .../components/portfolio/portfolio-card.tsx | 5 +++- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/frontend/src/app/portfolio/[id]/page.tsx b/frontend/src/app/portfolio/[id]/page.tsx index bdd6403..290a142 100644 --- a/frontend/src/app/portfolio/[id]/page.tsx +++ b/frontend/src/app/portfolio/[id]/page.tsx @@ -33,6 +33,7 @@ interface Target { interface Transaction { id: number; ticker: string; + name: string | null; tx_type: string; quantity: number; price: number; @@ -341,10 +342,7 @@ export default function PortfolioDetailPage() { {portfolio.holdings.map((holding, index) => ( -
{holding.name || holding.ticker}
- {holding.name && ( -
{holding.ticker}
- )} + {holding.name || holding.ticker} {holding.quantity.toLocaleString()} @@ -454,7 +452,7 @@ export default function PortfolioDetailPage() { {new Date(tx.executed_at).toLocaleString('ko-KR')} - {tx.ticker} + {tx.name || tx.ticker}
- {holding?.name || target.ticker} + {holding?.name || target.ticker} {actualRatio.toFixed(1)}% / {target.target_ratio.toFixed(1)}% (null); const [calculating, setCalculating] = useState(false); const [error, setError] = useState(null); + const [nameMap, setNameMap] = useState>({}); useEffect(() => { const init = async () => { @@ -81,6 +82,18 @@ export default function RebalancePage() { initialPrices[ticker] = ''; }); setPrices(initialPrices); + + // Fetch stock names from portfolio detail + try { + const detail = await api.get<{ holdings: { ticker: string; name: string | null }[] }>(`/api/portfolios/${portfolioId}/detail`); + const names: Record = {}; + for (const h of detail.holdings) { + if (h.name) names[h.ticker] = h.name; + } + setNameMap(names); + } catch { + // Names are optional, continue without + } } catch { router.push('/login'); } finally { @@ -115,6 +128,12 @@ export default function RebalancePage() { body ); setResult(data); + // Update name map from results + const newNames = { ...nameMap }; + for (const item of data.items) { + if (item.name) newNames[item.ticker] = item.name; + } + setNameMap(newNames); } catch (err) { setError(err instanceof Error ? err.message : 'Calculation failed'); } finally { @@ -180,7 +199,7 @@ export default function RebalancePage() { return (
( -
{item.ticker}
- {item.name && ( -
{item.name}
- )} + {item.name || item.ticker} {item.current_quantity.toLocaleString()} diff --git a/frontend/src/app/portfolio/page.tsx b/frontend/src/app/portfolio/page.tsx index eaa6b8b..c42be21 100644 --- a/frontend/src/app/portfolio/page.tsx +++ b/frontend/src/app/portfolio/page.tsx @@ -11,6 +11,7 @@ import { api } from '@/lib/api'; interface HoldingWithValue { ticker: string; + name: string | null; current_ratio: number | null; } diff --git a/frontend/src/components/portfolio/portfolio-card.tsx b/frontend/src/components/portfolio/portfolio-card.tsx index 5644220..f0397ae 100644 --- a/frontend/src/components/portfolio/portfolio-card.tsx +++ b/frontend/src/components/portfolio/portfolio-card.tsx @@ -6,6 +6,7 @@ import { PieChart, Pie, Cell, ResponsiveContainer } from 'recharts'; interface Holding { ticker: string; + name: string | null; current_ratio: number | null; } @@ -61,7 +62,8 @@ export function PortfolioCard({ .filter((h) => h.current_ratio !== null && h.current_ratio > 0) .slice(0, 6) .map((h, index) => ({ - name: h.ticker, + name: h.name || h.ticker, + ticker: h.ticker, value: h.current_ratio ?? 0, color: CHART_COLORS[index % CHART_COLORS.length], })); @@ -144,6 +146,7 @@ export function PortfolioCard({ {item.name}