Refactor StatsDisplay component to use Tag and Badge for visual indicators

- Replaced Alert with Tag for displaying stat colors.
- Updated color mapping function to return Tag colors instead of Alert types.
- Enhanced layout and styling for better visual representation of stats.
- Introduced Badge component for status indication alongside stat labels.
This commit is contained in:
Tom Butcher 2025-12-27 13:47:19 +00:00
parent b3c5357064
commit a7cd374375

View File

@ -1,5 +1,5 @@
import { useEffect, useState, useContext, useRef } from 'react' import { useEffect, useState, useContext, useRef } from 'react'
import { Flex, Alert, Card, Typography, Skeleton } from 'antd' import { Flex, Tag, Card, Typography, Skeleton, Badge } from 'antd'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { getModelByName } from '../../../database/ObjectModels' import { getModelByName } from '../../../database/ObjectModels'
import { ApiServerContext } from '../context/ApiServerContext' import { ApiServerContext } from '../context/ApiServerContext'
@ -9,9 +9,9 @@ import { round } from '../utils/Utils'
const { Text } = Typography const { Text } = Typography
/** /**
* Maps stat names to Alert types for visual indication * Maps stat names to Tag colors for visual indication
*/ */
const getAlertType = (statName) => { const getTagColor = (statName) => {
const name = statName.toLowerCase() const name = statName.toLowerCase()
// Success states // Success states
@ -43,14 +43,14 @@ const getAlertType = (statName) => {
} }
if (name.includes('printing')) { if (name.includes('printing')) {
return 'info' return 'processing'
} }
// Default states // Default states
return 'default' return 'default'
} }
/** /*i*
* Gets a nested value from an object using dot notation * Gets a nested value from an object using dot notation
* e.g., getNestedValue(obj, 'states.ready') -> obj.states.ready * e.g., getNestedValue(obj, 'states.ready') -> obj.states.ready
*/ */
@ -255,18 +255,41 @@ const StatsDisplay = ({ objectType, stats: statsProp }) => {
{modelStats.map((statDef) => { {modelStats.map((statDef) => {
const baseStatName = extractBaseStatName(statDef.name) const baseStatName = extractBaseStatName(statDef.name)
var statValue = getStatValue(stats, baseStatName, statDef) var statValue = getStatValue(stats, baseStatName, statDef)
const alertType = getAlertType(statDef.name) const tagColor = statDef.color || getTagColor(statDef.name)
const label = statDef.label || statDef.name const label = statDef.label || statDef.name
if (statDef?.roundNumber) { if (statDef?.roundNumber) {
statValue = round(statValue, statDef?.roundNumber) statValue = round(statValue, statDef?.roundNumber)
} }
const statusColors = [
'success',
'warning',
'error',
'processing',
'default'
]
var badgeProps = {
status: tagColor
}
if (!statusColors.includes(tagColor)) {
badgeProps = { color: tagColor }
}
const content = ( const content = (
<Flex vertical> <Flex vertical gap='3px'>
<Text type='secondary'>{label}</Text> <Flex gap={'12px'} align='center'>
<Flex gap={'small'}> <Badge {...badgeProps} />
{Icon && <Icon style={{ fontSize: 26 }} />} <Text>{label}</Text>
</Flex>
<Flex gap={'12px'} align='center'>
{Icon && (
<Text>
<Icon style={{ fontSize: 26 }} />
</Text>
)}
{loading ? ( {loading ? (
<Flex justify='center' align='center' style={{ height: 44 }}> <Flex justify='center' align='center' style={{ height: 44 }}>
<Skeleton.Button <Skeleton.Button
@ -286,12 +309,12 @@ const StatsDisplay = ({ objectType, stats: statsProp }) => {
</Flex> </Flex>
) )
if (alertType === 'default') { if (tagColor === 'default') {
return ( return (
<Card <Card
key={statDef.name} key={statDef.name}
style={{ minWidth: statDef?.cardWidth || 175 }} style={{ minWidth: statDef?.cardWidth || 175 }}
styles={{ body: { padding: '20px 24px' } }} styles={{ body: { padding: '16px 24px' } }}
> >
{content} {content}
</Card> </Card>
@ -299,12 +322,17 @@ const StatsDisplay = ({ objectType, stats: statsProp }) => {
} }
return ( return (
<Alert <Tag
key={statDef.name} key={statDef.name}
type={alertType} color={tagColor}
style={{ minWidth: statDef?.cardWidth || 175 }} style={{
description={content} minWidth: statDef?.cardWidth || 175,
/> padding: '16px 24px',
margin: 0
}}
>
{content}
</Tag>
) )
})} })}
</Flex> </Flex>