({ activeUsers, totalDownloads })
| 7 | } |
| 8 | |
| 9 | const BundleUsageChart: React.FC<BundleUsageChartProps> = ({ activeUsers, totalDownloads }) => { |
| 10 | // Ensure we don't have a negative inactive count or exceed total downloads |
| 11 | const sanitizedActiveUsers = Math.min(Math.max(0, activeUsers), totalDownloads); |
| 12 | const activePercentage = totalDownloads > 0 |
| 13 | ? (sanitizedActiveUsers / totalDownloads) * 100 |
| 14 | : 0; |
| 15 | |
| 16 | return ( |
| 17 | <Box> |
| 18 | <Flex |
| 19 | justifyContent="space-between" |
| 20 | alignItems="center" |
| 21 | mb={3} |
| 22 | > |
| 23 | <Text fontSize="16px" fontWeight="bold">Usage Statistics</Text> |
| 24 | <Text color="#666" fontSize="14px"> |
| 25 | {sanitizedActiveUsers.toLocaleString()} active of {totalDownloads.toLocaleString()} downloads |
| 26 | <Text as="span" ml={1} color="#34C363" fontWeight="bold"> |
| 27 | ({activePercentage.toFixed(1)}%) |
| 28 | </Text> |
| 29 | </Text> |
| 30 | </Flex> |
| 31 | |
| 32 | <Box |
| 33 | height={24} |
| 34 | mb={3} |
| 35 | sx={{ |
| 36 | borderRadius: '12px', |
| 37 | overflow: 'hidden', |
| 38 | boxShadow: '0 2px 4px rgba(0,0,0,0.05)', |
| 39 | position: 'relative' |
| 40 | }} |
| 41 | > |
| 42 | {/* Background bar (inactive users) */} |
| 43 | <Box |
| 44 | sx={{ |
| 45 | height: '100%', |
| 46 | width: '100%', |
| 47 | backgroundColor: '#E0E0E0', |
| 48 | position: 'absolute' |
| 49 | }} |
| 50 | /> |
| 51 | |
| 52 | {/* Foreground bar (active users) */} |
| 53 | <Box |
| 54 | sx={{ |
| 55 | height: '100%', |
| 56 | width: `${activePercentage}%`, |
| 57 | backgroundColor: '#34C363', |
| 58 | position: 'absolute', |
| 59 | transition: 'width 0.5s ease-in-out' |
| 60 | }} |
| 61 | /> |
| 62 | |
| 63 | {/* Percentage label - only show if enough space */} |
| 64 | {activePercentage > 10 && ( |
| 65 | <Flex |
| 66 | sx={{ |
nothing calls this directly
no outgoing calls
no test coverage detected