Convert backends to Firebase and combine projects
This commit is contained in:
108
RIT-EVENT-MANAGEMENT--main/components/PortalAnimation.tsx
Normal file
108
RIT-EVENT-MANAGEMENT--main/components/PortalAnimation.tsx
Normal file
@@ -0,0 +1,108 @@
|
||||
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
|
||||
interface PortalAnimationProps {
|
||||
isVisible: boolean;
|
||||
onComplete: () => void;
|
||||
targetLink: string;
|
||||
}
|
||||
|
||||
const PortalAnimation: React.FC<PortalAnimationProps> = ({ isVisible, onComplete, targetLink }) => {
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
const [statusText, setStatusText] = useState("Initializing Port...");
|
||||
|
||||
useEffect(() => {
|
||||
if (isVisible) {
|
||||
// Sequence of status texts for a more high-tech feel
|
||||
const statusInterval = setInterval(() => {
|
||||
const texts = ["Synchronizing...", "Establishing Link...", "Calibrating Vortex...", "Dimensional Drift...", "Transmitting..."];
|
||||
setStatusText(prev => {
|
||||
const idx = texts.indexOf(prev);
|
||||
return texts[(idx + 1) % texts.length];
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
// 5-second delay for the high-quality transition
|
||||
const timer = setTimeout(() => {
|
||||
// Redirection logic starts - the page will unload
|
||||
// The overlay will naturally stay until the browser replaces the page
|
||||
window.location.href = targetLink;
|
||||
}, 5000);
|
||||
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
clearInterval(statusInterval);
|
||||
};
|
||||
}
|
||||
}, [isVisible, targetLink]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isVisible && videoRef.current) {
|
||||
videoRef.current.play().catch(err => console.error("Video play failed:", err));
|
||||
}
|
||||
}, [isVisible]);
|
||||
|
||||
if (!isVisible) return null;
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
// Using Fixed inset-0 and a massive z-index to cover EVERYTHING
|
||||
className="fixed inset-0 z-[999999] bg-black flex items-center justify-center overflow-hidden touch-none pointer-events-auto"
|
||||
>
|
||||
<div className="relative w-full h-full">
|
||||
{/* High-Quality Native Video - Absolute Full Screen */}
|
||||
<video
|
||||
ref={videoRef}
|
||||
src="/vortex.mp4"
|
||||
muted
|
||||
playsInline
|
||||
loop
|
||||
className="w-full h-full object-cover"
|
||||
style={{ width: '100vw', height: '100vh' }}
|
||||
/>
|
||||
|
||||
{/* Premium Overlay Filter */}
|
||||
<div className="absolute inset-0 bg-blue-900/20 mix-blend-overlay pointer-events-none"></div>
|
||||
|
||||
{/* Transition Status Text Overlay */}
|
||||
<div className="absolute inset-0 flex flex-col items-center justify-center pointer-events-none">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
className="text-center"
|
||||
>
|
||||
<div className="mb-4">
|
||||
<div className="w-64 h-[2px] bg-white/20 relative overflow-hidden mx-auto">
|
||||
<motion.div
|
||||
initial={{ x: "-100%" }}
|
||||
animate={{ x: "100%" }}
|
||||
transition={{ duration: 1.5, repeat: Infinity, ease: "linear" }}
|
||||
className="absolute inset-0 bg-orange-500 shadow-[0_0_10px_#f97316]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-[10px] font-black uppercase tracking-[0.8em] text-white/70">
|
||||
{statusText}
|
||||
</span>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
{/* Subliminal Transition Glow (Pulses just before redirect) */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: [0, 0, 0.6, 0] }}
|
||||
transition={{ duration: 5, times: [0, 0.85, 0.95, 1], ease: "easeInOut" }}
|
||||
className="absolute inset-0 bg-white pointer-events-none"
|
||||
/>
|
||||
</div>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
|
||||
export default PortalAnimation;
|
||||
Reference in New Issue
Block a user