Skip to content

Commit cd7df58

Browse files
committed
feat: implement sparkline charts for stock history with updated intervals.
1 parent 0ae6569 commit cd7df58

File tree

3 files changed

+55
-31
lines changed

3 files changed

+55
-31
lines changed
Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,51 @@
11
import { useMemo, useState } from "react";
22
import { useGetStockHistory } from "@/api/stock";
33
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
4-
import CandlestickChart from "@/components/valuecell/charts/candlestick-chart";
4+
import Sparkline from "@/components/valuecell/charts/sparkline";
55
import { TimeUtils } from "@/lib/time";
66
import { cn } from "@/lib/utils";
7-
import type { StockInterval } from "@/types/stock";
7+
import type { SparklineData } from "@/types/chart";
8+
import type { StockChangeType, StockInterval } from "@/types/stock";
89

910
interface StockHistoryChartProps {
1011
ticker: string;
1112
className?: string;
1213
}
1314

1415
const INTERVALS: { label: string; value: StockInterval }[] = [
15-
{ label: "1H", value: "1h" },
16-
{ label: "1D", value: "1d" },
17-
{ label: "1W", value: "1w" },
16+
{ label: "24h", value: "1m" },
17+
{ label: "7d", value: "1h" },
18+
{ label: "30d", value: "1d" },
1819
];
1920

2021
export const StockHistoryChart = ({
2122
ticker,
2223
className,
2324
}: StockHistoryChartProps) => {
24-
const [interval, setInterval] = useState<StockInterval>("1d");
25+
const [interval, setInterval] = useState<StockInterval>("1h");
2526

2627
// Calculate date range based on interval
2728
const { startDate, endDate } = useMemo(() => {
2829
const now = TimeUtils.now();
2930

3031
let start = now;
3132
switch (interval) {
33+
case "1m":
34+
start = now.subtract(1, "day");
35+
break;
3236
case "1h":
33-
start = now.subtract(6, "month");
37+
start = now.subtract(1, "week");
3438
break;
3539
case "1d":
36-
start = now.subtract(3, "year");
37-
break;
38-
case "1w":
39-
start = now.subtract(10, "year");
40+
start = now.subtract(1, "month");
4041
break;
4142
default:
42-
start = now.subtract(3, "year");
43+
start = now.subtract(1, "week");
4344
}
4445

4546
return {
46-
startDate: start.format("YYYY-MM-DD"),
47-
endDate: now.format("YYYY-MM-DD"),
47+
startDate: start.utc().toISOString(),
48+
endDate: now.utc().toISOString(),
4849
};
4950
}, [interval]);
5051

@@ -55,9 +56,39 @@ export const StockHistoryChart = ({
5556
end_date: endDate,
5657
});
5758

59+
// Convert StockHistory[] to SparklineData format and calculate changeType
60+
const { sparklineData, changeType } = useMemo(() => {
61+
if (!historyData || historyData.length === 0) {
62+
return {
63+
sparklineData: [] as SparklineData,
64+
changeType: "neutral" as StockChangeType,
65+
};
66+
}
67+
68+
// Convert to SparklineData format: [timestamp, price]
69+
const data: SparklineData = historyData.map((item) => [
70+
item.time,
71+
item.price,
72+
]);
73+
74+
// Determine changeType based on first and last price
75+
const firstPrice = historyData[0].price;
76+
const lastPrice = historyData[historyData.length - 1].price;
77+
78+
let type: StockChangeType = "neutral";
79+
if (lastPrice > firstPrice) {
80+
type = "positive";
81+
} else if (lastPrice < firstPrice) {
82+
type = "negative";
83+
}
84+
85+
return { sparklineData: data, changeType: type };
86+
}, [historyData]);
87+
5888
return (
5989
<div className={cn("flex flex-col gap-4", className)}>
6090
<Tabs
91+
className="self-end"
6192
value={interval}
6293
onValueChange={(value) => setInterval(value as StockInterval)}
6394
>
@@ -69,12 +100,13 @@ export const StockHistoryChart = ({
69100
))}
70101
</TabsList>
71102
</Tabs>
72-
<CandlestickChart
73-
data={historyData ?? []}
74-
height={500}
75-
loading={isLoading}
76-
showVolume
77-
/>
103+
{isLoading ? (
104+
<div className="flex h-[500px] items-center justify-center">
105+
<div className="text-muted-foreground">Loading...</div>
106+
</div>
107+
) : (
108+
<Sparkline data={sparklineData} changeType={changeType} height={300} />
109+
)}
78110
</div>
79111
);
80112
};

frontend/src/components/valuecell/charts/sparkline.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ function Sparkline({
7878
{
7979
type: "line",
8080
data: data,
81+
smooth: true,
8182
symbol: "circle",
8283
symbolSize: 12,
8384
showSymbol: false,

frontend/src/types/stock.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,13 @@ export interface StockPrice {
3434
*/
3535
export type StockInterval =
3636
| "1m" // 1 minute
37-
| "5m" // 5 minutes
38-
| "15m" // 15 minutes
39-
| "30m" // 30 minutes
40-
| "60m" // 60 minutes
4137
| "1h" // 1 hour
4238
| "1d" // 1 day (default)
43-
| "1w" // 1 week
44-
| "1mo"; // 1 month
39+
| "1w"; // 1 week
4540

4641
export interface StockHistory {
4742
time: string;
48-
open: number;
49-
high: number;
50-
low: number;
51-
close: number;
52-
volume: number;
43+
price: number;
5344
}
5445

5546
export interface StockDetail {

0 commit comments

Comments
 (0)