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 };