File size: 4,299 Bytes
6cf508e
 
f50471e
6cf508e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77b8fea
eaa9a6e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6cf508e
 
515abf6
 
6cf508e
 
 
 
 
 
 
515abf6
6cf508e
 
 
 
 
 
 
515abf6
 
6cf508e
 
515abf6
6cf508e
 
515abf6
 
6cf508e
 
515abf6
6cf508e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
eaa9a6e
6cf508e
eaa9a6e
6cf508e
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
'use client';

import { createContext, useContext, useEffect, useState, ReactNode } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { WEB_VERSION } from '@/lib/config';

// Create Context
const LoadingContext = createContext<{
    loading: boolean;
    setLoading: (state: boolean) => void;
} | null>(null);

// Custom Hook
export function useLoading() {
    const context = useContext(LoadingContext);
    if (!context) {
        throw new Error('useLoading must be used within a LoadingProvider');
    }
    return context;
}

// Provider Component
export function LoadingProvider({ children }: { children: ReactNode }) {
    const [loading, setLoading] = useState(false);
    const [message, setMessage] = useState('Getting things ready for you');

    useEffect(() => {
        let interval: NodeJS.Timeout;
        let dotCount = 0;

        function loadingMessage() {
            setMessage(`Getting things ready for you ${'.'.repeat(dotCount)}`);
            dotCount = (dotCount + 1) % 4;
        }

        interval = setInterval(loadingMessage, 300);

        return () => clearInterval(interval);
    }, []);

    return (
        <LoadingContext.Provider value={{ loading, setLoading }}>
            <AnimatePresence mode="wait">
                {loading && (
                    <motion.div
                        initial={{ opacity: 1 }}
                        exit={{ opacity: 0 }}
                        transition={{ duration: 0.6, ease: 'easeInOut' }}
                        className="fixed inset-0 z-50 flex items-center justify-center bg-gray-900"
                    >
                        <div className="relative flex flex-col items-center">
                            {/* Logo Animation */}
                            <motion.div
                                initial={{ scale: 0.5, opacity: 0 }}
                                animate={{ scale: 1, opacity: 1 }}
                                transition={{ duration: 0.6, ease: 'easeOut' }}
                                className="mb-8"
                            >
                                <div className="w-44 h-44 relative ">
                                    <div className="animate-pulse absolute inset-0 bg-gradient-to-r from-purple-600 to-pink-600 rounded-2xl" />

                                    {/* Inner Background */}
                                    <div className="animate-pulse absolute inset-1 bg-gray-800 rounded-xl" />

                                    {/* Text */}
                                    <div className="absolute inset-0 flex-col items-center text-center flex justify-items-center justify-center">
                                        <span className="text-4xl font-bold bg-gradient-to-r from-purple-500 to-pink-500 bg-clip-text text-transparent drop-shadow-lg">
                                            NEXORA
                                        </span>
                                        <p className="text-gray-300 font-mono">{WEB_VERSION}</p>
                                    </div>
                                </div>
                            </motion.div>

                            {/* Loading Bar */}
                            <motion.div
                                initial={{ width: 0 }}
                                animate={{ width: '150px' }}
                                transition={{ duration: 1.5, repeat: Infinity, ease: 'easeInOut' }}
                                className="animate-pulse h-1 bg-gradient-to-r m from-purple-500 to-pink-500 rounded-full"
                            />

                            {/* Loading Text */}
                            <motion.p
                                initial={{ opacity: 0, y: 10 }}
                                animate={{ opacity: 1, y: 0 }}
                                transition={{ delay: 0.5, ease: 'easeOut' }}
                                className="mt-6 text-gray-300 text-sm font-mono tracking-wide"
                            >
                                {message}
                            </motion.p>
                        </div>
                    </motion.div>
                )}
            </AnimatePresence>
            {children}
        </LoadingContext.Provider>
    );
}