feat(settings): add settings route and API updates\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import * as LightweightCharts from "lightweight-charts";
|
||||
|
||||
type ChartTime = string | number;
|
||||
@@ -15,6 +15,9 @@ interface TradingViewChartProps {
|
||||
ticker: string;
|
||||
data?: ChartDataPoint[];
|
||||
timeframe?: string;
|
||||
currentPrice?: number;
|
||||
// priceStream.subscribe(cb) should return an unsubscribe function
|
||||
priceStream?: { subscribe: (cb: (price: number) => void) => () => void };
|
||||
}
|
||||
|
||||
const TIMEFRAME_HEIGHTS: Record<string, number> = {
|
||||
@@ -25,8 +28,9 @@ const TIMEFRAME_HEIGHTS: Record<string, number> = {
|
||||
"1W": 400,
|
||||
};
|
||||
|
||||
export default function TradingViewChart({ ticker, data, timeframe = "1D" }: TradingViewChartProps) {
|
||||
export default function TradingViewChart({ ticker, data, timeframe = "1D", currentPrice, priceStream }: TradingViewChartProps) {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [livePrice, setLivePrice] = useState<number | undefined>(undefined);
|
||||
const height = TIMEFRAME_HEIGHTS[timeframe] ?? 400;
|
||||
|
||||
const isIntraday = ["1Min", "5Min", "15Min", "30Min", "1H"].includes(timeframe);
|
||||
@@ -69,9 +73,38 @@ export default function TradingViewChart({ ticker, data, timeframe = "1D" }: Tra
|
||||
return () => chart.remove();
|
||||
}, [data, ticker, isIntraday, timeframe]);
|
||||
|
||||
// Subscribe to a streaming price if provided
|
||||
useEffect(() => {
|
||||
if (!priceStream) return;
|
||||
let unsub: (() => void) | void = undefined;
|
||||
try {
|
||||
unsub = priceStream.subscribe((p: number) => {
|
||||
setLivePrice(p);
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn("TradingViewChart: priceStream subscribe failed", e);
|
||||
}
|
||||
return () => {
|
||||
try {
|
||||
if (typeof unsub === "function") unsub();
|
||||
} catch (e) {
|
||||
/* ignore */
|
||||
}
|
||||
};
|
||||
}, [priceStream]);
|
||||
|
||||
const derivedPrice = currentPrice ?? livePrice ?? (data && data.length ? data[data.length - 1].close : undefined);
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-xl shadow-lg p-4">
|
||||
<h3 className="text-lg font-bold mb-3">{ticker} Price Chart</h3>
|
||||
<div className="flex items-baseline justify-between mb-3">
|
||||
<h3 className="text-lg font-bold">{ticker} Price Chart</h3>
|
||||
{typeof derivedPrice === "number" ? (
|
||||
<div data-testid="current-price" className="text-xl font-semibold text-gray-900">
|
||||
${derivedPrice.toFixed(2)}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div ref={containerRef} className="w-full" />
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user