docs: add stock name display implementation plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c836c133dd
commit
b92f8f298b
722
docs/plans/2026-02-16-stock-name-display-plan.md
Normal file
722
docs/plans/2026-02-16-stock-name-display-plan.md
Normal file
@ -0,0 +1,722 @@
|
|||||||
|
# Stock Name Display Implementation Plan
|
||||||
|
|
||||||
|
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||||
|
|
||||||
|
**Goal:** Replace stock code displays with stock name as primary text across all portfolio-related views, with stock codes available via tooltip.
|
||||||
|
|
||||||
|
**Architecture:** Backend schemas and API endpoints that currently lack stock names (`SnapshotHoldingResponse`, `TransactionResponse`, backtest `TransactionItem`) get `name` fields added, with name resolution via the existing `RebalanceService.get_stock_names()`. Frontend swaps display pattern from `ticker` (primary) + `name` (subtitle) to `name` (primary) with `title={ticker}` tooltip.
|
||||||
|
|
||||||
|
**Tech Stack:** FastAPI + SQLAlchemy (backend), Next.js 15 + React 19 + TypeScript (frontend)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 1: Add `name` field to `SnapshotHoldingResponse` schema
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `backend/app/schemas/portfolio.py:114-122`
|
||||||
|
|
||||||
|
**Step 1: Add name field to schema**
|
||||||
|
|
||||||
|
In `backend/app/schemas/portfolio.py`, add `name` field to `SnapshotHoldingResponse`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
class SnapshotHoldingResponse(BaseModel):
|
||||||
|
ticker: str
|
||||||
|
name: str | None = None
|
||||||
|
quantity: int
|
||||||
|
price: FloatDecimal
|
||||||
|
value: FloatDecimal
|
||||||
|
current_ratio: FloatDecimal
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
from_attributes = True
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add backend/app/schemas/portfolio.py
|
||||||
|
git commit -m "feat: add name field to SnapshotHoldingResponse schema"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 2: Add `name` field to `TransactionResponse` schema
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `backend/app/schemas/portfolio.py:72-76`
|
||||||
|
|
||||||
|
**Step 1: Add name field to schema**
|
||||||
|
|
||||||
|
In `backend/app/schemas/portfolio.py`, add `name` field to `TransactionResponse`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
class TransactionResponse(TransactionBase):
|
||||||
|
id: int
|
||||||
|
name: str | None = None
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
from_attributes = True
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add backend/app/schemas/portfolio.py
|
||||||
|
git commit -m "feat: add name field to TransactionResponse schema"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 3: Add `name` field to backtest `TransactionItem` schema
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `backend/app/schemas/backtest.py:119-131`
|
||||||
|
|
||||||
|
**Step 1: Add name field to schema**
|
||||||
|
|
||||||
|
In `backend/app/schemas/backtest.py`, add `name` field to `TransactionItem`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
class TransactionItem(BaseModel):
|
||||||
|
"""Single transaction."""
|
||||||
|
id: int
|
||||||
|
date: date
|
||||||
|
ticker: str
|
||||||
|
name: str | None = None
|
||||||
|
action: str
|
||||||
|
shares: int
|
||||||
|
price: FloatDecimal
|
||||||
|
commission: FloatDecimal
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
from_attributes = True
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add backend/app/schemas/backtest.py
|
||||||
|
git commit -m "feat: add name field to backtest TransactionItem schema"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 4: Populate snapshot holdings with stock names in snapshot API
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `backend/app/api/snapshot.py:53-128` (create_snapshot endpoint)
|
||||||
|
- Modify: `backend/app/api/snapshot.py:131-168` (get_snapshot endpoint)
|
||||||
|
|
||||||
|
**Step 1: Update imports**
|
||||||
|
|
||||||
|
Add `RebalanceService` import at top of `backend/app/api/snapshot.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from app.services.rebalance import RebalanceService
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Update `create_snapshot` endpoint to include names**
|
||||||
|
|
||||||
|
In the `create_snapshot` function, after getting prices and before creating snapshot, resolve names and include them in the response. Replace the return statement (lines 113-128):
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Get stock names
|
||||||
|
name_service = RebalanceService(db)
|
||||||
|
names = name_service.get_stock_names(tickers)
|
||||||
|
|
||||||
|
return SnapshotResponse(
|
||||||
|
id=snapshot.id,
|
||||||
|
portfolio_id=snapshot.portfolio_id,
|
||||||
|
total_value=snapshot.total_value,
|
||||||
|
snapshot_date=snapshot.snapshot_date,
|
||||||
|
holdings=[
|
||||||
|
SnapshotHoldingResponse(
|
||||||
|
ticker=h.ticker,
|
||||||
|
name=names.get(h.ticker),
|
||||||
|
quantity=h.quantity,
|
||||||
|
price=h.price,
|
||||||
|
value=h.value,
|
||||||
|
current_ratio=h.current_ratio,
|
||||||
|
)
|
||||||
|
for h in snapshot.holdings
|
||||||
|
],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Update `get_snapshot` endpoint to include names**
|
||||||
|
|
||||||
|
In the `get_snapshot` function, resolve names before returning. Replace lines 153-168:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Get stock names
|
||||||
|
tickers = [h.ticker for h in snapshot.holdings]
|
||||||
|
name_service = RebalanceService(db)
|
||||||
|
names = name_service.get_stock_names(tickers)
|
||||||
|
|
||||||
|
return SnapshotResponse(
|
||||||
|
id=snapshot.id,
|
||||||
|
portfolio_id=snapshot.portfolio_id,
|
||||||
|
total_value=snapshot.total_value,
|
||||||
|
snapshot_date=snapshot.snapshot_date,
|
||||||
|
holdings=[
|
||||||
|
SnapshotHoldingResponse(
|
||||||
|
ticker=h.ticker,
|
||||||
|
name=names.get(h.ticker),
|
||||||
|
quantity=h.quantity,
|
||||||
|
price=h.price,
|
||||||
|
value=h.value,
|
||||||
|
current_ratio=h.current_ratio,
|
||||||
|
)
|
||||||
|
for h in snapshot.holdings
|
||||||
|
],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 4: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add backend/app/api/snapshot.py
|
||||||
|
git commit -m "feat: include stock names in snapshot API responses"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 5: Populate transactions with stock names in portfolio API
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `backend/app/api/portfolio.py:218-234`
|
||||||
|
|
||||||
|
**Step 1: Update imports**
|
||||||
|
|
||||||
|
At top of `backend/app/api/portfolio.py`, `RebalanceService` is already imported (line 21). No change needed.
|
||||||
|
|
||||||
|
**Step 2: Update `get_transactions` endpoint**
|
||||||
|
|
||||||
|
Replace the `get_transactions` function body to resolve names:
|
||||||
|
|
||||||
|
```python
|
||||||
|
@router.get("/{portfolio_id}/transactions", response_model=List[TransactionResponse])
|
||||||
|
async def get_transactions(
|
||||||
|
portfolio_id: int,
|
||||||
|
current_user: CurrentUser,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
limit: int = 50,
|
||||||
|
):
|
||||||
|
"""Get transaction history for a portfolio."""
|
||||||
|
_get_portfolio(db, portfolio_id, current_user.id)
|
||||||
|
transactions = (
|
||||||
|
db.query(Transaction)
|
||||||
|
.filter(Transaction.portfolio_id == portfolio_id)
|
||||||
|
.order_by(Transaction.executed_at.desc())
|
||||||
|
.limit(limit)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
|
||||||
|
# Resolve stock names
|
||||||
|
tickers = list({tx.ticker for tx in transactions})
|
||||||
|
service = RebalanceService(db)
|
||||||
|
names = service.get_stock_names(tickers)
|
||||||
|
|
||||||
|
return [
|
||||||
|
TransactionResponse(
|
||||||
|
id=tx.id,
|
||||||
|
ticker=tx.ticker,
|
||||||
|
name=names.get(tx.ticker),
|
||||||
|
tx_type=tx.tx_type.value,
|
||||||
|
quantity=tx.quantity,
|
||||||
|
price=tx.price,
|
||||||
|
executed_at=tx.executed_at,
|
||||||
|
memo=tx.memo,
|
||||||
|
)
|
||||||
|
for tx in transactions
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add backend/app/api/portfolio.py
|
||||||
|
git commit -m "feat: include stock names in transaction API responses"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 6: Populate backtest transactions with stock names
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `backend/app/api/backtest.py:209-242`
|
||||||
|
|
||||||
|
**Step 1: Add import**
|
||||||
|
|
||||||
|
Add `RebalanceService` import at top of `backend/app/api/backtest.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from app.services.rebalance import RebalanceService
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Update `get_transactions` endpoint**
|
||||||
|
|
||||||
|
Replace the return logic in the backtest `get_transactions` endpoint:
|
||||||
|
|
||||||
|
```python
|
||||||
|
transactions = (
|
||||||
|
db.query(BacktestTransaction)
|
||||||
|
.filter(BacktestTransaction.backtest_id == backtest_id)
|
||||||
|
.order_by(BacktestTransaction.date, BacktestTransaction.id)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
|
||||||
|
# Resolve stock names
|
||||||
|
tickers = list({t.ticker for t in transactions})
|
||||||
|
name_service = RebalanceService(db)
|
||||||
|
names = name_service.get_stock_names(tickers)
|
||||||
|
|
||||||
|
return [
|
||||||
|
TransactionItem(
|
||||||
|
id=t.id,
|
||||||
|
date=t.date,
|
||||||
|
ticker=t.ticker,
|
||||||
|
name=names.get(t.ticker),
|
||||||
|
action=t.action,
|
||||||
|
shares=t.shares,
|
||||||
|
price=t.price,
|
||||||
|
commission=t.commission,
|
||||||
|
)
|
||||||
|
for t in transactions
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add backend/app/api/backtest.py
|
||||||
|
git commit -m "feat: include stock names in backtest transaction responses"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 7: Update portfolio-card.tsx - show name instead of ticker
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/components/portfolio/portfolio-card.tsx`
|
||||||
|
|
||||||
|
**Step 1: Add `name` to Holding interface**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface Holding {
|
||||||
|
ticker: string;
|
||||||
|
name: string | null;
|
||||||
|
current_ratio: number | null;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Update pieData mapping to use name**
|
||||||
|
|
||||||
|
Change line 64 from `name: h.ticker` to:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
name: h.name || h.ticker,
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Add title attribute to holdings preview badges**
|
||||||
|
|
||||||
|
Change the badge span (line 144-149) to include a `title`:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<span
|
||||||
|
key={index}
|
||||||
|
className="text-xs px-2 py-0.5 rounded bg-muted text-muted-foreground"
|
||||||
|
title={pieData[index]?.name !== holdings[index]?.name ? holdings.find(h => (h.name || h.ticker) === item.name)?.ticker : undefined}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</span>
|
||||||
|
```
|
||||||
|
|
||||||
|
Actually, simpler approach - since `pieData` is derived from `holdings`, we can track the original ticker. Let's use a simpler approach: map pieData to include the original ticker, then use `title={item.ticker}`:
|
||||||
|
|
||||||
|
Change the pieData mapping (lines 60-67):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const pieData = holdings
|
||||||
|
.filter((h) => h.current_ratio !== null && h.current_ratio > 0)
|
||||||
|
.slice(0, 6)
|
||||||
|
.map((h, index) => ({
|
||||||
|
name: h.name || h.ticker,
|
||||||
|
ticker: h.ticker,
|
||||||
|
value: h.current_ratio ?? 0,
|
||||||
|
color: CHART_COLORS[index % CHART_COLORS.length],
|
||||||
|
}));
|
||||||
|
```
|
||||||
|
|
||||||
|
Then update the badge (lines 143-149):
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
{pieData.slice(0, 4).map((item, index) => (
|
||||||
|
<span
|
||||||
|
key={index}
|
||||||
|
className="text-xs px-2 py-0.5 rounded bg-muted text-muted-foreground"
|
||||||
|
title={item.ticker}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 4: Also update HoldingWithValue in portfolio list page**
|
||||||
|
|
||||||
|
In `frontend/src/app/portfolio/page.tsx`, add `name` to the `HoldingWithValue` interface (line 12-15):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface HoldingWithValue {
|
||||||
|
ticker: string;
|
||||||
|
name: string | null;
|
||||||
|
current_ratio: number | null;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/components/portfolio/portfolio-card.tsx frontend/src/app/portfolio/page.tsx
|
||||||
|
git commit -m "feat: show stock names in portfolio cards"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 8: Update portfolio detail page - fix holdings ticker subtitle removal + transactions name
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/app/portfolio/[id]/page.tsx`
|
||||||
|
|
||||||
|
**Step 1: Add `name` to Transaction interface**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface Transaction {
|
||||||
|
id: number;
|
||||||
|
ticker: string;
|
||||||
|
name: string | null;
|
||||||
|
tx_type: string;
|
||||||
|
quantity: number;
|
||||||
|
price: number;
|
||||||
|
executed_at: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Update holdings table - remove ticker subtitle, add title tooltip**
|
||||||
|
|
||||||
|
Change lines 343-348 from:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-4 py-3">
|
||||||
|
<div className="font-medium text-sm">{holding.name || holding.ticker}</div>
|
||||||
|
{holding.name && (
|
||||||
|
<div className="text-xs text-muted-foreground">{holding.ticker}</div>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
To:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-4 py-3">
|
||||||
|
<span className="font-medium text-sm" title={holding.ticker}>{holding.name || holding.ticker}</span>
|
||||||
|
</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Update transactions table - show name instead of ticker**
|
||||||
|
|
||||||
|
Change line 457 from:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-4 py-3 text-sm font-medium">{tx.ticker}</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
To:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-4 py-3 text-sm font-medium" title={tx.ticker}>{tx.name || tx.ticker}</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 4: Update Target vs Actual section - add title tooltip**
|
||||||
|
|
||||||
|
Change line 522 from:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<span className="font-medium">{holding?.name || target.ticker}</span>
|
||||||
|
```
|
||||||
|
|
||||||
|
To:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<span className="font-medium" title={target.ticker}>{holding?.name || target.ticker}</span>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/app/portfolio/[id]/page.tsx
|
||||||
|
git commit -m "feat: show stock names as primary display in portfolio detail"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 9: Update rebalance page - name as primary display
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/app/portfolio/[id]/rebalance/page.tsx`
|
||||||
|
|
||||||
|
**Step 1: Fetch stock names for price input labels**
|
||||||
|
|
||||||
|
The rebalance page needs names for the price input section. The targets and holdings don't have names, but the rebalance result does. We need to store a name map. Add state and fetch names when targets/holdings load.
|
||||||
|
|
||||||
|
Add `nameMap` state after existing state declarations (after line 61):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const [nameMap, setNameMap] = useState<Record<string, string>>({});
|
||||||
|
```
|
||||||
|
|
||||||
|
In the `init` function, after setting targets and holdings, fetch portfolio detail to get names:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 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<string, string> = {};
|
||||||
|
for (const h of detail.holdings) {
|
||||||
|
if (h.name) names[h.ticker] = h.name;
|
||||||
|
}
|
||||||
|
setNameMap(names);
|
||||||
|
} catch {
|
||||||
|
// Names are optional, continue without
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Update price input labels to use name**
|
||||||
|
|
||||||
|
Change line 183 from:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
{ticker} {target ? `(목표 ${target.target_ratio}%)` : ''} - 보유 {getHoldingQty(ticker)}주
|
||||||
|
```
|
||||||
|
|
||||||
|
To:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
{nameMap[ticker] || ticker} {target ? `(목표 ${target.target_ratio}%)` : ''} - 보유 {getHoldingQty(ticker)}주
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Update results table - name as primary**
|
||||||
|
|
||||||
|
Change lines 299-304 from:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-3 py-3">
|
||||||
|
<div className="font-medium">{item.ticker}</div>
|
||||||
|
{item.name && (
|
||||||
|
<div className="text-xs text-muted-foreground">{item.name}</div>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
To:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-3 py-3">
|
||||||
|
<span className="font-medium" title={item.ticker}>{item.name || item.ticker}</span>
|
||||||
|
</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 4: Also update nameMap from rebalance results**
|
||||||
|
|
||||||
|
After the calculate function sets the result, update nameMap with any names from the result:
|
||||||
|
|
||||||
|
In the `calculate` function, after `setResult(data)` (line 117), add:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Update name map from results
|
||||||
|
const newNames = { ...nameMap };
|
||||||
|
for (const item of data.items) {
|
||||||
|
if (item.name) newNames[item.ticker] = item.name;
|
||||||
|
}
|
||||||
|
setNameMap(newNames);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/app/portfolio/[id]/rebalance/page.tsx
|
||||||
|
git commit -m "feat: show stock names as primary display in rebalance page"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 10: Update portfolio history page - show names in snapshot
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/app/portfolio/[id]/history/page.tsx`
|
||||||
|
|
||||||
|
**Step 1: Add `name` to SnapshotDetail holdings interface**
|
||||||
|
|
||||||
|
Change the `holdings` type in `SnapshotDetail` interface (lines 23-29):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
holdings: {
|
||||||
|
ticker: string;
|
||||||
|
name: string | null;
|
||||||
|
quantity: number;
|
||||||
|
price: string;
|
||||||
|
value: string;
|
||||||
|
current_ratio: string;
|
||||||
|
}[];
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Update snapshot detail modal table**
|
||||||
|
|
||||||
|
Change line 428 from:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-4 py-2 text-sm text-foreground">
|
||||||
|
{holding.ticker}
|
||||||
|
</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
To:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-4 py-2 text-sm text-foreground" title={holding.ticker}>
|
||||||
|
{holding.name || holding.ticker}
|
||||||
|
</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/app/portfolio/[id]/history/page.tsx
|
||||||
|
git commit -m "feat: show stock names in portfolio history snapshots"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 11: Update strategy pages - name as primary (3 files)
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/app/strategy/multi-factor/page.tsx:209-211`
|
||||||
|
- Modify: `frontend/src/app/strategy/quality/page.tsx:174-176`
|
||||||
|
- Modify: `frontend/src/app/strategy/value-momentum/page.tsx:190-192`
|
||||||
|
|
||||||
|
**Step 1: Update multi-factor page**
|
||||||
|
|
||||||
|
Change lines 209-211 from:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-4 py-3">
|
||||||
|
<div className="font-medium">{stock.ticker}</div>
|
||||||
|
<div className="text-xs text-muted-foreground">{stock.name}</div>
|
||||||
|
</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
To:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-4 py-3">
|
||||||
|
<span className="font-medium" title={stock.ticker}>{stock.name || stock.ticker}</span>
|
||||||
|
</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Update quality page**
|
||||||
|
|
||||||
|
Same change at lines 174-176.
|
||||||
|
|
||||||
|
**Step 3: Update value-momentum page**
|
||||||
|
|
||||||
|
Same change at lines 190-192.
|
||||||
|
|
||||||
|
**Step 4: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/app/strategy/multi-factor/page.tsx frontend/src/app/strategy/quality/page.tsx frontend/src/app/strategy/value-momentum/page.tsx
|
||||||
|
git commit -m "feat: show stock names as primary display in strategy pages"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 12: Update backtest detail page - name as primary
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/app/backtest/[id]/page.tsx`
|
||||||
|
|
||||||
|
**Step 1: Add `name` to TransactionItem interface**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface TransactionItem {
|
||||||
|
id: number;
|
||||||
|
date: string;
|
||||||
|
ticker: string;
|
||||||
|
name: string | null;
|
||||||
|
action: string;
|
||||||
|
shares: number;
|
||||||
|
price: number;
|
||||||
|
commission: number;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 2: Update holdings tab display**
|
||||||
|
|
||||||
|
Change lines 392-394 from:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-4 py-3">
|
||||||
|
<div className="font-medium">{h.ticker}</div>
|
||||||
|
<div className="text-xs text-muted-foreground">{h.name}</div>
|
||||||
|
</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
To:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-4 py-3">
|
||||||
|
<span className="font-medium" title={h.ticker}>{h.name || h.ticker}</span>
|
||||||
|
</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Update transactions tab display**
|
||||||
|
|
||||||
|
Change line 425 from:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-4 py-3 text-sm font-medium">{t.ticker}</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
To:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<td className="px-4 py-3 text-sm font-medium" title={t.ticker}>{t.name || t.ticker}</td>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 4: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/app/backtest/[id]/page.tsx
|
||||||
|
git commit -m "feat: show stock names as primary display in backtest detail"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 13: Verify frontend build
|
||||||
|
|
||||||
|
**Step 1: Run frontend build to check for TypeScript errors**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd frontend && npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: Build succeeds with no type errors.
|
||||||
|
|
||||||
|
**Step 2: If build fails, fix any TypeScript errors and re-run**
|
||||||
|
|
||||||
|
**Step 3: Commit any fixes**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add -A && git commit -m "fix: resolve build errors from stock name display changes"
|
||||||
|
```
|
||||||
Loading…
x
Reference in New Issue
Block a user