aethex-us/contribute/src/components/LoadingScreen.jsx

130 lines
No EOL
4.2 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import AeThexLogo from '@/components/AeThexLogo';
const BinaryDigit = () => {
const [position, setPosition] = useState({
top: `${Math.random() * 100}%`,
left: `${Math.random() * 100}%`,
});
const duration = Math.random() * 5 + 5; // 5 to 10 seconds
return (
<motion.span
className="absolute text-primary/20 text-xs font-mono"
style={{ ...position }}
initial={{ opacity: 0 }}
animate={{ opacity: [0, 1, 0] }}
transition={{ duration, repeat: Infinity, ease: "linear" }}
>
{Math.round(Math.random())}
</motion.span>
);
};
const DataFallBar = ({ i }) => {
const height = Math.random() * 24 + 8;
const duration = Math.random() * 0.5 + 0.8;
return (
<motion.div
className="w-1.5 bg-gradient-to-t from-primary/50 to-purple-600/50"
style={{ height: `${height}px`, opacity: 0 }}
animate={{
y: [0, 48],
opacity: [1, 0],
}}
transition={{
duration,
repeat: Infinity,
ease: 'linear',
delay: i * 0.15 + Math.random() * 0.5,
}}
/>
);
};
const LoadingScreen = () => {
const [progress, setProgress] = useState(0);
const [text, setText] = useState("Initializing AeThex OS...");
useEffect(() => {
let currentProgress = 0;
const interval = setInterval(() => {
currentProgress += 1;
if (currentProgress > 98) {
currentProgress = 98;
}
setProgress(currentProgress);
if (currentProgress > 60 && currentProgress < 80) {
setText("Calibrating systems...");
} else if (currentProgress >= 80) {
setText("Booting interface...");
}
}, 40);
return () => clearInterval(interval);
}, []);
return (
<div className="flex items-center justify-center min-h-screen bg-[#06080d] overflow-hidden relative">
<AnimatePresence>
<>
{Array.from({ length: 30 }).map((_, i) => (
<BinaryDigit key={i} />
))}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.5 }}
className="flex flex-col items-center gap-8 z-10 w-full max-w-sm px-4"
>
<motion.div
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, ease: "easeOut" }}
className="relative"
>
<div className="absolute -inset-2 bg-primary/20 rounded-[28px] blur-xl opacity-75"></div>
<div className="relative w-24 h-24 bg-slate-900/50 rounded-3xl flex items-center justify-center border border-primary/20 backdrop-blur-sm p-4">
<AeThexLogo className="h-full" hideText />
</div>
</motion.div>
<div className="flex justify-center items-start h-12 w-24 overflow-hidden relative -mt-4">
<div className="absolute top-0 flex justify-center items-start gap-1">
{Array.from({ length: 9 }).map((_, i) => (
<DataFallBar key={i} i={i} />
))}
</div>
</div>
<div className="w-full max-w-xs -mt-4">
<div className="h-1.5 bg-slate-800 rounded-full overflow-hidden">
<motion.div
className="h-full bg-gradient-to-r from-primary to-purple-500 rounded-full"
initial={{ width: 0 }}
animate={{ width: `${progress}%` }}
transition={{ duration: 0.1, ease: "linear" }}
/>
</div>
<p className="text-center text-sm text-gray-400 font-mono mt-2 tracking-widest">{progress}%</p>
</div>
<div className="text-center font-mono h-16">
<p className="text-lg text-primary">{text}</p>
<p className="text-sm text-gray-500 mt-1">Please wait while we prepare your experience...</p>
</div>
</motion.div>
</>
</AnimatePresence>
</div>
);
};
export default LoadingScreen;