Skip to content

Commit e273f4a

Browse files
authored
Merge pull request #35 from CleanEngine/develop
[FE] - 실시간 캔들차트 중복데이터 패칭 수정
2 parents 3221134 + caf57e9 commit e273f4a

File tree

7 files changed

+42
-21
lines changed

7 files changed

+42
-21
lines changed

src/app/routes/trade.$ticker.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export default function TradeRouteComponent({
8383
<CoinPriceWithName name={coinInfo?.name} ticker={coinInfo?.ticker} />
8484
)}
8585
<div className="scrollbar-hide relative flex h-[calc(100dvh-116px)] flex-col gap-4 overflow-y-scroll p-4 md:grid md:grid-cols-2 md:grid-rows-5 xl:grid-cols-3 xl:grid-rows-2 2xl:grid-cols-4 2xl:grid-rows-2">
86-
<div className="h-auto md:col-span-full md:row-span-2 md:row-start-1 xl:col-span-full xl:row-span-1 xl:row-start-1 2xl:col-span-2 2xl:col-start-2 2xl:row-start-1">
86+
<div className="h-auto min-h-75 md:col-span-full md:row-span-2 md:row-start-1 xl:col-span-full xl:row-span-1 xl:row-start-1 2xl:col-span-2 2xl:col-start-2 2xl:row-start-1">
8787
<Container>
8888
<ContainerTitle>실시간 차트</ContainerTitle>
8989
<Suspense fallback="차트데이터를 가져오고 있습니다.">

src/features/tradeview/const/chart.const.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ export const INTERVALS = [
77
];
88

99
export const INTERVAL_SELECTOR_HEIGHT = 26;
10+
11+
export const MINUTE = 60;

src/features/tradeview/ui/Orderbook/chart.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as am5 from '@amcharts/amcharts5';
22
import * as am5xy from '@amcharts/amcharts5/xy';
33
import { useEffect, useLayoutEffect, useRef } from 'react';
4+
import { formatCurrencyKR } from '~/shared/utils';
45
import type { OrderBookUnit } from '../../types/orderbook.type';
56

