DockerSpace / frontend /src /components /VolumeChart.tsx
DennisChan0909's picture
feat: market tabs (台股/美股/基金), autocomplete search, favorites filter tabs
b72deed
Raw
History Blame Contribute Delete
1.96 kB
import React from 'react'
import {
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Cell,
ResponsiveContainer,
} from 'recharts'
import { OHLCVPoint } from '../api/stockApi'
interface Props {
data: OHLCVPoint[]
}
function formatVolume(v: number): string {
if (v >= 1_000_000) return `${(v / 1_000_000).toFixed(1)}M`
if (v >= 1_000) return `${(v / 1_000).toFixed(0)}K`
return String(v)
}
const CustomTooltip = ({ active, payload, label }: any) => {
if (!active || !payload?.length) return null
const vol: number = payload[0]?.value
return (
<div className="bg-slate-800 border border-slate-600 rounded p-2 text-xs shadow-lg">
<p className="text-slate-300">{label}</p>
<p className="text-white font-semibold">Vol: {formatVolume(vol)}</p>
</div>
)
}
export const VolumeChart: React.FC<Props> = ({ data }) => {
const len = data.length
return (
<ResponsiveContainer width="100%" height={160}>
<BarChart data={data} margin={{ top: 4, right: 16, left: 0, bottom: 0 }}>
<CartesianGrid strokeDasharray="3 3" stroke="#1e293b" />
<XAxis
dataKey="date"
tick={{ fill: '#94a3b8', fontSize: 10 }}
tickLine={false}
tickFormatter={(val, idx) => {
const step = Math.max(1, Math.floor(len / 10))
return idx % step === 0 ? val : ''
}}
interval={0}
/>
<YAxis
tick={{ fill: '#94a3b8', fontSize: 10 }}
tickLine={false}
tickFormatter={formatVolume}
width={48}
/>
<Tooltip content={<CustomTooltip />} />
<Bar dataKey="volume" isAnimationActive={false} maxBarSize={6}>
{data.map((d, i) => (
<Cell
key={i}
fill={d.close >= d.open ? '#22c55e' : '#ef4444'}
fillOpacity={0.8}
/>
))}
</Bar>
</BarChart>
</ResponsiveContainer>
)
}