import { cn } from '@/lib/utils'; import { ChevronLeft, ChevronRight, Plus } from 'lucide-react'; import { useEffect, useState } from 'react'; interface LedCounterProps { value: number; className?: string; animate?: boolean; currentPrice?: number; onHover?: (isHovered: boolean) => void; // Progress bar props onStatsToggle?: () => void; showStats?: boolean; onAddPurchase?: () => void; } export default function LedCounter({ value, className, animate = true, currentPrice, onHover, onStatsToggle, showStats = false, onAddPurchase }: LedCounterProps) { const [displayValue, setDisplayValue] = useState(0); const [isHovered, setIsHovered] = useState(false); const [hoverTimeout, setHoverTimeout] = useState(null); const [currentMilestoneIndex, setCurrentMilestoneIndex] = useState(0); // Milestone definitions const milestones = [ { target: 1500, label: '1.5K', color: 'bg-blue-500' }, { target: 3000, label: '3K', color: 'bg-green-500' }, { target: 4500, label: '4.5K', color: 'bg-yellow-500' }, { target: 6000, label: '6K', color: 'bg-red-500' }, ]; const currentMilestone = milestones[currentMilestoneIndex]; const progress = Math.min((value / currentMilestone.target) * 100, 100); const isCompleted = value >= currentMilestone.target; // Milestone navigation const nextMilestone = () => { setCurrentMilestoneIndex((prev) => prev < milestones.length - 1 ? prev + 1 : 0 ); }; const prevMilestone = () => { setCurrentMilestoneIndex((prev) => prev > 0 ? prev - 1 : milestones.length - 1 ); }; const handleProgressBarClick = () => { if (onStatsToggle) { onStatsToggle(); } }; // Animate number changes useEffect(() => { if (!animate) { setDisplayValue(value); return; } const duration = 1000; // 1 second animation const steps = 60; // 60fps const stepValue = (value - displayValue) / steps; if (Math.abs(stepValue) < 0.01) { setDisplayValue(value); return; } const timer = setInterval(() => { setDisplayValue(prev => { const next = prev + stepValue; if (Math.abs(next - value) < Math.abs(stepValue)) { clearInterval(timer); return value; } return next; }); }, duration / steps); return () => clearInterval(timer); }, [value, displayValue, animate]); // Format number appropriately for shares const formatValue = (value: number) => { // If it's a whole number, show it as integer if (value % 1 === 0) { return value.toString(); } // Otherwise show up to 6 decimal places, removing trailing zeros return value.toFixed(6).replace(/\.?0+$/, ''); }; const formattedValue = formatValue(displayValue); const formatCurrency = (amount: number) => { return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR', minimumFractionDigits: 4, }).format(amount); }; return (
{ if (hoverTimeout) { clearTimeout(hoverTimeout); setHoverTimeout(null); } setIsHovered(true); if (onHover) onHover(true); }} onMouseLeave={() => { // Delay hiding to allow moving to progress bar const timeout = setTimeout(() => { setIsHovered(false); if (onHover) onHover(false); }, 300); // 300ms delay setHoverTimeout(timeout); }} >
{/* Background glow effect */}
{formattedValue}
{/* Main LED text */}
{formattedValue}
{/* Subtle scan line effect */}
{/* Label */}
total shares
{/* Hover overlay with price and add button */}
{/* Current Price Display */} {currentPrice ? (
current price
{formatCurrency(currentPrice)}
) : (
no price data
)}
{/* Progress Bar - shows when hovered */}
{/* Progress Bar */}
{/* Background pulse for completed milestones */} {isCompleted && (
)} {/* Progress fill */}
{/* Glow effect */}
{/* Milestone Info */}
{/* Left: Previous milestone button */} {/* Center: Milestone info */}
{value.toFixed(2)} / {currentMilestone.target}
{currentMilestone.label}
{isCompleted ? 'COMPLETED' : `${(100 - progress).toFixed(1)}% TO GO`}
{/* Right: Add Purchase, Next milestone button and stats toggle */}
{/* Add Purchase Button */} {onAddPurchase && ( )} {/* Stats indicator */}
{showStats ? '▲' : '▼'}
); }