Files
Neon-Desk/components/charts/interactive-price-chart.tsx

93 lines
2.7 KiB
TypeScript

'use client';
import { useState, useMemo } from 'react';
import type { InteractivePriceChartProps, ChartType, TimeRange } from '@/lib/types';
import { filterByTimeRange, isOHLCVData } from './utils/chart-data-transformers';
import { ChartContainer } from './primitives/chart-container';
import { ChartToolbar } from './primitives/chart-toolbar';
import { LineChartView } from './renderers/line-chart-view';
import { CombinationChartView } from './renderers/combination-chart-view';
import { VolumeIndicator } from './primitives/volume-indicator';
import { useChartExport } from './hooks/use-chart-export';
export function InteractivePriceChart({
data,
dataSeries,
defaultChartType = 'line',
defaultTimeRange = '1Y',
showVolume = false,
showToolbar = true,
height = 400,
loading = false,
error = null,
formatters,
onChartTypeChange,
onTimeRangeChange
}: InteractivePriceChartProps) {
const [chartType, setChartType] = useState<ChartType>(defaultChartType);
const [timeRange, setTimeRange] = useState<TimeRange>(defaultTimeRange);
const filteredData = useMemo(() => filterByTimeRange(data, timeRange), [data, timeRange]);
const filteredDataSeries = useMemo(
() => dataSeries?.map((series) => ({
...series,
data: filterByTimeRange(series.data, timeRange)
})),
[dataSeries, timeRange]
);
const { chartRef, exportChart } = useChartExport();
const handleChartTypeChange = (type: ChartType) => {
setChartType(type);
onChartTypeChange?.(type);
};
const handleTimeRangeChange = (range: TimeRange) => {
setTimeRange(range);
onTimeRangeChange?.(range);
};
const handleExport = () => {
exportChart(`chart-${Date.now()}.png`);
};
const shouldShowVolume = showVolume && filteredData.some(isOHLCVData);
return (
<div ref={chartRef} className="w-full">
{showToolbar && (
<ChartToolbar
chartType={chartType}
timeRange={timeRange}
onChartTypeChange={handleChartTypeChange}
onTimeRangeChange={handleTimeRangeChange}
onExport={handleExport}
/>
)}
<ChartContainer height={height} loading={loading} error={error}>
{chartType === 'line' && (
<LineChartView
data={filteredData}
formatters={formatters}
/>
)}
{chartType === 'combination' && filteredDataSeries && (
<CombinationChartView
dataSeries={filteredDataSeries}
formatters={formatters}
/>
)}
</ChartContainer>
{shouldShowVolume && (
<VolumeIndicator
data={filteredData.filter(isOHLCVData)}
height={80}
formatters={formatters}
/>
)}
</div>
);
}