import React, { useState, useEffect, useCallback, useRef } from 'react'; import Sidebar from './components/Sidebar'; import HeroSection from './components/HeroSection'; import BlogSection from './components/BlogSection'; import NewsSection from './components/NewsSection'; import ResearchSection from './components/ResearchSection'; import BusinessSection from './components/BusinessSection'; import ConnectSection from './components/ConnectSection'; import AboutUsSection from './components/AboutUsSection'; import OurMissionSection from './components/OurMissionSection'; import CareersSection from './components/CareersSection'; import BusinessLandingSection from './components/BusinessLandingSection'; import BusinessServicesSection from './components/BusinessServicesSection'; import EducationBusinessSection from './components/EducationBusinessSection'; import EducationStudentsSection from './components/EducationStudentsSection'; import ResearchAllSection from './components/ResearchAllSection'; import NewsAllSection from './components/NewsAllSection'; import StoriesAllSection from './components/StoriesAllSection'; import AcceleratorAboutSection from './components/AcceleratorAboutSection'; import AcceleratorProjectsSection from './components/AcceleratorProjectsSection'; import AcceleratorInvestmentSection from './components/AcceleratorInvestmentSection'; import TermsOfUseSection from './components/TermsOfUseSection'; import PrivacyPolicySection from './components/PrivacyPolicySection'; import Logo from './components/Logo'; import { Bars3Icon, XMarkIcon, SidebarToggleIcon } from './components/icons'; import { CurrentView, Post, NewsArticle, ResearchPaper, BusinessStory, ServiceItemData, ClientLogo, BusinessCourse, StudentProgram, AcceleratorProject, InvestmentProject, Vacancy } from './types'; import { SECTION_IDS, FOOTER_CONTENT, UI_TEXTS } from './constants'; import ChatInput from './components/ChatInput'; // Import Strapi service import { fetchPosts, fetchNewsArticles, fetchResearchPapers, fetchBusinessStories, fetchServiceItems, fetchClientLogos, fetchBusinessCourses, fetchStudentPrograms, fetchAcceleratorProjects, fetchInvestmentProjects, fetchVacancies } from './strapiService'; // Import Detail Page Components import BlogPostDetail from './components/BlogPostDetail'; import NewsArticleDetail from './components/NewsArticleDetail'; import ResearchPaperDetail from './components/ResearchPaperDetail'; import BusinessStoryDetail from './components/BusinessStoryDetail'; import VacancyDetail from './components/VacancyDetail'; const App: React.FC = () => { const [isSidebarOpen, setIsSidebarOpen] = useState(false); const [isDesktopSidebarCollapsed, setIsDesktopSidebarCollapsed] = useState(false); const [currentView, setCurrentView] = useState('main'); const [selectedItemId, setSelectedItemId] = useState(null); const [showStickyChat, setShowStickyChat] = useState(false); const [isStickyChatExpanded, setIsStickyChatExpanded] = useState(false); const stickyChatRef = useRef(null); // State for Strapi data const [posts, setPosts] = useState([]); const [newsArticles, setNewsArticles] = useState([]); const [researchPapers, setResearchPapers] = useState([]); const [businessStories, setBusinessStories] = useState([]); const [serviceItems, setServiceItems] = useState([]); const [clientLogos, setClientLogos] = useState([]); const [businessCourses, setBusinessCourses] = useState([]); const [studentPrograms, setStudentPrograms] = useState([]); const [acceleratorProjects, setAcceleratorProjects] = useState([]); const [investmentProjects, setInvestmentProjects] = useState([]); const [vacancies, setVacancies] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const toggleSidebar = useCallback(() => { setIsSidebarOpen(prev => !prev); }, []); const handleSetCurrentView = useCallback((view: CurrentView) => { setCurrentView(view); if (!view.endsWith('Detail') && view !== 'termsOfUse' && view !== 'privacyPolicy') { setSelectedItemId(null); } }, []); const handleSetSelectedItemId = useCallback((id: string | null) => { setSelectedItemId(id); }, []); useEffect(() => { const loadData = async () => { setIsLoading(true); setError(null); try { const [ fetchedPosts, fetchedNews, fetchedResearch, fetchedBusinessStories, fetchedServiceItems, fetchedClientLogos, fetchedBusinessCourses, fetchedStudentPrograms, fetchedAcceleratorProjects, fetchedInvestmentProjects, fetchedVacanciesData ] = await Promise.all([ fetchPosts(), fetchNewsArticles(), fetchResearchPapers(), fetchBusinessStories(), fetchServiceItems(), fetchClientLogos(), fetchBusinessCourses(), fetchStudentPrograms(), fetchAcceleratorProjects(), fetchInvestmentProjects(), fetchVacancies(), ]); setPosts(fetchedPosts); setNewsArticles(fetchedNews); setResearchPapers(fetchedResearch); setBusinessStories(fetchedBusinessStories); setServiceItems(fetchedServiceItems); setClientLogos(fetchedClientLogos); setBusinessCourses(fetchedBusinessCourses); setStudentPrograms(fetchedStudentPrograms); setAcceleratorProjects(fetchedAcceleratorProjects); setInvestmentProjects(fetchedInvestmentProjects); setVacancies(fetchedVacanciesData); } catch (err) { console.error("Failed to load data from Strapi:", err); setError("Не удалось загрузить данные. Пожалуйста, попробуйте позже."); } finally { setIsLoading(false); } }; loadData(); }, []); useEffect(() => { const handleResize = () => { if (window.innerWidth >= 768) { setIsSidebarOpen(false); } }; window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); useEffect(() => { // On non-main pages, the sticky chat should always be visible. if (currentView !== 'main') { setShowStickyChat(true); // We don't need a scroll listener on these pages for this feature. return; } // On the main page, show the sticky chat only after scrolling past the hero. const handleScroll = () => { const heroSection = document.getElementById(SECTION_IDS.hero); if (heroSection) { const shouldShow = heroSection.getBoundingClientRect().bottom < 0; setShowStickyChat(current => current === shouldShow ? current : shouldShow); } else { // Fallback if hero section is not found on main page for some reason setShowStickyChat(false); } }; // Set initial state for 'main' view (in case user reloads scrolled down) handleScroll(); window.addEventListener('scroll', handleScroll, { passive: true }); return () => { window.removeEventListener('scroll', handleScroll); }; }, [currentView]); // Dependency on currentView ensures this logic re-runs on page change // Hook for handling clicks outside of the sticky chat input to collapse it useEffect(() => { function handleClickOutside(event: MouseEvent) { if (isStickyChatExpanded && stickyChatRef.current && !stickyChatRef.current.contains(event.target as Node)) { setIsStickyChatExpanded(false); } } document.addEventListener("mousedown", handleClickOutside); return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, [isStickyChatExpanded]); useEffect(() => { let targetId: string | null = null; const baseTitle = 'iiEasy'; let newTitle = `iiEasy: Разработка Сайтов, Приложений, ИИ-Решений | ИИ Исследования и Обучение Уфа`; // Default const findItemTitle = (items: {id: string; title: string}[], id: string | null) => items.find(item => item.id === id)?.title; switch(currentView) { case 'about': targetId = SECTION_IDS.aboutUsPage; newTitle = `О нас | ${baseTitle}`; break; case 'mission': targetId = SECTION_IDS.ourMissionPage; newTitle = `Наша Миссия | ${baseTitle}`; break; case 'careers': targetId = SECTION_IDS.careersPage; newTitle = `Карьера | ${baseTitle}`; break; case 'businessLanding': targetId = SECTION_IDS.businessLandingPage; newTitle = `Кейсы для Бизнеса | ${baseTitle}`; break; case 'businessServices': targetId = SECTION_IDS.businessServicesPage; newTitle = `Услуги для Бизнеса | ${baseTitle}`; break; case 'educationBusiness': targetId = SECTION_IDS.educationBusinessPage; newTitle = `Обучение для Бизнеса | ${baseTitle}`; break; case 'educationStudents': targetId = SECTION_IDS.educationStudentsPage; newTitle = `Обучение для Студентов | ${baseTitle}`; break; case 'researchAll': targetId = SECTION_IDS.researchAllPage; newTitle = `Все Исследования | ${baseTitle}`; break; case 'newsAll': targetId = SECTION_IDS.newsAllPage; newTitle = `Все Новости | ${baseTitle}`; break; case 'storiesAll': targetId = SECTION_IDS.storiesAllPage; newTitle = `Все Истории | ${baseTitle}`; break; case 'acceleratorAbout': targetId = SECTION_IDS.acceleratorAboutPage; newTitle = `Об Акселераторе | ${baseTitle}`; break; case 'acceleratorProjects': targetId = SECTION_IDS.acceleratorProjectsPage; newTitle = `Проекты Акселератора | ${baseTitle}`; break; case 'acceleratorInvestment': targetId = SECTION_IDS.acceleratorInvestmentPage; newTitle = `Инвестиции в стартапы | ${baseTitle}`; break; case 'blogPostDetail': targetId = SECTION_IDS.blogPostDetailPage; newTitle = `${findItemTitle(posts, selectedItemId) || 'История'} | ${baseTitle}`; break; case 'newsArticleDetail': targetId = SECTION_IDS.newsArticleDetailPage; newTitle = `${findItemTitle(newsArticles, selectedItemId) || 'Новость'} | ${baseTitle}`; break; case 'researchPaperDetail': targetId = SECTION_IDS.researchPaperDetailPage; newTitle = `${findItemTitle(researchPapers, selectedItemId) || 'Исследование'} | ${baseTitle}`; break; case 'businessStoryDetail': targetId = SECTION_IDS.businessStoryDetail; newTitle = `${findItemTitle(businessStories, selectedItemId) || 'Кейс'} | ${baseTitle}`; break; case 'vacancyDetail': targetId = SECTION_IDS.vacancyDetailPage; newTitle = `${findItemTitle(vacancies, selectedItemId) || 'Вакансия'} | ${baseTitle}`; break; case 'termsOfUse': targetId = SECTION_IDS.termsOfUsePage; newTitle = `Правила использования | ${baseTitle}`; break; case 'privacyPolicy': targetId = SECTION_IDS.privacyPolicyPage; newTitle = `Политика конфиденциальности | ${baseTitle}`; break; case 'main': window.scrollTo({ top: 0, behavior: 'smooth' }); break; } document.title = newTitle; if (targetId) { const element = document.getElementById(targetId); if (element) { element.scrollIntoView({behavior: 'smooth', block: 'start'}); } else { setTimeout(() => { document.getElementById(targetId)?.scrollIntoView({behavior: 'smooth', block: 'start'}); }, 150); } } else if (currentView !== 'main') { window.scrollTo({ top: 0, behavior: 'smooth' }); } }, [currentView, selectedItemId, posts, newsArticles, researchPapers, businessStories, vacancies]); if (isLoading) { return (

