Skip to content

Commit 83bb55f

Browse files
committed
💄 app: tweak historical rate chart
1 parent d7fc224 commit 83bb55f

10 files changed

Lines changed: 416 additions & 296 deletions

File tree

components/asset/FloatingPool/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ const AssetFloatingPool: FC<AssetFloatingPoolProps> = ({ symbol }) => {
2929
boxShadow={({ palette }) => (palette.mode === 'light' ? '0px 4px 12px rgba(175, 177, 182, 0.2)' : '')}
3030
borderRadius="0px 0px 6px 6px"
3131
bgcolor="components.bg"
32-
p="16px"
32+
px="16px"
33+
pt="16px"
34+
pb="12px"
3335
height={280}
3436
>
3537
<HistoricalRateChart symbol={symbol} />

components/asset/Header.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ const AssetHeaderInfo: FC<Props> = ({ symbol }) => {
214214
)}
215215
{symbol === 'USDC.e' && <FrozenPill />}
216216

217-
<Typography sx={{ width: '100%' }} variant="dashboardMainSubtitle">
217+
<Typography sx={{ width: '100%', minHeight: '16px' }} variant="dashboardMainSubtitle">
218218
{assetDescription(symbol)}
219219
</Typography>
220220
</Grid>

components/asset/MaturityPool/MaturityPoolsTable/index.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ import { toPercentage } from 'utils/utils';
1515
import numbers from 'config/numbers.json';
1616
import useActionButton from 'hooks/useActionButton';
1717
import useMaturityPools from 'hooks/useMaturityPools';
18+
import usePreviewerExactly from 'hooks/usePreviewerExactly';
1819
import { useTranslation } from 'react-i18next';
1920
import getHourUTC2Local from 'utils/getHourUTC2Local';
2021
import { track } from 'utils/mixpanel';
22+
import Skeleton from '@mui/material/Skeleton';
2123

