Современный интернет-магазин электроники с каталогом товаров, корзиной и системой промокодов.
- Описание проекта
- Основные функции
- Стек технологий
- Архитектура
- Установка и запуск
- Примеры использования
- FAQ
- Для разработчиков
TechStore — это одностраничное приложение (SPA) интернет-магазина, разработанное на React с использованием современных инструментов и практик. Приложение предоставляет пользователям удобный интерфейс для просмотра каталога электроники, управления корзиной покупок и применения скидок через промокоды.
Ключевые особенности:
- Адаптивный дизайн на базе Material UI
- Компонентная архитектура
- Валидация и линтинг кода
- Модульное тестирование
- Сетка товаров — отображение карточек с изображениями, ценами и описаниями
- Индикаторы скидок — визуальное отображение товаров со скидкой
- Добавление в корзину — быстрое добавление товаров из каталога
- Слайдер баннеров — промо-баннеры на главной странице
- Популярные товары — секция с рекомендуемыми товарами
- Детальная информация — полное описание товара с характеристиками
- Галерея изображений — просмотр фотографий товара с навигацией
- Связанные товары — рекомендации похожих товаров
- Блок цены — отображение цены со скидкой и без
- Таблица товаров — структурированное отображение выбранных товаров
- Управление количеством — увеличение/уменьшение количества каждого товара
- Лимит покупок — ограничение максимального количества одного товара (макс. 2 шт.)
- Удаление товаров — удаление позиций из корзины
- Проверка кода — валидация промокода при вводе
- Автоматический расчёт — применение скидки 15% при вводе кода
Кекс - Пересчёт итогов — автоматическое обновление суммы заказа
- Интерактивная карта — отображение местоположения на базе Leaflet
- Маршрутизация — построение маршрута между точками
- Секция локации — информация о местоположении магазина
- Информирование о лимитах — предупреждение при достижении максимального количества товара
- Страница 404 — страница для несуществующих маршрутов
| Технология | Версия | Назначение |
|---|---|---|
| React | 19.2.5 | UI библиотека |
| React DOM | 19.2.5 | Рендеринг компонентов |
| React Router DOM | 7.14.1 | Маршрутизация |
| Vite | 7.3.2 | Сборка и dev-сервер |
| Технология | Версия | Назначение |
|---|---|---|
| Material UI | 9.0.0 | Компоненты интерфейса |
| MUI Icons | 9.0.0 | Иконки |
| Emotion | 11.14.x | CSS-in-JS стилизация |
| Технология | Версия | Назначение |
|---|---|---|
| Leaflet | 1.9.4 | Интерактивные карты |
| React Leaflet | 5.0.0 | React-компоненты для Leaflet |
| Leaflet Routing Machine | 3.2.12 | Построение маршрутов |
| Технология | Версия | Назначение |
|---|---|---|
| ESLint | 8.57.1 | Линтинг JavaScript |
| eslint-config-htmlacademy | 10.0.1 | Конфигурация ESLint |
| Stylelint | 16.6.0 | Линтинг CSS |
| stylelint-config-htmlacademy | 4.2.2 | Конфигурация Stylelint |
| Технология | Версия | Назначение |
|---|---|---|
| Vitest | 4.1.4 | Unit-тестирование |
| @testing-library/react | 16.3.0 | Тестирование React компонентов |
| @testing-library/jest-dom | 6.1.5 | Матчеры для DOM |
| jsdom | 26.1.0 | Среда для тестов |
src/
├── pages/ # Страницы приложения
│ ├── CartPage/ # Страница корзины
│ ├── CatalogPage/ # Страница каталога
│ ├── HomePage/ # Главная страница
│ └── ProductDetailPage/ # Страница детальной информации о товаре
├── components/ # React компоненты
│ ├── App/ # Корневой компонент приложения
│ ├── BackButton/ # Кнопка возврата
│ ├── BannerSlider/ # Слайдер баннеров
│ ├── CartItem/ # Элемент корзины
│ ├── CartTable/ # Таблица корзины
│ ├── CartTotals/ # Итоговые суммы корзины
│ ├── Footer/ # Подвал сайта
│ ├── GalleryDot/ # Точка навигации галереи
│ ├── GallerySlide/ # Слайд галереи
│ ├── Header/ # Шапка сайта
│ ├── IntroSection/ # Вводная секция
│ ├── LimitNotification/ # Уведомление о лимите
│ ├── LocationSection/ # Секция локации
│ ├── Map/ # Интерактивная карта
│ ├── NotFoundState/ # Страница 404
│ ├── PopularProductsSection/ # Секция популярных товаров
│ ├── PriceBlock/ # Блок цены
│ ├── ProductCard/ # Карточка товара
│ ├── ProductGallery/ # Галерея товара
│ ├── ProductGrid/ # Сетка товаров
│ ├── ProductInfo/ # Информация о товаре
│ ├── PromoCodeForm/ # Форма промокода
│ ├── QuantityControl/ # Контроль количества
│ ├── RelatedProductCard/ # Карточка связанного товара
│ ├── RelatedProducts/ # Связанные товары
│ └── RoutingControl/ # Контроль маршрутизации
├── hooks/ # Кастомные хуки
│ ├── useCartItem/ # Логика элемента корзины
│ ├── useGallery/ # Логика галереи
│ ├── useLimitNotification/ # Логика уведомлений о лимите
│ └── useProductDetail/ # Логика страницы товара
├── utils/ # Утилиты
│ ├── array/ # Функции для работы с массивами
│ ├── cart/ # Функции для работы с корзиной
│ └── price/ # Функции для работы с ценами
├── constants/ # Константы приложения
│ ├── cart.js # Параметры корзины (лимиты, промокоды)
│ └── map.js # Координаты для карты
├── data/ # Данные приложения
│ ├── banners.js # Данные баннеров
│ ├── products.js # Каталог товаров
│ └── productsDetail.js # Детальная информация о товарах
├── assets/ # Статические ресурсы
├── index.css # Глобальные стили
└── main.jsx # Точка входа
- Атомарный дизайн — компоненты разделены по функциональности
- Изоляция стилей — CSS-модули для каждого компонента
- Централизация данных — константы и данные вынесены в отдельные директории
- Чистые компоненты — презентационные компоненты без side-effects
- Node.js ≥ 18.0.0
- npm ≥ 9.0.0
npm installnpm run devПриложение будет доступно по адресу: http://localhost:5173
npm run buildСобранные файлы будут в директории dist/
npm run preview1. Просмотр каталога
- Откройте главную страницу
- Просматривайте товары в сетке
- Обратите внимание на карточки со скидками (маркер
-X%)
2. Добавление в корзину
- Нажмите кнопку «В корзину» на карточке товара
- Товар автоматически добавится в корзину
- При попытке добавить более 2 штук одного товара — появится уведомление о лимите
3. Управление корзиной
- Перейдите в раздел корзины
- Используйте кнопки
+и-для изменения количества - Нажмите иконку корзины для удаления товара
4. Применение промокода
- Введите промокод
Кексв поле промокода - Нажмите «Применить»
- Итоговая сумма пересчитается с учётом скидки 15%
Запуск линтеров
# JavaScript/JSX
npm run lint:scripts
npm run lint:scripts:fix # с автоматическим исправлением
# CSS
npm run lint:styles
npm run lint:styles:fix # с автоматическим исправлениемЗапуск тестов
npm run test # интерактивный режим
npm run test -- --run # однократный запускДобавление нового товара
// src/data/products.js
{
id: 11,
name: 'Название товара',
price: 9990,
discount: 10, // опционально
description: 'Описание товара',
image: 'https://example.com/image.jpg',
}Q: Почему не могу добавить более 2 штук одного товара?
A: Это ограничение бизнес-логики (MAX_PRODUCT_QUANTITY = 2), предотвращающее перекупку товаров. Для изменения отредактируйте @/constants/cart.js:1.
Q: Какие промокоды работают?
A: Активный промокод — Кекс (скидка 15%). Добавить новые можно в @/constants/cart.js.
Q: Поддерживается ли TypeScript?
A: Текущая версия использует JavaScript. Для миграции на TypeScript установите typescript и @types/* пакеты, затем переименуйте файлы в .tsx.
Q: Как добавить страницу оформления заказа?
A: Используйте React Router DOM — добавьте маршрут в App компонент и создайте соответствующий компонент страницы.
Q: Можно ли подключить реальное API?
A: Да. Замените импорт статических данных в компонентах на fetch/axios запросы к вашему бэкенду.
- ESLint — конфигурация HTML Academy для JavaScript
- Stylelint — конфигурация HTML Academy для CSS
- Компоненты — функциональные с хуками, без классов
- Именование — PascalCase для компонентов, camelCase для функций и переменных
Каждый компонент располагается в отдельной директории:
ComponentName/
├── ComponentName.jsx # Компонент
├── ComponentName.css # Стили
└── index.js # Реэкспорт (опционально)
Тесты размещаются рядом с компонентами в файлах *.test.jsx:
import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import ProductCard from './ProductCard';
describe('ProductCard', () => {
it('renders product name', () => {
render(<ProductCard product={mockProduct} />);
expect(screen.getByText('Product Name')).toBeInTheDocument();
});
});vite.config.js— настройки Vitevitest.config.js— настройки тестирования.eslintrc.cjs— правила ESLint.stylelintrc— правила Stylelint
Проект создан в образовательных целях. Свободно используйте код для обучения и разработки.