라벨 중복문제 수정

This commit is contained in:
Macbook
2026-05-26 22:45:54 +09:00
parent a4830e9bd8
commit 94e96b9a9b
9 changed files with 388 additions and 43 deletions
@@ -247,6 +247,7 @@ const TradeOrderPanel: React.FC<TradeOrderPanelProps> = ({
return (
<div className={`top-panel top-panel--${side}`}>
<div className="top-panel-fields">
{paperTradingEnabled && !paperAutoTradeEnabled && showSymbolField && (
<p className="top-paper-hint"> OFF · .</p>
)}
@@ -399,6 +400,7 @@ const TradeOrderPanel: React.FC<TradeOrderPanelProps> = ({
<span> {feeRate}%</span>
</span>
</div>
</div>
<div className="top-actions">
<button type="button" className="top-reset" onClick={handleReset}>
+9 -1
View File
@@ -345,6 +345,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
}, [market, barsMarket]);
const queueIndicatorRecovery = useCallback(() => {
if (reloadInFlightRef.current) return;
if (recoveryTimerRef.current) clearTimeout(recoveryTimerRef.current);
recoveryTimerRef.current = window.setTimeout(() => {
recoveryTimerRef.current = null;
@@ -889,7 +890,13 @@ const TradingChart: React.FC<TradingChartProps> = ({
if (!barsChanged && !indChanged && !ctChanged && !thChanged && !lsChanged && !indicatorsIncomplete) return;
if (barsChanged || ctChanged || thChanged || indicatorsIncomplete) {
if (thChanged && !barsChanged && !indChanged && !ctChanged && !lsChanged && !indicatorsIncomplete) {
prevTheme.current = theme;
mgr.setTheme(theme);
return;
}
if (barsChanged || ctChanged || indicatorsIncomplete) {
// 데이터·차트 형식 변경 또는 지표 누락 → 전체 재로드
void reloadAll(mgr, bars, chartType, theme, logScale, indicators);
} else if (lsChanged) {
@@ -1011,6 +1018,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
const timers = [120, 400, 900].map(delay =>
window.setTimeout(() => {
if (reloadInFlightRef.current) return;
const m = managerRef.current;
if (!m || !m.hasMainSeries()) return;
if (!canApplyChartBars(bars, barsMarket, market)) return;
@@ -122,21 +122,36 @@ const TrendSearchCardChart: React.FC<Props> = ({
}, [market, chartTf]);
useEffect(() => {
const wrap = canvasWrapRef.current;
if (!wrap) return;
const applyPaneHeights = () => {
const h = wrap.clientHeight;
if (h <= 0) return;
const mgr = managerRef.current;
if (mgr?.hasMainSeries()) mgr.resetPaneHeights(h);
};
const timers = [100, 300, 800, 1500].map(delay =>
setTimeout(() => {
const wrap = canvasWrapRef.current;
const mgr = managerRef.current;
if (!wrap) return;
const h = wrap.clientHeight;
if (!canvasWrapRef.current) return;
const h = canvasWrapRef.current.clientHeight;
if (h <= 0) return;
if (mgr?.hasMainSeries()) mgr.resetPaneHeights(h);
if (managerRef.current?.hasMainSeries()) managerRef.current.resetPaneHeights(h);
else if (!chartReloadTriggeredRef.current && delay >= 800 && bars.length > 0) {
chartReloadTriggeredRef.current = true;
setChartReloadTick(t => t + 1);
}
}, delay),
);
return () => timers.forEach(clearTimeout);
const ro = new ResizeObserver(() => applyPaneHeights());
ro.observe(wrap);
return () => {
timers.forEach(clearTimeout);
ro.disconnect();
};
}, [market, chartTf, bars.length]);
useEffect(() => {
@@ -145,8 +160,11 @@ const TrendSearchCardChart: React.FC<Props> = ({
}, [market, chartTf, useUpbit]);
return (
<div className="vtd-card-chart-wrap">
<div ref={canvasWrapRef} className="vtd-card-chart slot-chart-wrap">
<div className="vtd-card-chart-panel vtd-card-chart-panel--fill">
<div
ref={canvasWrapRef}
className="vtd-card-chart-canvas slot-chart-wrap vtd-card-chart-canvas--fill"
>
{isLoading && <div className="vtd-card-chart-loading"> </div>}
{isLoadingMore && (
<div className="chart-history-loading">
@@ -71,8 +71,8 @@ const TrendSearchResultCard: React.FC<Props> = ({
className={[
'vtd-card',
'vtd-card--signal',
'vtd-card--detail',
isChart ? 'vtd-card--chart-mode' : '',
!isChart ? 'vtd-card--detail' : '',
isChart ? 'vtd-card--chart-mode tsd-result-card--chart' : '',
selected ? 'vtd-card--selected' : '',
flashCls,
].filter(Boolean).join(' ')}
@@ -4,7 +4,7 @@ import type { StrategyDto } from '../../utils/backendApi';
import type { VirtualIndicatorSnapshot } from '../../hooks/useVirtualIndicatorSnapshots';
import { useLiveReceiveFlash } from '../../hooks/useLiveReceiveFlash';
import type { ChartRealtimeSource } from '../../hooks/useChartRealtimeData';
import { buildConditionMetrics, resolveVirtualTradeTiming } from '../../utils/virtualSignalMetrics';
import { buildConditionMetrics } from '../../utils/virtualSignalMetrics';
import { candleTypeToTimeframe } from '../../utils/strategyToChartIndicators';
import { normalizeStartCandleType } from '../../utils/strategyStartNodes';
import type { Timeframe } from '../../types';
@@ -76,7 +76,6 @@ const VirtualTargetCard: React.FC<Props> = ({
const rows = snapshot?.rows ?? [];
const metrics = useMemo(() => buildConditionMetrics(rows), [rows]);
const tradeTiming = useMemo(() => resolveVirtualTradeTiming(metrics), [metrics]);
const metCount = metrics.filter(m => m.status === 'match').length;
const evalCount = metrics.filter(m => m.status !== 'unknown').length;
@@ -102,8 +101,6 @@ const VirtualTargetCard: React.FC<Props> = ({
isDetail ? 'vtd-card--detail' : 'vtd-card--summary',
isChart ? 'vtd-card--chart-mode' : '',
selected ? 'vtd-card--selected' : '',
tradeTiming === 'buy' ? 'vtd-card--timing-buy' : '',
tradeTiming === 'sell' ? 'vtd-card--timing-sell' : '',
].filter(Boolean).join(' ')}
onClick={onSelect}
onKeyDown={e => {