import { useCallback, useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; import { loadInitialData, setOption } from './api/promoApi'; import { Cart } from './components/Cart/Cart'; import { CookiePopup } from './components/CookiePopup/CookiePopup'; import { FamilySection } from './components/Family/FamilySection'; import { CategoriesSection } from './components/Categories/CategoriesSection'; import { DaysSection } from './components/Days/DaysSection'; import { Accordion } from './components/Accordion/Accordion'; import { normalizeProductImage } from './utils/product'; import type { InitialData } from './types/api'; import type { Product } from './types/cart'; import type { User } from './types/user'; export function App() { const [initialData, setInitialData] = useState(null); const [products, setProducts] = useState([]); const [isCartComplete, setIsCartComplete] = useState(false); const [isCartLoading, setIsCartLoading] = useState(true); const [openSection, setOpenSection] = useState('family'); useEffect(() => { loadInitialData().then(data => { setInitialData(data); setProducts(data.cart.flat().map(product => normalizeProductImage(product))); }); }, []); const users = initialData?.users ?? []; const categories = initialData?.available_groups ?? []; const selectedCategories = initialData?.initial_groups ?? []; const days = initialData?.days ?? 7; const handleDaysChange = useCallback(async (nextDays: number) => { setInitialData(current => current ? { ...current, days: nextDays } : current); await setOption('days', nextDays); }, []); const handleUsersChange = useCallback(async (nextUsers: User[]) => { setInitialData(current => current ? { ...current, users: nextUsers } : current); await setOption('users', nextUsers); }, []); const handleCategoriesChange = useCallback((nextCategories: string[]) => { setInitialData(current => current ? { ...current, initial_groups: nextCategories } : current); }, []); const pageContent = useMemo(() => { if (!initialData) { return Загрузка...; } return (

Автокорзина

Собираем продукты под ваши настройки

{ setIsCartComplete(true); setIsCartLoading(false); }} onLoadingChange={setIsCartLoading} />

Настройте корзину под себя

Чем больше вы расскажете, тем точнее будет подбор

} isOpen={openSection === 'days'} onToggle={() => setOpenSection(openSection === 'days' ? '' : 'days')} > 0 ? `${users.length} человек` : 'Не указаны' } icon={семья} isOpen={openSection === 'family'} onToggle={() => setOpenSection(openSection === 'family' ? '' : 'family')} > 0 ? `Выбраны ${selectedCategories.length}` : 'Не указаны' } isHighlighted={selectedCategories.length > 0} isOpen={openSection === 'preferences'} onToggle={() => setOpenSection(openSection === 'preferences' ? '' : 'preferences')} > undefined} />
); }, [ categories, days, handleCategoriesChange, handleDaysChange, handleUsersChange, initialData, isCartComplete, isCartLoading, openSection, products, selectedCategories.length, users, ]); return ( <> {pageContent} ); } const LoadingPage = styled.div` min-height: 100vh; display: flex; align-items: center; justify-content: center; color: ${({ theme }) => theme.colors.white}; font-size: 20px; `; const Container = styled.main` position: relative; display: flex; width: calc(100% - 40px); max-width: 1228px; height: 90vh; margin: 40px auto 0; background: ${({ theme }) => theme.colors.white}; border-radius: ${({ theme }) => theme.radius.page}; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.04); overflow: hidden; @media (max-width: 900px) { flex-direction: column; height: auto; min-height: 90vh; } `; const Column = styled.section` padding: 40px; flex: 1; width: 50%; overflow-y: auto; & + & { border-left: 1px solid #f0f0f0; } @media (max-width: 900px) { width: 100%; padding: 20px; & + & { border-left: none; border-top: 1px solid #f0f0f0; } } `; const LeftColumn = styled(Column)` display: flex; flex-direction: column; height: 100%; max-width: 490px; `; const RightColumn = styled(Column)``; const TitleBlock = styled.div` margin-bottom: 32px; h1 { font-size: 32px; line-height: 38px; font-weight: 700; color: ${({ theme }) => theme.colors.darkGreen}; margin-bottom: 8px; } p { font-size: 16px; line-height: 19px; color: ${({ theme }) => theme.colors.gray}; font-weight: 350; } `; const FilterTitle = styled.div` margin-bottom: 40px; h2 { font-size: 20px; line-height: 24px; margin-bottom: 8px; color: ${({ theme }) => theme.colors.darkGreen}; } p { font-size: 16px; line-height: 19px; color: ${({ theme }) => theme.colors.gray}; font-weight: 350; } `; const SettingsPanel = styled.div` border: 1px solid ${({ theme }) => theme.colors.border}; border-radius: 16px; `;