285 lines
8.6 KiB
TypeScript
285 lines
8.6 KiB
TypeScript
import { motion } from 'framer-motion';
|
||
import Head from 'next/head';
|
||
import Image from 'next/image';
|
||
import { useState, useEffect } from 'react';
|
||
import Header from '../components/Header';
|
||
import Hero from '../components/Hero';
|
||
import CookieNotification from '../components/CookieNotification';
|
||
import TabSelector from '../components/TabSelector';
|
||
import NewArrivals from '../components/NewArrivals';
|
||
import Collections from '../components/Collections';
|
||
import PopularCategories from '../components/PopularCategories';
|
||
import fs from 'fs';
|
||
import path from 'path';
|
||
import { Heart } from 'lucide-react';
|
||
import Footer from '../components/Footer';
|
||
|
||
// Типы для свойств компонента
|
||
interface HomeProps {
|
||
heroImages: string[];
|
||
products: Product[];
|
||
collections: Collection[];
|
||
categories: Category[];
|
||
}
|
||
|
||
// Тип для товара
|
||
interface Product {
|
||
id: number;
|
||
name: string;
|
||
price: number;
|
||
images: string[];
|
||
description: string;
|
||
isNew?: boolean;
|
||
}
|
||
|
||
// Тип для коллекции
|
||
interface Collection {
|
||
id: number;
|
||
name: string;
|
||
image: string;
|
||
description: string;
|
||
url: string;
|
||
}
|
||
|
||
// Тип для категории
|
||
interface Category {
|
||
id: number;
|
||
name: string;
|
||
image: string;
|
||
url: string;
|
||
}
|
||
|
||
export default function Home({ heroImages, products, collections, categories }: HomeProps) {
|
||
// Состояние для отслеживания наведения на карточки товаров
|
||
const [hoveredProduct, setHoveredProduct] = useState<number | null>(null);
|
||
// Состояние для отслеживания избранных товаров
|
||
const [favorites, setFavorites] = useState<number[]>([]);
|
||
// Состояние для отслеживания активного таба
|
||
const [activeTab, setActiveTab] = useState(0);
|
||
|
||
// Состояние для отслеживания прокрутки страницы
|
||
const [scrolled, setScrolled] = useState(false);
|
||
|
||
// Эффект для отслеживания прокрутки
|
||
useEffect(() => {
|
||
const handleScroll = () => {
|
||
const isScrolled = window.scrollY > 50;
|
||
if (isScrolled !== scrolled) {
|
||
setScrolled(isScrolled);
|
||
}
|
||
};
|
||
|
||
window.addEventListener('scroll', handleScroll);
|
||
return () => {
|
||
window.removeEventListener('scroll', handleScroll);
|
||
};
|
||
}, [scrolled]);
|
||
|
||
// Функция для добавления/удаления товара из избранного
|
||
const toggleFavorite = (id: number, e: React.MouseEvent) => {
|
||
e.stopPropagation();
|
||
setFavorites(prev =>
|
||
prev.includes(id)
|
||
? prev.filter(itemId => itemId !== id)
|
||
: [...prev, id]
|
||
);
|
||
};
|
||
|
||
// Функция для обработки изменения активного таба
|
||
const handleTabChange = (index: number) => {
|
||
setActiveTab(index);
|
||
};
|
||
|
||
// Рендерим контент в зависимости от активного таба
|
||
const renderTabContent = () => {
|
||
switch (activeTab) {
|
||
case 0:
|
||
return <NewArrivals products={products} />;
|
||
case 1:
|
||
return <Collections collections={collections} />;
|
||
case 2:
|
||
return <PopularCategories categories={categories} />;
|
||
default:
|
||
return <NewArrivals products={products} />;
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className="min-h-screen bg-white font-['Arimo']">
|
||
<Head>
|
||
<title>Brand Store | Элегантная мода</title>
|
||
<link rel="icon" href="/favicon.ico" />
|
||
<link href="https://fonts.googleapis.com/css2?family=Arimo:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
||
</Head>
|
||
|
||
<Header />
|
||
|
||
<main>
|
||
{/* Секция с HERO элементом */}
|
||
<Hero images={heroImages} />
|
||
|
||
{/* Табы для выбора категорий */}
|
||
<TabSelector onTabChange={handleTabChange} />
|
||
|
||
{/* Контент в зависимости от выбранного таба */}
|
||
{renderTabContent()}
|
||
</main>
|
||
|
||
<Footer />
|
||
|
||
<CookieNotification />
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// Функция для получения данных на стороне сервера
|
||
export async function getStaticProps() {
|
||
// Данные о товарах
|
||
const products = [
|
||
{
|
||
id: 1,
|
||
name: 'Пальто оверсайз',
|
||
price: 43800,
|
||
images: ['/wear/palto1.jpg', '/wear/palto2.jpg'],
|
||
description: 'Элегантное пальто оверсайз высокого качества',
|
||
isNew: true
|
||
},
|
||
{
|
||
id: 2,
|
||
name: 'Костюм хлопок',
|
||
price: 12800,
|
||
images: ['/wear/pidzak2.jpg', '/wear/pidzak1.jpg'],
|
||
description: 'Стильный костюм для особых случаев',
|
||
isNew: true
|
||
},
|
||
{
|
||
id: 3,
|
||
name: 'Блузка',
|
||
price: 3500,
|
||
images: ['/wear/sorochka1.jpg', '/wear/sorochka2.jpg'],
|
||
description: 'Классическая блузка в коричневом цвете',
|
||
isNew: true
|
||
},
|
||
{
|
||
id: 4,
|
||
name: 'Платье со сборкой',
|
||
price: 28800,
|
||
images: ['/wear/jumpsuit_1.jpg', '/wear/jumpsuit_2.jpg'],
|
||
description: 'Элегантное платье высокого качества',
|
||
isNew: true
|
||
}
|
||
];
|
||
|
||
// Данные о коллекциях
|
||
const collections = [
|
||
{
|
||
id: 1,
|
||
name: 'Весна-Лето 2024',
|
||
image: '/photos/photo1.jpg',
|
||
description: 'Легкие ткани и яркие цвета для теплого сезона',
|
||
url: '/collections/spring-summer-2024'
|
||
},
|
||
{
|
||
id: 2,
|
||
name: 'Осень-Зима 2023',
|
||
image: '/photos/photo2.jpg',
|
||
description: 'Теплые и уютные модели для холодного времени года',
|
||
url: '/collections/autumn-winter-2023'
|
||
},
|
||
{
|
||
id: 3,
|
||
name: 'Базовый гардероб',
|
||
image: '/photos/head_photo.png',
|
||
description: 'Классические модели, которые никогда не выходят из моды',
|
||
url: '/collections/basic'
|
||
}
|
||
];
|
||
|
||
// Данные о категориях
|
||
const categories = [
|
||
{
|
||
id: 1,
|
||
name: 'Женская обувь',
|
||
image: '/category/shoes.jpg',
|
||
url: '/category/shoes'
|
||
},
|
||
{
|
||
id: 2,
|
||
name: 'Шляпы и перчатки',
|
||
image: '/category/hat.jpg',
|
||
url: '/category/hats-and-gloves'
|
||
},
|
||
{
|
||
id: 3,
|
||
name: 'Штаны и брюки',
|
||
image: '/category/pants.jpg',
|
||
url: '/category/pants'
|
||
},
|
||
{
|
||
id: 4,
|
||
name: 'Свитеры и кардиганы',
|
||
image: '/category/sweaters.jpg',
|
||
url: '/category/sweaters'
|
||
},
|
||
{
|
||
id: 5,
|
||
name: 'Платья и юбки',
|
||
image: '/category/dress.jpg',
|
||
url: '/category/dress'
|
||
},
|
||
{
|
||
id: 6,
|
||
name: 'Костюмы',
|
||
image: '/category/jacket.jpg',
|
||
url: '/category/jackets'
|
||
},
|
||
{
|
||
id: 7,
|
||
name: 'Женский шелк',
|
||
image: '/category/silk.jpg',
|
||
url: '/category/womens-silk'
|
||
},
|
||
{
|
||
id: 8,
|
||
name: 'Аксессуары',
|
||
image: '/category/scarf.jpg',
|
||
url: '/category/accessories'
|
||
}
|
||
];
|
||
|
||
// Получение изображений для слайдера из папки hero_photos
|
||
const heroImagesDirectory = path.join(process.cwd(), 'public/hero_photos');
|
||
let heroImages = [];
|
||
|
||
try {
|
||
const fileNames = fs.readdirSync(heroImagesDirectory);
|
||
// Фильтруем только изображения
|
||
const imageExtensions = ['.jpg', '.jpeg', '.png', '.webp', '.gif'];
|
||
const imageFiles = fileNames.filter(file =>
|
||
imageExtensions.some(ext => file.toLowerCase().endsWith(ext))
|
||
);
|
||
|
||
if (imageFiles.length > 0) {
|
||
heroImages = imageFiles.map(fileName => `/hero_photos/${fileName}`);
|
||
} else {
|
||
// Если нет изображений, используем изображения из папки photos
|
||
heroImages = ['/photos/head_photo.png'];
|
||
}
|
||
} catch (error) {
|
||
console.error('Error reading hero_photos directory:', error);
|
||
// Если папка не существует или пуста, используем изображение из папки photos
|
||
heroImages = ['/photos/head_photo.png'];
|
||
}
|
||
|
||
return {
|
||
props: {
|
||
heroImages,
|
||
products,
|
||
collections,
|
||
categories
|
||
},
|
||
// Перегенерация страницы каждые 10 минут
|
||
revalidate: 600,
|
||
};
|
||
}
|