update
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { usePathname } from "next/navigation";
|
||||
import Image from "next/image";
|
||||
import "./Preloader.css";
|
||||
|
||||
interface PreloaderProps {
|
||||
children: React.ReactNode;
|
||||
@@ -9,377 +10,140 @@ interface PreloaderProps {
|
||||
|
||||
const Preloader = ({ children }: PreloaderProps) => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
const [progress, setProgress] = useState(0);
|
||||
const [currentPath, setCurrentPath] = useState("");
|
||||
const pathname = usePathname();
|
||||
|
||||
// Debug mode - set to true to see console logs
|
||||
const DEBUG = false;
|
||||
|
||||
// Skip preloader for faster development/testing (set to true to disable preloader)
|
||||
const SKIP_PRELOADER = false;
|
||||
|
||||
// Fast mode - set to true for even faster loading (200ms total)
|
||||
const FAST_MODE = true;
|
||||
|
||||
// Initial mount - show preloader on first load
|
||||
useEffect(() => {
|
||||
// Only show preloader if path has changed or it's initial load
|
||||
if (currentPath !== pathname) {
|
||||
if (DEBUG) console.log('Preloader: Starting transition from', currentPath, 'to', pathname);
|
||||
setIsLoading(true);
|
||||
setProgress(0);
|
||||
|
||||
// Simulate loading progress - faster and more responsive
|
||||
const progressInterval = setInterval(() => {
|
||||
setProgress((prev) => {
|
||||
if (prev >= 85) {
|
||||
clearInterval(progressInterval);
|
||||
return 85;
|
||||
}
|
||||
return prev + Math.random() * 25 + 10; // Faster progress increments
|
||||
});
|
||||
}, 50); // Reduced interval from 100ms to 50ms for smoother animation
|
||||
setIsMounted(true);
|
||||
setIsLoading(true);
|
||||
setProgress(0);
|
||||
|
||||
// Simulate loading progress
|
||||
const progressInterval = setInterval(() => {
|
||||
setProgress((prev) => {
|
||||
if (prev >= 90) {
|
||||
clearInterval(progressInterval);
|
||||
return 90;
|
||||
}
|
||||
return prev + Math.random() * 15 + 5;
|
||||
});
|
||||
}, 50);
|
||||
|
||||
// Complete loading much faster - adjust timing based on FAST_MODE
|
||||
const loadingDuration = FAST_MODE ? 200 : 400;
|
||||
const fadeOutDuration = FAST_MODE ? 50 : 100;
|
||||
|
||||
const completeTimer = setTimeout(() => {
|
||||
setProgress(100);
|
||||
setTimeout(() => {
|
||||
if (DEBUG) console.log('Preloader: Transition complete');
|
||||
setIsLoading(false);
|
||||
setCurrentPath(pathname);
|
||||
}, fadeOutDuration);
|
||||
}, loadingDuration);
|
||||
|
||||
// Fallback: Force complete after reasonable time
|
||||
const fallbackDuration = FAST_MODE ? 800 : 1500;
|
||||
const fallbackTimer = setTimeout(() => {
|
||||
if (DEBUG) console.log('Preloader: Fallback triggered - force completing');
|
||||
// Complete loading after minimum duration
|
||||
const completeTimer = setTimeout(() => {
|
||||
setProgress(100);
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
setCurrentPath(pathname);
|
||||
setProgress(100);
|
||||
}, fallbackDuration);
|
||||
}, 200);
|
||||
}, 600);
|
||||
|
||||
return () => {
|
||||
clearInterval(progressInterval);
|
||||
clearTimeout(completeTimer);
|
||||
clearTimeout(fallbackTimer);
|
||||
};
|
||||
}
|
||||
}, [pathname, currentPath, DEBUG, FAST_MODE]);
|
||||
return () => {
|
||||
clearInterval(progressInterval);
|
||||
clearTimeout(completeTimer);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Skip preloader entirely if SKIP_PRELOADER is true
|
||||
if (SKIP_PRELOADER) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
// Handle route changes
|
||||
useEffect(() => {
|
||||
if (!isMounted) return;
|
||||
|
||||
// Don't show preloader if not loading
|
||||
if (!isLoading) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
// Show preloader on route change
|
||||
setIsLoading(true);
|
||||
setProgress(0);
|
||||
|
||||
// Simulate loading progress
|
||||
const progressInterval = setInterval(() => {
|
||||
setProgress((prev) => {
|
||||
if (prev >= 90) {
|
||||
clearInterval(progressInterval);
|
||||
return 90;
|
||||
}
|
||||
return prev + Math.random() * 20 + 10;
|
||||
});
|
||||
}, 40);
|
||||
|
||||
// Complete loading
|
||||
const completeTimer = setTimeout(() => {
|
||||
setProgress(100);
|
||||
setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
}, 150);
|
||||
}, 400);
|
||||
|
||||
return () => {
|
||||
clearInterval(progressInterval);
|
||||
clearTimeout(completeTimer);
|
||||
};
|
||||
}, [pathname, isMounted]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="preloader-overlay">
|
||||
<div className="preloader-container">
|
||||
{/* Logo with shine effect */}
|
||||
<div className="preloader-logo">
|
||||
<div className="logo-wrapper">
|
||||
<Image
|
||||
src="/images/logo.png"
|
||||
alt="GNX Logo"
|
||||
width={80}
|
||||
height={60}
|
||||
className="logo-image"
|
||||
priority
|
||||
/>
|
||||
<div className="shine-effect"></div>
|
||||
{isLoading && (
|
||||
<div className="gnx-preloader-overlay">
|
||||
{/* Geometric background pattern */}
|
||||
<div className="gnx-preloader-bg-pattern"></div>
|
||||
|
||||
<div className="gnx-preloader-container">
|
||||
{/* Logo with professional wrapper */}
|
||||
<div className="gnx-preloader-logo">
|
||||
<div className="gnx-logo-wrapper">
|
||||
<div className="gnx-logo-border"></div>
|
||||
<Image
|
||||
src="/images/logo.png"
|
||||
alt="GNX Logo"
|
||||
width={100}
|
||||
height={75}
|
||||
className="gnx-logo-image"
|
||||
priority
|
||||
unoptimized
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Enterprise branding */}
|
||||
<div className="gnx-enterprise-brand">
|
||||
<h1 className="gnx-brand-title">GNX Enterprise</h1>
|
||||
<p className="gnx-brand-subtitle">Digital Transformation Solutions</p>
|
||||
</div>
|
||||
|
||||
{/* Professional progress indicator */}
|
||||
<div className="gnx-progress-container">
|
||||
<div className="gnx-progress-bar">
|
||||
<div
|
||||
className="gnx-progress-fill"
|
||||
style={{ width: `${progress}%` }}
|
||||
>
|
||||
<div className="gnx-progress-shine"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="gnx-progress-info">
|
||||
<span className="gnx-progress-text">Loading</span>
|
||||
<span className="gnx-progress-percentage">{Math.round(progress)}%</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Professional loading indicator */}
|
||||
<div className="gnx-loading-indicator">
|
||||
<div className="gnx-spinner">
|
||||
<div className="gnx-spinner-ring"></div>
|
||||
<div className="gnx-spinner-ring"></div>
|
||||
<div className="gnx-spinner-ring"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Corporate footer */}
|
||||
<div className="gnx-preloader-footer">
|
||||
<p className="gnx-footer-text">Powered by Advanced Technology</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Progress bar */}
|
||||
<div className="progress-container">
|
||||
<div className="progress-bar">
|
||||
<div
|
||||
className="progress-fill"
|
||||
style={{ width: `${progress}%` }}
|
||||
></div>
|
||||
</div>
|
||||
<div className="progress-text">{Math.round(progress)}%</div>
|
||||
</div>
|
||||
|
||||
{/* Loading text */}
|
||||
<div className="loading-text">
|
||||
<span className="loading-dots">
|
||||
<span>.</span>
|
||||
<span>.</span>
|
||||
<span>.</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Enterprise tagline */}
|
||||
<div className="enterprise-tagline">
|
||||
<span>Enterprise Solutions</span>
|
||||
<span>Excellence in Every Project</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<style jsx>{`
|
||||
.preloader-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0f0f0f 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.preloader-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.preloader-logo {
|
||||
position: relative;
|
||||
animation: logoFloat 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.logo-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
padding: 1.5rem;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
overflow: hidden;
|
||||
transition: all 0.2s ease; /* Faster transitions */
|
||||
}
|
||||
|
||||
.logo-image {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
filter: brightness(1.1);
|
||||
transition: all 0.2s ease; /* Faster transitions */
|
||||
}
|
||||
|
||||
.shine-effect {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
rgba(255, 255, 255, 0.4),
|
||||
transparent
|
||||
);
|
||||
animation: shine 2s infinite;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.progress-container {
|
||||
width: 200px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 3px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #4f46e5, #7c3aed, #ec4899);
|
||||
border-radius: 2px;
|
||||
transition: width 0.2s ease; /* Faster progress bar animation */
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-fill::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
rgba(255, 255, 255, 0.6),
|
||||
transparent
|
||||
);
|
||||
animation: progressShine 1.5s infinite;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 0.875rem;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
.loading-dots {
|
||||
display: inline-flex;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.loading-dots span {
|
||||
animation: dotPulse 1.4s infinite ease-in-out;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
.loading-dots span:nth-child(1) {
|
||||
animation-delay: -0.32s;
|
||||
}
|
||||
|
||||
.loading-dots span:nth-child(2) {
|
||||
animation-delay: -0.16s;
|
||||
}
|
||||
|
||||
.loading-dots span:nth-child(3) {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.enterprise-tagline {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
margin-top: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.enterprise-tagline span {
|
||||
font-size: 0.75rem;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
font-weight: 300;
|
||||
letter-spacing: 0.15em;
|
||||
text-transform: uppercase;
|
||||
animation: fadeInUp 0.8s ease-out 0.5s both;
|
||||
}
|
||||
|
||||
.enterprise-tagline span:first-child {
|
||||
animation-delay: 0.7s;
|
||||
}
|
||||
|
||||
.enterprise-tagline span:last-child {
|
||||
animation-delay: 0.9s;
|
||||
}
|
||||
|
||||
@keyframes logoFloat {
|
||||
0%, 100% {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shine {
|
||||
0% {
|
||||
left: -100%;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes progressShine {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dotPulse {
|
||||
0%, 80%, 100% {
|
||||
opacity: 0.3;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
40% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.preloader-container {
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.logo-wrapper {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.logo-image {
|
||||
width: 60px;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
.progress-container {
|
||||
width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.preloader-container {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.logo-wrapper {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
.logo-image {
|
||||
width: 50px;
|
||||
height: 37px;
|
||||
}
|
||||
|
||||
.progress-container {
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
<div className={isLoading ? "gnx-content-hidden" : "gnx-content-visible"}>
|
||||
{children}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user