2224
type MaturityPoolsTableProps = {
2325
symbol: string;
@@ -40,6 +42,7 @@ const MaturityPoolsTable: FC<MaturityPoolsTableProps> = ({ symbol }) => {
4042
const { handleActionClick } = useActionButton();
4143
const { minAPRValue } = numbers;
4244
const rows = useMaturityPools(symbol);
45+
const { data } = usePreviewerExactly();
4346

4447
return (
4548
<TableContainer>
@@ -65,6 +68,26 @@ const MaturityPoolsTable: FC<MaturityPoolsTableProps> = ({ symbol }) => {
6568
</TableRow>
6669
</TableHead>
6770
<TableBody>
71+
{!data &&
72+
Array.from({ length: 3 }, (_, index) => (
73+
<TableRow key={`maturity-pool-skeleton-${index}`} sx={{ height: 65 }}>
74+
<TableCell sx={{ pl: 1.5 }}>
75+
<Skeleton variant="rounded" width={80} height={20} />
76+
</TableCell>
77+
<TableCell>
78+
<Skeleton variant="rounded" width={50} height={20} />
79+
</TableCell>
80+
<TableCell>
81+
<Skeleton variant="rounded" width={80} height={34} />
82+
</TableCell>
83+
<TableCell>
84+
<Skeleton variant="rounded" width={50} height={20} />
85+
</TableCell>
86+
<TableCell size="small">
87+
<Skeleton variant="rounded" width={80} height={34} />
88+
</TableCell>
89+
</TableRow>
90+
))}
6891
{rows.map(({ maturity, totalDeposited, totalBorrowed, depositAPR, borrowAPR }) => (
6992
<TableRow
7093
key={Number(maturity)}

components/charts/HistoricalRateChart/index.tsx

Lines changed: 127 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Box, Checkbox, FormControlLabel, Typography, useTheme } from '@mui/material';
2-
import { useQuery } from '@tanstack/react-query';
2+
import { keepPreviousData, useQuery } from '@tanstack/react-query';
33
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
44
import { useTranslation } from 'react-i18next';
5-
import { CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
5+
import { CartesianGrid, Line, LineChart, Tooltip, XAxis, YAxis } from 'recharts';
66
import { formatEther, formatUnits } from 'viem';
77
import { usePublicClient } from 'wagmi';
88
import { floatingDepositRates } from '@exactly/lib';
@@ -39,7 +39,7 @@ const HistoricalRateChart: FC<Props> = ({ symbol }) => {
3939
const { t } = useTranslation();
4040
const { palette } = useTheme();
4141
const { setLoadError } = useGlobalError();
42-
const [showDeposits, setShowDeposits] = useState(false);
42+
const [showDeposits, setShowDeposits] = useState(true);
4343
const [range, setRange] = useState<Range>('6M');
4444

4545
const marketAccount = usePreviewerExactly().data?.find((market) => market.assetSymbol === symbol);
@@ -50,12 +50,13 @@ const HistoricalRateChart: FC<Props> = ({ symbol }) => {
5050

5151
const {
5252
data: points = [],
53-
isLoading,
53+
isFetching,
5454
isError,
5555
} = useQuery({
5656
queryKey: ['historicalRates', defaultChain.id, market, range],
5757
enabled: Boolean(client && market && ratePreviewer && code),
5858
staleTime: 60_000,
59+
placeholderData: keepPreviousData,
5960
queryFn: async () => {
6061
if (!client || !market || !marketAccount || !ratePreviewer || !code) return [];
6162

@@ -112,7 +113,7 @@ const HistoricalRateChart: FC<Props> = ({ symbol }) => {
112113
},
113114
});
114115

115-
const loading = isLoading || !marketAccount;
116+
const loading = isFetching || !marketAccount;
116117

117118
useEffect(() => {
118119
if (isError) setLoadError();
@@ -148,7 +149,7 @@ const HistoricalRateChart: FC<Props> = ({ symbol }) => {
148149
}, [showDeposits, symbol]);
149150

150151
return (
151-
<Box data-testid="historical-rate-chart" display="flex" flexDirection="column" width="100%" height="100%" gap={2}>
152+
<Box data-testid="historical-rate-chart" display="flex" flexDirection="column" width="100%" height="100%" gap={1}>
152153
<Box display="flex" justifyContent="space-between">
153154
<Typography variant="h6" fontSize="16px">
154155
{t('Historical Variable Rates')}
@@ -157,109 +158,144 @@ const HistoricalRateChart: FC<Props> = ({ symbol }) => {
157158
<ButtonsChart buttons={buttons} defaultSelected={3} />
158159
</Box>
159160
</Box>
160-
<Box flex={1} minHeight={0}>
161+
<Box position="relative" flex={1} minWidth={0} minHeight={0}>
162+
<LineChart responsive style={{ width: '100%', height: '100%' }} data={points} margin={{ top: 2 }}>
163+
<CartesianGrid yAxisId="left" horizontal vertical={false} stroke={palette.grey[300]} />
164+
<XAxis
165+
dataKey="date"
166+
type="number"
167+
domain={['dataMin', 'dataMax']}
168+
minTickGap={50}
169+
padding={{ left: 8, right: 8 }}
170+
tickFormatter={(value) =>
171+
formatDate(new Date(value as number), range === '6M' || range === '1Y' || range === 'ALL')
172+
}
173+
stroke="#B4BABF"
174+
fontSize="12px"
175+
height={20}
176+
/>
177+
<YAxis
178+
yAxisId="left"
179+
domain={['auto', 'auto']}
180+
tickFormatter={(tick) => toPercentage(tick).replace(/(\.\d*?[1-9])0+(?=\D*$)|\.0+(?=\D*$)/, '$1')}
181+
axisLine={false}
182+
tick={{ fill: palette.grey[500], fontWeight: 500, fontSize: 11 }}
183+
tickLine={false}
184+
width="auto"
185+
/>
186+
{showDeposits && (
187+
<YAxis
188+
yAxisId="right"
189+
orientation="right"
190+
domain={['auto', 'auto']}
191+
tickFormatter={(value) =>
192+
formatNumber(value as number, symbol).replace(/(\.\d*?[1-9])0+(?=\D*$)|\.0+(?=\D*$)/, '$1')
193+
}
194+
tick={{ fill: palette.blue, fontWeight: 500, fontSize: 11 }}
195+
axisLine={false}
196+
tickLine={false}
197+
width="auto"
198+
/>
199+
)}
200+
<Tooltip
201+
active={loading ? false : undefined}
202+
labelFormatter={(value) => formatDate(new Date(value as number), true)}
203+
content={
204+
<TooltipChart
205+
formatter={(value, { dataKey }) =>
206+
dataKey === 'deposits' ? `${formatNumber(value, symbol)} ${symbol}` : toPercentage(value)
207+
}
208+
/>
209+
}
210+
/>
211+
<Line
212+
yAxisId="left"
213+
type="monotone"
214+
dataKey="depositApr"
215+
name={t('Deposit APR')}
216+
stroke={palette.mode === 'light' ? 'black' : 'white'}
217+
dot={false}
218+
strokeWidth={2}
219+
animationDuration={300}
220+
animationEasing="ease-out"
221+
/>
222+
<Line
223+
yAxisId="left"
224+
type="monotone"
225+
dataKey="borrowApr"
226+
name={t('Borrow APR')}
227+
stroke={palette.green}
228+
dot={false}
229+
strokeWidth={2}
230+
animationDuration={300}
231+
animationEasing="ease-out"
232+
/>
233+
{showDeposits && (
234+
<Line
235+
yAxisId="right"
236+
type="monotone"
237+
dataKey="deposits"
238+
name={t('Total Deposits')}
239+
stroke={palette.blue}
240+
dot={false}
241+
strokeDasharray="5 5"
242+
animationDuration={300}
243+
animationEasing="ease-out"
244+
/>
245+
)}
246+
</LineChart>
161247
{loading ? (
162-
<LoadingChart />
248+
<LoadingChart overlay />
163249
) : points.length < 2 ? (
164-
<Box display="flex" width="100%" height="100%" alignItems="center" justifyContent="center">
250+
<Box position="absolute" display="flex" alignItems="center" justifyContent="center" sx={{ inset: 0 }}>
165251
<Typography color="grey.500" variant="subtitle2" fontSize="14px">
166252
{t('Not enough variable rate activity to chart yet.')}
167253
</Typography>
168254
</Box>
169-
) : (
170-
<ResponsiveContainer width="100%" height="100%">
171-
<LineChart data={points} margin={{ top: 5, bottom: 5 }}>
172-
<CartesianGrid horizontal vertical={false} stroke={palette.grey[300]} />
173-
<XAxis
174-
dataKey="date"
175-
type="number"
176-
domain={['dataMin', 'dataMax']}
177-
minTickGap={50}
178-
padding={{ left: 20, right: 30 }}
179-
tickFormatter={(value) =>
180-
formatDate(new Date(value as number), range === '6M' || range === '1Y' || range === 'ALL')
181-
}
182-
stroke="#B4BABF"
183-
fontSize="12px"
184-
height={20}
185-
/>
186-
<YAxis
187-
yAxisId="left"
188-
tickFormatter={(tick) => toPercentage(tick)}
189-
axisLine={false}
190-
tick={{ fill: palette.grey[500], fontWeight: 500, fontSize: 11 }}
191-
tickLine={false}
192-
width={50}
193-
/>
194-
{showDeposits && (
195-
<YAxis
196-
yAxisId="right"
197-
orientation="right"
198-
tickFormatter={(value) => formatNumber(value as number, symbol)}
199-
tick={{ fill: palette.blue, fontWeight: 500, fontSize: 11 }}
200-
axisLine={false}
201-
tickLine={false}
202-
width={50}
203-
/>
204-
)}
205-
<Tooltip
206-
labelFormatter={(value) => formatDate(new Date(value as number), true)}
207-
content={
208-
<TooltipChart
209-
formatter={(value, { dataKey }) =>
210-
dataKey === 'deposits' ? `${formatNumber(value, symbol)} ${symbol}` : toPercentage(value)
211-
}
212-
sortItems={(a, b) => (a.value > b.value ? -1 : 1)}
213-
/>
214-
}
215-
/>
216-
<Line
217-
yAxisId="left"
218-
type="monotone"
219-
dataKey="depositApr"
220-
name={t('Deposit APR')}
221-
stroke={palette.mode === 'light' ? 'black' : 'white'}
222-
dot={false}
223-
strokeWidth={2}
224-
/>
225-
<Line
226-
yAxisId="left"
227-
type="monotone"
228-
dataKey="borrowApr"
229-
name={t('Borrow APR')}
230-
stroke={palette.green}
231-
dot={false}
232-
strokeWidth={2}
233-
/>
234-
{showDeposits && (
235-
<Line
236-
yAxisId="right"
237-
type="monotone"
238-
dataKey="deposits"
239-
name={t('Total Deposits')}
240-
stroke={palette.blue}
241-
dot={false}
242-
strokeDasharray="5 5"
243-
/>
244-
)}
245-
</LineChart>
246-
</ResponsiveContainer>
247-
)}
255+
) : null}
248256
</Box>
249-
<Box display="flex" alignItems="center" mt={-2.5} pl={1}>
257+
<Box display="flex" alignItems="center" justifyContent="space-between" gap={1}>
258+
<Box data-testid="historical-rate-chart-legend" display="flex" alignItems="center" gap={1.5}>
259+
<Box display="flex" alignItems="center" gap={0.5}>
260+
<Box
261+
width={16}
262+
flexShrink={0}
263+
borderTop="2px solid"
264+
borderColor={palette.mode === 'light' ? 'black' : 'white'}
265+
/>
266+
<Typography variant="subtitle1" fontSize="10px" lineHeight={1} whiteSpace="nowrap">
267+
{t('Deposit APR')}
268+
</Typography>
269+
</Box>
270+
<Box display="flex" alignItems="center" gap={0.5}>
271+
<Box width={16} flexShrink={0} borderTop="2px solid" borderColor={palette.green} />
272+
<Typography variant="subtitle1" fontSize="10px" lineHeight={1} whiteSpace="nowrap">
273+
{t('Borrow APR')}
274+
</Typography>
275+
</Box>
276+
<Box display="flex" alignItems="center" gap={0.5} sx={{ opacity: showDeposits ? 1 : 0.4 }}>
277+
<Box width={16} flexShrink={0} borderTop="2px dashed" borderColor={palette.blue} />
278+
<Typography variant="subtitle1" fontSize="10px" lineHeight={1} whiteSpace="nowrap">
279+
{t('Total Deposits')}
280+
</Typography>
281+
</Box>
282+
</Box>
250283
<FormControlLabel
251284
control={
252285
<Checkbox
253286
size="small"
287+
checked={showDeposits}
254288
onChange={onShowDepositsChange}
255-
sx={{ color: palette.blue, '&.Mui-checked': { color: palette.blue } }}
289+
sx={{ px: 0.25, pt: 0.25, pb: 0, color: palette.blue, '&.Mui-checked': { color: palette.blue } }}
256290
/>
257291
}
258292
label={
259-
<Typography variant="subtitle1" fontSize="12px">
293+
<Typography variant="subtitle1" fontSize="12px" lineHeight={1}>
260294
{t('Show total deposits')}
261295
</Typography>
262296
}
297+
labelPlacement="start"
298+
sx={{ m: 0, gap: 0.5 }}
263299
/>
264300
</Box>
265301
</Box>

components/charts/LoadingChart/index.tsx

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,39 @@ import React from 'react';
22
import { Box, CircularProgress, Typography } from '@mui/material';
33
import { useTranslation } from 'react-i18next';
44

5-
function LoadingChart() {
5+
function LoadingChart({ overlay = false }: { overlay?: boolean }) {
66
const { t } = useTranslation();
77
return (
8-
<Box display="flex" width="100%" height="100%">
9-
<Box display="flex" flexDirection="column" justifyContent="center" m="auto" gap={1}>
10-
<CircularProgress sx={{ color: 'grey.500', mx: 'auto' }} size={24} thickness={4} />
11-
<Typography color="grey.500" variant="subtitle2" fontSize="16px">
8+
<Box
9+
data-testid="loading-chart"
10+
display="flex"
11+
width="100%"
12+
height="100%"
13+
sx={
14+
overlay
15+
? {
16+
position: 'absolute',
17+
inset: 0,
18+
zIndex: 1,
19+
}
20+
: undefined
21+
}
22+
>
23+
<Box
24+
display="flex"
25+
alignItems="center"
26+
m="auto"
27+
gap={1}
28+
px={2}
29+
py={1}
30+
bgcolor="grey.200"
31+
border="1px solid"
32+
borderColor="grey.300"
33+
borderRadius="999px"
34+
boxShadow="0 2px 8px rgb(0 0 0 / 18%)"
35+
>
36+
<CircularProgress sx={{ color: 'text.primary' }} size={18} thickness={4} />
37+
<Typography color="text.primary" variant="subtitle2" fontSize="14px" lineHeight={1}>
1238
{t('Loading data...')}
1339
</Typography>
1440
</Box>

0 commit comments

Comments
 (0)