목록 로딩 로직 개선
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
parseTargetStrategySelectValue,
|
||||
targetStrategySelectValue,
|
||||
} from '../../utils/virtualTargetStrategy';
|
||||
import { VirtualScroll } from '../common/VirtualScroll';
|
||||
|
||||
interface Props {
|
||||
targets: VirtualTargetItem[];
|
||||
@@ -131,11 +132,18 @@ const VirtualLeftTargetPanel: React.FC<Props> = ({
|
||||
<span className="vtd-target-count">{targets.length}/{virtualTargetMaxCount}종목</span>
|
||||
</div>
|
||||
|
||||
<div className="vtd-target-list">
|
||||
{targets.length === 0 && (
|
||||
<p className="vtd-muted">검색 후 + 버튼으로 종목을 추가하세요.</p>
|
||||
)}
|
||||
{targets.map(item => {
|
||||
{targets.length === 0 ? (
|
||||
<p className="vtd-muted">검색 후 + 버튼으로 종목을 추가하세요.</p>
|
||||
) : (
|
||||
<VirtualScroll
|
||||
className="vtd-target-list vl-scroll"
|
||||
items={targets}
|
||||
estimateSize={132}
|
||||
measureDynamic
|
||||
getItemKey={item => item.market}
|
||||
aria-label="투자대상 목록"
|
||||
>
|
||||
{item => {
|
||||
const { koreanName: ko, englishName: en } = resolveVirtualTargetNames(
|
||||
item.market,
|
||||
item.koreanName,
|
||||
@@ -144,7 +152,6 @@ const VirtualLeftTargetPanel: React.FC<Props> = ({
|
||||
const active = item.market === selectedMarket;
|
||||
return (
|
||||
<div
|
||||
key={item.market}
|
||||
className={[
|
||||
'vtd-target-item',
|
||||
active ? 'vtd-target-item--active' : '',
|
||||
@@ -213,8 +220,9 @@ const VirtualLeftTargetPanel: React.FC<Props> = ({
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
}}
|
||||
</VirtualScroll>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
getTradeNotificationGridPreset,
|
||||
type TradeNotificationGridPresetId,
|
||||
} from '../../utils/tradeNotificationGridPresets';
|
||||
import { VirtualGridScroll } from '../common/VirtualScroll';
|
||||
|
||||
interface Props {
|
||||
targets: VirtualTargetItem[];
|
||||
@@ -60,6 +61,17 @@ const VirtualTargetGrid: React.FC<Props> = ({
|
||||
gridPreset,
|
||||
}) => {
|
||||
const gridCols = getTradeNotificationGridPreset(gridPreset).cols;
|
||||
|
||||
const gridRowEstimate = useMemo(() => {
|
||||
if (viewMode === 'detail') return 540;
|
||||
if (globalDisplayMode === 'chart') return 460;
|
||||
return 400;
|
||||
}, [viewMode, globalDisplayMode]);
|
||||
|
||||
const gridRemeasureKey = useMemo(
|
||||
() => `${viewMode}:${globalDisplayMode}:${targets.map(t => t.market).join(',')}:${Object.values(snapshots).map(s => s?.updatedAt ?? 0).join('|')}`,
|
||||
[viewMode, globalDisplayMode, targets, snapshots],
|
||||
);
|
||||
const [cardDisplayOverrides, setCardDisplayOverrides] = useState<Record<string, VirtualCardDisplayMode>>({});
|
||||
const [focusMarket, setFocusMarket] = useState<string | null>(null);
|
||||
|
||||
@@ -144,20 +156,29 @@ const VirtualTargetGrid: React.FC<Props> = ({
|
||||
englishName={focusTarget.englishName}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
<VirtualGridScroll
|
||||
className={[
|
||||
'vtd-grid',
|
||||
'vtd-grid--layout-preset',
|
||||
'vtd-grid-scroll',
|
||||
'vl-scroll',
|
||||
`vtd-grid--${viewMode}`,
|
||||
`vtd-grid--cols-${gridCols}`,
|
||||
].join(' ')}
|
||||
style={{ ['--vtd-grid-cols' as string]: gridCols }}
|
||||
rowClassName="vl-grid-row vtd-grid-row"
|
||||
items={targets}
|
||||
columns={gridCols}
|
||||
estimateRowSize={gridRowEstimate}
|
||||
rowGap={14}
|
||||
measureDynamic
|
||||
remeasureKey={gridRemeasureKey}
|
||||
overscan={2}
|
||||
getItemKey={t => t.market}
|
||||
aria-label="가상매매 종목 그리드"
|
||||
>
|
||||
{targets.map(t => {
|
||||
{t => {
|
||||
const strat = strategies.find(s => s.id === resolveVirtualTargetStrategyId(t, session.globalStrategyId));
|
||||
return (
|
||||
<VirtualTargetCard
|
||||
key={t.market}
|
||||
market={t.market}
|
||||
strategy={strat}
|
||||
strategies={strategies}
|
||||
@@ -178,16 +199,16 @@ const VirtualTargetGrid: React.FC<Props> = ({
|
||||
theme={theme}
|
||||
chartRealtimeSource={chartRealtimeSource}
|
||||
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||
chartPaneSeparator={chartPaneSeparator}
|
||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||
chartPaneSeparator={chartPaneSeparator}
|
||||
chartLiveReceiveHighlight={chartLiveReceiveHighlight}
|
||||
ticker={tickers?.get(t.market)}
|
||||
koreanName={t.koreanName}
|
||||
englishName={t.englishName}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
}}
|
||||
</VirtualGridScroll>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user