투자관리 화면 수정

This commit is contained in:
Macbook
2026-05-31 17:34:26 +09:00
parent d6c2f3e451
commit 4f2d98d4ba
20 changed files with 696 additions and 56 deletions
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useMemo, useState } from 'react';
import {
loadStrategies,
loadLiveStrategySettings,
@@ -6,13 +6,18 @@ import {
type PaperSummaryDto,
type StrategyDto,
} from '../../utils/backendApi';
import { loadVirtualSession } from '../../utils/virtualTradingStorage';
import { loadVirtualSession, type VirtualTargetItem } from '../../utils/virtualTradingStorage';
import { resolveVirtualTargetNames } from '../../utils/virtualTargetNames';
import type { TickerData } from '../../hooks/useMarketTicker';
import { fmtKrw } from '../TradeOrderPanel';
import PaperSplitPanel from './PaperSplitPanel';
interface Props {
market: string;
summary: PaperSummaryDto | null;
/** 가상매매 투자대상 — 보유 목록은 이 종목만 표시 */
virtualTargets?: VirtualTargetItem[];
tickers?: Map<string, TickerData>;
paperAutoTradeEnabled?: boolean;
onMarketSelect?: (market: string) => void;
}
@@ -20,6 +25,8 @@ interface Props {
const PaperLeftStrategyTab: React.FC<Props> = ({
market,
summary,
virtualTargets = [],
tickers,
paperAutoTradeEnabled = false,
onMarketSelect,
}) => {
@@ -91,7 +98,23 @@ const PaperLeftStrategyTab: React.FC<Props> = ({
</>
);
const positions = summary?.positions ?? [];
const targetMarkets = useMemo(
() => new Set(virtualTargets.map(t => t.market)),
[virtualTargets],
);
const positions = useMemo(() => {
const all = (summary?.positions ?? []).filter(p => p.quantity > 0);
if (targetMarkets.size === 0) return [];
const order = virtualTargets.map(t => t.market);
return all
.filter(p => targetMarkets.has(p.symbol))
.sort((a, b) => {
const ia = order.indexOf(a.symbol);
const ib = order.indexOf(b.symbol);
return (ia < 0 ? 999 : ia) - (ib < 0 ? 999 : ib);
});
}, [summary?.positions, targetMarkets, virtualTargets]);
const bottom = (
<div className="ptd-item-card-section ptd-holdings-card-section">
@@ -99,14 +122,21 @@ const PaperLeftStrategyTab: React.FC<Props> = ({
<span> </span>
<span className="vtd-target-count">{positions.length}</span>
</div>
{positions.length === 0 ? (
<p className="ptd-muted ptd-item-card-empty"> .</p>
{targetMarkets.size === 0 ? (
<p className="ptd-muted ptd-item-card-empty"> . .</p>
) : positions.length === 0 ? (
<p className="ptd-muted ptd-item-card-empty"> .</p>
) : (
<div className="ptd-item-card-scroll">
<div className="vtd-target-list ptd-item-card-list">
{positions.map(p => {
const code = p.symbol.replace(/^KRW-/, '');
const name = p.koreanName || code;
const ticker = tickers?.get(p.symbol);
const vt = virtualTargets.find(t => t.market === p.symbol);
const { koreanName: ko, englishName: en } = resolveVirtualTargetNames(
p.symbol,
p.koreanName ?? vt?.koreanName ?? ticker?.koreanName,
vt?.englishName,
);
const up = (p.profitLoss ?? 0) >= 0;
const selected = market === p.symbol;
const retPct = p.profitLossPct;
@@ -132,8 +162,8 @@ const PaperLeftStrategyTab: React.FC<Props> = ({
>
<div className="vtd-target-item-main">
<div className="vtd-target-names">
<span className="vtd-target-ko">{name}</span>
<span className="vtd-target-en">{code}/KRW</span>
<span className="vtd-target-ko">{ko}</span>
<span className="vtd-target-en">{en}</span>
</div>
{p.profitLoss != null && (
<div className="vtd-target-item-actions">