57 lines
1.9 KiB
TypeScript
57 lines
1.9 KiB
TypeScript
interface DigitalProgressBarProps {
|
|
current: number;
|
|
capacity: number;
|
|
projected?: number;
|
|
}
|
|
|
|
const BAR_COUNT = 20;
|
|
|
|
function getGlow(index: number): string {
|
|
if (index < 10) return '0 0 8px rgba(239, 68, 68, 0.6)';
|
|
if (index < BAR_COUNT - 1) return '0 0 8px rgba(249, 115, 22, 0.6)';
|
|
return '0 0 8px rgba(34, 197, 94, 0.6)';
|
|
}
|
|
|
|
function getBarColor(index: number): string {
|
|
if (index < 10) return 'bg-red-500';
|
|
if (index < BAR_COUNT - 1) return 'bg-orange-500';
|
|
return 'bg-green-500';
|
|
}
|
|
|
|
const PROJECTED_GLOW = '0 0 8px rgba(234, 179, 8, 0.6)';
|
|
|
|
export default function DigitalProgressBar({ current, capacity, projected }: DigitalProgressBarProps) {
|
|
const filledBars = capacity > 0
|
|
? Math.min(Math.round((current / capacity) * BAR_COUNT), BAR_COUNT)
|
|
: 0;
|
|
const projectedBars = capacity > 0 && projected
|
|
? Math.min(Math.round(((current + projected) / capacity) * BAR_COUNT), BAR_COUNT)
|
|
: filledBars;
|
|
|
|
return (
|
|
<div
|
|
style={{
|
|
display: 'grid',
|
|
gridTemplateColumns: `repeat(${BAR_COUNT}, 1fr)`,
|
|
gap: '10px',
|
|
height: '2rem',
|
|
}}
|
|
>
|
|
{Array.from({ length: BAR_COUNT }, (_, i) => {
|
|
const filled = i < filledBars;
|
|
const isProjected = !filled && i < projectedBars;
|
|
return (
|
|
<div
|
|
key={i}
|
|
style={{
|
|
borderRadius: '3px',
|
|
transition: 'background-color 300ms, box-shadow 300ms',
|
|
boxShadow: filled ? getGlow(i) : isProjected ? PROJECTED_GLOW : 'none',
|
|
}}
|
|
className={filled ? getBarColor(i) : isProjected ? 'bg-yellow-500' : 'bg-red-500/10'}
|
|
/>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|