Convert backends to Firebase and combine projects
This commit is contained in:
100
RIT-EVENT-MANAGEMENT--main/components/StatsSection.tsx
Normal file
100
RIT-EVENT-MANAGEMENT--main/components/StatsSection.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { motion } from 'motion/react';
|
||||
import { Event } from '../types';
|
||||
|
||||
interface StatsSectionProps {
|
||||
events: Event[];
|
||||
}
|
||||
|
||||
const StatsSection: React.FC<StatsSectionProps> = ({ events }) => {
|
||||
const [counts, setCounts] = useState({
|
||||
nonTechnical: 0,
|
||||
technical: 0,
|
||||
workshops: 0,
|
||||
totalEvents: 0
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (events) {
|
||||
const nonTech = events.filter(e => e.category === 'NON-TECHNICAL').length;
|
||||
const tech = events.filter(e => e.category === 'TECHNICAL').length;
|
||||
const workshops = events.filter(e => e.category === 'WORKSHOP').length;
|
||||
|
||||
setCounts({
|
||||
nonTechnical: nonTech,
|
||||
technical: tech,
|
||||
workshops: workshops,
|
||||
totalEvents: events.length
|
||||
});
|
||||
}
|
||||
}, [events]);
|
||||
|
||||
const stats = [
|
||||
{
|
||||
label: "Active Non-Tech Events",
|
||||
value: counts.nonTechnical,
|
||||
suffix: "+",
|
||||
delay: 0.1
|
||||
},
|
||||
{
|
||||
label: "Technical Events",
|
||||
value: counts.technical,
|
||||
suffix: "+",
|
||||
delay: 0.2
|
||||
},
|
||||
{
|
||||
label: "Workshops",
|
||||
value: counts.workshops,
|
||||
suffix: "+",
|
||||
delay: 0.3
|
||||
},
|
||||
{
|
||||
label: "Total Events",
|
||||
value: counts.totalEvents,
|
||||
suffix: "+",
|
||||
delay: 0.4
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<section className="w-full bg-[#F9FAFB] py-12 px-6 md:px-12 lg:px-20">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{stats.map((stat, index) => (
|
||||
<motion.div
|
||||
key={index}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.5, delay: stat.delay }}
|
||||
viewport={{ once: true }}
|
||||
className="bg-white p-8 rounded-2xl shadow-sm hover:shadow-md transition-shadow duration-300 border border-gray-100 relative overflow-hidden group"
|
||||
>
|
||||
{/* Corner accents similar to the image */}
|
||||
<div className="absolute top-2 right-2 opacity-50 transform rotate-90">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 19V5C1 2.79086 2.79086 1 5 1H19" stroke="#f97316" strokeWidth="2" strokeLinecap="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="absolute bottom-2 left-2 opacity-50 transform -rotate-90">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 19V5C1 2.79086 2.79086 1 5 1H19" stroke="#f97316" strokeWidth="2" strokeLinecap="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center justify-center text-center z-10 relative">
|
||||
<h3 className="text-4xl md:text-5xl font-bold text-[#2D3748] mb-2 font-serif group-hover:text-[#f97316] transition-colors duration-300">
|
||||
{stat.value}{stat.suffix}
|
||||
</h3>
|
||||
<p className="text-gray-500 font-medium text-sm uppercase tracking-wider">
|
||||
{stat.label}
|
||||
</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatsSection;
|
||||
Reference in New Issue
Block a user