Initial commit gov-llm-v2
This commit is contained in:
164
App.tsx
Executable file
164
App.tsx
Executable file
@@ -0,0 +1,164 @@
|
||||
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import Hero from './components/Hero';
|
||||
import Infrastructure from './components/Infrastructure';
|
||||
import Science from './components/Science';
|
||||
import Social from './components/Social';
|
||||
import Leadership from './components/Leadership';
|
||||
import Metrics from './components/Metrics';
|
||||
import Scaling from './components/Scaling';
|
||||
import Team from './components/Team';
|
||||
import Timeline from './components/Timeline';
|
||||
import BootAnimation from './components/BootAnimation';
|
||||
import Modal from './components/Modal';
|
||||
import { ModalData } from './types';
|
||||
// import TechVisualizer from './components/TechVisualizer'; // Disabled per user request
|
||||
import { ArrowUp } from 'lucide-react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
|
||||
const App: React.FC = () => {
|
||||
const [isBooting, setIsBooting] = useState(true);
|
||||
const [showScrollTop, setShowScrollTop] = useState(false);
|
||||
const [modalData, setModalData] = useState<ModalData | null>(null);
|
||||
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Theme and Scroll Logic
|
||||
useEffect(() => {
|
||||
const container = scrollContainerRef.current;
|
||||
if (!container) return;
|
||||
|
||||
const handleScroll = () => {
|
||||
const scrollY = container.scrollTop;
|
||||
const windowHeight = window.innerHeight;
|
||||
|
||||
const leadershipSection = document.getElementById('leadership'); // Block 4
|
||||
const teamSection = document.getElementById('team');
|
||||
|
||||
// --- Theme Logic: Light mode starting from Leadership (Block 4) ---
|
||||
if (leadershipSection && teamSection) {
|
||||
// We use offsetTop relative to the container usually, but since sections are stacked
|
||||
// and container scrolls, standard offsetTop works if container is relative/static.
|
||||
const leadershipTrigger = leadershipSection.offsetTop - windowHeight * 0.6;
|
||||
const teamTrigger = teamSection.offsetTop - windowHeight * 0.8;
|
||||
|
||||
// Active Light Mode for Leadership, Metrics, Scaling. Back to Dark for Team.
|
||||
if (scrollY >= leadershipTrigger && scrollY < teamTrigger) {
|
||||
document.body.classList.add('theme-light');
|
||||
} else {
|
||||
document.body.classList.remove('theme-light');
|
||||
}
|
||||
}
|
||||
|
||||
if (scrollY > 300) setShowScrollTop(true);
|
||||
else setShowScrollTop(false);
|
||||
};
|
||||
|
||||
container.addEventListener('scroll', handleScroll);
|
||||
handleScroll(); // Trigger once on load
|
||||
|
||||
return () => {
|
||||
container.removeEventListener('scroll', handleScroll);
|
||||
document.body.classList.remove('theme-light');
|
||||
};
|
||||
}, [isBooting]);
|
||||
|
||||
const scrollToTop = () => {
|
||||
if (scrollContainerRef.current) {
|
||||
scrollContainerRef.current.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
};
|
||||
|
||||
const handleOpenModal = (data: ModalData) => {
|
||||
setModalData(data);
|
||||
};
|
||||
|
||||
const handleCloseModal = () => {
|
||||
setModalData(null);
|
||||
};
|
||||
|
||||
const handleContactClick = () => {
|
||||
handleOpenModal({
|
||||
title: 'Связь с разработчиком',
|
||||
type: 'form',
|
||||
theme: 'dark', // Keep header interaction dark themed typically
|
||||
content: {
|
||||
text: 'Оставьте свои контакты, и мы свяжемся с вами для обсуждения интеграции.'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-screen w-full bg-theme-main overflow-hidden relative">
|
||||
<AnimatePresence>
|
||||
{isBooting && <BootAnimation onComplete={() => setIsBooting(false)} />}
|
||||
</AnimatePresence>
|
||||
|
||||
{!isBooting && (
|
||||
<div className="relative h-full w-full">
|
||||
{/* Grid Pattern Background */}
|
||||
<div className="absolute inset-0 pointer-events-none grid-pattern z-0" />
|
||||
|
||||
{/* Header */}
|
||||
<nav className="fixed top-0 left-0 right-0 z-[90] py-6 mix-blend-difference text-white pointer-events-none">
|
||||
<div className="max-w-7xl mx-auto px-6 flex justify-between items-center pointer-events-auto">
|
||||
<div className="font-mono text-sm font-bold tracking-widest flex items-center gap-3">
|
||||
{/* Logo Icon */}
|
||||
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg" className="w-12 h-12">
|
||||
<circle cx="100" cy="100" r="70" stroke="#ff4b4b" strokeWidth="6" fill="none" strokeDasharray="15 85"/>
|
||||
<circle cx="100" cy="100" r="50" stroke="#ff4b4b" strokeWidth="6" fill="none" strokeDasharray="12 58" transform="rotate(30 100 100)"/>
|
||||
<circle cx="100" cy="100" r="30" stroke="#ff4b4b" strokeWidth="6" fill="none" strokeDasharray="8 32" transform="rotate(60 100 100)"/>
|
||||
</svg>
|
||||
iiEasy <span className="opacity-50"> // Будущее.Просто.</span>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={handleContactClick}
|
||||
className="text-xs font-mono font-bold hover:text-[#20e3b2] transition-colors uppercase cursor-pointer"
|
||||
>
|
||||
[ Связь ]
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<Timeline />
|
||||
|
||||
{/* Scroll Container */}
|
||||
<main
|
||||
ref={scrollContainerRef}
|
||||
className="h-full w-full overflow-y-scroll snap-y snap-proximity lg:snap-mandatory snap-container scroll-smooth relative z-10"
|
||||
>
|
||||
<Hero id="hero" onOpenModal={handleOpenModal} />
|
||||
<Infrastructure onOpenModal={handleOpenModal} />
|
||||
<Science onOpenModal={handleOpenModal} />
|
||||
<Social onOpenModal={handleOpenModal} />
|
||||
<Leadership onOpenModal={handleOpenModal} />
|
||||
<Metrics onOpenModal={handleOpenModal} />
|
||||
<Scaling onOpenModal={handleOpenModal} />
|
||||
<Team onOpenModal={handleOpenModal} />
|
||||
</main>
|
||||
|
||||
{/* Global Modal */}
|
||||
<AnimatePresence>
|
||||
{modalData && <Modal data={modalData} onClose={handleCloseModal} />}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<AnimatePresence>
|
||||
{showScrollTop && !isBooting && !modalData && (
|
||||
<motion.button
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: 20 }}
|
||||
onClick={scrollToTop}
|
||||
className="fixed bottom-8 right-8 z-50 p-4 bg-theme-main border border-theme text-theme-main hover:border-[#ff4b4b] transition-colors"
|
||||
>
|
||||
<ArrowUp className="w-5 h-5" />
|
||||
</motion.button>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
Reference in New Issue
Block a user