incr/resources/js/components/Display/LedDisplay.tsx

61 lines
1.7 KiB
TypeScript
Raw Normal View History

2025-07-12 19:59:22 +02:00
import { cn } from '@/lib/utils';
import { useEffect, useState } from 'react';
interface LedDisplayProps {
value: number;
className?: string;
animate?: boolean;
onClick?: () => void;
}
2025-07-13 00:03:34 +02:00
export default function LedDisplay({
value,
className,
2025-07-12 19:59:22 +02:00
onClick
}: LedDisplayProps) {
const [displayValue, setDisplayValue] = useState(0);
// Animate number changes
useEffect(() => {
2025-07-13 00:03:34 +02:00
setDisplayValue(value);
return;
}, [value]);
2025-07-12 19:59:22 +02:00
2025-07-13 00:03:34 +02:00
// Format number with zero-padding for consistent width
2025-07-12 19:59:22 +02:00
const formatValue = (value: number) => {
2025-07-13 00:03:34 +02:00
// Always pad to 5 digits for consistent display width
const integerPart = Math.floor(value);
return integerPart.toString().padStart(5, '0');
2025-07-12 19:59:22 +02:00
};
2025-07-13 00:03:34 +02:00
2025-07-12 19:59:22 +02:00
const formattedValue = formatValue(displayValue);
return (
2025-07-13 00:03:34 +02:00
<div
2025-07-12 19:59:22 +02:00
className={cn(
2025-07-13 00:03:34 +02:00
"w-full text-center select-none cursor-pointer",
2025-07-12 19:59:22 +02:00
"bg-black text-red-500",
2025-07-13 00:03:34 +02:00
"px-8 py-12 transition-all duration-300",
2025-07-12 19:59:22 +02:00
className
)}
onClick={onClick}
>
2025-07-13 00:03:34 +02:00
<div className="relative w-full flex items-center justify-center">
2025-07-12 19:59:22 +02:00
<div className={cn(
"relative z-10",
2025-07-13 00:03:34 +02:00
"text-[8rem] md:text-[12rem] lg:text-[16rem]",
"font-digital font-normal",
2025-07-12 19:59:22 +02:00
"text-red-500",
"drop-shadow-[0_0_10px_rgba(239,68,68,0.8)]",
2025-07-13 00:03:34 +02:00
"filter brightness-110",
"leading-none",
"transition-all duration-300"
)}
style={{ letterSpacing: '0.15em' }}>
2025-07-12 19:59:22 +02:00
{formattedValue}
</div>
</div>
</div>
);
2025-07-13 00:03:34 +02:00
}