personal_website/src/pages/Index.tsx
gpt-engineer-app[bot] 427e2b22ee Changes
2025-12-07 18:17:33 +00:00

149 lines
5.2 KiB
TypeScript

import { useState, useEffect, lazy, Suspense } from 'react';
import { useLocation } from 'react-router-dom';
import MatrixRain from '@/components/MatrixRain';
import LoadingScreen from '@/components/LoadingScreen';
import MainLayout from '@/components/MainLayout';
import MatrixCursor from '@/components/MatrixCursor';
import { VERIFIED_KEY, BYPASS_KEY } from '@/components/HumanVerification';
import { useSettings } from '@/contexts/SettingsContext';
import { useAchievements } from '@/contexts/AchievementsContext';
import { useKonamiCode } from '@/hooks/useKonamiCode';
import { toast } from '@/hooks/use-toast';
// Lazy load conditionally rendered components to reduce initial bundle
const HumanVerification = lazy(() => import('@/components/HumanVerification'));
const MusicPlayer = lazy(() => import('@/components/MusicPlayer'));
const SettingsPanel = lazy(() => import('@/components/SettingsPanel'));
const CryptoConsentModal = lazy(() => import('@/components/CryptoConsentModal'));
const TerminalCommand = lazy(() => import('@/components/TerminalCommand'));
const Index = () => {
const [isVerified, setIsVerified] = useState(() => {
// Check localStorage or bypass URL
if (localStorage.getItem(VERIFIED_KEY) === 'true') return true;
const params = new URLSearchParams(window.location.search);
if (params.has(BYPASS_KEY) || window.location.pathname.includes(BYPASS_KEY)) return true;
return false;
});
const [isLoading, setIsLoading] = useState(true);
const [isRedTheme, setIsRedTheme] = useState(() => {
const saved = localStorage.getItem('themeColor');
// Default to red theme unless explicitly set to green
return saved !== 'green';
});
const [showConsentModal, setShowConsentModal] = useState(false);
const [konamiActive, setKonamiActive] = useState(false);
const { crtEnabled, playSound } = useSettings();
const { unlockAchievement } = useAchievements();
const { activated: konamiActivated, reset: resetKonami } = useKonamiCode();
const location = useLocation();
// Hide mini music player when on the full music page (to avoid UI duplication)
// but audio continues playing via MusicContext
const showMiniPlayer = location.pathname !== '/music';
// Handle Konami code activation
useEffect(() => {
if (konamiActivated) {
setKonamiActive(true);
// Unlock achievement
unlockAchievement('konami_master');
// Play special sound sequence
playSound('success');
setTimeout(() => playSound('boot'), 200);
setTimeout(() => playSound('success'), 400);
// Show secret toast
toast({
title: "🎮 KONAMI CODE ACTIVATED",
description: "You found the secret! You are a true hacker.",
});
// Reset after animation
setTimeout(() => {
setKonamiActive(false);
resetKonami();
}, 3000);
}
}, [konamiActivated, playSound, resetKonami, unlockAchievement]);
// Persist theme to localStorage
useEffect(() => {
localStorage.setItem('themeColor', isRedTheme ? 'red' : 'green');
}, [isRedTheme]);
useEffect(() => {
const timer = setTimeout(() => {
setIsLoading(false);
// Show consent modal after loading if user hasn't made a choice yet
const hasSeenConsent = localStorage.getItem('cryptoConsentSeen');
if (!hasSeenConsent) {
setShowConsentModal(true);
}
}, 3000); // Extended to 3s for boot sequence
return () => clearTimeout(timer);
}, []);
useEffect(() => {
if (isRedTheme) {
document.documentElement.classList.add('red-theme');
document.body.classList.add('red-theme');
} else {
document.documentElement.classList.remove('red-theme');
document.body.classList.remove('red-theme');
}
}, [isRedTheme]);
const toggleTheme = () => {
setIsRedTheme(!isRedTheme);
playSound('click');
unlockAchievement('theme_switcher');
};
const handleConsentClose = () => {
localStorage.setItem('cryptoConsentSeen', 'true');
setShowConsentModal(false);
};
// Show verification gate if not verified
if (!isVerified) {
return (
<div className={`min-h-screen overflow-x-hidden ${crtEnabled ? 'crt' : ''}`}>
<MatrixRain color={isRedTheme ? '#FF0000' : '#00FF00'} />
<Suspense fallback={null}>
<HumanVerification onVerified={() => setIsVerified(true)} />
</Suspense>
</div>
);
}
return (
<div className={`min-h-screen overflow-x-hidden ${crtEnabled ? 'crt' : ''} ${konamiActive ? 'konami-active' : ''}`}>
<MatrixCursor />
<MatrixRain color={isRedTheme ? '#FF0000' : '#00FF00'} />
<LoadingScreen isLoading={isLoading} />
{/* Moving scanline - only visible when CRT is enabled */}
<div className="moving-scanline" />
{!isLoading && (
<Suspense fallback={null}>
<CryptoConsentModal isOpen={showConsentModal} onClose={handleConsentClose} />
<SettingsPanel onToggleTheme={toggleTheme} isRedTheme={isRedTheme} />
<TerminalCommand />
<div className="relative z-10 flex flex-col items-center min-h-screen pb-16">
<MainLayout />
</div>
{showMiniPlayer && <MusicPlayer />}
</Suspense>
)}
</div>
);
};
export default Index;