127 lines
3.5 KiB
TypeScript
127 lines
3.5 KiB
TypeScript
|
|
import type { DashboardChartTimeframe } from "@/features/trade/types/trade.types";
|
||
|
|
import type { ChartBar } from "./chart-utils";
|
||
|
|
|
||
|
|
export const UP_COLOR = "#ef4444";
|
||
|
|
export const MINUTE_SYNC_INTERVAL_MS = 30000;
|
||
|
|
export const REALTIME_STALE_THRESHOLD_MS = 12000;
|
||
|
|
export const CHART_MIN_HEIGHT = 220;
|
||
|
|
|
||
|
|
export interface ChartPalette {
|
||
|
|
backgroundColor: string;
|
||
|
|
downColor: string;
|
||
|
|
volumeDownColor: string;
|
||
|
|
textColor: string;
|
||
|
|
borderColor: string;
|
||
|
|
gridColor: string;
|
||
|
|
crosshairColor: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export const DEFAULT_CHART_PALETTE: ChartPalette = {
|
||
|
|
backgroundColor: "#ffffff",
|
||
|
|
downColor: "#2563eb",
|
||
|
|
volumeDownColor: "rgba(37, 99, 235, 0.45)",
|
||
|
|
textColor: "#6d28d9",
|
||
|
|
borderColor: "#e9d5ff",
|
||
|
|
gridColor: "#f3e8ff",
|
||
|
|
crosshairColor: "#c084fc",
|
||
|
|
};
|
||
|
|
|
||
|
|
export const MINUTE_TIMEFRAMES: Array<{
|
||
|
|
value: DashboardChartTimeframe;
|
||
|
|
label: string;
|
||
|
|
}> = [
|
||
|
|
{ value: "1m", label: "1분" },
|
||
|
|
{ value: "30m", label: "30분" },
|
||
|
|
{ value: "1h", label: "1시간" },
|
||
|
|
];
|
||
|
|
|
||
|
|
export const PERIOD_TIMEFRAMES: Array<{
|
||
|
|
value: DashboardChartTimeframe;
|
||
|
|
label: string;
|
||
|
|
}> = [
|
||
|
|
{ value: "1d", label: "일" },
|
||
|
|
{ value: "1w", label: "주" },
|
||
|
|
];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @description 브랜드 CSS 변수에서 차트 팔레트를 읽어옵니다.
|
||
|
|
* @see features/trade/components/chart/StockLineChart.tsx 차트 생성/테마 반영
|
||
|
|
*/
|
||
|
|
export function getChartPaletteFromCssVars(
|
||
|
|
themeMode: "light" | "dark",
|
||
|
|
): ChartPalette {
|
||
|
|
const isDark = themeMode === "dark";
|
||
|
|
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 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,
|
||
|
|
),
|
||
|
|
volumeDownColor: readCssVar(
|
||
|
|
"--brand-chart-volume-down",
|
||
|
|
DEFAULT_CHART_PALETTE.volumeDownColor,
|
||
|
|
),
|
||
|
|
textColor: readCssVar(textVar, DEFAULT_CHART_PALETTE.textColor),
|
||
|
|
borderColor: readCssVar(borderVar, DEFAULT_CHART_PALETTE.borderColor),
|
||
|
|
gridColor: readCssVar(gridVar, DEFAULT_CHART_PALETTE.gridColor),
|
||
|
|
crosshairColor: readCssVar(
|
||
|
|
crosshairVar,
|
||
|
|
DEFAULT_CHART_PALETTE.crosshairColor,
|
||
|
|
),
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @description 차트 데이터 배열이 동일한지 비교합니다.
|
||
|
|
* @see features/trade/components/chart/StockLineChart.tsx 분봉 동기화 시 불필요한 상태 업데이트 방지
|
||
|
|
*/
|
||
|
|
export function areBarsEqual(left: ChartBar[], right: ChartBar[]) {
|
||
|
|
if (left.length !== right.length) return false;
|
||
|
|
|
||
|
|
for (let index = 0; index < left.length; index += 1) {
|
||
|
|
const lhs = left[index];
|
||
|
|
const rhs = right[index];
|
||
|
|
if (!lhs || !rhs) return false;
|
||
|
|
if (
|
||
|
|
lhs.time !== rhs.time ||
|
||
|
|
lhs.open !== rhs.open ||
|
||
|
|
lhs.high !== rhs.high ||
|
||
|
|
lhs.low !== rhs.low ||
|
||
|
|
lhs.close !== rhs.close ||
|
||
|
|
lhs.volume !== rhs.volume
|
||
|
|
) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
function readCssVar(name: string, fallback: string) {
|
||
|
|
if (typeof window === "undefined") return fallback;
|
||
|
|
const value = window
|
||
|
|
.getComputedStyle(document.documentElement)
|
||
|
|
.getPropertyValue(name)
|
||
|
|
.trim();
|
||
|
|
return value || fallback;
|
||
|
|
}
|