import { styled, useTheme, Typography } from '@mui/material'; import { Link } from 'react-router-dom'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import { useProjectStatus } from 'hooks/api/getters/useProjectStatus/useProjectStatus'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { HealthGridTile } from './ProjectHealthGrid.styles'; import { PrettifyLargeNumber } from 'component/common/PrettifyLargeNumber/PrettifyLargeNumber'; import { getTechnicalDebtColor } from 'utils/getTechnicalDebtColor.ts'; import { useUiFlag } from 'hooks/useUiFlag'; const ChartRadius = 40; const ChartStrokeWidth = 13; const ChartTotalWidth = ChartRadius * 2 + ChartStrokeWidth; const ChartContainerWidth = 100; const TextContainer = styled('div')(({ theme }) => ({ display: 'flex', flexDirection: 'column', gap: theme.spacing(1), })); const ChartRow = styled('div')(({ theme }) => ({ display: 'flex', alignItems: 'center', gap: theme.spacing(2), })); const SVGWrapper = styled('div')(({ theme }) => ({ flex: 'none', height: 85, width: ChartContainerWidth, position: 'relative', })); const StyledSVG = styled('svg')({ position: 'absolute', }); const BigText = styled('span')(({ theme }) => ({ fontSize: theme.typography.h1.fontSize, })); const UnhealthyStatContainer = styled('div')(({ theme }) => ({ flex: 'none', display: 'grid', placeItems: 'center', width: ChartContainerWidth, })); const UnhealthyStatText = styled('p')(({ theme }) => ({ fontSize: theme.typography.body2.fontSize, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', borderRadius: '50%', backgroundColor: theme.mode === 'light' ? theme.palette.background.elevation2 : '#302E42', // in dark mode, elevation2 and elevation1 are the same color. This is an alternative width: ChartTotalWidth, height: ChartTotalWidth, overflow: 'hidden', })); const UnhealthyFlagBox = ({ flagCount }: { flagCount: number }) => { const flagWord = flagCount === 1 ? 'flag' : 'flags'; return ( unhealthy {flagWord} ); }; const useHealthColor = (healthRating: number) => { const theme = useTheme(); if (healthRating <= 24) { return theme.palette.error.main; } if (healthRating <= 74) { return theme.palette.warning.border; } return theme.palette.success.border; }; const useTechnicalDebtColor = (techicalDebt: number) => { const theme = useTheme(); switch (getTechnicalDebtColor(techicalDebt)) { case 'error': return theme.palette.error.main; case 'warning': return theme.palette.warning.border; default: return theme.palette.success.border; } }; const Wrapper = styled(HealthGridTile)(({ theme }) => ({ display: 'flex', flexDirection: 'column', justifyContent: 'space-around', gap: theme.spacing(2), })); export const ProjectHealth = () => { const projectId = useRequiredPathParam('projectId'); const { data: { health, technicalDebt, staleFlags }, } = useProjectStatus(projectId); const { isOss } = useUiConfig(); const theme = useTheme(); const healthToDebtEnabled = useUiFlag('healthToTechDebt'); const circumference = 2 * Math.PI * ChartRadius; const healthRating = health.current; const gapLength = 0.3; const filledLength = 1 - gapLength; const offset = 0.75 - gapLength / 2; const healthLength = (healthRating / 100) * circumference * 0.7; const technicalDebtLength = ((technicalDebt.current || 0) / 100) * circumference * 0.7; const healthColor = useHealthColor(healthRating); const technicalDebtColor = useTechnicalDebtColor( technicalDebt.current || 0, ); return ( {healthToDebtEnabled ? technicalDebt.current || 0 : healthRating} % {healthToDebtEnabled ? ( <> Your current technical debt rating is{' '} {technicalDebt.current}%. ) : ( <> Your current project health rating is{' '} {healthRating}%. )} {!isOss() && ( {healthToDebtEnabled ? 'View technical debt over time' : 'View health over time'} )} To keep your project healthy, archive stale feature flags and remove code from your code base to reduce technical debt. View unhealthy flags ); };