93 lines
2.7 KiB
TypeScript
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>
|
|
);
|
|
}
|