67
const THEME = {
@@ -33,18 +34,14 @@ export default function OrderbookChart({
3334
if (!chartRef.current || !yAxisRef.current || !seriesRef.current) return;
3435

3536
const formattedData = data.map((item) => ({
36-
price: item.price.toString(),
37+
price: formatCurrencyKR(+item.price),
3738
size: item.size,
3839
priceY: item.price,
3940
sizeX: item.size,
4041
}));
4142

4243
yAxisRef.current.data.setAll(formattedData);
4344
seriesRef.current.data.setAll(formattedData);
44-
45-
chartRef.current.series.each((series) => {
46-
series.appear(1000);
47-
});
4845
}, [data]);
4946

5047
useLayoutEffect(() => {
@@ -69,7 +66,6 @@ export default function OrderbookChart({
6966
am5.Rectangle.new(rootRef.current, {
7067
stroke: am5.color('#fff'),
7168
strokeOpacity: 0,
72-
fill: THEME[type].barColor,
7369
fillOpacity: 0.05,
7470
}),
7571
);
@@ -116,7 +112,7 @@ export default function OrderbookChart({
116112
sequencedInterpolation: true,
117113
tooltip: am5.Tooltip.new(rootRef.current, {
118114
pointerOrientation: 'horizontal',
119-
labelText: '[bold]{priceY}원 {sizeX}개',
115+
labelText: "[bold]{priceY.formatNumber('#,###.##')}원 {sizeX}개",
120116
}),
121117
paddingBottom: 0,
122118
paddingTop: 0,

src/features/tradeview/ui/StockChart/Series.tsx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import {
1515
useContext,
1616
useImperativeHandle,
1717
useLayoutEffect,
18-
useMemo,
1918
useRef,
2019
} from 'react';
2120

@@ -114,13 +113,6 @@ export default function Series<T extends SeriesType>({
114113

115114
useImperativeHandle(ref, () => seriesApiRef.current.getInstance(), []);
116115

117-
const context = useMemo(
118-
() => ({
119-
series: seriesApiRef.current,
120-
}),
121-
[],
122-
);
123-
124116
return (
125117
<SeriesContext.Provider value={seriesApiRef.current}>
126118
{children}

src/features/tradeview/ui/StockChart/ToolTip.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { CandlestickData } from 'lightweight-charts';
22
import { useLayoutEffect, useRef } from 'react';
33
import { formatCurrencyKR } from '~/shared/utils';
4+
import { formatDateKr } from '../../utils';
45
import { useChartContainer } from './ChartContainer';
56
import { useChartRoot } from './ChartRoot';
67
import { useSeries } from './Series';
@@ -36,6 +37,8 @@ export default function ToolTip() {
3637
const { close, high, low, open, time } = param.seriesData.get(
3738
chartSeries,
3839
) as CandlestickData;
40+
const date = new Date((time as number) * 1000);
41+
const koreanDate = new Date(date.setHours(date.getHours() - 9));
3942

4043
toolTipElementRef.current.style.display = 'block';
4144
toolTipElementRef.current.innerHTML = `<div style="border: 1px solid #d1d5db; background-color: white; padding: 0.5rem; border-radius: 0.5rem; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); color: #1f2937; z-index: 40;">
@@ -50,7 +53,7 @@ export default function ToolTip() {
5053
<div style="font-weight: 500;">${formatCurrencyKR(close)}원</div>
5154
</div>
5255
<div style="border-top: 1px solid #e5e7eb; padding-top: 0.25rem; margin-top: 0.25rem;">
53-
<div style="color: #6b7280; font-size: 0.75rem; line-height: 1rem;">${new Date((time as number) * 1000).toLocaleString()}</div>
56+
<div style="color: #6b7280; font-size: 0.75rem; line-height: 1rem;">${formatDateKr(koreanDate)}</div>
5457
</div>
5558
</div>`;
5659

src/features/tradeview/ui/StockChart/index.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@ import Series from './Series';
2121
import ToolTip from './ToolTip';
2222

2323
import api from '../../api/tradeview.endpoints';
24-
import { INTERVALS } from '../../const/chart.const';
24+
import { INTERVALS, MINUTE } from '../../const/chart.const';
2525
import usePastTimeData from '../../hooks/usePastTimeData';
2626
import useRealTimeData from '../../hooks/useRealTimeData';
27-
import { extractCandlestickData, timestampToISOString } from '../../utils';
27+
import {
28+
extractCandlestickData,
29+
priceFormatter,
30+
timestampToISOString,
31+
} from '../../utils';
2832
import IntervalSelector from '../IntervalSelector';
2933

3034
type ChartProps = {
@@ -39,13 +43,15 @@ export default function Chart({ ticker = 'BTC', count = 30 }: ChartProps) {
3943
const [isChartReady, setIsChartReady] = useState(false);
4044
const realTimeData = useRealTimeData(ticker);
4145
const pastTimeData = usePastTimeData(ticker, selectedInterval, count);
46+
const prevRequestDate = useRef<Time | null>(null);
4247

4348
const chartOption: DeepPartial<TimeChartOptions> = useMemo(() => {
4449
return {
4550
timeScale: { timeVisible: true },
4651
localization: {
4752
locale: 'kr',
4853
dateFormat: 'yyyy-MM-dd',
54+
priceFormatter: priceFormatter(),
4955
},
5056
rightPriceScale: {
5157
borderVisible: false,
@@ -89,6 +95,12 @@ export default function Chart({ ticker = 'BTC', count = 30 }: ChartProps) {
8995
if (logicalRange.from < -0.5) {
9096
const firstData = seriesRef.current?.dataByIndex(0) as CandlestickData;
9197
if (!firstData || !firstData.time) return;
98+
if (
99+
prevRequestDate.current &&
100+
prevRequestDate.current <= firstData.time
101+
)
102+
return;
103+
prevRequestDate.current = firstData.time;
92104

93105
const firstDate = timestampToISOString(firstData.time as number);
94106

@@ -137,12 +149,12 @@ export default function Chart({ ticker = 'BTC', count = 30 }: ChartProps) {
137149

138150
const timeDiff = +realTimeData.time - +latestTime.time;
139151

140-
if (timeDiff < 60 * selectedInterval) {
152+
if (timeDiff < MINUTE * selectedInterval) {
141153
seriesRef.current?.update({ ...realTimeData, time: latestTime.time });
142154
} else {
143155
seriesRef.current?.update({
144156
...realTimeData,
145-
time: (+latestTime.time + 60 * selectedInterval) as Time,
157+
time: (+latestTime.time + MINUTE * selectedInterval) as Time,
146158
});
147159
}
148160
}, [realTimeData, selectedInterval]);

src/features/tradeview/utils/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,19 @@ export function timestampToISOString(timestamp: number) {
2929
const date = new Date(timestamp * 1000);
3030
return date.toISOString().slice(0, -1);
3131
}
32+
33+
export function priceFormatter() {
34+
const currentLocale = window.navigator.languages[0];
35+
36+
return Intl.NumberFormat(currentLocale, {
37+
style: 'currency',
38+
currency: 'KRW',
39+
}).format;
40+
}
41+
42+
export function formatDateKr(date: Date) {
43+
return Intl.DateTimeFormat('ko-KR', {
44+
dateStyle: 'full',
45+
timeStyle: 'short',
46+
}).format(date);
47+
}

0 commit comments

Comments
 (0)