Final commit

This commit is contained in:
2026-06-23 09:37:43 +05:30
parent 2c28c27120
commit 512c04bb6f
90 changed files with 26358 additions and 0 deletions

View File

@@ -0,0 +1,181 @@
import React, { useState, useEffect, useMemo } from 'react';
import type { Event, Announcement, SpecialEvent } from '../../types';
import { motion, AnimatePresence } from 'framer-motion';
import SpecialEventsBanner from './SpecialEventsBanner';
import AccreditationsSection from './AccreditationsSection';
interface HomeDashboardProps {
events: Event[];
announcements: Announcement[];
onNavigateToEvents: () => void;
specialEvents: SpecialEvent[];
settings?: Record<string, any>;
}
const HomeDashboard: React.FC<HomeDashboardProps> = ({
events = [],
announcements = [],
onNavigateToEvents,
specialEvents = [],
settings = {}
}) => {
const [now, setNow] = useState(new Date());
useEffect(() => {
const timer = setInterval(() => setNow(new Date()), 30000);
return () => clearInterval(timer);
}, []);
const filteredAnnouncements = useMemo(() => {
return (announcements || []).filter(ann => {
if (!ann.expiresAt) return true;
const expiry = new Date(ann.expiresAt);
return expiry > now;
});
}, [announcements, now]);
// Generate stable random values for rotation and color based on announcement ID
const getNoteStyle = (id: string) => {
// Simple hash function for stability
const hash = id.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
const rotations = [-2, -1, 1, 2, 3, -3];
const colors = [
'bg-[#fdfd96]', // Classic Yellow
'bg-[#ff7eb9]', // Hot Pink
'bg-[#7afcff]', // Light Blue
'bg-[#feff9c]', // Light Yellow
'bg-[#fff740]' // Darker Yellow
];
return {
rotation: rotations[hash % rotations.length],
color: colors[hash % colors.length]
};
};
return (
<div className="px-6 md:px-12 lg:px-24 py-12 bg-transparent animate-in fade-in duration-700">
<div
onClick={onNavigateToEvents}
className="relative w-full h-64 md:h-80 rounded-[2.5rem] overflow-hidden cursor-pointer group mb-12 shadow-xl shadow-gray-200/20 hover:shadow-2xl transition-all duration-500"
>
<div className="absolute inset-0 bg-black/40 group-hover:bg-black/30 transition-colors duration-500 z-10"></div>
<img
src="https://img.freepik.com/premium-photo/outdoor-music-festival-evening-ambiance-with-festive-lights-crowd_114541-6739.jpg"
alt="Events"
className="absolute inset-0 w-full h-full object-cover transition-transform duration-700 group-hover:scale-105"
/>
<div className="absolute inset-0 z-20 flex flex-col justify-center px-12 md:px-20">
<div className="transform transition-transform duration-500 group-hover:translate-x-2 space-y-4">
<h2 className="text-4xl md:text-6xl font-serif text-white font-bold tracking-tight drop-shadow-lg">
Let's get started
</h2>
<div className="flex items-center gap-3 text-white/90 group-hover:text-[#f97316] transition-colors w-fit">
<span className="text-sm font-bold uppercase tracking-widest bg-black/20 backdrop-blur-sm px-4 py-2 rounded-full border border-white/20 group-hover:bg-white group-hover:text-[#f97316] transition-all duration-300">
Explore Events <i className="fas fa-arrow-right ml-2"></i>
</span>
</div>
</div>
</div>
</div>
{/* Notice Board Section */}
<div className="w-full bg-[#e8e4c9] p-8 md:p-12 rounded-[2rem] shadow-2xl border-[12px] border-[#8d6e63] relative overflow-hidden min-h-[600px] mt-12">
{/* Cork texture pattern */}
<div className="absolute inset-0 opacity-30 bg-[url('https://www.transparenttextures.com/patterns/cork-board.png')] pointer-events-none"></div>
<div className="relative z-10 mb-12 flex flex-col md:flex-row items-start md:items-center justify-between gap-6 border-b-2 border-[#8d6e63]/20 pb-6">
<div>
<h2 className="text-4xl md:text-5xl font-serif text-[#3e2723] tracking-tight font-bold drop-shadow-sm mb-2">
Campus Notice Board
</h2>
<p className="text-[#5d4037] font-medium opacity-80">Real-time updates from the administration</p>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 md:gap-12 p-6">
<AnimatePresence mode="popLayout">
{filteredAnnouncements.length > 0 ? (
filteredAnnouncements.slice(0, 3).map((ann) => {
const style = getNoteStyle(ann.id);
return (
<motion.div
key={ann.id}
layout
initial={{ scale: 0.8, opacity: 0, y: 50, rotate: style.rotation + (Math.random() * 10 - 5) }}
animate={{ scale: 1, opacity: 1, y: 0, rotate: style.rotation }}
exit={{ scale: 0.8, opacity: 0, transition: { duration: 0.2 } }}
whileHover={{ scale: 1.05, rotate: 0, zIndex: 50, transition: { duration: 0.2 } }}
transition={{ type: "spring", stiffness: 300, damping: 20 }}
className={`${style.color} p-8 shadow-[4px_4px_10px_rgba(0,0,0,0.2)] hover:shadow-[15px_15px_30px_rgba(0,0,0,0.3)] transition-shadow duration-300 relative group cursor-pointer min-h-[300px] flex flex-col transform-gpu`}
>
{/* Pin */}
<div className="absolute -top-3 left-1/2 -translate-x-1/2 w-5 h-5 rounded-full bg-[#d32f2f] shadow-[2px_2px_4px_rgba(0,0,0,0.3)] z-20 border border-[#b71c1c] after:content-[''] after:absolute after:top-1 after:left-1 after:w-1.5 after:h-1.5 after:bg-white/50 after:rounded-full"></div>
<div className="mb-6 pt-2">
<span className={`text-xs font-black uppercase tracking-widest px-3 py-1.5 rounded-sm ${
ann.type === 'URGENT' ? 'bg-red-500/20 text-red-800' :
ann.type === 'DELAY' ? 'bg-amber-500/20 text-amber-800' :
'bg-black/5 text-gray-800'
}`}>
{ann.type || 'NOTICE'}
</span>
</div>
<h3 className="font-serif font-bold text-2xl text-gray-900 mb-4 leading-tight">
{ann.title}
</h3>
{(ann as any).image && (
<img
src={(ann as any).image}
alt={ann.title}
className="w-full h-40 object-cover rounded-xl mb-4 shrink-0 shadow-sm border border-black/10"
/>
)}
<p className="font-sans text-gray-800 text-base flex-grow mb-6 leading-relaxed opacity-90">
{ann.message}
</p>
<div className="mt-auto pt-4 border-t border-black/10 flex flex-col gap-2 text-[11px] font-bold text-gray-700 uppercase tracking-wider">
<div className="flex justify-between items-center">
<span className="flex items-center gap-2">
<i className="far fa-calendar-alt"></i>
{new Date(ann.timestamp).toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric' })}
</span>
<span className="flex items-center gap-2">
<i className="far fa-clock"></i>
{new Date(ann.timestamp).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}
</span>
</div>
{ann.expiresAt && <span className="text-red-700/70 text-right">Exp: {new Date(ann.expiresAt).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'})}</span>}
</div>
</motion.div>
);
})
) : (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="col-span-full flex flex-col items-center justify-center py-32 text-[#8d6e63]/50"
>
<i className="fas fa-thumbtack text-6xl mb-6 opacity-30 rotate-45"></i>
<p className="font-serif text-2xl font-bold">The board is empty right now.</p>
<p className="font-sans text-sm mt-2 uppercase tracking-widest">Check back later for updates</p>
</motion.div>
)}
</AnimatePresence>
</div>
</div>
<AccreditationsSection />
<SpecialEventsBanner specialEvents={specialEvents} />
</div>
);
};
export default HomeDashboard;