/ src / components / caps / CapsCircularStatus.tsx
CapsCircularStatus.tsx
 1  import Box from '@mui/material/Box';
 2  import CircularProgress, { circularProgressClasses } from '@mui/material/CircularProgress';
 3  import Typography from '@mui/material/Typography';
 4  import { ReactNode, useState } from 'react';
 5  
 6  import { ContentWithTooltip } from '../ContentWithTooltip';
 7  
 8  type CapsCircularStatusProps = {
 9    value: number;
10    tooltipContent: ReactNode;
11    onClick?: (open: boolean) => void;
12  };
13  
14  export const CapsCircularStatus = ({ value, tooltipContent, onClick }: CapsCircularStatusProps) => {
15    const [open, setOpen] = useState<boolean>(false);
16  
17    // If value is zero, don't show anything
18    if (value === 0) return null;
19  
20    const determineColor = (): 'error' | 'warning' | 'success' => {
21      if (Math.round(value) >= 99.99) {
22        return 'error';
23      } else if (value >= 98) {
24        return 'warning';
25      } else {
26        return 'success';
27      }
28    };
29  
30    const determineValueDisplay = (): string => {
31      if (value >= 99.99) {
32        return '100%';
33      } else if (value === 0) {
34        return 'N/A';
35      } else if (value < 0.01) {
36        return '<0.01%';
37      } else {
38        return `${value.toFixed(2)}%`;
39      }
40    };
41  
42    return (
43      <ContentWithTooltip
44        tooltipContent={<>{tooltipContent}</>}
45        open={open}
46        setOpen={(value) => {
47          setOpen(value);
48          if (onClick) onClick(value);
49        }}
50      >
51        <Box sx={{ position: 'relative', mr: 4 }}>
52          <CircularProgress
53            variant="determinate"
54            sx={{
55              color: (theme) => theme.palette.grey[theme.palette.mode === 'light' ? 200 : 800],
56              position: 'absolute',
57              left: 1.25,
58              top: 1.25,
59            }}
60            size={77.5}
61            thickness={2}
62            value={100}
63          />
64          <CircularProgress
65            variant="determinate"
66            color={determineColor()}
67            sx={{
68              [`& .${circularProgressClasses.circle}`]: {
69                strokeLinecap: 'round',
70              },
71            }}
72            size={80}
73            thickness={3}
74            // We show at minimum, 2% color to represent small values
75            value={value <= 2 ? 2 : value > 100 ? 100 : value}
76          />
77          <Typography
78            variant="secondary14"
79            sx={{
80              position: 'absolute',
81              top: 0,
82              bottom: 0,
83              left: 0,
84              right: 0,
85              display: 'flex',
86              alignItems: 'center',
87              justifyContent: 'center',
88            }}
89          >
90            {determineValueDisplay()}
91          </Typography>
92        </Box>
93      </ContentWithTooltip>
94    );
95  };