Initial commit from remix

This commit is contained in:
gpt-engineer-app[bot]
2025-09-25 16:01:00 +00:00
commit 5ddc52658d
149 changed files with 32798 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
import { useEffect, useRef } from 'react';
import CountUp from 'react-countup';
interface CounterCardProps {
icon: React.ReactNode;
title: string;
value: number;
suffix?: string;
trend?: number;
color?: string;
}
const CounterCard: React.FC<CounterCardProps> = ({
icon,
title,
value,
suffix = '',
trend,
color = '#F84525'
}) => {
const cardRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!('IntersectionObserver' in window)) return;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
(entry.target as Element).classList.add('animate-fade-in-up');
}
});
},
{ threshold: 0.1 }
);
try {
if (cardRef.current && cardRef.current instanceof Element) {
observer.observe(cardRef.current);
}
} catch (e) {
console.warn('IntersectionObserver.observe failed:', e);
}
return () => observer.disconnect();
}, []);
return (
<div
ref={cardRef}
className="card-enhanced widget-card position-relative overflow-hidden"
style={{ minHeight: '140px' }}
>
<div className="card-body p-4">
<div className="d-flex align-items-center justify-content-between">
<div className="flex-grow-1">
<div className="d-flex align-items-center mb-2">
<div
className="rounded-circle p-2 me-3"
style={{ backgroundColor: `${color}20`, color: color }}
>
{icon}
</div>
<h6 className="text-muted mb-0 small">{title}</h6>
</div>
<div className="d-flex align-items-center">
<h3 className="mb-0 fw-bold me-2" style={{ color: color }}>
<CountUp
start={0}
end={value}
duration={2.5}
separator=","
suffix={suffix}
/>
</h3>
{trend && (
<span
className={`badge ${trend > 0 ? 'bg-success' : 'bg-danger'} d-flex align-items-center`}
style={{ fontSize: '10px' }}
>
<i className={`bi bi-arrow-${trend > 0 ? 'up' : 'down'} me-1`}></i>
{Math.abs(trend)}%
</span>
)}
</div>
</div>
<div
className="rounded-circle d-flex align-items-center justify-content-center"
style={{
width: '60px',
height: '60px',
backgroundColor: `${color}10`,
color: color
}}
>
{icon}
</div>
</div>
</div>
{/* Animated background element */}
<div
className="position-absolute"
style={{
bottom: '-20px',
right: '-20px',
width: '80px',
height: '80px',
borderRadius: '50%',
backgroundColor: `${color}08`,
opacity: 0.3
}}
></div>
</div>
);
};
export default CounterCard;