트레이딩창 UI 배치 및 UX 수정 및 기획서 추가
This commit is contained in:
@@ -37,6 +37,7 @@ import {
|
||||
const UP_COLOR = "#ef4444";
|
||||
const MINUTE_SYNC_INTERVAL_MS = 30000;
|
||||
const REALTIME_STALE_THRESHOLD_MS = 12000;
|
||||
const CHART_MIN_HEIGHT = 220;
|
||||
|
||||
interface ChartPalette {
|
||||
backgroundColor: string;
|
||||
@@ -60,7 +61,10 @@ const DEFAULT_CHART_PALETTE: ChartPalette = {
|
||||
|
||||
function readCssVar(name: string, fallback: string) {
|
||||
if (typeof window === "undefined") return fallback;
|
||||
const value = window.getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
||||
const value = window
|
||||
.getComputedStyle(document.documentElement)
|
||||
.getPropertyValue(name)
|
||||
.trim();
|
||||
return value || fallback;
|
||||
}
|
||||
|
||||
@@ -69,16 +73,28 @@ function getChartPaletteFromCssVars(themeMode: "light" | "dark"): ChartPalette {
|
||||
const backgroundVar = isDark
|
||||
? "--brand-chart-background-dark"
|
||||
: "--brand-chart-background-light";
|
||||
const textVar = isDark ? "--brand-chart-text-dark" : "--brand-chart-text-light";
|
||||
const borderVar = isDark ? "--brand-chart-border-dark" : "--brand-chart-border-light";
|
||||
const gridVar = isDark ? "--brand-chart-grid-dark" : "--brand-chart-grid-light";
|
||||
const textVar = isDark
|
||||
? "--brand-chart-text-dark"
|
||||
: "--brand-chart-text-light";
|
||||
const borderVar = isDark
|
||||
? "--brand-chart-border-dark"
|
||||
: "--brand-chart-border-light";
|
||||
const gridVar = isDark
|
||||
? "--brand-chart-grid-dark"
|
||||
: "--brand-chart-grid-light";
|
||||
const crosshairVar = isDark
|
||||
? "--brand-chart-crosshair-dark"
|
||||
: "--brand-chart-crosshair-light";
|
||||
|
||||
return {
|
||||
backgroundColor: readCssVar(backgroundVar, DEFAULT_CHART_PALETTE.backgroundColor),
|
||||
downColor: readCssVar("--brand-chart-down", DEFAULT_CHART_PALETTE.downColor),
|
||||
backgroundColor: readCssVar(
|
||||
backgroundVar,
|
||||
DEFAULT_CHART_PALETTE.backgroundColor,
|
||||
),
|
||||
downColor: readCssVar(
|
||||
"--brand-chart-down",
|
||||
DEFAULT_CHART_PALETTE.downColor,
|
||||
),
|
||||
volumeDownColor: readCssVar(
|
||||
"--brand-chart-volume-down",
|
||||
DEFAULT_CHART_PALETTE.volumeDownColor,
|
||||
@@ -237,7 +253,8 @@ export function StockLineChart({
|
||||
* @see lib/kis/domestic.ts getDomesticChart cursor
|
||||
*/
|
||||
const handleLoadMore = useCallback(async () => {
|
||||
if (!symbol || !credentials || !nextCursor || loadingMoreRef.current) return;
|
||||
if (!symbol || !credentials || !nextCursor || loadingMoreRef.current)
|
||||
return;
|
||||
|
||||
loadingMoreRef.current = true;
|
||||
setIsLoadingMore(true);
|
||||
@@ -284,7 +301,7 @@ export function StockLineChart({
|
||||
|
||||
const chart = createChart(container, {
|
||||
width: Math.max(container.clientWidth, 320),
|
||||
height: Math.max(container.clientHeight, 340),
|
||||
height: Math.max(container.clientHeight, CHART_MIN_HEIGHT),
|
||||
layout: {
|
||||
background: { type: ColorType.Solid, color: palette.backgroundColor },
|
||||
textColor: palette.textColor,
|
||||
@@ -298,7 +315,7 @@ export function StockLineChart({
|
||||
borderColor: palette.borderColor,
|
||||
scaleMargins: {
|
||||
top: 0.08,
|
||||
bottom: 0.24,
|
||||
bottom: 0.2,
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
@@ -372,7 +389,7 @@ export function StockLineChart({
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
chart.resize(
|
||||
Math.max(container.clientWidth, 320),
|
||||
Math.max(container.clientHeight, 340),
|
||||
Math.max(container.clientHeight, CHART_MIN_HEIGHT),
|
||||
);
|
||||
});
|
||||
resizeObserver.observe(container);
|
||||
@@ -380,7 +397,7 @@ export function StockLineChart({
|
||||
const rafId = window.requestAnimationFrame(() => {
|
||||
chart.resize(
|
||||
Math.max(container.clientWidth, 320),
|
||||
Math.max(container.clientHeight, 340),
|
||||
Math.max(container.clientHeight, CHART_MIN_HEIGHT),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -452,7 +469,9 @@ export function StockLineChart({
|
||||
if (disposed) return;
|
||||
|
||||
let mergedBars = normalizeCandles(firstPage.candles, timeframe);
|
||||
let resolvedNextCursor = firstPage.hasMore ? firstPage.nextCursor : null;
|
||||
let resolvedNextCursor = firstPage.hasMore
|
||||
? firstPage.nextCursor
|
||||
: null;
|
||||
|
||||
// 분봉은 기본 3페이지까지 순차 조회해 오전 구간 누락을 줄입니다.
|
||||
if (
|
||||
@@ -474,7 +493,9 @@ export function StockLineChart({
|
||||
|
||||
const olderBars = normalizeCandles(olderPage.candles, timeframe);
|
||||
mergedBars = mergeBars(olderBars, mergedBars);
|
||||
resolvedNextCursor = olderPage.hasMore ? olderPage.nextCursor : null;
|
||||
resolvedNextCursor = olderPage.hasMore
|
||||
? olderPage.nextCursor
|
||||
: null;
|
||||
minuteCursor = olderPage.hasMore ? olderPage.nextCursor : null;
|
||||
extraPageCount += 1;
|
||||
} catch {
|
||||
@@ -522,11 +543,11 @@ export function StockLineChart({
|
||||
}
|
||||
}, [isChartReady, renderableBars, setSeriesData]);
|
||||
|
||||
/**
|
||||
* @description WebSocket 체결 틱을 현재 timeframe 캔들에 반영합니다.
|
||||
* @see features/trade/hooks/useKisTradeWebSocket.ts latestTick
|
||||
* @see features/trade/components/chart/chart-utils.ts toRealtimeTickBar
|
||||
*/
|
||||
/**
|
||||
* @description WebSocket 체결 틱을 현재 timeframe 캔들에 반영합니다.
|
||||
* @see features/trade/hooks/useKisTradeWebSocket.ts latestTick
|
||||
* @see features/trade/components/chart/chart-utils.ts toRealtimeTickBar
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!latestTick) return;
|
||||
if (bars.length === 0) return;
|
||||
@@ -600,7 +621,7 @@ export function StockLineChart({
|
||||
})();
|
||||
|
||||
return (
|
||||
<div className="flex h-full min-h-[340px] flex-col bg-white dark:bg-brand-900/10">
|
||||
<div className="flex h-full min-h-[280px] flex-col bg-white dark:bg-brand-900/10 xl:min-h-0">
|
||||
{/* ========== CHART TOOLBAR ========== */}
|
||||
<div className="flex flex-wrap items-center justify-between gap-2 border-b border-brand-100 bg-muted/20 px-2 py-2 sm:px-3 dark:border-brand-800/45 dark:bg-brand-900/35">
|
||||
<div className="flex flex-wrap items-center gap-1 text-xs sm:text-sm">
|
||||
@@ -668,14 +689,15 @@ export function StockLineChart({
|
||||
</div>
|
||||
|
||||
<div className="text-[11px] text-muted-foreground dark:text-brand-100/85 sm:text-xs">
|
||||
O {formatPrice(latest?.open ?? 0)} H {formatPrice(latest?.high ?? 0)} L{" "}
|
||||
{formatPrice(latest?.low ?? 0)} C{" "}
|
||||
O {formatPrice(latest?.open ?? 0)} H {formatPrice(latest?.high ?? 0)}{" "}
|
||||
L {formatPrice(latest?.low ?? 0)} C{" "}
|
||||
<span
|
||||
className={cn(
|
||||
change >= 0 ? "text-red-600" : "text-blue-600 dark:text-blue-400",
|
||||
)}
|
||||
>
|
||||
{formatPrice(latest?.close ?? 0)} ({formatSignedPercent(changeRate)})
|
||||
{formatPrice(latest?.close ?? 0)} ({formatSignedPercent(changeRate)}
|
||||
)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user