Skip to content

Commit 983a82d

Browse files
committed
refactor: relocate TradingView components to shared src/components directory
1 parent fddb78f commit 983a82d

File tree

5 files changed

+37
-46
lines changed

5 files changed

+37
-46
lines changed

frontend/src/app/home/home.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { useState } from "react";
22
import { useNavigate } from "react-router";
33
import { useAllPollTaskList } from "@/api/conversation";
4+
import TradingViewTickerTape from "@/components/tradingview/tradingview-ticker-tape";
45
import { agentSuggestions } from "@/mock/agent-data";
56
import ChatInputArea from "../agent/components/chat-conversation/chat-input-area";
67
import { AgentSuggestionsList, AgentTaskCards } from "./components";
7-
import TradingViewTickerTape from "./components/tradingview-ticker-tape";
88

99
const INDEX_SYMBOLS = [
1010
"FOREXCOM:SPXUSD",

frontend/src/app/home/stock.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,15 @@ import {
66
useGetStockPrice,
77
useRemoveStockFromWatchlist,
88
} from "@/api/stock";
9+
import TradingViewAdvancedChart from "@/components/tradingview/tradingview-advanced-chart";
910
import { Button } from "@/components/ui/button";
10-
import { useStockColors } from "@/store/settings-store";
1111
import type { Route } from "./+types/stock";
12-
import TradingViewAdvancedChart from "./components/tradingview-advanced-chart";
1312

1413
function Stock() {
1514
const { stockId } = useParams<Route.LoaderArgs["params"]>();
1615
const navigate = useNavigate();
1716
// Use stockId as ticker to fetch real data from API
1817
const ticker = stockId || "";
19-
const stockColors = useStockColors();
2018

2119
// Fetch current stock price data
2220
const {
@@ -116,10 +114,6 @@ function Stock() {
116114
interval="D"
117115
minHeight={420}
118116
theme="light"
119-
colors={{
120-
upColor: stockColors.positive,
121-
downColor: stockColors.negative,
122-
}}
123117
locale="en"
124118
timezone="UTC"
125119
/>

frontend/src/app/home/components/tradingview-advanced-chart.tsx renamed to frontend/src/components/tradingview/tradingview-advanced-chart.tsx

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,43 @@
11
import { memo, useEffect, useMemo, useRef } from "react";
22
import defaultMap from "./tv-symbol-map.json";
33

4-
type Props = {
4+
interface TradingViewAdvancedChartProps {
55
ticker: string;
66
mappingUrl?: string;
77
interval?: string;
88
minHeight?: number;
99
theme?: "light" | "dark";
10-
colors?: { upColor: string; downColor: string };
1110
locale?: string;
1211
timezone?: string;
13-
};
12+
}
13+
14+
interface TradingViewWindow extends Window {
15+
TradingView?: {
16+
widget: new (
17+
config: Record<string, unknown>,
18+
) => {
19+
remove?: () => void;
20+
};
21+
};
22+
__tvScriptPromise?: Promise<void>;
23+
}
24+
25+
interface TradingViewContainer extends HTMLDivElement {
26+
__tv_widget__?: {
27+
remove?: () => void;
28+
} | null;
29+
}
1430

1531
function TradingViewAdvancedChart({
1632
ticker,
1733
mappingUrl,
1834
interval = "D",
1935
minHeight = 420,
2036
theme = "light",
21-
colors,
2237
locale = "en",
2338
timezone = "UTC",
24-
}: Props) {
25-
const symbolMapRef = useRef<Record<string, string> | null>(
39+
}: TradingViewAdvancedChartProps) {
40+
const symbolMapRef = useRef<Record<string, string>>(
2641
defaultMap as Record<string, string>,
2742
);
2843

@@ -57,17 +72,17 @@ function TradingViewAdvancedChart({
5772
if (typeof v === "string" && v.length > 0) return v;
5873
}
5974
return t;
60-
}, [ticker, mappingUrl]);
75+
}, [ticker]);
6176

6277
const containerId = useMemo(
6378
() => `tv_${tvSymbol.replace(/[^A-Za-z0-9_]/g, "_")}_${interval}`,
6479
[tvSymbol, interval],
6580
);
6681

67-
const containerRef = useRef<HTMLDivElement | null>(null);
82+
const containerRef = useRef<TradingViewContainer | null>(null);
6883

6984
const loadTradingView = () => {
70-
const w = window as any;
85+
const w = window as TradingViewWindow;
7186
if (w.TradingView) return Promise.resolve();
7287
if (w.__tvScriptPromise) return w.__tvScriptPromise;
7388
w.__tvScriptPromise = new Promise<void>((resolve, reject) => {
@@ -85,15 +100,15 @@ function TradingViewAdvancedChart({
85100
let cancelled = false;
86101

87102
const cleanup = () => {
88-
const current = containerRef.current as any;
103+
const current = containerRef.current;
89104
const widget = current?.__tv_widget__;
90105
if (widget && typeof widget.remove === "function") {
91106
try {
92107
widget.remove();
93108
} catch {}
94109
}
95110
if (containerRef.current) {
96-
(containerRef.current as any).__tv_widget__ = null;
111+
containerRef.current.__tv_widget__ = null;
97112
containerRef.current.innerHTML = "";
98113
}
99114
};
@@ -102,26 +117,9 @@ function TradingViewAdvancedChart({
102117
if (!tvSymbol) return;
103118

104119
loadTradingView().then(() => {
105-
const w = window as any;
120+
const w = window as TradingViewWindow;
106121
if (cancelled || !containerRef.current || !w.TradingView) return;
107122

108-
const overrides = colors
109-
? {
110-
"mainSeriesProperties.candleStyle.upColor": colors.upColor,
111-
"mainSeriesProperties.candleStyle.downColor": colors.downColor,
112-
"mainSeriesProperties.candleStyle.borderUpColor": colors.upColor,
113-
"mainSeriesProperties.candleStyle.borderDownColor":
114-
colors.downColor,
115-
"mainSeriesProperties.candleStyle.wickUpColor": colors.upColor,
116-
"mainSeriesProperties.candleStyle.wickDownColor": colors.downColor,
117-
"mainSeriesProperties.candleStyle.drawWick": true,
118-
"mainSeriesProperties.candleStyle.drawBorder": true,
119-
}
120-
: {
121-
"mainSeriesProperties.candleStyle.drawWick": true,
122-
"mainSeriesProperties.candleStyle.drawBorder": true,
123-
};
124-
125123
const widget = new w.TradingView.widget({
126124
container_id: containerId,
127125
symbol: tvSymbol,
@@ -135,18 +133,17 @@ function TradingViewAdvancedChart({
135133
hide_bottom_toolbar: false,
136134
allow_symbol_change: false,
137135
details: true,
138-
overrides,
139136
});
140137

141-
const current = containerRef.current as any;
138+
const current = containerRef.current;
142139
if (current) current.__tv_widget__ = widget;
143140
});
144141

145142
return () => {
146143
cancelled = true;
147144
cleanup();
148145
};
149-
}, [tvSymbol, interval, theme, colors, locale, timezone]);
146+
}, [tvSymbol, interval, theme, locale, timezone, containerId]);
150147

151148
return (
152149
<div className="w-full" style={{ height: minHeight }}>

frontend/src/app/home/components/tradingview-ticker-tape.tsx renamed to frontend/src/components/tradingview/tradingview-ticker-tape.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
import { useEffect, useMemo, useRef } from "react";
1+
import { memo, useEffect, useMemo, useRef } from "react";
22

3-
type Props = {
4-
symbols: readonly string[];
3+
interface TradingViewTickerTapeProps {
4+
symbols: string[];
55
theme?: "light" | "dark";
66
locale?: string;
7-
};
7+
}
88

99
function TradingViewTickerTape({
1010
symbols,
1111
theme = "light",
1212
locale = "en",
13-
}: Props) {
13+
}: TradingViewTickerTapeProps) {
1414
const containerRef = useRef<HTMLDivElement | null>(null);
1515
const scriptRef = useRef<HTMLScriptElement | null>(null);
1616

@@ -68,4 +68,4 @@ function TradingViewTickerTape({
6868
);
6969
}
7070

71-
export default TradingViewTickerTape;
71+
export default memo(TradingViewTickerTape);
File renamed without changes.

0 commit comments

Comments
 (0)