55 lines
1.3 KiB
TypeScript
55 lines
1.3 KiB
TypeScript
import { getOnTimeDeliveryBand, type OnTimeDeliveryBand } from './core-metrics'
|
||
|
||
type OnTimeDeliveryRateProps = {
|
||
rate: number
|
||
contextLabel: string
|
||
size?: 'card' | 'summary'
|
||
}
|
||
|
||
const BAND_PRESENTATION: Record<OnTimeDeliveryBand, {
|
||
label: string
|
||
range: string
|
||
textClassName: string
|
||
}> = {
|
||
green: {
|
||
label: '绿色区间',
|
||
range: '>95%',
|
||
textClassName: 'text-[#067647]',
|
||
},
|
||
yellow: {
|
||
label: '黄色区间',
|
||
range: '90%–95%',
|
||
textClassName: 'text-[#a88a00]',
|
||
},
|
||
red: {
|
||
label: '红色区间',
|
||
range: '<90%',
|
||
textClassName: 'text-[#b42318]',
|
||
},
|
||
}
|
||
|
||
function formatRate(rate: number) {
|
||
return `${Number.isInteger(rate) ? rate.toFixed(0) : rate.toFixed(1)}%`
|
||
}
|
||
|
||
export default function OnTimeDeliveryRate({
|
||
rate,
|
||
contextLabel,
|
||
size = 'card',
|
||
}: OnTimeDeliveryRateProps) {
|
||
const band = getOnTimeDeliveryBand(rate)
|
||
const presentation = BAND_PRESENTATION[band]
|
||
const value = formatRate(rate)
|
||
|
||
return (
|
||
<div>
|
||
<p
|
||
className={`mt-2 font-bold tabular-nums tracking-[-0.03em] ${size === 'card' ? 'text-3xl sm:text-4xl' : 'text-2xl'} ${presentation.textClassName}`}
|
||
aria-label={`${contextLabel}${value},${presentation.label}${presentation.range}`}
|
||
>
|
||
{value}
|
||
</p>
|
||
</div>
|
||
)
|
||
}
|