ApyGraphContainer.tsx
1 import { Trans } from '@lingui/macro'; 2 import { Box, Button, CircularProgress, Typography } from '@mui/material'; 3 import { ParentSize } from '@visx/responsive'; 4 import { useState } from 'react'; 5 import type { ComputedReserveData } from 'src/hooks/app-data-provider/useAppDataProvider'; 6 import { ReserveRateTimeRange, useReserveRatesHistory } from 'src/hooks/useReservesHistory'; 7 import { MarketDataType } from 'src/utils/marketsAndNetworksConfig'; 8 9 import { ESupportedTimeRanges } from '../TimeRangeSelector'; 10 import { ApyGraph, PlaceholderChart } from './ApyGraph'; 11 import { GraphLegend } from './GraphLegend'; 12 import { GraphTimeRangeSelector } from './GraphTimeRangeSelector'; 13 14 type Field = 'liquidityRate' | 'variableBorrowRate'; 15 16 type Fields = { name: Field; color: string; text: string }[]; 17 18 type ApyGraphContainerKey = 'supply' | 'borrow'; 19 20 type ApyGraphContainerProps = { 21 graphKey: ApyGraphContainerKey; 22 reserve: ComputedReserveData; 23 currentMarketData: MarketDataType; 24 }; 25 26 /** 27 * NOTES: 28 * This may not be named accurately. 29 * This container uses the same graph but with different fields, so we use a 'graphKey' to determine which to show 30 * This likely may need to be turned into two different container components if the graphs become wildly different. 31 * This graph gets its data via an external API call, thus having loading/error states 32 */ 33 export const ApyGraphContainer = ({ 34 graphKey, 35 reserve, 36 currentMarketData, 37 }: ApyGraphContainerProps): JSX.Element => { 38 const [selectedTimeRange, setSelectedTimeRange] = useState<ReserveRateTimeRange>( 39 ESupportedTimeRanges.OneMonth 40 ); 41 42 const CHART_HEIGHT = 155; 43 const CHART_HEIGHT_LOADING_FIX = 3; 44 let reserveAddress = ''; 45 if (reserve) { 46 if (currentMarketData.v3) { 47 reserveAddress = `${reserve.underlyingAsset}${currentMarketData.addresses.LENDING_POOL_ADDRESS_PROVIDER}${currentMarketData.chainId}`; 48 } else { 49 reserveAddress = `${reserve.underlyingAsset}${currentMarketData.addresses.LENDING_POOL_ADDRESS_PROVIDER}`; 50 } 51 } 52 const { data, loading, error, refetch } = useReserveRatesHistory( 53 reserveAddress, 54 selectedTimeRange 55 ); 56 57 // Supply fields 58 const supplyFields: Fields = [{ name: 'liquidityRate', color: '#2EBAC6', text: 'Supply APR' }]; 59 60 // Borrow fields 61 const borrowFields: Fields = [ 62 { 63 name: 'variableBorrowRate', 64 color: '#B6509E', 65 text: 'Borrow APR, variable', 66 }, 67 ]; 68 69 const fields = graphKey === 'supply' ? supplyFields : borrowFields; 70 71 const graphLoading = ( 72 <Box 73 sx={{ 74 height: CHART_HEIGHT + CHART_HEIGHT_LOADING_FIX, 75 width: 'auto', 76 display: 'flex', 77 flexDirection: 'column', 78 alignItems: 'center', 79 justifyContent: 'center', 80 }} 81 > 82 <CircularProgress size={20} sx={{ mb: 2, opacity: 0.5 }} /> 83 <Typography variant="subheader1" color="text.muted"> 84 <Trans>Loading data...</Trans> 85 </Typography> 86 </Box> 87 ); 88 89 const graphError = ( 90 <Box 91 sx={{ 92 height: CHART_HEIGHT + CHART_HEIGHT_LOADING_FIX, 93 width: 'auto', 94 display: 'flex', 95 flexDirection: 'column', 96 alignItems: 'center', 97 justifyContent: 'center', 98 }} 99 > 100 <Typography variant="subheader1"> 101 <Trans>Something went wrong</Trans> 102 </Typography> 103 <Typography variant="caption" sx={{ mb: 3 }}> 104 <Trans>Data couldn't be fetched, please reload graph.</Trans> 105 </Typography> 106 <Button variant="outlined" color="primary" onClick={refetch}> 107 <Trans>Reload</Trans> 108 </Button> 109 </Box> 110 ); 111 112 return ( 113 <Box sx={{ mt: 10, mb: 4 }}> 114 <Box 115 sx={{ 116 display: 'flex', 117 alignItems: 'center', 118 justifyContent: 'space-between', 119 mb: 4, 120 }} 121 > 122 <GraphLegend labels={fields} /> 123 <GraphTimeRangeSelector 124 disabled={loading || error} 125 timeRange={selectedTimeRange} 126 onTimeRangeChanged={setSelectedTimeRange} 127 /> 128 </Box> 129 {loading && graphLoading} 130 {error && graphError} 131 {!loading && !error && ( 132 <ParentSize> 133 {({ width }) => 134 data.length > 0 ? ( 135 <ApyGraph 136 width={width} 137 height={CHART_HEIGHT} 138 data={data} 139 fields={fields} 140 selectedTimeRange={selectedTimeRange} 141 avgFieldName={graphKey === 'supply' ? 'liquidityRate' : 'variableBorrowRate'} 142 /> 143 ) : ( 144 /* Placeholder chart in the case where there is no rate data available yet */ 145 <PlaceholderChart height={CHART_HEIGHT} width={width} /> 146 ) 147 } 148 </ParentSize> 149 )} 150 </Box> 151 ); 152 };