diff --git a/projects/dex-ui/src/components/Well/Chart/Chart.tsx b/projects/dex-ui/src/components/Well/Chart/Chart.tsx index 5eb4dbb9e5..80e86cc172 100644 --- a/projects/dex-ui/src/components/Well/Chart/Chart.tsx +++ b/projects/dex-ui/src/components/Well/Chart/Chart.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useMemo, useState } from "react"; import { FC } from "src/types"; import { ChartContainer } from "./ChartStyles"; -import { createChart } from "lightweight-charts"; +import { createChart, IChartApi, ISeriesApi, Time } from "lightweight-charts"; import { useRef } from "react"; import styled from "styled-components"; import { IChartDataItem } from "./ChartSection"; @@ -9,27 +9,37 @@ import { IChartDataItem } from "./ChartSection"; type Props = { legend: string; data: IChartDataItem[]; + refetching?: boolean; +}; + +type ChartData = { + value: number; + time: Time; }; function formatToUSD(value: any) { - const formattedValue = Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(value); + const formattedValue = Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format( + value + ); return formattedValue; } -export const Chart: FC = ({ legend, data: _data }) => { +function mapChartData(data: IChartDataItem[]) { + return data.map(({ time, value }) => ({ + time: time as Time, + value: parseFloat(value) + })); +} + +export const Chart: FC = ({ legend, data: _data, refetching }) => { const chartContainerRef = useRef(); - const chart = useRef(); - const lineSeries = useRef(); - const [lastDataPoint, setLastDataPoint] = useState(); + const chart = useRef(); + const lineSeries = useRef>(); + const [lastDataPoint, setLastDataPoint] = useState(null); const [dataPoint, setDataPoint] = useState(); const [dataPointValue, setDataPointValue] = useState(); - const data = useMemo(() => { - return _data.map(({ time, value }) => ({ - time, - value: parseFloat(value) - })); - }, [_data]); + const data = useMemo(() => mapChartData(_data), [_data]); useEffect(() => { if (!chartContainerRef.current) return; @@ -51,47 +61,72 @@ export const Chart: FC = ({ legend, data: _data }) => { }, timeScale: { timeVisible: true, - secondsVisible: false + secondsVisible: false, + minBarSpacing: 0.01 // allow for zooming out } }; const handleResize = () => { - chart.current.applyOptions({ width: chartContainerRef.current.clientWidth }); + chart.current?.applyOptions({ + width: chartContainerRef.current.clientWidth, + height: chartContainerRef.current.clientHeight + }); }; chart.current = createChart(chartContainerRef.current, chartOptions); - lineSeries.current = chart.current.addLineSeries({ color: "#000" }); + lineSeries.current = chart.current.addLineSeries({ color: "#000", lineWidth: 2 }); window.addEventListener("resize", handleResize); return () => { window.removeEventListener("resize", handleResize); - chart.current.remove(); + chart.current?.remove(); }; }, []); useEffect(() => { - lineSeries.current.setData(data); - chart.current.timeScale().fitContent(); - setLastDataPoint(data[data.length - 1] && data[data.length - 1].value ? data[data.length - 1].value : null); - chart.current.subscribeCrosshairMove((param: any) => setDataPoint(param.seriesData.get(lineSeries.current) || null)); + lineSeries.current?.setData(data); + let lastData = null; + let firstData = null; + + if (data.length) { + lastData = data[data.length - 1]; + firstData = data[0]; + } + if (!lastData || !firstData) { + chart.current?.timeScale().fitContent(); + } else { + chart.current?.timeScale().setVisibleRange({ + from: 0 as Time, + to: lastData.time + }); + } + + const handleSubscribeCrosshairMove = (param: any) => { + setDataPoint(param.seriesData.get(lineSeries.current) || null); + }; + + setLastDataPoint(lastData); + chart.current?.subscribeCrosshairMove(handleSubscribeCrosshairMove); return () => { - chart.current.unsubscribeCrosshairMove(); + chart.current?.unsubscribeCrosshairMove(handleSubscribeCrosshairMove); }; - }, [data, lastDataPoint]); + }, [data]); useEffect(() => { setDataPointValue(dataPoint && dataPoint.value ? dataPoint.value : null); }, [dataPoint]); return ( - - -
{legend}
- {formatToUSD(dataPointValue || lastDataPoint || 0)} -
-
+
+ + +
{legend}
+ {formatToUSD(dataPointValue || lastDataPoint?.value || 0)} +
+
+
); }; diff --git a/projects/dex-ui/src/components/Well/Chart/ChartSection.tsx b/projects/dex-ui/src/components/Well/Chart/ChartSection.tsx index ff161cedf7..c42979807d 100644 --- a/projects/dex-ui/src/components/Well/Chart/ChartSection.tsx +++ b/projects/dex-ui/src/components/Well/Chart/ChartSection.tsx @@ -78,7 +78,13 @@ const ChartSectionContent: FC<{ well: Well }> = ({ well }) => { const [timePeriod, setTimePeriod] = useState("week"); const [dropdownButtonText, setDropdownButtonText] = useState("1 WEEK"); - const { data: chartData, refetch, error, isLoading: chartDataLoading } = useWellChartData(well, timePeriod); + const { + data: chartData, + refetch, + error, + isLoading: chartDataLoading, + isRefetching + } = useWellChartData(well, timePeriod); const [liquidityData, setLiquidityData] = useState([]); const [volumeData, setVolumeData] = useState([]); @@ -174,8 +180,14 @@ const ChartSectionContent: FC<{ well: Well }> = ({ well }) => { - setChartTypeDrawerOpen(true)}>{tab === 0 ? "LIQUIDITY" : "VOLUME"} - + setChartTypeDrawerOpen(true)}> + {tab === 0 ? "LIQUIDITY" : "VOLUME"} + + { setTab(0), setChartTypeDrawerOpen(false); @@ -194,7 +206,11 @@ const ChartSectionContent: FC<{ well: Well }> = ({ well }) => { setChartRangeDrawerOpen(true)}> {dropdownButtonText} - + { setChartRange("day"), setChartRangeDrawerOpen(false); @@ -235,15 +251,22 @@ const ChartSectionContent: FC<{ well: Well }> = ({ well }) => { ) : ( <> - {tab === 0 && !error && } - {tab === 1 && !error && } + {tab === 0 && !error && ( + + )} + {tab === 1 && !error && ( + + )} )} ); }; -export const ChartSection: FC<{ well: Well | undefined; loading?: boolean }> = ({ well, loading }) => { +export const ChartSection: FC<{ well: Well | undefined; loading?: boolean }> = ({ + well, + loading +}) => { if (!well || loading) { return ( @@ -325,7 +348,6 @@ const Container = styled.div` display: flex; flex-direction: column; outline: 0.5px solid #9ca3af; - outline-offset: -0.5px; background-color: #f9f8f6; `;