Загрузка данных...

); } if (error) { return (

Ошибка загрузки

{error}

); } return (
setIsSidebarOpen(false)} currentView={currentView} setCurrentView={handleSetCurrentView} isDesktopCollapsed={isDesktopSidebarCollapsed} /> {/* Desktop toggle button */}
{isSidebarOpen && ( )}
{currentView === 'main' && ( <> )} {currentView === 'about' && } {currentView === 'mission' && } {currentView === 'careers' && } {currentView === 'businessLanding' && } {currentView === 'businessServices' && } {currentView === 'educationBusiness' && } {currentView === 'educationStudents' && } {currentView === 'researchAll' && } {currentView === 'newsAll' && } {currentView === 'storiesAll' && } {currentView === 'acceleratorAbout' && } {currentView === 'acceleratorProjects' && } {currentView === 'acceleratorInvestment' && } {/* Detail Pages */} {currentView === 'blogPostDetail' && selectedItemId && ( )} {currentView === 'newsArticleDetail' && selectedItemId && ( )} {currentView === 'researchPaperDetail' && selectedItemId && ( )} {currentView === 'businessStoryDetail' && selectedItemId && ( )} {currentView === 'vacancyDetail' && selectedItemId && ( )} {/* Legal Pages */} {currentView === 'termsOfUse' && } {currentView === 'privacyPolicy' && }
{/* Sticky Chat Area */}
{isStickyChatExpanded ? (
) : (
)}
); }; export default App;