diff --git a/OLD_CODE/.gitignore b/OLD_CODE/.gitignore deleted file mode 100644 index 9c84dff..0000000 --- a/OLD_CODE/.gitignore +++ /dev/null @@ -1,49 +0,0 @@ -# IDE и редакторы -.idea/ -.vscode/ -*.swp -*.swo -*~ -.DS_Store - -# Зависимости -/vendor/ -/node_modules/ - -# Логи -*.log -logs/ - -# Загруженные файлы пользователей -/uploads/products/* -!/uploads/products/.gitkeep - -# Конфигурационные файлы с секретами (если есть) -.env -.env.local -.env.*.local - -# Кэш -/cache/ -*.cache - -# Временные файлы -/tmp/ -*.tmp - -# Скомпилированные CSS -*.css.map - -# База данных SQLite (если используется локально) -*.db -*.sqlite -*.sqlite3 - -# Файлы резервных копий -*.bak -*.backup - -# PHP debug/profiling -.phpunit.result.cache -phpunit.xml - diff --git a/OLD_CODE/README.md b/OLD_CODE/README.md deleted file mode 100644 index 681dd8d..0000000 --- a/OLD_CODE/README.md +++ /dev/null @@ -1,1207 +0,0 @@ -# AETERNA - Интернет-магазин мебели и интерьера - -``` - ___ ________________ _ _____ - / | / ____/_ __/ __ \/ | / / | - / /| | / __/ / / / /_/ / |/ / /| | - / ___ |/ /___ / / / _, _/ /| / ___ | -/_/ |_/_____/ /_/ /_/ |_/_/ |_/_/ |_| - -``` ---- - -## Оглавление - -- [Возможности](#возможности) -- [Технологический стек](#технологический-стек) -- [Структура проекта](#структура-проекта) -- [База данных](#база-данных) -- [Установка и настройка](#установка-и-настройка) -- [Запуск проекта](#запуск-проекта) -- [Аутентификация и авторизация](#аутентификация-и-авторизация) -- [Функционал](#функционал) -- [API Endpoints](#api-endpoints) -- [Административная панель](#административная-панель) -- [Функции и утилиты](#функции-и-утилиты) -- [Безопасность](#безопасность) -- [Тестовые аккаунты](#тестовые-аккаунты) -- [Разработка](#разработка) - ---- - -## Возможности - -### Для покупателей -- Просмотр каталога товаров с фильтрацией по категориям, цене, цвету и материалу -- Поиск товаров по названию -- Детальная страница товара с характеристиками -- Корзина покупок с возможностью изменения количества -- Оформление заказа с выбором способа доставки и оплаты -- Личный кабинет с историей заказов -- Регистрация и авторизация - -### Для администраторов -- Полное управление каталогом товаров (CRUD) -- Управление категориями и подкатегориями -- Просмотр и обработка заказов -- Управление пользователями -- Статистика продаж - ---- - -## Технологический стек - -| Компонент | Технология | -|-----------|------------| -| Backend | PHP 7.4+ | -| База данных | PostgreSQL 12+ | -| Стилизация | LESS (компилируется в CSS) | -| JavaScript | jQuery 3.6+ | -| Иконки | Font Awesome 5.15 | -| ORM/DB | PDO (PHP Data Objects) | - -### Зависимости -- PHP расширения: `pdo`, `pdo_pgsql`, `mbstring`, `json` -- Браузерная компиляция LESS (less.js) - ---- - -## Структура проекта - -``` -cite_practica1/ -├── admin/ # Административная панель -│ └── index.php # Главная страница админки -│ -├── api/ # API endpoints (дублируются в public/api/) -│ ├── auth.php # Аутентификация пользователя -│ ├── add_to_cart.php # Добавление товара в корзину -│ ├── cart.php # Управление корзиной (add/update/remove/get/count) -│ ├── get_cart.php # Получение содержимого корзины -│ ├── get_cart_count.php # Количество товаров в корзине -│ ├── get_product.php # Получение информации о товаре -│ ├── process_order.php # Оформление заказа -│ ├── register_handler.php # Регистрация пользователя -│ └── update_cart.php # Обновление количества в корзине -│ -├── assets/ # Статические ресурсы -│ ├── css/ # Скомпилированные CSS файлы -│ ├── img/ # Изображения товаров и интерфейса -│ ├── js/ # JavaScript файлы -│ │ ├── checkout.js # Логика оформления заказа -│ │ └── profile.js # Логика профиля пользователя -│ └── less/ # LESS исходники стилей -│ ├── style.less # Основные стили -│ ├── checkout.less # Стили страницы оформления -│ └── mixins.less # LESS миксины -│ -├── config/ # Конфигурация -│ ├── database.php # Подключение к PostgreSQL -│ └── check_auth.js # Клиентская проверка авторизации -│ -├── includes/ # Общие компоненты -│ ├── auth.php # Функции авторизации -│ ├── footer.php # Футер сайта -│ ├── functions.php # Вспомогательные функции -│ └── header.php # Шапка сайта -│ -├── migrations/ # SQL миграции базы данных -│ ├── 001_initial_schema.sql # Начальная схема (users, categories, products) -│ ├── 002_add_cart_orders.sql # Корзина и заказы -│ ├── 003_add_product_fields.sql # Дополнительные поля товаров -│ ├── 004_grant_admin_to_admin_mail.sql # Права администратора -│ ├── grant_admin.php # Скрипт назначения админа -│ ├── migrate.php # Раннер миграций -│ └── seed_data.sql # Тестовые данные -│ -├── public/ # Публичная директория (точка входа веб-сервера) -│ ├── index.php # Главная страница -│ ├── catalog.php # Каталог товаров -│ ├── product.php # Страница товара -│ ├── checkout.php # Оформление заказа / корзина -│ ├── login.php # Страница входа -│ ├── logout.php # Выход из аккаунта -│ ├── register.php # Регистрация -│ ├── services.php # Страница услуг -│ ├── delivery.php # Доставка и оплата -│ ├── warranty.php # Гарантия -│ ├── header_common.php # Общий header -│ ├── footer.php # Footer -│ ├── api/ # API endpoints -│ ├── config/ # Конфигурация -│ ├── includes/ # Общие компоненты -│ ├── img/ # Изображения -│ └── assets/ # Статические ресурсы -│ -├── uploads/ # Загруженные файлы -│ └── products/ # Изображения товаров -│ -├── setup.sh # Скрипт первоначальной настройки -├── style_for_cite.less # Основной файл стилей -└── README.md # Этот файл -``` - ---- - -## База данных - -### Схема базы данных - -```mermaid -erDiagram - users ||--o{ cart : has - users ||--o{ orders : places - categories ||--o{ products : contains - categories ||--o{ subcategories : has - products ||--o{ cart : added_to - products ||--o{ order_items : included_in - orders ||--|{ order_items : contains - - users { - int user_id PK - varchar email UK - varchar password_hash - varchar full_name - varchar phone - varchar city - timestamp created_at - timestamp updated_at - timestamp last_login - boolean is_active - boolean is_admin - } - - categories { - int category_id PK - varchar name - varchar slug UK - int parent_id FK - text description - int sort_order - boolean is_active - timestamp created_at - timestamp updated_at - } - - subcategories { - int subcategory_id PK - int category_id FK - varchar name - varchar slug UK - text description - int sort_order - boolean is_active - timestamp created_at - } - - products { - int product_id PK - int category_id FK - varchar name - varchar slug UK - text description - decimal price - decimal old_price - varchar sku UK - int stock_quantity - boolean is_available - boolean is_featured - decimal rating - int review_count - varchar image_url - varchar color - varchar material - varchar card_size - timestamp created_at - timestamp updated_at - } - - cart { - int cart_id PK - int user_id FK - int product_id FK - int quantity - timestamp created_at - timestamp updated_at - } - - orders { - int order_id PK - varchar order_number UK - int user_id FK - varchar customer_name - varchar customer_email - varchar customer_phone - text delivery_address - varchar delivery_region - varchar postal_code - varchar delivery_method - varchar payment_method - decimal subtotal - decimal discount_amount - decimal delivery_price - decimal final_amount - varchar promo_code - varchar status - text notes - timestamp created_at - timestamp updated_at - timestamp completed_at - } - - order_items { - int item_id PK - int order_id FK - int product_id FK - varchar product_name - decimal product_price - int quantity - decimal total_price - timestamp created_at - } -``` - -### Описание таблиц - -| Таблица | Описание | -|---------|----------| -| `users` | Пользователи системы (покупатели и администраторы) | -| `categories` | Категории товаров (Диваны, Кресла, Кровати и т.д.) | -| `subcategories` | Подкатегории для более детальной классификации | -| `products` | Товары с ценами, описанием и характеристиками | -| `cart` | Корзина покупок (связь пользователь-товар-количество) | -| `orders` | Заказы с информацией о доставке и оплате | -| `order_items` | Позиции заказа (товары в заказе) | -| `migrations` | Служебная таблица для отслеживания миграций | - -### Миграции - -Миграции выполняются в следующем порядке: - -1. `001_initial_schema.sql` - Создание таблиц users, categories, subcategories, products -2. `002_add_cart_orders.sql` - Добавление таблиц cart, orders, order_items -3. `003_add_product_fields.sql` - Дополнительные поля для товаров (color, material, card_size) -4. `004_grant_admin_to_admin_mail.sql` - Назначение прав администратора - ---- - -## Установка и настройка - -### Требования - -- PHP 7.4 или выше -- PostgreSQL 12 или выше -- Веб-сервер (Apache) или встроенный PHP сервер для разработки - -### Шаг 1: Клонирование репозитория - -```bash -git clone -cd cite_practica1 -``` - -### Шаг 2: Настройка базы данных - -Отредактируйте файл `config/database.php`: - -```php -connection = new PDO( - "pgsql:host=ВАШ_ХОСТ;port=5432;dbname=ВАШ_DBNAME", - "ВАШ_ЛОГИН", - "ВАШ_ПАРОЛЬ" - ); - $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $this->connection->exec("SET NAMES 'utf8'"); - } catch(PDOException $e) { - die("Ошибка подключения: " . $e->getMessage()); - } - } - - public static function getInstance() { - if (self::$instance == null) { - self::$instance = new Database(); - } - return self::$instance; - } - - public function getConnection() { - return $this->connection; - } -} -``` - -### Шаг 3: Запуск миграций - -**Вариант 1: Автоматическая настройка** -```bash -chmod +x setup.sh -./setup.sh -``` - -**Вариант 2: Ручной запуск миграций** -```bash -php migrations/migrate.php -``` - -**Вариант 3: Загрузка тестовых данных** -```bash -php migrations/migrate.php --seed -``` - -### Шаг 4: Настройка прав доступа - -```bash -chmod -R 755 public/ -chmod -R 777 uploads/ -``` - ---- - -## Запуск проекта - -### Разработка (встроенный PHP сервер) - -```bash -cd public -php -S localhost:8000 -``` - -Затем откройте в браузере: http://localhost:8000 - -### Production (Apache) - -Пример конфигурации Virtual Host: - -```apache - - ServerName aeterna.local - DocumentRoot /path/to/cite_practica1/public - - - AllowOverride All - Require all granted - - - ErrorLog ${APACHE_LOG_DIR}/aeterna_error.log - CustomLog ${APACHE_LOG_DIR}/aeterna_access.log combined - -``` - -## Аутентификация и авторизация - -### Архитектура аутентификации - -```mermaid -flowchart TD - A[Пользователь] --> B{Авторизован?} - B -->|Нет| C[Страница входа] - B -->|Да| D{Роль?} - - C --> E[Ввод email/пароль] - E --> F[API: auth.php] - F --> G{Проверка в БД} - G -->|Успех| H[Создание сессии] - G -->|Ошибка| I[Сообщение об ошибке] - - H --> J[Сохранение в SESSION] - J --> K[Редирект на каталог] - - D -->|Пользователь| L[Доступ к каталогу, корзине, заказам] - D -->|Админ| M[Доступ к админ-панели] -``` - -### Система сессий - -При успешной авторизации в сессию сохраняются: - -```php -$_SESSION['user_id'] // ID пользователя -$_SESSION['user_email'] // Email -$_SESSION['full_name'] // Полное имя -$_SESSION['isLoggedIn'] // true -$_SESSION['isAdmin'] // true/false -$_SESSION['login_time'] // Время входа -``` - -### Защита страниц - -```php -// Требовать авторизацию -if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) { - header('Location: login.php?error=auth_required'); - exit(); -} - -// Требовать права администратора -if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) { - header('Location: login.php?error=admin_required'); - exit(); -} -``` - -### Роли пользователей - -| Роль | Доступ | -|------|--------| -| Гость | Главная страница, услуги, доставка, гарантия | -| Пользователь | + Каталог, корзина, оформление заказов, личный кабинет | -| Администратор | + Админ-панель, управление товарами, заказами, пользователями | - ---- - -## Функционал - -### Пользовательский интерфейс - -```mermaid -flowchart LR - subgraph pages [Страницы] - A[Главная] --> B[Каталог] - B --> C[Товар] - C --> D[Корзина] - D --> E[Оформление] - E --> F[Успех] - end - - subgraph auth [Авторизация] - G[Вход] --> H[Регистрация] - end - - subgraph info [Информация] - I[Услуги] - J[Доставка] - K[Гарантия] - L[Контакты] - end -``` - -#### Главная страница (`public/index.php`) -- Hero-секция с призывом к действию -- Преимущества компании -- Промо-блоки с акциями -- Секция "О нас" -- Слайдер с готовыми решениями -- Статистика компании -- FAQ (частые вопросы) - -#### Каталог товаров (`public/catalog.php`) -- Сетка товаров с изображениями -- Фильтрация по: - - Категориям - - Диапазону цен - - Цвету - - Материалу -- Поиск по названию -- Добавление в корзину - -#### Страница товара (`public/product.php`) -- Галерея изображений -- Описание и характеристики -- Цена и скидка -- Наличие на складе -- Кнопка добавления в корзину -- Рекомендуемые товары - -#### Корзина (`public/checkout.php`) -- Список товаров в корзине -- Изменение количества -- Удаление товаров -- Расчет итоговой суммы -- Применение промокода -- Форма оформления заказа - ---- - -## API Endpoints - -### Аутентификация - -#### POST `/api/auth.php` -Авторизация пользователя - -**Запрос:** -```json -{ - "email": "user@example.com", - "password": "password123" -} -``` - -**Ответ (успех):** -```json -{ - "success": true, - "redirect": "catalog.php" -} -``` - -**Ответ (ошибка):** -```json -{ - "success": false, - "message": "Неверный пароль" -} -``` - ---- - -### Корзина - -#### POST `/api/cart.php?action=add` -Добавление товара в корзину - -**Запрос:** -```json -{ - "product_id": 1, - "quantity": 2 -} -``` - -**Ответ:** -```json -{ - "success": true, - "message": "Товар добавлен в корзину" -} -``` - ---- - -#### POST `/api/cart.php?action=update` -Обновление количества товара - -**Запрос:** -```json -{ - "product_id": 1, - "quantity": 3 -} -``` - ---- - -#### POST `/api/cart.php?action=remove` -Удаление товара из корзины - -**Запрос:** -```json -{ - "product_id": 1 -} -``` - ---- - -#### GET `/api/cart.php?action=get` -Получение содержимого корзины - -**Ответ:** -```json -{ - "success": true, - "items": [ - { - "cart_id": 1, - "product_id": 5, - "quantity": 2, - "name": "Диван ROYALTY", - "price": 78999, - "image_url": "img2/6_6.png" - } - ], - "total": 157998 -} -``` - ---- - -#### GET `/api/cart.php?action=count` -Количество товаров в корзине - -**Ответ:** -```json -{ - "success": true, - "count": 3 -} -``` - ---- - -### Товары - -#### GET `/api/get_product.php?id=1` -Получение информации о товаре - -**Ответ:** -```json -{ - "success": true, - "product": { - "product_id": 1, - "name": "Светильник MINNIGHT", - "description": "Настольный светильник в современном стиле", - "price": 7999, - "old_price": 9999, - "image_url": "img2/1_2.png", - "color": "Черный", - "material": "Металл", - "stock_quantity": 15, - "is_available": true - } -} -``` - ---- - -### Заказы - -#### POST `/api/process_order.php` -Оформление заказа - -**Запрос:** -```json -{ - "customer_name": "Иван Иванов", - "customer_email": "ivan@example.com", - "customer_phone": "+79001234567", - "delivery_address": "г. Москва, ул. Примерная, д. 1", - "delivery_method": "courier", - "payment_method": "card" -} -``` - -**Ответ:** -```json -{ - "success": true, - "order_number": "AET-20251216-ABC123", - "message": "Заказ успешно оформлен" -} -``` - ---- - -## Административная панель - -### Доступ - -URL: `/admin/index.php` или `/public/catalog_admin.php` - -Требуется авторизация с правами администратора (`is_admin = TRUE`) - -### Функции - -```mermaid -flowchart TD - A[Админ-панель] --> B[Dashboard] - A --> C[Категории] - A --> D[Товары] - A --> E[Заказы] - A --> F[Пользователи] - - C --> C1[Список категорий] - C --> C2[Добавить категорию] - C --> C3[Редактировать] - C --> C4[Удалить] - - D --> D1[Список товаров] - D --> D2[Добавить товар] - D --> D3[Редактировать] - D --> D4[Удалить] - D --> D5[Загрузка изображений] - - E --> E1[Список заказов] - E --> E2[Детали заказа] - E --> E3[Изменить статус] -``` - -### Управление категориями - -- Создание категорий и подкатегорий -- Редактирование названия и описания -- Установка порядка сортировки -- Активация/деактивация - -### Управление товарами - -- Добавление новых товаров -- Редактирование характеристик -- Загрузка изображений -- Установка цен и скидок -- Управление наличием - -### Управление заказами - -Статусы заказов: -| Статус | Описание | -|--------|----------| -| `pending` | Ожидает обработки | -| `processing` | В обработке | -| `shipped` | Отправлен | -| `delivered` | Доставлен | -| `cancelled` | Отменен | - ---- - -## Функции и утилиты - -### `includes/functions.php` - -#### Проверка авторизации - -```php -/** - * Проверка авторизации пользователя - */ -function isLoggedIn(): bool { - return isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true; -} - -/** - * Проверка прав администратора - */ -function isAdmin(): bool { - return isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true; -} -``` - -#### Защита страниц - -```php -/** - * Требовать авторизацию - редирект на login если не авторизован - */ -function requireAuth(string $redirectUrl = 'login.php'): void { - if (!isLoggedIn()) { - header('Location: ' . $redirectUrl . '?error=auth_required'); - exit(); - } -} - -/** - * Требовать права администратора - */ -function requireAdmin(string $redirectUrl = 'login.php'): void { - if (!isAdmin()) { - header('Location: ' . $redirectUrl . '?error=admin_required'); - exit(); - } -} -``` - -#### Получение текущего пользователя - -```php -/** - * Получить текущего пользователя - */ -function getCurrentUser(): ?array { - if (!isLoggedIn()) { - return null; - } - - return [ - 'user_id' => $_SESSION['user_id'] ?? 0, - 'email' => $_SESSION['user_email'] ?? '', - 'full_name' => $_SESSION['full_name'] ?? '', - 'is_admin' => isAdmin() - ]; -} -``` - -#### Форматирование - -```php -/** - * Форматирование цены - */ -function formatPrice(float $price): string { - return number_format($price, 0, '', ' ') . ' ₽'; -} - -/** - * Безопасный вывод HTML - */ -function e(string $str): string { - return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); -} -``` - -#### Генерация идентификаторов - -```php -/** - * Генерация номера заказа - */ -function generateOrderNumber(): string { - return 'AET-' . date('Ymd') . '-' . strtoupper(substr(uniqid(), -6)); -} - -/** - * Создание slug из строки - */ -function createSlug(string $str): string { - $slug = transliterate($str); - $slug = strtolower($slug); - $slug = preg_replace('/[^a-z0-9]+/', '-', $slug); - return trim($slug, '-'); -} -``` - -#### Транслитерация - -```php -/** - * Транслитерация кириллицы в латиницу - */ -function transliterate(string $str): string { - $converter = [ - 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', - 'е' => 'e', 'ё' => 'e', 'ж' => 'zh', 'з' => 'z', 'и' => 'i', - // ... и т.д. - ]; - return strtr($str, $converter); -} -``` - -#### Flash-сообщения - -```php -/** - * Установить flash-сообщение - */ -function setFlashMessage(string $type, string $message): void { - $_SESSION['flash_message'] = [ - 'type' => $type, - 'message' => $message - ]; -} - -/** - * Получить и удалить flash-сообщение - */ -function getFlashMessage(): ?array { - if (isset($_SESSION['flash_message'])) { - $message = $_SESSION['flash_message']; - unset($_SESSION['flash_message']); - return $message; - } - return null; -} -``` - ---- - -## Безопасность - -### Защита от SQL-инъекций - -Все запросы к базе данных используют подготовленные выражения (Prepared Statements): - -```php -// ПРАВИЛЬНО - безопасно -$stmt = $db->prepare("SELECT * FROM users WHERE email = ?"); -$stmt->execute([$email]); - -// НЕПРАВИЛЬНО - уязвимо для SQL-инъекций -$result = $db->query("SELECT * FROM users WHERE email = '$email'"); -``` - -### Хеширование паролей - -Пароли хешируются с использованием bcrypt: - -```php -// Хеширование при регистрации -$password_hash = password_hash($password, PASSWORD_DEFAULT); - -// Проверка при авторизации -if (password_verify($password, $user['password_hash'])) { - // Пароль верный -} -``` - -### Защита от XSS - -Все пользовательские данные экранируются при выводе: - -```php -// Безопасный вывод -echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8'); - -// Или используя функцию-хелпер -echo e($user_input); -``` - -### Защита сессий - -```php -// Регенерация ID сессии после авторизации -session_regenerate_id(true); - -// Проверка авторизации на каждой странице -if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) { - header('Location: login.php'); - exit(); -} -``` - -### CSRF-защита - -Рекомендуется добавить токены для форм: - -```php -// Генерация токена -$_SESSION['csrf_token'] = bin2hex(random_bytes(32)); - -// В форме - - -// Проверка -if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) { - die('CSRF token mismatch'); -} -``` - -### Проверка прав доступа - -```php -// Проверка на каждой защищенной странице -if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) { - header('Location: login.php?error=auth_required'); - exit(); -} - -// Проверка прав администратора -if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) { - die('Доступ запрещен'); -} -``` - ---- - -## Тестовые аккаунты - -При подключении к удаленной DB доступны тестовые аккаунты: - -### Администратор -| Поле | Значение | -|------|----------| -| Email | `admin@mail.ru` | -| Пароль | `admin123` | -| Имя | Администратор AETERNA | -| Права | Полный доступ к админ-панели | - ---- - -## Разработка - -### Создание новой миграции - -1. Создайте файл `migrations/XXX_название.sql` (где XXX - следующий номер) -2. Напишите SQL-код -3. Запустите `php migrations/migrate.php` - -Пример миграции: -```sql --- 005_add_reviews.sql --- Добавление таблицы отзывов - -CREATE TABLE IF NOT EXISTS reviews ( - review_id SERIAL PRIMARY KEY, - product_id INTEGER REFERENCES products(product_id) ON DELETE CASCADE, - user_id INTEGER REFERENCES users(user_id) ON DELETE SET NULL, - rating INTEGER CHECK (rating >= 1 AND rating <= 5), - comment TEXT, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); - -CREATE INDEX IF NOT EXISTS idx_reviews_product ON reviews(product_id); -``` - -### Стиль кода - -- Используйте PSR-12 для PHP -- Именование переменных: `snake_case` -- Именование функций: `camelCase` или `snake_case` -- Именование классов: `PascalCase` -- Комментируйте сложную логику -- Используйте типизацию где возможно - -### Структура API endpoint - -```php - false, 'message' => 'Требуется авторизация']); - exit(); -} - -try { - $db = Database::getInstance()->getConnection(); - - // Ваша логика здесь - - echo json_encode(['success' => true, 'data' => $result]); - -} catch (PDOException $e) { - echo json_encode(['success' => false, 'message' => 'Ошибка базы данных']); -} -``` - -### Добавление новой страницы - -1. Создайте файл в `public/` -2. Подключите header и footer -3. Добавьте проверку авторизации если нужно -4. Используйте единый стиль оформления - -```php - - - - - - AETERNA - Название страницы - - - - - - - -
- -
- - - - -``` - ---- - -## Диаграмма архитектуры - -```mermaid -flowchart TB - subgraph client [Клиент] - Browser[Браузер] - end - - subgraph server [Сервер] - subgraph public [Public Directory] - Index[index.php] - Catalog[catalog.php] - Product[product.php] - Checkout[checkout.php] - Login[login.php] - end - - subgraph api [API Layer] - Auth[auth.php] - Cart[cart.php] - Order[process_order.php] - end - - subgraph core [Core] - Config[database.php] - Functions[functions.php] - Includes[header/footer] - end - - subgraph admin [Admin Panel] - AdminIndex[admin/index.php] - end - end - - subgraph database [База данных] - PostgreSQL[(PostgreSQL)] - end - - Browser <--> Index - Browser <--> Catalog - Browser <--> Product - Browser <--> Checkout - Browser <--> Login - Browser <--> Auth - Browser <--> Cart - Browser <--> Order - Browser <--> AdminIndex - - Index --> Config - Catalog --> Config - Product --> Config - Checkout --> Config - Login --> Config - Auth --> Config - Cart --> Config - Order --> Config - AdminIndex --> Config - - Config <--> PostgreSQL -``` - ---- - -## Поток оформления заказа - -```mermaid -sequenceDiagram - participant U as Пользователь - participant B as Браузер - participant C as checkout.php - participant API as process_order.php - participant DB as PostgreSQL - - U->>B: Открывает корзину - B->>C: GET /checkout.php - C->>DB: SELECT cart items - DB-->>C: Товары корзины - C-->>B: HTML страница корзины - - U->>B: Заполняет форму заказа - U->>B: Нажимает "Оформить" - B->>API: POST /api/process_order.php - - API->>DB: BEGIN TRANSACTION - API->>DB: INSERT INTO orders - DB-->>API: order_id - - loop Для каждого товара - API->>DB: INSERT INTO order_items - API->>DB: UPDATE products (stock) - end - - API->>DB: DELETE FROM cart - API->>DB: COMMIT - - API-->>B: JSON success + order_number - B-->>U: Страница успеха -``` - - diff --git a/OLD_CODE/admin/index.php b/OLD_CODE/admin/index.php deleted file mode 100644 index b0a9aa4..0000000 --- a/OLD_CODE/admin/index.php +++ /dev/null @@ -1,691 +0,0 @@ -alert('Требуется авторизация администратора'); window.location.href = 'login.php';"; - exit(); -} - -$db = Database::getInstance()->getConnection(); - -$action = $_GET['action'] ?? 'dashboard'; -$message = $_GET['message'] ?? ''; -$error = $_GET['error'] ?? ''; - -if ($_SERVER['REQUEST_METHOD'] === 'POST') { - $post_action = $_POST['action'] ?? ''; - - try { - if ($post_action === 'add_category') { - $name = trim($_POST['name'] ?? ''); - $slug = strtolower(preg_replace('/[^a-z0-9]+/i', '-', $name)); - $parent_id = !empty($_POST['parent_id']) ? (int)$_POST['parent_id'] : NULL; - $description = trim($_POST['description'] ?? ''); - $sort_order = (int)($_POST['sort_order'] ?? 0); - $is_active = isset($_POST['is_active']) ? 1 : 0; - - if (empty($name)) { - throw new Exception('Название категории обязательно'); - } - - $stmt = $db->prepare(" - INSERT INTO categories (name, slug, parent_id, description, sort_order, is_active) - VALUES (?, ?, ?, ?, ?, ?) - "); - - $result = $stmt->execute([$name, $slug, $parent_id, $description, $sort_order, $is_active]); - - if ($result) { - header('Location: admin_panel.php?action=categories&message=Категория+успешно+добавлена'); - exit(); - } - } - - if ($post_action === 'edit_category' && isset($_POST['category_id'])) { - $category_id = (int)$_POST['category_id']; - $name = trim($_POST['name'] ?? ''); - $parent_id = !empty($_POST['parent_id']) ? (int)$_POST['parent_id'] : NULL; - $description = trim($_POST['description'] ?? ''); - $sort_order = (int)($_POST['sort_order'] ?? 0); - $is_active = isset($_POST['is_active']) ? 1 : 0; - - if (empty($name)) { - throw new Exception('Название категории обязательно'); - } - - $slug = strtolower(preg_replace('/[^a-z0-9]+/i', '-', $name)); - - $stmt = $db->prepare(" - UPDATE categories SET - name = ?, - slug = ?, - parent_id = ?, - description = ?, - sort_order = ?, - is_active = ?, - updated_at = CURRENT_TIMESTAMP - WHERE category_id = ? - "); - - $stmt->execute([$name, $slug, $parent_id, $description, $sort_order, $is_active, $category_id]); - - header('Location: admin_panel.php?action=categories&message=Категория+обновлена'); - exit(); - } - - if ($post_action === 'add_product') { - $name = trim($_POST['name'] ?? ''); - $slug = strtolower(preg_replace('/[^a-z0-9]+/i', '-', $name)); - $category_id = (int)($_POST['category_id'] ?? 0); - $description = trim($_POST['description'] ?? ''); - $price = (float)($_POST['price'] ?? 0); - $old_price = !empty($_POST['old_price']) ? (float)$_POST['old_price'] : NULL; - $sku = trim($_POST['sku'] ?? ''); - $stock_quantity = (int)($_POST['stock_quantity'] ?? 0); - $is_available = isset($_POST['is_available']) ? 1 : 0; - $is_featured = isset($_POST['is_featured']) ? 1 : 0; - $image_url = trim($_POST['image_url'] ?? ''); - $color = trim($_POST['color'] ?? ''); - $material = trim($_POST['material'] ?? ''); - $card_size = trim($_POST['card_size'] ?? 'small'); - - if ($category_id <= 0) { - $_SESSION['error'] = 'Выберите корректную категорию'; - header('Location: admin_panel.php?action=add_product'); - exit(); - } - - $check_category = $db->prepare("SELECT COUNT(*) FROM categories WHERE category_id = ?"); - $check_category->execute([$category_id]); - if ($check_category->fetchColumn() == 0) { - $_SESSION['error'] = 'Выбранная категория не существует'; - header('Location: admin_panel.php?action=add_product'); - exit(); - } - - if (empty($name)) throw new Exception('Название товара обязательно'); - if ($price <= 0) throw new Exception('Цена должна быть больше 0'); - - if (empty($sku)) { - $sku = 'PROD-' . strtoupper(substr(preg_replace('/[^a-z0-9]/i', '', $name), 0, 6)) . '-' . rand(100, 999); - } - - $stmt = $db->prepare(" - INSERT INTO products ( - category_id, name, slug, description, price, old_price, - sku, stock_quantity, is_available, is_featured, image_url, - color, material, card_size - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - "); - - $result = $stmt->execute([ - $category_id, $name, $slug, $description, $price, $old_price, - $sku, $stock_quantity, $is_available, $is_featured, $image_url, - $color, $material, $card_size - ]); - - if ($result) { - $_SESSION['message'] = 'Товар успешно добавлен'; - header('Location: admin_panel.php?action=products'); - exit(); - } - } - - if ($post_action === 'edit_product' && isset($_POST['product_id'])) { - $product_id = (int)$_POST['product_id']; - $name = trim($_POST['name'] ?? ''); - $category_id = (int)($_POST['category_id'] ?? 1); - $description = trim($_POST['description'] ?? ''); - $price = (float)($_POST['price'] ?? 0); - $old_price = !empty($_POST['old_price']) ? (float)$_POST['old_price'] : NULL; - $stock_quantity = (int)($_POST['stock_quantity'] ?? 0); - $is_available = isset($_POST['is_available']) ? 1 : 0; - $image_url = trim($_POST['image_url'] ?? ''); - $color = trim($_POST['color'] ?? ''); - $material = trim($_POST['material'] ?? ''); - - if ($category_id <= 0) { - - $firstCat = $db->query("SELECT category_id FROM categories LIMIT 1")->fetchColumn(); - $category_id = $firstCat ?: 1; - } - - $stmt = $db->prepare(" - UPDATE products SET - name = ?, - category_id = ?, - description = ?, - price = ?, - old_price = ?, - stock_quantity = ?, - is_available = ?, - image_url = ?, - color = ?, - material = ?, - updated_at = CURRENT_TIMESTAMP - WHERE product_id = ? - "); - - $stmt->execute([ - $name, $category_id, $description, $price, $old_price, - $stock_quantity, $is_available, $image_url, $color, $material, $product_id - ]); - - header('Location: admin_panel.php?action=products&message=Товар+обновлен'); - exit(); - } - - if ($post_action === 'delete_category' && isset($_POST['category_id'])) { - $categoryId = intval($_POST['category_id']); - - $checkProducts = $db->prepare("SELECT COUNT(*) FROM products WHERE category_id = ?"); - $checkProducts->execute([$categoryId]); - $productCount = $checkProducts->fetchColumn(); - - $checkChildren = $db->prepare("SELECT COUNT(*) FROM categories WHERE parent_id = ?"); - $checkChildren->execute([$categoryId]); - $childCount = $checkChildren->fetchColumn(); - - if ($productCount > 0) { - - $stmt = $db->prepare("UPDATE categories SET is_active = FALSE WHERE category_id = ?"); - $stmt->execute([$categoryId]); - - header('Location: admin_panel.php?action=categories&message=Категория+скрыта+(содержит+товары)'); - exit(); - } elseif ($childCount > 0) { - - $stmt = $db->prepare("UPDATE categories SET is_active = FALSE WHERE category_id = ?"); - $stmt->execute([$categoryId]); - - header('Location: admin_panel.php?action=categories&message=Категория+скрыта+(имеет+дочерние+категории)'); - exit(); - } else { - - $stmt = $db->prepare("DELETE FROM categories WHERE category_id = ?"); - $stmt->execute([$categoryId]); - - header('Location: admin_panel.php?action=categories&message=Категория+удалена'); - exit(); - } - } - } catch (PDOException $e) { - header('Location: admin_panel.php?action=' . $action . '&error=' . urlencode('Ошибка БД: ' . $e->getMessage())); - exit(); - } catch (Exception $e) { - header('Location: admin_panel.php?action=' . $action . '&error=' . urlencode($e->getMessage())); - exit(); - } - } - -try { - - $stats = [ - 'total_products' => $db->query("SELECT COUNT(*) FROM products")->fetchColumn(), - 'active_products' => $db->query("SELECT COUNT(*) FROM products WHERE is_available = TRUE")->fetchColumn(), - 'total_orders' => $db->query("SELECT COUNT(*) FROM orders")->fetchColumn(), - 'total_users' => $db->query("SELECT COUNT(*) FROM users")->fetchColumn(), - 'revenue' => $db->query("SELECT COALESCE(SUM(final_amount), 0) FROM orders WHERE status = 'completed'")->fetchColumn() - ]; - - $allCategories = $db->query("SELECT * FROM categories WHERE is_active = TRUE ORDER BY name")->fetchAll(); - - $parentCategories = $db->query("SELECT * FROM categories WHERE parent_id IS NULL AND is_active = TRUE ORDER BY name")->fetchAll(); - - switch ($action) { - case 'products': - $showAll = isset($_GET['show_all']) && $_GET['show_all'] == '1'; - $sql = $showAll - ? "SELECT p.*, c.name as category_name FROM products p LEFT JOIN categories c ON p.category_id = c.category_id ORDER BY p.created_at DESC" - : "SELECT p.*, c.name as category_name FROM products p LEFT JOIN categories c ON p.category_id = c.category_id WHERE p.is_available = TRUE ORDER BY p.created_at DESC"; - $data = $db->query($sql)->fetchAll(); - break; - - case 'categories': - $data = $db->query(" - SELECT c1.*, c2.name as parent_name, - (SELECT COUNT(*) FROM products p WHERE p.category_id = c1.category_id) as product_count - FROM categories c1 - LEFT JOIN categories c2 ON c1.parent_id = c2.category_id - ORDER BY c1.sort_order, c1.name - ")->fetchAll(); - break; - - case 'orders': - $data = $db->query(" - SELECT o.*, u.email as user_email - FROM orders o - LEFT JOIN users u ON o.user_id = u.user_id - ORDER BY o.created_at DESC - LIMIT 50 - ")->fetchAll(); - break; - - case 'users': - $data = $db->query("SELECT * FROM users ORDER BY created_at DESC LIMIT 50")->fetchAll(); - break; - - case 'add_product': - case 'edit_product': - if ($action === 'edit_product' && isset($_GET['id'])) { - $productId = (int)$_GET['id']; - $stmt = $db->prepare("SELECT * FROM products WHERE product_id = ?"); - $stmt->execute([$productId]); - $edit_data = $stmt->fetch(); - } - break; - - case 'add_category': - case 'edit_category': - if ($action === 'edit_category' && isset($_GET['id'])) { - $categoryId = (int)$_GET['id']; - $stmt = $db->prepare("SELECT * FROM categories WHERE category_id = ?"); - $stmt->execute([$categoryId]); - $edit_data = $stmt->fetch(); - } - break; - - } - -} catch (PDOException $e) { - $error = "Ошибка базы данных: " . $e->getMessage(); -} -?> - - - - - - AETERNA - Админ-панель - - - - -
-

Админ-панель AETERNA

-
- - В каталог - Выйти -
-
- -
- - Дашборд - - - Товары - - - Категории - - - Заказы - - - Пользователи - -
- -
- -
- -
- - - -
- -
- - - - -

Статистика

-
-
-

-

Всего товаров

-
-
-

-

Активных товаров

-
-
-

-

Заказов

-
-
-

-

Пользователей

-
-
- -
- - Добавить новый товар - - - Добавить категорию - -
- - - -
-

Управление товарами

-
- - Добавить товар - - - Только активные - - Показать все - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
IDНазваниеКатегорияЦенаНа складеСтатусДействия
- 0): ?> - ✓ Доступен - - ✗ Недоступен - - ⚠ Нет на складе - - - - - - -
- - - - -
- -
- - - - -
- -
- - - -
-

Управление категориями

- - Добавить категорию - -
- - - - - - - - - - - - - - - - - - - - - - - - -
IDНазваниеSlugРодительскаяТоваровДействия
- - - Редактировать - - - -
- - - -
-

- -
- - - - - - -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- -
- - - Отмена -
-
- - - -

Заказы

- - - - - - - - - - - - - - - - - - - - - - - -
№ заказаКлиентСуммаСтатусДатаДействия
- - - -
- - - -

Пользователи

- - - - - - - - - - - - - - - - - - - - - -
IDEmailФИОДата регистрацииСтатус
- - ✓ Активен - - ✗ Неактивен - -
- - -
- - - \ No newline at end of file diff --git a/OLD_CODE/api/add_to_cart.php b/OLD_CODE/api/add_to_cart.php deleted file mode 100644 index a452dcc..0000000 --- a/OLD_CODE/api/add_to_cart.php +++ /dev/null @@ -1,112 +0,0 @@ - false, 'message' => 'Требуется авторизация']); - exit(); -} - -if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['product_id'])) { - $product_id = intval($_POST['product_id']); - $quantity = intval($_POST['quantity'] ?? 1); - $user_id = $_SESSION['user_id'] ?? 0; - - if ($user_id == 0) { - echo json_encode(['success' => false, 'message' => 'Пользователь не найден']); - exit(); - } - - $db = Database::getInstance()->getConnection(); - - try { - - $checkStock = $db->prepare(" - SELECT stock_quantity, name, price - FROM products - WHERE product_id = ? AND is_available = TRUE - "); - $checkStock->execute([$product_id]); - $product = $checkStock->fetch(); - - if (!$product) { - echo json_encode(['success' => false, 'message' => 'Товар не найден']); - exit(); - } - - if ($product['stock_quantity'] < $quantity) { - echo json_encode(['success' => false, 'message' => 'Недостаточно товара на складе']); - exit(); - } - - $checkCart = $db->prepare(" - SELECT cart_id, quantity - FROM cart - WHERE user_id = ? AND product_id = ? - "); - $checkCart->execute([$user_id, $product_id]); - $cartItem = $checkCart->fetch(); - - if ($cartItem) { - - $newQuantity = $cartItem['quantity'] + $quantity; - - if ($newQuantity > $product['stock_quantity']) { - echo json_encode(['success' => false, 'message' => 'Превышено доступное количество']); - exit(); - } - - $updateStmt = $db->prepare(" - UPDATE cart - SET quantity = ?, updated_at = CURRENT_TIMESTAMP - WHERE cart_id = ? - "); - $updateStmt->execute([$newQuantity, $cartItem['cart_id']]); - } else { - - $insertStmt = $db->prepare(" - INSERT INTO cart (user_id, product_id, quantity) - VALUES (?, ?, ?) - "); - $insertStmt->execute([$user_id, $product_id, $quantity]); - } - - if (!isset($_SESSION['cart'])) { - $_SESSION['cart'] = []; - } - - if (isset($_SESSION['cart'][$product_id])) { - $_SESSION['cart'][$product_id]['quantity'] += $quantity; - } else { - $_SESSION['cart'][$product_id] = [ - 'quantity' => $quantity, - 'name' => $product['name'], - 'price' => $product['price'], - 'added_at' => time() - ]; - } - - $cartCountStmt = $db->prepare(" - SELECT SUM(quantity) as total - FROM cart - WHERE user_id = ? - "); - $cartCountStmt->execute([$user_id]); - $cart_count = $cartCountStmt->fetchColumn() ?: 0; - - echo json_encode([ - 'success' => true, - 'cart_count' => $cart_count, - 'message' => 'Товар добавлен в корзину' - ]); - - } catch (PDOException $e) { - echo json_encode([ - 'success' => false, - 'message' => 'Ошибка базы данных: ' . $e->getMessage() - ]); - } -} else { - echo json_encode(['success' => false, 'message' => 'Неверный запрос']); -} -?> \ No newline at end of file diff --git a/OLD_CODE/api/auth.php b/OLD_CODE/api/auth.php deleted file mode 100644 index 41f8cd7..0000000 --- a/OLD_CODE/api/auth.php +++ /dev/null @@ -1,63 +0,0 @@ - false, 'message' => 'Заполните все поля']); - exit(); - } - - $db = Database::getInstance()->getConnection(); - - try { - - $stmt = $db->prepare(" - SELECT user_id, email, password_hash, full_name, phone, city, is_admin, is_active - FROM users - WHERE email = ? - "); - $stmt->execute([$email]); - $user = $stmt->fetch(); - - if (!$user) { - echo json_encode(['success' => false, 'message' => 'Пользователь не найден']); - exit(); - } - - if (!$user['is_active']) { - echo json_encode(['success' => false, 'message' => 'Аккаунт заблокирован']); - exit(); - } - - if (!password_verify($password, $user['password_hash'])) { - echo json_encode(['success' => false, 'message' => 'Неверный пароль']); - exit(); - } - - $_SESSION['user_id'] = $user['user_id']; - $_SESSION['user_email'] = $user['email']; - $_SESSION['full_name'] = $user['full_name']; - $_SESSION['user_phone'] = $user['phone'] ?? ''; - $_SESSION['user_city'] = $user['city'] ?? ''; - $_SESSION['isLoggedIn'] = true; - $_SESSION['isAdmin'] = (bool)$user['is_admin']; - $_SESSION['login_time'] = time(); - - $updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?"); - $updateStmt->execute([$user['user_id']]); - - echo json_encode(['success' => true, 'redirect' => 'catalog.php']); - - } catch (PDOException $e) { - echo json_encode(['success' => false, 'message' => 'Ошибка базы данных']); - } - -} else { - echo json_encode(['success' => false, 'message' => 'Неверный запрос']); -} -?> \ No newline at end of file diff --git a/OLD_CODE/api/cart.php b/OLD_CODE/api/cart.php deleted file mode 100644 index cd68d7b..0000000 --- a/OLD_CODE/api/cart.php +++ /dev/null @@ -1,127 +0,0 @@ - false, 'message' => 'Требуется авторизация']); - exit(); -} - -$userId = $_SESSION['user_id'] ?? 0; -$action = $_GET['action'] ?? $_POST['action'] ?? ''; - -$db = Database::getInstance()->getConnection(); - -try { - switch ($action) { - case 'add': - $productId = (int)($_POST['product_id'] ?? 0); - $quantity = (int)($_POST['quantity'] ?? 1); - - if ($productId <= 0) { - echo json_encode(['success' => false, 'message' => 'Неверный ID товара']); - exit(); - } - - $checkProduct = $db->prepare("SELECT product_id, stock_quantity FROM products WHERE product_id = ? AND is_available = TRUE"); - $checkProduct->execute([$productId]); - $product = $checkProduct->fetch(); - - if (!$product) { - echo json_encode(['success' => false, 'message' => 'Товар не найден']); - exit(); - } - - $checkCart = $db->prepare("SELECT cart_id, quantity FROM cart WHERE user_id = ? AND product_id = ?"); - $checkCart->execute([$userId, $productId]); - $cartItem = $checkCart->fetch(); - - if ($cartItem) { - - $newQuantity = $cartItem['quantity'] + $quantity; - $stmt = $db->prepare("UPDATE cart SET quantity = ?, updated_at = CURRENT_TIMESTAMP WHERE cart_id = ?"); - $stmt->execute([$newQuantity, $cartItem['cart_id']]); - } else { - - $stmt = $db->prepare("INSERT INTO cart (user_id, product_id, quantity) VALUES (?, ?, ?)"); - $stmt->execute([$userId, $productId, $quantity]); - } - - echo json_encode(['success' => true, 'message' => 'Товар добавлен в корзину']); - break; - - case 'update': - $productId = (int)($_POST['product_id'] ?? 0); - $quantity = (int)($_POST['quantity'] ?? 1); - - if ($quantity <= 0) { - - $stmt = $db->prepare("DELETE FROM cart WHERE user_id = ? AND product_id = ?"); - $stmt->execute([$userId, $productId]); - } else { - $stmt = $db->prepare("UPDATE cart SET quantity = ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ? AND product_id = ?"); - $stmt->execute([$quantity, $userId, $productId]); - } - - echo json_encode(['success' => true, 'message' => 'Корзина обновлена']); - break; - - case 'remove': - $productId = (int)($_POST['product_id'] ?? 0); - - $stmt = $db->prepare("DELETE FROM cart WHERE user_id = ? AND product_id = ?"); - $stmt->execute([$userId, $productId]); - - echo json_encode(['success' => true, 'message' => 'Товар удален из корзины']); - break; - - case 'get': - $stmt = $db->prepare(" - SELECT c.cart_id, c.product_id, c.quantity, p.name, p.price, p.image_url, p.stock_quantity - FROM cart c - JOIN products p ON c.product_id = p.product_id - WHERE c.user_id = ? AND p.is_available = TRUE - ORDER BY c.created_at DESC - "); - $stmt->execute([$userId]); - $items = $stmt->fetchAll(); - - $total = 0; - foreach ($items as &$item) { - $item['subtotal'] = $item['price'] * $item['quantity']; - $total += $item['subtotal']; - } - - echo json_encode([ - 'success' => true, - 'items' => $items, - 'total' => $total, - 'count' => array_sum(array_column($items, 'quantity')) - ]); - break; - - case 'count': - $stmt = $db->prepare("SELECT COALESCE(SUM(quantity), 0) FROM cart WHERE user_id = ?"); - $stmt->execute([$userId]); - $count = $stmt->fetchColumn(); - - echo json_encode(['success' => true, 'count' => (int)$count]); - break; - - case 'clear': - $stmt = $db->prepare("DELETE FROM cart WHERE user_id = ?"); - $stmt->execute([$userId]); - - echo json_encode(['success' => true, 'message' => 'Корзина очищена']); - break; - - default: - echo json_encode(['success' => false, 'message' => 'Неизвестное действие']); - } - -} catch (PDOException $e) { - echo json_encode(['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]); -} diff --git a/OLD_CODE/api/get_cart.php b/OLD_CODE/api/get_cart.php deleted file mode 100644 index 2d43ea4..0000000 --- a/OLD_CODE/api/get_cart.php +++ /dev/null @@ -1,61 +0,0 @@ - false, 'message' => 'Требуется авторизация']); - exit(); -} - -$user_id = $_SESSION['user_id'] ?? 0; - -if ($user_id == 0) { - echo json_encode(['success' => false, 'message' => 'Пользователь не найден']); - exit(); -} - -$db = Database::getInstance()->getConnection(); - -try { - - $stmt = $db->prepare(" - SELECT - c.cart_id, - c.product_id, - c.quantity, - p.name, - p.price, - p.image_url, - p.stock_quantity - FROM cart c - JOIN products p ON c.product_id = p.product_id - WHERE c.user_id = ? AND p.is_available = TRUE - ORDER BY c.created_at DESC - "); - $stmt->execute([$user_id]); - $cart_items = $stmt->fetchAll(); - - $_SESSION['cart'] = []; - foreach ($cart_items as $item) { - $_SESSION['cart'][$item['product_id']] = [ - 'quantity' => $item['quantity'], - 'name' => $item['name'], - 'price' => $item['price'], - 'added_at' => time() - ]; - } - - echo json_encode([ - 'success' => true, - 'cart_items' => $cart_items, - 'total_items' => count($cart_items) - ]); - -} catch (PDOException $e) { - echo json_encode([ - 'success' => false, - 'message' => 'Ошибка базы данных: ' . $e->getMessage() - ]); -} -?> \ No newline at end of file diff --git a/OLD_CODE/api/get_cart_count.php b/OLD_CODE/api/get_cart_count.php deleted file mode 100644 index f1d59c2..0000000 --- a/OLD_CODE/api/get_cart_count.php +++ /dev/null @@ -1,22 +0,0 @@ - false, 'cart_count' => 0]); - exit(); -} - -$user_id = $_SESSION['user_id'] ?? 0; -$db = Database::getInstance()->getConnection(); - -try { - $stmt = $db->prepare("SELECT SUM(quantity) as total FROM cart WHERE user_id = ?"); - $stmt->execute([$user_id]); - $cart_count = $stmt->fetchColumn() ?: 0; - - echo json_encode(['success' => true, 'cart_count' => $cart_count]); -} catch (PDOException $e) { - echo json_encode(['success' => false, 'cart_count' => 0]); -} \ No newline at end of file diff --git a/OLD_CODE/api/get_product.php b/OLD_CODE/api/get_product.php deleted file mode 100644 index 0cd3ca6..0000000 --- a/OLD_CODE/api/get_product.php +++ /dev/null @@ -1,32 +0,0 @@ - false, 'message' => 'Доступ запрещен']); - exit(); -} - -if (!isset($_GET['id'])) { - echo json_encode(['success' => false, 'message' => 'ID не указан']); - exit(); -} - -try { - $db = Database::getInstance()->getConnection(); - $product_id = $_GET['id']; - - $stmt = $db->prepare("SELECT * FROM products WHERE product_id = ?"); - $stmt->execute([$product_id]); - $product = $stmt->fetch(); - - if ($product) { - echo json_encode($product); - } else { - echo json_encode(['success' => false, 'message' => 'Товар не найден']); - } - -} catch (PDOException $e) { - echo json_encode(['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]); -} -?> \ No newline at end of file diff --git a/OLD_CODE/api/process_order.php b/OLD_CODE/api/process_order.php deleted file mode 100644 index 8c94036..0000000 --- a/OLD_CODE/api/process_order.php +++ /dev/null @@ -1,124 +0,0 @@ -getConnection(); - - try { - $db->beginTransaction(); - - $customer_name = $_POST['full_name'] ?? ''; - $customer_email = $_POST['email'] ?? ''; - $customer_phone = $_POST['phone'] ?? ''; - $delivery_address = $_POST['address'] ?? ''; - $region = $_POST['region'] ?? ''; - $payment_method = $_POST['payment'] ?? 'card'; - $delivery_method = $_POST['delivery'] ?? 'courier'; - $notes = $_POST['notes'] ?? ''; - $discount_amount = floatval($_POST['discount'] ?? 0); - $delivery_cost = floatval($_POST['delivery_price'] ?? 2000); - - $order_number = 'ORD-' . date('Ymd-His') . '-' . rand(1000, 9999); - - $cartStmt = $db->prepare(" - SELECT - c.product_id, - c.quantity, - p.name, - p.price, - p.stock_quantity - FROM cart c - JOIN products p ON c.product_id = p.product_id - WHERE c.user_id = ? - "); - $cartStmt->execute([$user_id]); - $cart_items = $cartStmt->fetchAll(); - - if (empty($cart_items)) { - throw new Exception('Корзина пуста'); - } - - $total_amount = 0; - foreach ($cart_items as $item) { - $total_amount += $item['price'] * $item['quantity']; - } - - $final_amount = $total_amount - $discount_amount + $delivery_cost; - - $orderStmt = $db->prepare(" - INSERT INTO orders ( - user_id, order_number, total_amount, discount_amount, - delivery_cost, final_amount, status, payment_method, - delivery_method, delivery_address, customer_name, - customer_email, customer_phone, notes - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - RETURNING order_id - "); - - $orderStmt->execute([ - $user_id, $order_number, $total_amount, $discount_amount, - $delivery_cost, $final_amount, 'pending', $payment_method, - $delivery_method, $delivery_address, $customer_name, - $customer_email, $customer_phone, $notes - ]); - - $order_id = $orderStmt->fetchColumn(); - - foreach ($cart_items as $item) { - - $itemStmt = $db->prepare(" - INSERT INTO order_items ( - order_id, product_id, product_name, - quantity, unit_price, total_price - ) VALUES (?, ?, ?, ?, ?, ?) - "); - - $item_total = $item['price'] * $item['quantity']; - $itemStmt->execute([ - $order_id, $item['product_id'], $item['name'], - $item['quantity'], $item['price'], $item_total - ]); - - $updateStmt = $db->prepare(" - UPDATE products - SET stock_quantity = stock_quantity - ?, - updated_at = CURRENT_TIMESTAMP - WHERE product_id = ? - "); - $updateStmt->execute([$item['quantity'], $item['product_id']]); - } - - $clearCartStmt = $db->prepare("DELETE FROM cart WHERE user_id = ?"); - $clearCartStmt->execute([$user_id]); - - unset($_SESSION['cart']); - - $db->commit(); - - header('Location: order_success.php?id=' . $order_id); - exit(); - - } catch (Exception $e) { - $db->rollBack(); - header('Location: checkout.php?error=' . urlencode($e->getMessage())); - exit(); - } -} else { - header('Location: checkout.php'); - exit(); -} -?> \ No newline at end of file diff --git a/OLD_CODE/api/register_handler.php b/OLD_CODE/api/register_handler.php deleted file mode 100644 index 3bbb0cb..0000000 --- a/OLD_CODE/api/register_handler.php +++ /dev/null @@ -1,151 +0,0 @@ - $full_name, - 'city' => $city, - 'email' => $email, - 'phone' => $phone - ]; - header('Location: register.php'); - exit(); - } - - $db = Database::getInstance()->getConnection(); - - try { - - $checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?"); - $checkStmt->execute([$email]); - - if ($checkStmt->fetch()) { - $_SESSION['registration_errors'] = ['Пользователь с таким email уже существует']; - $_SESSION['old_data'] = [ - 'fio' => $full_name, - 'city' => $city, - 'email' => $email, - 'phone' => $phone - ]; - header('Location: register.php'); - exit(); - } - - $password_hash = password_hash($password, PASSWORD_DEFAULT); - - $is_admin = false; - $admin_emails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru']; - if (in_array(strtolower($email), $admin_emails)) { - $is_admin = true; - } - - $stmt = $db->prepare(" - INSERT INTO users (email, password_hash, full_name, phone, city, is_admin) - VALUES (?, ?, ?, ?, ?, ?) - RETURNING user_id - "); - - $stmt->execute([ - $email, - $password_hash, - $full_name, - $phone, - $city, - $is_admin ? 1 : 0 - ]); - - $user_id = $stmt->fetchColumn(); - - if ($user_id) { - - $_SESSION['user_id'] = $user_id; - $_SESSION['user_email'] = $email; - $_SESSION['full_name'] = $full_name; - $_SESSION['user_phone'] = $phone; - $_SESSION['user_city'] = $city; - $_SESSION['isLoggedIn'] = true; - $_SESSION['isAdmin'] = $is_admin; - $_SESSION['login_time'] = time(); - - $updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?"); - $updateStmt->execute([$user_id]); - - $_SESSION['registration_success'] = 'Регистрация прошла успешно! ' . - ($is_admin ? 'Вы зарегистрированы как администратор.' : 'Добро пожаловать в AETERNA!'); - - header('Location: catalog.php'); - exit(); - } else { - throw new Exception('Ошибка при создании пользователя'); - } - - } catch (PDOException $e) { - - error_log("Registration DB Error: " . $e->getMessage()); - error_log("SQL State: " . $e->getCode()); - error_log("Email: " . $email); - - $_SESSION['registration_errors'] = ['Ошибка базы данных: ' . $e->getMessage()]; - $_SESSION['old_data'] = [ - 'fio' => $full_name, - 'city' => $city, - 'email' => $email, - 'phone' => $phone - ]; - header('Location: register.php'); - exit(); - } catch (Exception $e) { - error_log("Registration Error: " . $e->getMessage()); - - $_SESSION['registration_errors'] = [$e->getMessage()]; - header('Location: register.php'); - exit(); - } - -} else { - - header('Location: register.php'); - exit(); -} -?> \ No newline at end of file diff --git a/OLD_CODE/api/update_cart.php b/OLD_CODE/api/update_cart.php deleted file mode 100644 index 0063946..0000000 --- a/OLD_CODE/api/update_cart.php +++ /dev/null @@ -1,31 +0,0 @@ - false, 'message' => 'Требуется авторизация']); - exit(); -} - -if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['product_id'])) { - $product_id = intval($_POST['product_id']); - $quantity = intval($_POST['quantity'] ?? 1); - $user_id = $_SESSION['user_id'] ?? 0; - - $db = Database::getInstance()->getConnection(); - - try { - $stmt = $db->prepare(" - UPDATE cart - SET quantity = ?, updated_at = CURRENT_TIMESTAMP - WHERE user_id = ? AND product_id = ? - "); - $stmt->execute([$quantity, $user_id, $product_id]); - - echo json_encode(['success' => true]); - - } catch (PDOException $e) { - echo json_encode(['success' => false, 'message' => 'Ошибка базы данных']); - } -} -?> \ No newline at end of file diff --git a/OLD_CODE/assets/img/1 — копия.jpg b/OLD_CODE/assets/img/1 — копия.jpg deleted file mode 100644 index 68992d6..0000000 Binary files a/OLD_CODE/assets/img/1 — копия.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/1.jpg b/OLD_CODE/assets/img/1.jpg deleted file mode 100644 index 1df7668..0000000 Binary files a/OLD_CODE/assets/img/1.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/100.jpg b/OLD_CODE/assets/img/100.jpg deleted file mode 100644 index 646480d..0000000 Binary files a/OLD_CODE/assets/img/100.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/11.jpg b/OLD_CODE/assets/img/11.jpg deleted file mode 100644 index 3a8270e..0000000 Binary files a/OLD_CODE/assets/img/11.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/111.jpg b/OLD_CODE/assets/img/111.jpg deleted file mode 100644 index 33dc453..0000000 Binary files a/OLD_CODE/assets/img/111.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/11_1.png b/OLD_CODE/assets/img/11_1.png deleted file mode 100644 index 4735774..0000000 Binary files a/OLD_CODE/assets/img/11_1.png and /dev/null differ diff --git a/OLD_CODE/assets/img/1_1.jpg b/OLD_CODE/assets/img/1_1.jpg deleted file mode 100644 index 3f9e1a1..0000000 Binary files a/OLD_CODE/assets/img/1_1.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/1_2.jpg b/OLD_CODE/assets/img/1_2.jpg deleted file mode 100644 index 2d7a54a..0000000 Binary files a/OLD_CODE/assets/img/1_2.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/1_2.png b/OLD_CODE/assets/img/1_2.png deleted file mode 100644 index 9a8a6c0..0000000 Binary files a/OLD_CODE/assets/img/1_2.png and /dev/null differ diff --git a/OLD_CODE/assets/img/2.jpg b/OLD_CODE/assets/img/2.jpg deleted file mode 100644 index 417df4a..0000000 Binary files a/OLD_CODE/assets/img/2.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/22.jpg b/OLD_CODE/assets/img/22.jpg deleted file mode 100644 index f59b320..0000000 Binary files a/OLD_CODE/assets/img/22.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/25.jpg b/OLD_CODE/assets/img/25.jpg deleted file mode 100644 index 03eddcf..0000000 Binary files a/OLD_CODE/assets/img/25.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/2_2.jpg b/OLD_CODE/assets/img/2_2.jpg deleted file mode 100644 index 76ba9ba..0000000 Binary files a/OLD_CODE/assets/img/2_2.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/2_2.png b/OLD_CODE/assets/img/2_2.png deleted file mode 100644 index 8fa6e8c..0000000 Binary files a/OLD_CODE/assets/img/2_2.png and /dev/null differ diff --git a/OLD_CODE/assets/img/3.jpg b/OLD_CODE/assets/img/3.jpg deleted file mode 100644 index 973449d..0000000 Binary files a/OLD_CODE/assets/img/3.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/3_3.jpg b/OLD_CODE/assets/img/3_3.jpg deleted file mode 100644 index 7e56605..0000000 Binary files a/OLD_CODE/assets/img/3_3.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/3_3.png b/OLD_CODE/assets/img/3_3.png deleted file mode 100644 index ba16e91..0000000 Binary files a/OLD_CODE/assets/img/3_3.png and /dev/null differ diff --git a/OLD_CODE/assets/img/4.jpg b/OLD_CODE/assets/img/4.jpg deleted file mode 100644 index da2945c..0000000 Binary files a/OLD_CODE/assets/img/4.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/44.jpg b/OLD_CODE/assets/img/44.jpg deleted file mode 100644 index e38c994..0000000 Binary files a/OLD_CODE/assets/img/44.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/444 b/OLD_CODE/assets/img/444 deleted file mode 100644 index dc6e3fa..0000000 Binary files a/OLD_CODE/assets/img/444 and /dev/null differ diff --git a/OLD_CODE/assets/img/444 (1).png b/OLD_CODE/assets/img/444 (1).png deleted file mode 100644 index ddf7e92..0000000 Binary files a/OLD_CODE/assets/img/444 (1).png and /dev/null differ diff --git a/OLD_CODE/assets/img/444.jpg b/OLD_CODE/assets/img/444.jpg deleted file mode 100644 index dc6e3fa..0000000 Binary files a/OLD_CODE/assets/img/444.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/444.png b/OLD_CODE/assets/img/444.png deleted file mode 100644 index cd53804..0000000 Binary files a/OLD_CODE/assets/img/444.png and /dev/null differ diff --git a/OLD_CODE/assets/img/4_1.jpg b/OLD_CODE/assets/img/4_1.jpg deleted file mode 100644 index 69f2236..0000000 Binary files a/OLD_CODE/assets/img/4_1.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/5.jpg b/OLD_CODE/assets/img/5.jpg deleted file mode 100644 index 456cec1..0000000 Binary files a/OLD_CODE/assets/img/5.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/5_5.jpg b/OLD_CODE/assets/img/5_5.jpg deleted file mode 100644 index 9ced54f..0000000 Binary files a/OLD_CODE/assets/img/5_5.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/5_5.png b/OLD_CODE/assets/img/5_5.png deleted file mode 100644 index 369b63b..0000000 Binary files a/OLD_CODE/assets/img/5_5.png and /dev/null differ diff --git a/OLD_CODE/assets/img/6.jpg b/OLD_CODE/assets/img/6.jpg deleted file mode 100644 index 550e17d..0000000 Binary files a/OLD_CODE/assets/img/6.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/6_6.jpg b/OLD_CODE/assets/img/6_6.jpg deleted file mode 100644 index 0aa5c4b..0000000 Binary files a/OLD_CODE/assets/img/6_6.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/6_6.png b/OLD_CODE/assets/img/6_6.png deleted file mode 100644 index af949f9..0000000 Binary files a/OLD_CODE/assets/img/6_6.png and /dev/null differ diff --git a/OLD_CODE/assets/img/7.jpg b/OLD_CODE/assets/img/7.jpg deleted file mode 100644 index 17150c7..0000000 Binary files a/OLD_CODE/assets/img/7.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/77.jpg b/OLD_CODE/assets/img/77.jpg deleted file mode 100644 index d9bf304..0000000 Binary files a/OLD_CODE/assets/img/77.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/777 (1).png b/OLD_CODE/assets/img/777 (1).png deleted file mode 100644 index 6b01d3f..0000000 Binary files a/OLD_CODE/assets/img/777 (1).png and /dev/null differ diff --git a/OLD_CODE/assets/img/777.jpg b/OLD_CODE/assets/img/777.jpg deleted file mode 100644 index 908d164..0000000 Binary files a/OLD_CODE/assets/img/777.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/777.png b/OLD_CODE/assets/img/777.png deleted file mode 100644 index 41d57c8..0000000 Binary files a/OLD_CODE/assets/img/777.png and /dev/null differ diff --git a/OLD_CODE/assets/img/7_7.jpg b/OLD_CODE/assets/img/7_7.jpg deleted file mode 100644 index 5ee1524..0000000 Binary files a/OLD_CODE/assets/img/7_7.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/7_7.png b/OLD_CODE/assets/img/7_7.png deleted file mode 100644 index d50782e..0000000 Binary files a/OLD_CODE/assets/img/7_7.png and /dev/null differ diff --git a/OLD_CODE/assets/img/8.jpg b/OLD_CODE/assets/img/8.jpg deleted file mode 100644 index 8b41c63..0000000 Binary files a/OLD_CODE/assets/img/8.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/88.jpg b/OLD_CODE/assets/img/88.jpg deleted file mode 100644 index 713eeec..0000000 Binary files a/OLD_CODE/assets/img/88.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/888 (1).png b/OLD_CODE/assets/img/888 (1).png deleted file mode 100644 index 127e80d..0000000 Binary files a/OLD_CODE/assets/img/888 (1).png and /dev/null differ diff --git a/OLD_CODE/assets/img/888.jpg b/OLD_CODE/assets/img/888.jpg deleted file mode 100644 index e8f33f7..0000000 Binary files a/OLD_CODE/assets/img/888.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/888.png b/OLD_CODE/assets/img/888.png deleted file mode 100644 index 35e3403..0000000 Binary files a/OLD_CODE/assets/img/888.png and /dev/null differ diff --git a/OLD_CODE/assets/img/8_8.png b/OLD_CODE/assets/img/8_8.png deleted file mode 100644 index 9f86b2c..0000000 Binary files a/OLD_CODE/assets/img/8_8.png and /dev/null differ diff --git a/OLD_CODE/assets/img/9.jpg b/OLD_CODE/assets/img/9.jpg deleted file mode 100644 index 0b772e3..0000000 Binary files a/OLD_CODE/assets/img/9.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/99.jpg b/OLD_CODE/assets/img/99.jpg deleted file mode 100644 index ed309ba..0000000 Binary files a/OLD_CODE/assets/img/99.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/99.png b/OLD_CODE/assets/img/99.png deleted file mode 100644 index 8fd29b2..0000000 Binary files a/OLD_CODE/assets/img/99.png and /dev/null differ diff --git a/OLD_CODE/assets/img/99_1.jpg b/OLD_CODE/assets/img/99_1.jpg deleted file mode 100644 index 0247358..0000000 Binary files a/OLD_CODE/assets/img/99_1.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/99_2.jpg b/OLD_CODE/assets/img/99_2.jpg deleted file mode 100644 index 468fd51..0000000 Binary files a/OLD_CODE/assets/img/99_2.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/99_3.png b/OLD_CODE/assets/img/99_3.png deleted file mode 100644 index ae2cd8e..0000000 Binary files a/OLD_CODE/assets/img/99_3.png and /dev/null differ diff --git a/OLD_CODE/assets/img/9_9.jpg b/OLD_CODE/assets/img/9_9.jpg deleted file mode 100644 index a77f2ae..0000000 Binary files a/OLD_CODE/assets/img/9_9.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/9_9.png b/OLD_CODE/assets/img/9_9.png deleted file mode 100644 index 733a453..0000000 Binary files a/OLD_CODE/assets/img/9_9.png and /dev/null differ diff --git a/OLD_CODE/assets/img/black.png b/OLD_CODE/assets/img/black.png deleted file mode 100644 index a10af51..0000000 Binary files a/OLD_CODE/assets/img/black.png and /dev/null differ diff --git a/OLD_CODE/assets/img/black1.png b/OLD_CODE/assets/img/black1.png deleted file mode 100644 index f529bd3..0000000 Binary files a/OLD_CODE/assets/img/black1.png and /dev/null differ diff --git a/OLD_CODE/assets/img/black2.png b/OLD_CODE/assets/img/black2.png deleted file mode 100644 index 75758a2..0000000 Binary files a/OLD_CODE/assets/img/black2.png and /dev/null differ diff --git a/OLD_CODE/assets/img/brown.png b/OLD_CODE/assets/img/brown.png deleted file mode 100644 index 9ef4db4..0000000 Binary files a/OLD_CODE/assets/img/brown.png and /dev/null differ diff --git a/OLD_CODE/assets/img/brown1.png b/OLD_CODE/assets/img/brown1.png deleted file mode 100644 index 0b178f1..0000000 Binary files a/OLD_CODE/assets/img/brown1.png and /dev/null differ diff --git a/OLD_CODE/assets/img/brown2.png b/OLD_CODE/assets/img/brown2.png deleted file mode 100644 index 346b22f..0000000 Binary files a/OLD_CODE/assets/img/brown2.png and /dev/null differ diff --git a/OLD_CODE/assets/img/chair.PNG b/OLD_CODE/assets/img/chair.PNG deleted file mode 100644 index 12af9db..0000000 Binary files a/OLD_CODE/assets/img/chair.PNG and /dev/null differ diff --git a/OLD_CODE/assets/img/gray.png b/OLD_CODE/assets/img/gray.png deleted file mode 100644 index 55ab5bb..0000000 Binary files a/OLD_CODE/assets/img/gray.png and /dev/null differ diff --git a/OLD_CODE/assets/img/gray1.png b/OLD_CODE/assets/img/gray1.png deleted file mode 100644 index 3137e25..0000000 Binary files a/OLD_CODE/assets/img/gray1.png and /dev/null differ diff --git a/OLD_CODE/assets/img/gray2.png b/OLD_CODE/assets/img/gray2.png deleted file mode 100644 index 95b8781..0000000 Binary files a/OLD_CODE/assets/img/gray2.png and /dev/null differ diff --git a/OLD_CODE/assets/img/диван.jpg b/OLD_CODE/assets/img/диван.jpg deleted file mode 100644 index 578d1a3..0000000 Binary files a/OLD_CODE/assets/img/диван.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/диван_1.jpg b/OLD_CODE/assets/img/диван_1.jpg deleted file mode 100644 index 3618723..0000000 Binary files a/OLD_CODE/assets/img/диван_1.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/кресло.jpg b/OLD_CODE/assets/img/кресло.jpg deleted file mode 100644 index 6d1c12b..0000000 Binary files a/OLD_CODE/assets/img/кресло.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/кресло_1.jpg b/OLD_CODE/assets/img/кресло_1.jpg deleted file mode 100644 index e59b3b1..0000000 Binary files a/OLD_CODE/assets/img/кресло_1.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/слайдер_1.jpg b/OLD_CODE/assets/img/слайдер_1.jpg deleted file mode 100644 index 255440e..0000000 Binary files a/OLD_CODE/assets/img/слайдер_1.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/слайдер_2.jpg b/OLD_CODE/assets/img/слайдер_2.jpg deleted file mode 100644 index 9cb6403..0000000 Binary files a/OLD_CODE/assets/img/слайдер_2.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/слайдер_3.jpg b/OLD_CODE/assets/img/слайдер_3.jpg deleted file mode 100644 index dc65d0b..0000000 Binary files a/OLD_CODE/assets/img/слайдер_3.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/слайдер_4.jpg b/OLD_CODE/assets/img/слайдер_4.jpg deleted file mode 100644 index f6d8d38..0000000 Binary files a/OLD_CODE/assets/img/слайдер_4.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/слайдер_5.jpg b/OLD_CODE/assets/img/слайдер_5.jpg deleted file mode 100644 index a9cfbb6..0000000 Binary files a/OLD_CODE/assets/img/слайдер_5.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/слайдер_6.jpg b/OLD_CODE/assets/img/слайдер_6.jpg deleted file mode 100644 index 0dc28a0..0000000 Binary files a/OLD_CODE/assets/img/слайдер_6.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/спальня.jpg b/OLD_CODE/assets/img/спальня.jpg deleted file mode 100644 index f403324..0000000 Binary files a/OLD_CODE/assets/img/спальня.jpg and /dev/null differ diff --git a/OLD_CODE/assets/img/стили_оформления.css b/OLD_CODE/assets/img/стили_оформления.css deleted file mode 100644 index 2e1d09c..0000000 --- a/OLD_CODE/assets/img/стили_оформления.css +++ /dev/null @@ -1,61 +0,0 @@ - -.error-message { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; -} - -.form__input.error { - border-color: #ff0000; -} - -.form__group { - position: relative; - margin-bottom: 15px; -} - -.page-messages { - position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - z-index: 1000; - width: 90%; - max-width: 500px; -} - -.message { - padding: 15px; - margin: 10px 0; - border-radius: 5px; - text-align: center; - font-weight: bold; - display: none; -} - -.message.error { - background-color: #ffebee; - color: #c62828; - border: 1px solid #ffcdd2; -} - -.message.success { - background-color: #e8f5e9; - color: #453227; - border: 1px solid #c8e6c9; -} - -.message.warning { - background-color: #fff3e0; - color: #ef6c00; - border: 1px solid #ffe0b2; -} - -.privacy-error { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; - text-align: center; -} diff --git a/OLD_CODE/assets/js/checkout.js b/OLD_CODE/assets/js/checkout.js deleted file mode 100644 index 45a09f5..0000000 --- a/OLD_CODE/assets/js/checkout.js +++ /dev/null @@ -1,306 +0,0 @@ - -$(document).ready(function() { - - let cart = { - items: [ - { id: 1, name: 'Кресло OPPORTUNITY', price: 16999, quantity: 1 }, - { id: 2, name: 'Кресло GOLDEN', price: 19999, quantity: 1 }, - { id: 3, name: 'Светильник POLET', price: 7999, quantity: 1 } - ], - delivery: 2000, - discount: 0 - }; - - function updateTotal() { - let productsTotal = 0; - let totalCount = 0; - - $('.products__item').each(function() { - const $item = $(this); - const price = parseInt($item.data('price')); - const quantity = parseInt($item.find('.products__qty-value').text()); - - productsTotal += price * quantity; - totalCount += quantity; - }); - - $('.products-total').text(productsTotal + ' ₽'); - $('.summary-count').text(totalCount); - $('.total-count').text(totalCount + ' шт.'); - $('.cart-count').text(totalCount); - - const finalTotal = productsTotal + cart.delivery - cart.discount; - $('.final-total').text(finalTotal + ' ₽'); - } - - function validateEmail(email) { - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - return emailRegex.test(email); - } - - function validateFullName(name) { - - const nameRegex = /^[a-zA-Zа-яА-ЯёЁ\s\-']+$/; - - const words = name.trim().split(/\s+/); - - return nameRegex.test(name) && words.length >= 2; - } - - function validatePhone(phone) { - const phoneRegex = /^\+7\d{10}$/; - return phoneRegex.test(phone); - } - - function showMessage(messageId, duration = 5000) { - $('.message').hide(); - - $(messageId).fadeIn(300); - - if (duration > 0) { - setTimeout(() => { - $(messageId).fadeOut(300); - }, duration); - } - } - - function showPrivacyError(show) { - if (show) { - $('#privacy-error').show(); - } else { - $('#privacy-error').hide(); - } - } - - function showFieldError(fieldId, message) { - $(fieldId).removeClass('error-input'); - $(fieldId + '-error').remove(); - - if (message) { - $(fieldId).addClass('error-input'); - $(fieldId).after('
' + message + '
'); - } - } - - $('#fullname').on('blur', function() { - const value = $(this).val().trim(); - if (value) { - if (!validateFullName(value)) { - showFieldError('#fullname', 'ФИО должно содержать только буквы и состоять минимум из 2 слов'); - } else { - showFieldError('#fullname', ''); - } - } else { - showFieldError('#fullname', ''); - } - }); - - $('#email').on('blur', function() { - const value = $(this).val().trim(); - if (value) { - if (!validateEmail(value)) { - showFieldError('#email', 'Введите корректный email адрес (например: example@mail.ru)'); - } else { - showFieldError('#email', ''); - } - } else { - showFieldError('#email', ''); - } - }); - - $('#phone').on('blur', function() { - const value = $(this).val().trim(); - if (value) { - if (!validatePhone(value)) { - showFieldError('#phone', 'Введите номер в формате +7XXXXXXXXXX (10 цифр после +7)'); - } else { - showFieldError('#phone', ''); - } - } else { - showFieldError('#phone', ''); - } - }); - - $('#region').on('blur', function() { - const value = $(this).val().trim(); - if (!value) { - showFieldError('#region', 'Укажите регион доставки'); - } else { - showFieldError('#region', ''); - } - }); - - $('#address').on('blur', function() { - const value = $(this).val().trim(); - if (!value) { - showFieldError('#address', 'Укажите адрес доставки (улица, дом, квартира)'); - } else { - showFieldError('#address', ''); - } - }); - - $('.form__input').on('input', function() { - const fieldId = '#' + $(this).attr('id'); - showFieldError(fieldId, ''); - }); - - $('.products__qty-btn.plus').click(function() { - const $qtyValue = $(this).siblings('.products__qty-value'); - let quantity = parseInt($qtyValue.text()); - $qtyValue.text(quantity + 1); - updateTotal(); - }); - - $('.products__qty-btn.minus').click(function() { - const $qtyValue = $(this).siblings('.products__qty-value'); - let quantity = parseInt($qtyValue.text()); - if (quantity > 1) { - $qtyValue.text(quantity - 1); - updateTotal(); - } - }); - - $('.remove-from-cart').click(function() { - const $productItem = $(this).closest('.products__item'); - $productItem.fadeOut(300, function() { - $(this).remove(); - updateTotal(); - - if ($('.products__item').length === 0) { - $('.products__list').html('
Корзина пуста
'); - } - }); - }); - - $('.promo__btn').click(function() { - const promoCode = $('.promo__input').val().toUpperCase(); - - if (promoCode === 'SALE10') { - cart.discount = Math.round(parseInt($('.products-total').text()) * 0.1); - $('.discount-total').text(cart.discount + ' ₽'); - showMessage('#form-error', 3000); - $('#form-error').text('Промокод применен! Скидка 10%').removeClass('error').addClass('success'); - } else if (promoCode === 'FREE') { - cart.delivery = 0; - $('.delivery-price').text('0 ₽'); - showMessage('#form-error', 3000); - $('#form-error').text('Промокод применен! Бесплатная доставка').removeClass('error').addClass('success'); - } else if (promoCode) { - showMessage('#form-error', 3000); - $('#form-error').text('Промокод недействителен').removeClass('success').addClass('error'); - } - - updateTotal(); - }); - - $('input[name="delivery"]').change(function() { - if ($(this).val() === 'pickup') { - cart.delivery = 0; - $('.delivery-price').text('0 ₽'); - } else { - cart.delivery = 2000; - $('.delivery-price').text('2000 ₽'); - } - updateTotal(); - }); - - function validateForm() { - let isValid = true; - let errorMessages = []; - - $('.field-error').remove(); - $('.form__input').removeClass('error-input'); - - const requiredFields = [ - { - id: '#fullname', - value: $('#fullname').val().trim(), - validator: validateFullName, - required: true, - message: 'ФИО должно содержать только буквы и состоять минимум из 2 слов' - }, - { - id: '#phone', - value: $('#phone').val().trim(), - validator: validatePhone, - required: true, - message: 'Введите корректный номер телефона в формате +7XXXXXXXXXX' - }, - { - id: '#email', - value: $('#email').val().trim(), - validator: validateEmail, - required: true, - message: 'Введите корректный email адрес' - }, - { - id: '#region', - value: $('#region').val().trim(), - validator: (val) => val.length > 0, - required: true, - message: 'Поле "Регион" обязательно для заполнения' - }, - { - id: '#address', - value: $('#address').val().trim(), - validator: (val) => val.length > 0, - required: true, - message: 'Поле "Адрес" обязательно для заполнения' - } - ]; - - requiredFields.forEach(field => { - if (field.required && (!field.value || !field.validator(field.value))) { - isValid = false; - errorMessages.push(field.message); - showFieldError(field.id, field.message); - } - }); - - if (!$('#privacy-checkbox').is(':checked')) { - isValid = false; - showPrivacyError(true); - errorMessages.push('Необходимо согласие на обработку персональных данных'); - } else { - showPrivacyError(false); - } - - if (!isValid && errorMessages.length > 0) { - showMessage('#form-error', 5000); - $('#form-error').text('Исправьте следующие ошибки: ' + errorMessages.join('; ')).removeClass('success').addClass('error'); - - $('html, body').animate({ - scrollTop: $('.error-input').first().offset().top - 100 - }, 500); - } - - return isValid; - } - - $('#submit-order').click(function() { - if (!validateForm()) { - return; - } - - $(this).prop('disabled', true).text('ОБРАБОТКА...'); - - setTimeout(() => { - showMessage('#order-success', 5000); - $(this).prop('disabled', false).text('ОФОРМИТЬ ЗАКАЗ'); - - }, 2000); - }); - - $('#phone').on('input', function() { - let phone = $(this).val().replace(/\D/g, ''); - if (phone.length > 0) { - if (phone[0] !== '7' && phone[0] !== '8') { - phone = '7' + phone; - } - phone = '+7' + phone.substring(1, 11); - $(this).val(phone); - } - }); - - updateTotal(); -}); diff --git a/OLD_CODE/assets/js/profile.js b/OLD_CODE/assets/js/profile.js deleted file mode 100644 index 0224b62..0000000 --- a/OLD_CODE/assets/js/profile.js +++ /dev/null @@ -1,348 +0,0 @@ -$(document).ready(function() { - - function showMessage(type, text) { - const messageId = type + 'Message'; - const $message = $('#' + messageId); - $message.text(text).fadeIn(300); - setTimeout(() => { - $message.fadeOut(300); - }, 5000); - } - - function isAdminEmail(email) { - const adminEmails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru']; - return adminEmails.includes(email.toLowerCase()); - } - - function validateFIO(fio) { - const words = fio.trim().split(/\s+/); - - const hasNoDigits = !/\d/.test(fio); - return words.length >= 2 && words.every(word => word.length >= 2) && hasNoDigits; - } - - function validateCity(city) { - return city.trim().length >= 2 && /^[а-яА-ЯёЁ\s-]+$/.test(city); - } - - function validateEmail(email) { - const localPart = email.split('@')[0]; - - if (/[а-яА-ЯёЁ]/.test(localPart)) { - showError('email', 'В тексте перед знаком "@" не должно быть кириллических символов'); - return false; - } - - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - if (!emailRegex.test(email)) { - showError('email', 'Введите корректный email адрес'); - return false; - } - - hideError('email'); - return true; - } - - function validatePhone(phone) { - const phoneRegex = /^(\+7|8)[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/; - return phoneRegex.test(phone.replace(/\s/g, '')); - } - - function validatePassword(password) { - return password.length >= 6; - } - - function showError(fieldId, message) { - $('#' + fieldId).addClass('error'); - $('#' + fieldId + '-error').text(message).show(); - } - - function hideError(fieldId) { - $('#' + fieldId).removeClass('error'); - $('#' + fieldId + '-error').hide(); - } - - function validateForm() { - let isValid = true; - - const fio = $('#fio').val(); - if (!validateFIO(fio)) { - if (/\d/.test(fio)) { - showError('fio', 'ФИО не должно содержать цифры'); - } else { - showError('fio', 'ФИО должно содержать минимум 2 слова (каждое от 2 символов)'); - } - isValid = false; - } else { - hideError('fio'); - } - - const city = $('#city').val(); - if (!validateCity(city)) { - showError('city', 'Укажите корректное название города (только русские буквы)'); - isValid = false; - } else { - hideError('city'); - } - - const email = $('#email').val(); - if (!validateEmail(email)) { - showError('email', 'Введите корректный email адрес'); - isValid = false; - } else { - hideError('email'); - } - - const phone = $('#phone').val(); - if (!validatePhone(phone)) { - showError('phone', 'Введите номер в формате: +7(912)999-12-23'); - isValid = false; - } else { - hideError('phone'); - } - - const password = $('#password').val(); - if (!validatePassword(password)) { - showError('password', 'Пароль должен содержать минимум 6 символов'); - isValid = false; - } else { - hideError('password'); - } - - const confirmPassword = $('#confirm-password').val(); - if (password !== confirmPassword) { - showError('confirm-password', 'Пароли не совпадают'); - isValid = false; - } else { - hideError('confirm-password'); - } - - if (!$('#privacy').is(':checked')) { - $('#privacy-error').show(); - isValid = false; - } else { - $('#privacy-error').hide(); - } - - return isValid; - } - - $('input').on('blur', function() { - const fieldId = $(this).attr('id'); - const value = $(this).val(); - - switch(fieldId) { - case 'fio': - if (!validateFIO(value)) { - if (/\d/.test(value)) { - showError(fieldId, 'ФИО не должно содержать цифры'); - } else { - showError(fieldId, 'ФИО должно содержать минимум 2 слова'); - } - } else { - hideError(fieldId); - } - break; - case 'city': - if (!validateCity(value)) { - showError(fieldId, 'Укажите корректное название города'); - } else { - hideError(fieldId); - } - break; - case 'email': - if (!validateEmail(value)) { - showError(fieldId, 'Введите корректный email адрес'); - } else { - hideError(fieldId); - } - break; - case 'phone': - if (!validatePhone(value)) { - showError(fieldId, 'Введите номер в формате: +7(912)999-12-23'); - } else { - hideError(fieldId); - } - break; - case 'password': - if (!validatePassword(value)) { - showError(fieldId, 'Пароль должен содержать минимум 6 символов'); - } else { - hideError(fieldId); - } - break; - case 'confirm-password': - const password = $('#password').val(); - if (value !== password) { - showError(fieldId, 'Пароли не совпадают'); - } else { - hideError(fieldId); - } - break; - } - }); - - $('#registrationForm').on('submit', function(e) { - e.preventDefault(); - - if (validateForm()) { - const email = $('#email').val(); - const isAdmin = isAdminEmail(email); - - const userData = { - email: email, - fio: $('#fio').val(), - phone: $('#phone').val(), - isAdmin: isAdmin, - registered: new Date().toISOString() - }; - - localStorage.setItem('userData', JSON.stringify(userData)); - localStorage.setItem('isLoggedIn', 'true'); - localStorage.setItem('isAdmin', isAdmin.toString()); - - showMessage('success', 'Регистрация прошла успешно! ' + - (isAdmin ? 'Вы зарегистрированы как администратор.' : 'Добро пожаловать в AETERNA!')); - - setTimeout(() => { - - window.location.href = 'cite_mebel.php'; - }, 2000); - } else { - showMessage('error', 'Пожалуйста, исправьте ошибки в форме'); - } - }); - - $('a[href^="#"]').on('click', function(event) { - var target = $(this.getAttribute('href')); - if (target.length) { - event.preventDefault(); - $('html, body').stop().animate({ - scrollTop: target.offset().top - }, 1000); - } - }); - - $('.login-btn').on('click', function() { - showMessage('warning', 'Переход к форме входа...'); - setTimeout(() => { - window.location.href = 'вход.php'; - }, 1000); - }); - - $('.password-link').on('click', function(e) { - e.preventDefault(); - showMessage('warning', 'Функция смены пароля будет доступна после регистрации'); - }); - - $('#phone').on('input', function() { - let value = $(this).val().replace(/\D/g, ''); - if (value.startsWith('7') || value.startsWith('8')) { - value = value.substring(1); - } - if (value.length > 0) { - value = '+7(' + value; - if (value.length > 6) value = value.substring(0, 6) + ')' + value.substring(6); - if (value.length > 10) value = value.substring(0, 10) + '-' + value.substring(10); - if (value.length > 13) value = value.substring(0, 13) + '-' + value.substring(13); - if (value.length > 16) value = value.substring(0, 16); - } - $(this).val(value); - }); - - $('#fio').on('input', function() { - let value = $(this).val(); - - value = value.replace(/\d/g, ''); - $(this).val(value); - }); -}); - -$(document).ready(function() { - - if (localStorage.getItem('isLoggedIn') === 'true') { - const userData = JSON.parse(localStorage.getItem('userData') || '{}'); - if (userData.email) { - $('#login-email').val(userData.email); - } - } - - function checkAdminPassword(email, password) { - - const adminAccounts = { - 'admin@aeterna.ru': 'admin123', - 'administrator@aeterna.ru': 'admin123', - 'aeterna@mail.ru': 'admin123' - }; - - return adminAccounts[email.toLowerCase()] === password; - } - - $('#loginForm').on('submit', function(e) { - e.preventDefault(); - - let isValid = true; - const email = $('#login-email').val(); - const password = $('#login-password').val(); - - if (!isValidEmail(email)) { - $('#email-error').show(); - isValid = false; - } else { - $('#email-error').hide(); - } - - if (password.length < 6) { - $('#password-error').show(); - isValid = false; - } else { - $('#password-error').hide(); - } - - if (isValid) { - - showMessage('success', 'Вы успешно вошли в систему!'); - - setTimeout(function() { - window.location.href = 'cite_mebel.php'; - }, 1500); - } - }); - - function showMessage(type, text) { - const messageId = type + 'Message'; - const $message = $('#' + messageId); - - $message.text(text).show(); - - setTimeout(function() { - $message.fadeOut(); - }, 3000); - } - - $('input').on('focus', function() { - $(this).next('.error-message').hide(); - }); - - $('#remember').on('change', function() { - if ($(this).is(':checked')) { - const email = $('#login-email').val(); - if (email) { - localStorage.setItem('rememberedEmail', email); - } - } else { - localStorage.removeItem('rememberedEmail'); - } - }); - - const rememberedEmail = localStorage.getItem('rememberedEmail'); - if (rememberedEmail) { - $('#login-email').val(rememberedEmail); - $('#remember').prop('checked', true); - } - - $('.forgot-password').on('click', function(e) { - e.preventDefault(); - showMessage('info', 'Для восстановления пароля обратитесь к администратору'); - }); -}); diff --git a/OLD_CODE/assets/less/checkout.less b/OLD_CODE/assets/less/checkout.less deleted file mode 100644 index a6fe073..0000000 --- a/OLD_CODE/assets/less/checkout.less +++ /dev/null @@ -1,137 +0,0 @@ -.error-message { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; -} - -.form__input.error { - border-color: #ff0000; -} - -.form__group { - position: relative; - margin-bottom: 15px; -} - -.page-messages { - position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - z-index: 1000; - width: 90%; - max-width: 500px; -} - -.message { - padding: 15px; - margin: 10px 0; - border-radius: 5px; - text-align: center; - font-weight: bold; - display: none; -} - -.message.error { - background-color: #ffebee; - color: #c62828; - border: 1px solid #ffcdd2; -} - -.message.success { - background-color: #e8f5e9; - color: #453227; - border: 1px solid #c8e6c9; -} - -.message.warning { - background-color: #fff3e0; - color: #ef6c00; - border: 1px solid #ffe0b2; -} - -.privacy-error { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; - text-align: center; -} - -.input-group { - position: relative; - margin-bottom: 20px; -} - -.profile-form input.error { - border-color: #ff0000; - background-color: #fff5f5; -} - -.privacy-checkbox { - margin: 20px 0; - text-align: center; -} - -.privacy-checkbox label { - display: flex; - align-items: center; - justify-content: center; - gap: 8px; - cursor: pointer; - font-size: 14px; -} - -.privacy-checkbox input[type="checkbox"] { - margin: 0; -} - -.profile-page-main { - padding: 40px 0; - min-height: calc(100vh - 200px); -} - -.profile-container { - margin: 0 auto; - position: relative; - z-index: 1; -} - -.input-hint { - font-size: 12px; - color: #666; - margin-top: 5px; -} - -.form-options { - display: flex; - justify-content: space-between; - align-items: center; - margin: 20px 0; -} - -.remember-me { - display: flex; - align-items: center; - gap: 8px; - font-size: 14px; - color: #453227; -} - -.remember-me input[type="checkbox"] { - width: 16px; - height: 16px; - cursor: pointer; -} - -.forgot-password { - font-size: 14px; - color: #453227; - text-decoration: underline; -} - -.forgot-password:hover { - color: #617365; - text-decoration: none; -} \ No newline at end of file diff --git a/OLD_CODE/assets/less/mixins.less b/OLD_CODE/assets/less/mixins.less deleted file mode 100644 index 10638f0..0000000 --- a/OLD_CODE/assets/less/mixins.less +++ /dev/null @@ -1,85 +0,0 @@ -// =================================== -// === ПЕРЕМЕННЫЕ И МИКСИНЫ AETERNA === -// =================================== -@color-primary: #617365; -@color-secondary: #D1D1D1; -@color-accent: #453227; -@color-text-dark: #333; -@color-text-light: #fff; -@color-button: @color-accent; -@color-beige: #A2A09A; - -@font-logo: 'Anek Kannada', sans-serif; -@font-main: 'Anonymous Pro', monospace; -@font-heading: 'Playfair Display', serif; - -@shadow-light: 0 5px 15px rgba(0, 0, 0, 0.2); -@shadow-dark: 2px 2px 4px rgba(0, 0, 0, 0.3); - -.flex-center(@gap: 0) { - display: flex; - align-items: center; - justify-content: center; - gap: @gap; -} - -.flex-between() { - display: flex; - align-items: center; - justify-content: space-between; -} - -.flex-column() { - display: flex; - flex-direction: column; -} - -.icon-base(@size: 18px, @hover-scale: 1.1) { - cursor: pointer; - transition: all 0.3s ease; - font-size: @size; - &:hover { - transform: scale(@hover-scale); - } -} - -.image-overlay() { - position: absolute; - inset: 0; - .flex-center(15px); - flex-direction: column; - text-align: center; - background-color: rgba(0, 0, 0, 0.4); - padding: 20px; - color: @color-text-light; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7); - transition: all 0.3s ease; -} - -.menu-base() { - position: absolute; - top: 100%; - left: 0; - width: 250px; - background: white; - border-radius: 8px; - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); - padding: 15px; - z-index: 1000; - margin-top: 5px; - display: none; -} - -.input-base() { - width: 100%; - padding: 12px 15px; - border: 1px solid #ccc; - background-color: #fff; - font-family: @font-main; - font-size: 14px; - outline: none; - transition: border-color 0.3s ease; - &:focus { - border-color: @color-primary; - } -} diff --git a/OLD_CODE/assets/less/style.less b/OLD_CODE/assets/less/style.less deleted file mode 100644 index 667a7f4..0000000 --- a/OLD_CODE/assets/less/style.less +++ /dev/null @@ -1,3177 +0,0 @@ -@import "mixins.less"; -// ======================= -// === БАЗОВЫЕ СТИЛИ === -// ======================= -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -html, body { - height: 100%; -} - -html { - scroll-behavior: smooth; -} - -body { - font-family: @font-main; - background-color: @color-secondary; - color: @color-text-dark; - line-height: 1.6; - display: flex; - flex-direction: column; - min-height: 100vh; -} - -.container { - max-width: 1210px; - margin: 0 auto; - padding: 0 20px; -} - -ul { - list-style: none; -} - -a { - text-decoration: none; - color: inherit; - transition: all 0.3s ease; -} - -h1, h2, h3, h4, h5, h6 { - font-family: @font-heading; - margin: 0; -} - -p, li, span { - font-family: @font-main; -} - -// ======================= -// === КОМПОНЕНТЫ === -// ======================= - -.logo, .footer-logo { - font: bold 32px/1 @font-logo; - letter-spacing: 2px; - text-shadow: @shadow-dark; - flex-shrink: 0; -} - -.btn { - padding: 12px 30px; - border: none; - cursor: pointer; - font-size: 14px; - text-transform: uppercase; - transition: all 0.3s ease; - font-family: @font-main; - - &.primary-btn { - background-color: @color-button; - color: @color-text-light; - - &:hover { - background-color: lighten(@color-button, 10%); - transform: translateY(-2px); - box-shadow: @shadow-light; - } - } -} - -.number-circle { - .flex-center(); - width: 28px; - height: 28px; - border-radius: 50%; - background-color: @color-button; - color: @color-text-light; - font-size: 16px; - font-weight: bold; - flex-shrink: 0; -} - -.breadcrumbs { - font-size: 14px; - margin-bottom: 20px; - color: #666; - - a { - color: #666; - opacity: 0.7; - &:hover { opacity: 1; } - } - - .current-page { - font-weight: bold; - color: @color-text-dark; - } -} - -// ======================= -// === ШАПКА САЙТА === -// ======================= -.header { - background-color: @color-secondary; - border-bottom: 1px solid rgba(0, 0, 0, 0.05); - z-index: 1000; - - &__top, &__bottom { - padding: 15px 0; - .container { - .flex-between(); - gap: 20px; - } - } - - &__bottom { - padding: 10px 0; - border-top: 1px solid rgba(0, 0, 0, 0.05); - - .catalog-link.active-catalog { - background-color: rgba(0, 0, 0, 0.08); - pointer-events: none; - } - } - - .search-catalog { - .flex-center(); - border: 2px solid @color-text-dark; - background-color: #fff; - max-width: 600px; - width: 100%; - margin: 0 auto; - overflow: hidden; - - .catalog-dropdown { - position: relative; - background-color: #f8f8f8; - padding: 10px 15px 10px 25px; - font-size: 18px; - cursor: pointer; - border-right: 1px solid @color-text-dark; - .flex-center(10px); - width: 200px; - flex-shrink: 0; - - &__menu { - .menu-base(); - li { - padding: 8px 0; - cursor: pointer; - transition: color 0.3s; - border-bottom: 1px solid #f0f0f0; - &:last-child { border-bottom: none; } - &:hover { color: @color-accent; } - } - } - &:hover &__menu { display: block; } - } - - .search-box { - .flex-center(); - padding: 0 15px; - flex-grow: 1; - position: relative; - font-size: 15px; - - input { - border: none; - padding: 10px 30px 10px 0; - outline: none; - font-size: 16px; - width: 100%; - text-align: left; - } - - .search-icon { - font-size: 20px; - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; - } - }} - - &__icons--top { - .flex-center(15px); - flex-shrink: 0; - .icon { .icon-base(); font-size: 20px;} - } - - .nav-list { - .flex-center(30px); - font-size: 18px; - a { - text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); - &:hover { text-shadow: @shadow-dark; } - &.active { - border-bottom: 2px solid @color-button; - padding-bottom: 5px; - text-shadow: @shadow-dark; - } - &[href="#footer"] { - cursor: pointer; - } - } - } - - .catalog-link { - .flex-center(10px); - border-radius: 4px; - white-space: nowrap; - font-size: 18px; - padding: 10px 18px; - &:hover { background-color: rgba(0, 0, 0, 0.05); } - } - - .header-phone { - font-weight: bold; - color: @color-button; - flex-shrink: 0; - } -} - -// ======================= -// === ОСНОВНЫЕ СЕКЦИИ === -// ======================= -.hero { - padding: 15px 0; - - &__content { - .flex-center(50px); - min-height: 60vh; - align-items: center; - } - - &__image-block { - position: relative; - flex: 0 0 40%; - max-width: 600px; - height: 600px; - .flex-center(); - - .hero__circle { - position: absolute; - width: 450px; - height: 450px; - background-color: @color-primary; - border-radius: 50%; - z-index: 1; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - - .hero__img { - position: relative; - width: 100%; - height: 100%; - object-fit: contain; - z-index: 2; - } - } - - &__text-block { - flex: 0 0 60%; - padding-left: 50px; - - h1 { - font-size: 42px; - font-weight: normal; - margin-bottom: 25px; - line-height: 1.3; - } - - .hero__usp-text { - position: relative; - padding-left: 50px; - margin-bottom: 35px; - line-height: 1.7; - .flex-center(); - justify-content: flex-start; - min-height: 40px; - font-size: 16px; - - &::before { - content: "✓"; - position: absolute; - left: 0; - top: 50%; - transform: translateY(-50%); - width: 32px; - height: 32px; - border: 2px solid @color-button; - background-color: transparent; - color: @color-button; - border-radius: 50%; - .flex-center(); - font-size: 16px; - font-weight: bold; - } - } - - .btn.primary-btn { - margin: 25px 0 0 50px; - padding: 14px 35px; - font-size: 15px; - } - } -} - -.advantages { - padding: 30px 0 40px; - - &__header { - display: flex; - align-items: center; - gap: 50px; - margin-bottom: 40px; - h2 { - font-size: 32px; - font-weight: normal; - flex: 0 0 30%; - } - } - - &__items { - flex: 0 0 70%; - display: flex; - gap: 30px; - } - - .advantage-item { - flex: 1; - text-align: left; - position: relative; - padding-top: 30px; - - &__number { - .number-circle(); - position: absolute; - top: 0; - left: 0; - } - - h4 { - font-weight: 600; - margin-bottom: 10px; - } - } -} - -.promo-images { - display: flex; - gap: 20px; - margin-top: 50px; - - .promo-image-col { - position: relative; - overflow: hidden; - border-radius: 8px; - flex: 1; - transition: all 0.3s ease; - - &:hover { - transform: translateY(-5px); - box-shadow: @shadow-light; - .image-overlay-text { background-color: rgba(0, 0, 0, 0.6); } - img { transform: scale(1.05); } - .image-overlay-text h4, - .image-overlay-text .overlay-link { transform: translateY(0); } - } - - img { - width: 100%; - height: 350px; - object-fit: cover; - display: block; - transition: transform 0.5s ease; - } - - .image-overlay-text { - .image-overlay(); - h4 { - font-size: 24px; - text-transform: uppercase; - line-height: 1.2; - margin-bottom: 15px; - transform: translateY(20px); - transition: transform 0.3s ease; - } - } - - .overlay-link { - display: inline-block; - text-transform: uppercase; - font-weight: bold; - border-radius: 3px; - margin-top: 15px; - padding: 10px 25px; - background-color: @color-button; - color: @color-text-light; - font-size: 12px; - transform: translateY(20px); - transition: all 0.3s ease; - - &:hover { - background-color: lighten(@color-button, 10%); - transform: translateY(-2px); - box-shadow: @shadow-light; - } - } - } -} - -.about { - padding: 40px 0 80px; - - &__content { - display: flex; - align-items: flex-start; - gap: 50px; - } - - &__column { - display: flex; - flex-direction: column; - gap: 20px; - &--left { flex: 0 0 40%; margin-bottom: 30px; } - &--right { - flex: 0 0 60%; - .about__caption { - padding-right: 50px; - } - } - } - - &__text-block { - margin-bottom: 30px; - h2 { margin-bottom: 15px; } - } - - &__img { - width: 93%; - object-fit: cover; - display: block; - &--small { height: 300px; } - &--large { height: 450px; } - } - - .text-justified { - text-align: justify; - color: #555; - } -} - -.solutions { - padding: 0; - background-color: @color-secondary; - - &-slider { - position: relative; - width: 100%; - max-width: 1200px; - margin: 40px auto; - border-radius: 8px; - overflow: hidden; - - &__slides { - display: flex; - width: 200%; - height: 100%; - animation: slideLeftRight 10s infinite ease-in-out; - } - - &__slide { - width: 50%; - flex-shrink: 0; - position: relative; - overflow: hidden; - transition: transform 0.5s ease, box-shadow 0.5s ease; - - &:hover { - transform: scale(1.02); - box-shadow: 0 10px 25px rgba(0,0,0,0.3); - .solution-img { - transform: scale(1.05); - filter: brightness(0.8); - } - .solution-text-overlay { - opacity: 1; - transform: translateY(-5px); - } - .solution-image-link { - transform: translateX(-50%) translateY(-6px); - background-color: rgba(255,255,255,0.9); - color: @color-text-dark; - } - } - } - - .solution-img { - width: 100%; - height: auto; - object-fit: cover; - display: block; - } - - .solution-text-overlay { - position: absolute; - top: 15%; - left: 8%; - color: #493131; - text-shadow: 2px 2px 4px rgba(0,0,0,0.6); - z-index: 2; - opacity: 0.9; - transition: opacity 0.5s ease, transform 0.5s ease; - h2 { - font-size: 35px; - text-transform: uppercase; - margin-bottom: 10px; - } - p { - font-size: 25px; - text-transform: uppercase; - } - } - - .solution-image-link { - position: absolute; - bottom: 40px; - left: 50%; - transform: translateX(-50%); - padding: 12px 30px; - border: 2px solid @color-text-light; - color: #493131; - text-transform: uppercase; - font-size: 16px; - font-weight: bold; - background: transparent; - transition: 0.4s ease; - z-index: 2; - &:hover { - background: @color-text-light; - color: @color-text-dark; - transform: translateX(-50%) translateY(-2px); - } - } - } -} - -@keyframes slideLeftRight { - 0%, 40% { transform: translateX(0); } - 50%, 90% { transform: translateX(-50%); } - 100% { transform: translateX(0); } -} - -.stats { - padding: 0; - margin-top: 20px; - - .container { - display: flex; - justify-content: flex-end; - } - - &__items { - display: flex; - gap: 20px; - .stat-item { - text-align: left; - .stat-number { - font-size: 36px; - font-weight: bold; - color: @color-text-dark; - margin-bottom: 5px; - } - .stat-label { color: @color-text-dark; } - } - } -} - -.faq { - padding: 50px 0; - - h2 { - text-align: left; - font-size: 32px; - font-weight: normal; - margin-bottom: 40px; - } - - &__items { - display: flex; - flex-wrap: wrap; - gap: 40px 60px; - margin-bottom: 40px; - } - - .faq-item { - flex: 0 0 calc(50% - 30px); - .flex-center(15px); - align-items: flex-start; - &__content h4 { - font-weight: 600; - margin-bottom: 10px; - } - } - - .btn.primary-btn { - display: block; - width: 100%; - margin: 20px auto 80px; - } -} - -// ======================= -// === СТИЛИ КАТАЛОГА === -// ======================= -.catalog-main { - padding: 30px 0 60px; - background-color: lighten(@color-secondary, 5%); -} - -.catalog-wrapper { - display: flex; - gap: 20px; -} - -.catalog-sidebar { - flex: 0 0 250px; - background-color: #fff; - padding: 20px; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); - height: fit-content; -} - -.filter-group { - margin-bottom: 30px; -} - -.filter-title { - font-size: 16px; - font-weight: bold; - margin-bottom: 15px; - text-transform: uppercase; -} - -.filter-list li { - padding: 5px 0; - font-size: 16px; - a { - color: #555; - transition: color 0.2s; - &:hover { color: @color-accent; } - &.active-category { - font-weight: bold; - color: @color-primary; - } - } -} - -.price-range { - display: flex; - flex-direction: column; - gap: 15px; - width: 100%; - - .range-slider { - width: 100%; - - input[type="range"] { - -webkit-appearance: none; - appearance: none; - width: 100%; - height: 5px; - background: @color-primary; - border-radius: 5px; - outline: none; - margin: 0; - - &::-webkit-slider-thumb { - -webkit-appearance: none; - appearance: none; - width: 20px; - height: 20px; - background: @color-accent; - border: 2px solid #fff; - border-radius: 50%; - cursor: pointer; - box-shadow: 0 2px 4px rgba(0,0,0,0.2); - transition: all 0.3s ease; - - &:hover { - transform: scale(1.1); - background: lighten(@color-accent, 10%); - } - } - - &::-moz-range-thumb { - width: 20px; - height: 20px; - background: @color-accent; - border: 2px solid #fff; - border-radius: 50%; - cursor: pointer; - box-shadow: 0 2px 4px rgba(0,0,0,0.2); - transition: all 0.3s ease; - - &:hover { - transform: scale(1.1); - background: lighten(@color-accent, 10%); - } - } - } - } - - .price-display { - font-size: 14px; - font-weight: bold; - text-align: center; - color: @color-text-dark; - padding: 10px; - background: #f8f8f8; - border-radius: 4px; - } -} - -.filter-options { - list-style: none; - li { - display: flex; - align-items: center; - padding: 4px 0; - font-size: 14px; - } - label { - margin-left: 10px; - cursor: pointer; - color: #555; - } - input[type="checkbox"] { - width: 15px; - height: 15px; - cursor: pointer; - accent-color: @color-primary; - &:checked + label { - font-weight: bold; - color: @color-primary; - } - } -} - -.filter-apply-btn { - width: 100%; - margin-top: 20px; -} - -.catalog-products { - flex-grow: 1; -} - -.products-container { - display: flex; - flex-wrap: wrap; - gap: 20px; -} - -.product-card { - background-color: #fff; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); - display: flex; - flex-direction: column; - position: relative; - transition: transform 0.3s ease; - box-sizing: border-box; - - &:hover { - transform: translateY(-5px); - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); - .product-img { transform: scale(1.05); } - } -} - -.product-image-container { - position: relative; - overflow: hidden; - margin-bottom: 0; - padding: 0; - height: 250px; - .flex-center(); -} - -.product-img { - width: 100%; - height: 100%; - object-fit: contain; - display: block; - transition: transform 0.3s ease; - margin: 0; -} - -.product-img1 { - width: 100%; - height: 100%; - object-fit: cover; - display: block; - transition: transform 0.3s ease; - margin: 0; -} - -.product-discount { - position: absolute; - top: 10px; - right: 10px; - background-color: @color-button; - color: @color-text-light; - padding: 3px 8px; - font-size: 12px; - font-weight: bold; - z-index: 10; -} - -.product-wishlist-icon { - position: absolute; - top: 10px; - left: 10px; - color: #333; - font-size: 18px; - cursor: pointer; - transition: color 0.3s ease; - z-index: 10; - &:hover { color: @color-accent; } -} - -.product-name { - font-size: 16px; - font-weight: bold; - margin-bottom: 5px; -} - -.product-details { - font-size: 13px; - color: #777; - margin-bottom: 10px; - flex-grow: 1; -} - -.product-price { - font-size: 18px; - font-weight: bold; - color: @color-button; -} - -.product-card.small { flex: 0 0 300px; max-width: 300px; height: 200px; } -.product-card.small1 { flex: 0 0 320px; max-width: 320px; height: 250px;width: 320px; } -.product-card.large { flex: 0 0 580px; max-width: 580px; height: 380px; } -.product-card.wide { flex: 0 0 240px; max-width: 240px; height: 250px; } -.product-card.wide1 { flex: 0 0 350px; max-width: 350px; height: 250px; } -.product-card.wide2 { flex: 0 0 560px; max-width: 560px; height: 260px; } -.product-card.wide2_1 { flex: 0 0 560px; max-width: 560px; height: 260px; margin: -280px 0 0; } -.product-card.wide3 { - flex: 0 0 320px; max-width: 320px; height: 540px; - .product-image-container { height: 580px; } -} -.product-card.wide4 { - flex: 0 0 545px; max-width: 545px; margin: -270px 0 0; height: 250px; - .product-image-container { padding: 0; justify-content: flex-start; } - .product-img { margin-left: 0; align-self: flex-start; object-position: left center; } -} -.product-card.tall { flex: 0 0 300px; max-width: 300px; margin: -180px 0 0; height: 430px; } -.product-card.full-width { flex: 0 0 100%; margin: -20px 0 0; max-width: 900px; height: 300px;} - -.product-card.full-width { - flex: 0 0 100%; - max-width: 100%; - height: 300px; - - .product-image-container { - height: 100%; - padding: 0; - margin: 0; - - .product-img1 { - width: 100%; - height: 100%; - object-fit: cover; - margin: 0; - padding: 0; - } - } -} - -.product-card.tall .product-image-container, -.product-card.large .product-image-container { height: 430px; } - -// ======================= -// === СТРАНИЦА ТОВАРА === -// ======================= -.product__section { - display: flex; - gap: 0; - margin: 30px 0; -} - -.product__gallery, .product__info { - flex: 1; -} - -.product__main-image { - margin-bottom: 15px; -} - -.product__image { - width: 500px; - height: 300px; - border-radius: 4px; -} - -.product__thumbnails { - display: flex; - gap: 10px; -} - -.product__thumbnail { - border: none; - background: none; - cursor: pointer; - padding: 0; -} - -.product__thumbnail img { - width: 245px; - height: 150px; - object-fit: cover; - border-radius: 4px; -} - -.product__title { - font-size: 30px; - margin-bottom: 35px; -} - -.product__rating { - display: flex; - align-items: center; - gap: 10px; - margin-bottom: 30px; -} - -.product__color-selector { - display: flex; - gap: 10px; - margin-bottom: 40px; -} - -.product__color-option { - width: 45px; - height: 45px; - border-radius: 50%; - border: 2px solid transparent; - cursor: pointer; - transition: transform 0.3s ease; - - &:hover{ - transform: translateY(-2px); - } -} - -.product__color-option.active { - border-color: @color-primary; -} - -.product__description { - margin-bottom: 65px; - line-height: 1.5; -} - -.product__details-link { - display: inline-block; - margin-bottom: 20px; - color: @color-primary; - font-weight: bold; -} - -.product__purchase { - display: flex; - justify-content: space-between; - margin-bottom: 35px; -} - -.product__price { - font-size: 24px; - font-weight: bold; -} - -.product__quantity { - display: flex; - align-items: center; - gap: 10px; -} - -.product__qty-btn { - width: 30px; - height: 30px; - background: @color-button; - color: @color-text-light; - border: none; - border-radius: 50%; - cursor: pointer; - font-weight: bold; - transition: all 0.3s ease; - - &:hover { - background: lighten(@color-button, 10%); - transform: scale(1.1); - } -} - -.product__qty-value { - font-weight: bold; - min-width: 30px; - text-align: center; -} - -.product__actions { - display: flex; - gap: 15px; -} - -.product__btn { - flex: 1; - padding: 12px 20px; - border: none; - border-radius: 4px; - font-weight: bold; - cursor: pointer; - transition: all 0.3s ease; - - &:hover { - transform: translateY(-2px); - box-shadow: @shadow-light; - } -} - -.product__btn.primary { - background: @color-button; - color: @color-text-light; - - &:hover { - background: lighten(@color-button, 10%); - } -} - -.product__btn.secondary { - background: transparent; - border: 1px solid @color-button; - color: @color-button; - - &:hover { - background: @color-button; - color: @color-text-light; - } -} - -.similar { - margin: 60px 0; -} - -.similar__title { - margin-bottom: 30px; - font-size: 28px; - font-weight: bold; -} - -.similar__grid { - display: flex; - gap: 25px; - flex-wrap: wrap; - justify-content: space-between; -} - -.similar__card { - flex: 0 0 calc(33.333% - 17px); - min-width: 320px; - background: @color-secondary; - border-radius: 12px; - overflow: hidden; - transition: all 0.3s ease; - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); - - &:hover { - transform: translateY(-8px); - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); - } -} - -.similar__card-image { - height: 300px; - overflow: hidden; - background: white; - - img { - width: 100%; - height: 100%; - object-fit: contain; - transition: transform 0.3s ease; - - &:hover { - transform: scale(1.05); - } - } -} - -.similar__card-content { - padding: 25px; -} - -.similar__card-title { - font-weight: bold; - margin-bottom: 10px; - font-size: 20px; - color: @color-text-dark; -} - -.similar__card-description { - font-size: 15px; - margin-bottom: 15px; - color: #666; - line-height: 1.5; -} - -.similar__card-price { - font-weight: bold; - font-size: 22px; - color: @color-button; -} - -@media (max-width: 1024px) { - .similar { - &__card { - flex: 0 0 calc(50% - 13px); - min-width: 280px; - } - } -} - -@media (max-width: 768px) { - .similar { - &__grid { - justify-content: center; - } - - &__card { - flex: 0 0 100%; - max-width: 400px; - } - } -} - -// ======================= -// === КОРЗИНА И ЗАКАЗ === -// ======================= -.main__content { - display: flex; - gap: 40px; - margin: 30px 0; - - .products { - flex: 1; - } - - .order { - flex: 0 0 65%; - padding: 40px; - - &__header { - .flex-between(); - margin-bottom: 20px; - } - - &__title { - font-family: @font-logo; - font-size: 28px; - color: @color-text-dark; - margin: 0; - } - - &__total { - font-weight: bold; - color: @color-text-dark; - } - - &__section { - margin-bottom: 25px; - } - - &__section-title { - font-family: @font-logo; - margin-bottom: 15px; - font-size: 18px; - color: @color-text-dark; - } - } -} - -.products { - &__title { - font-family: @font-logo; - margin-bottom: 20px; - font-size: 24px; - color: @color-text-dark; - } - - &__list { - .flex-column(); - gap: 20px; - } - - &__item { - background-color: @color-secondary; - border-radius: 8px; - padding: 20px; - display: flex; - gap: 15px; - border: 1px solid @color-secondary; - transition: transform 0.3s ease; - align-items: flex-start; - position: relative; - - &:hover { - transform: translateY(-2px); - } - } - - &__image { - width: 300px; - height: 200px; - border-radius: 4px; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: flex-start; - } - - .product-img { - width: 100%; - height: 100%; - object-fit: cover; - display: block; - transition: transform 0.3s ease; - margin: 0; - } - - &__details { - flex: 1; - .flex-column(); - justify-content: space-between; - align-items: flex-start; - min-height: 200px; - } - - &__name { - font-weight: bold; - margin-bottom: 5px; - color: @color-accent; - font-size: 18px; - font-family: @font-main; - } - - &__price { - font-weight: bold; - font-size: 18px; - margin-bottom: 15px; - color: @color-text-dark; - } - - &__controls { - display: flex; - align-items: center; - gap: 15px; - margin-top: auto; - width: 100%; - justify-content: space-between; - } - - &__quantity { - display: flex; - align-items: center; - gap: 10px; - } - - &__qty-btn { - width: 30px; - height: 30px; - background-color: @color-text-dark; - color: @color-text-light; - border: none; - border-radius: 50%; - cursor: pointer; - .flex-center(); - font-family: @font-main; - font-weight: bold; - transition: all 0.3s ease; - - &:hover { - transform: scale(1.1); - } - } - - &__qty-value { - font-weight: bold; - min-width: 30px; - text-align: center; - font-size: 16px; - } - - &__cart-icon { - background-color: transparent; - color: @color-text-dark; - width: 40px; - height: 40px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: all 0.3s ease; - border: 2px solid @color-text-dark; - margin-left: 20px; - - &:hover { - transform: scale(1.1); - } - - i { font-size: 18px; } - } -} - -.form { - &__group { margin-bottom: 15px; } - &__label { - display: block; - margin-bottom: 5px; - font-weight: bold; - color: #000000; - } - &__input { - width: 100%; - padding: 14px 16px; - border: 2px solid #ccc; - font-family: @font-main; - font-size: 15px; - transition: border-color 0.3s ease; - - &:focus { - border-color: @color-primary; - } - - &:hover { - border-color: darken(#ccc, 10%); - } - &::placeholder { - font-style: italic; - color: #999; - } - } - &__row { - display: flex; - gap: 20px; - justify-content: space-between; - } - &__input--half { - width: 100%; - } - &__radio-group { - display: flex; - justify-content: space-between; - margin-bottom: 20px; - margin-top: 20px; - } - &__radio-label { - display: flex; - align-items: center; - cursor: pointer; - color: @color-text-dark; - position: relative; - padding-left: 30px; - flex: 1; - - &:hover { - .form__custom-radio { - border-color: lighten(@color-accent, 10%); - } - } - } - &__radio-input { - position: absolute; - opacity: 0; - cursor: pointer; - } - &__custom-radio { - position: absolute; - left: 0; - height: 20px; - width: 20px; - background-color: @color-secondary; - border: 2px solid @color-accent; - border-radius: 50%; - transition: border-color 0.3s ease; - } - &__radio-input:checked ~ &__custom-radio { - background-color: @color-accent; - - &:after { - content: ""; - position: absolute; - display: block; - top: 4px; - left: 4px; - width: 8px; - height: 8px; - border-radius: 50%; - background: white; - } - } -} - -.divider { - height: 1px; - background-color: #999; - margin: 20px 0; -} - -.promo { - display: flex; - margin-bottom: 20px; - - &__input { - flex: 1; - padding: 10px; - border: 1px solid #000; - background-color: @color-secondary; - font-family: @font-main; - height: auto; - min-height: 48px; - - &:hover { - border-color: @color-primary; - } - - &::placeholder { - font-style: italic; - color: #999; - } - } - - &__btn { - background-color: @color-accent; - color: @color-secondary; - border: none; - padding: 10px 60px; - cursor: pointer; - font-family: @font-main; - font-size: 18px; - transition: all 0.3s ease; - - &:hover { - background-color: lighten(@color-accent, 10%); - transform: translateY(-2px); - } - } -} - -.summary { - margin-bottom: 20px; - - &__item { - display: flex; - justify-content: space-between; - margin-bottom: 10px; - color: @color-text-dark; - - &.total { - font-weight: bold; - font-size: 18px; - padding-top: 10px; - margin-top: 10px; - } - } -} - -.order-btn { - width: 100%; - background-color: @color-accent; - color: @color-secondary; - border: none; - padding: 15px; - border-radius: 4px; - font-size: 18px; - cursor: pointer; - margin-bottom: 10px; - font-family: @font-main; - transition: all 0.3s ease; - - &:hover { - background-color: lighten(@color-accent, 10%); - transform: translateY(-2px); - } -} - -.privacy { - display: flex; - gap: 8px; - font-size: 16px; - color: #666; - margin-bottom: 20px; - - input[type="checkbox"] { - width: 18px; - height: 18px; - cursor: pointer; - } -} - -.services { - display: flex; - flex-direction: row; - justify-content: center; - flex-wrap: wrap; - gap: 24px; - margin-bottom: 24px; - - &__title { - font-family: @font-logo; - margin-bottom: 10px; - font-size: 18px; - color: @color-text-dark; - display: block; - width: 100%; - } - - &__item { - display: flex; - justify-content: space-between; - margin-bottom: 8px; - color: @color-text-dark; - width: 100%; - } -} - -.cart-icon { - position: relative; -} - -.cart-count { - position: absolute; - top: -8px; - right: -8px; - background: @color-accent; - color: @color-text-light; - border-radius: 50%; - width: 18px; - height: 18px; - font-size: 12px; - display: flex; - align-items: center; - justify-content: center; -} - -.form__input.error { - border-color: #ff4444; - box-shadow: 0 0 5px rgba(255, 68, 68, 0.3); -} - -.empty-cart { - text-align: center; - padding: 40px; - color: #666; - font-size: 18px; -} - -// ======================= -// === АВТОРИЗАЦИЯ === -// ======================= -.profile-page-main { - .flex-center(); - min-height: 80vh; - padding: 40px 0; - background-color: lighten(@color-secondary, 5%); - z-index: 1; - - .profile-container { - display: flex; - width: 100%; - max-width: 1000px; - min-height: 600px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); - background-color: @color-text-light; - } - - .profile-left-col { - flex: 0 0 35%; - background-color: @color-primary; - color: @color-text-light; - display: flex; - justify-content: flex-start; - align-items: flex-start; - padding: 40px; - .logo { - font-size: 32px; - font-weight: normal; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4); - color: @color-text-light; - } - } - - .profile-right-col { - flex: 0 0 65%; - .flex-center(); - padding: 40px; - .profile-form-block { - width: 100%; - max-width: 400px; - h2 { - font-size: 28px; - font-weight: normal; - margin-bottom: 40px; - text-align: left; - color: @color-text-dark; - } - } - } - - .profile-form { - .input-group { - margin-bottom: 20px; - label { - display: block; - font-size: 12px; - font-weight: bold; - color: @color-text-dark; - margin-bottom: 5px; - text-transform: uppercase; - } - } - - input[type="text"], - input[type="email"], - input[type="tel"] { - .input-base(); - } - - .password-link { - display: block; - text-align: left; - font-size: 13px; - color: @color-text-dark; - text-decoration: underline; - margin: 10px 0 20px; - &:hover { - color: @color-accent; - text-decoration: none; - } - } - - .save-btn { - padding: 15px 30px; - border: none; - cursor: pointer; - font-size: 15px; - text-transform: uppercase; - transition: all 0.3s ease; - font-family: @font-main; - width: 100%; - margin-top: 20px; - background-color: @color-primary; - color: @color-text-light; - - &:hover { - background-color: lighten(@color-primary, 10%); - transform: translateY(-2px); - box-shadow: @shadow-light; - } - } - - .auth-actions { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 25px; - padding-top: 20px; - border-top: 1px solid #eee; - - .auth-text { - font-size: 13px; - color: @color-text-dark; - } - - .login-btn { - background-color: transparent; - color: @color-accent; - border: 1px solid @color-accent; - padding: 10px 25px; - font-size: 13px; - cursor: pointer; - transition: all 0.3s ease; - - &:hover { - background-color: @color-primary; - color: @color-text-light; - } - } - } - } -} - -// ======================= -// === СЕКЦИЯ УСЛУГ === -// ======================= -.services-section { - padding: 60px 0; - background-color: @color-secondary; -} - -.services__wrapper { - display: flex; - flex-direction: column; - gap: 30px; -} - -.services__top-row { - display: flex; - gap: 30px; - justify-content: center; - - @media (max-width: 768px) { - flex-direction: column; - align-items: center; - } -} - -.service-card { - border-radius: 8px; - padding: 40px; - min-height: 200px; - text-align: center; - transition: all 0.3s ease; - - &:hover { - transform: translateY(-5px); - box-shadow: @shadow-light; - } - - &--green { - background: @color-primary; - color: @color-text-light; - flex: 1; - max-width: 450px; - } - - &--beige { - background: @color-beige; - color: @color-text-light; - width: 100%; - max-width: 930px; - margin: 0 auto; - } - - &__title { - font-family: @font-logo; - font-size: 24px; - font-weight: bold; - margin-bottom: 15px; - text-transform: uppercase; - } - - &__text { - font-family: @font-main; - font-size: 16px; - line-height: 1.6; - margin: 0; - } -} - -// ======================= -// === ФУТЕР === -// ======================= -.footer { - background-color: @color-primary; - color: black; - padding: 40px 0 10px; - position: relative; - z-index: 1000; - - &::before { - content: ''; - display: block; - position: absolute; - top: -80px; - left: 0; - width: 100%; - height: 1px; - visibility: hidden; - } - - &__content { - display: flex; - gap: 20px; - padding-bottom: 30px; - border-bottom: 1px solid rgba(255, 255, 255, 0.2); - } - - &__col { - flex: 1; - &--logo { flex: 1.5; } - h5 { - margin-bottom: 15px; - font-size: 14px; - text-transform: uppercase; - } - ul li { - margin-bottom: 8px; - a:hover { text-decoration: underline; } - } - .social-icons, - .payment-icons { - .flex-center(15px); - justify-content: flex-start; - margin-top: 10px; - } - .social-icons .icon { - .icon-base(20px, 1.1); - color: black; - &:hover { color: @color-accent; } - } - .payment-icons .pay-icon { - .icon-base(24px, 1.05); - color: black; - } - } - - .copyright { - text-align: center; - font-size: 12px; - padding-top: 20px; - color: rgba(255, 255, 255, 0.6); - } -} - -// ======================= -// === ДОСТАВКА === -// ======================= -.delivery-content { - max-width: 1200px; - margin: 0 auto; - padding: 40px 20px; -} - -.delivery-content h1 { - font-family: @font-logo; - font-size: 42px; - text-align: center; - margin-bottom: 50px; - color: #453227; -} - -.delivery-section { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 30px; - margin-bottom: 60px; -} - -.delivery-card { - background: white; - padding: 30px; - border-radius: 12px; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); - text-align: center; - transition: transform 0.3s ease; - flex: 1; - min-width: 350px; - max-width: 400px; -} - -.delivery-card:hover { - transform: translateY(-5px); -} - -.delivery-icon { - font-size: 48px; - color: #617365; - margin-bottom: 20px; -} - -.delivery-card h3 { - font-family: @font-logo; - font-size: 24px; - margin-bottom: 20px; - color: #453227; -} - -.delivery-details { - text-align: left; -} - -.detail-item { - display: flex; - justify-content: space-between; - margin-bottom: 12px; - padding-bottom: 12px; - border-bottom: 1px solid #f0f0f0; -} - -.detail-label { - font-weight: bold; - color: #333; -} - -.detail-value { - color: #617365; - text-align: right; -} - -// ======================= -// === ГАРАНТИЯ === -// ======================= -.warranty-content { - max-width: 1200px; - margin: 0 auto; - padding: 40px 20px; -} - -.warranty-content h1 { - font-family: 'Anek Kannada', sans-serif; - font-size: 42px; - text-align: center; - margin-bottom: 50px; - color: #453227; -} - -.warranty-overview { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 25px; - margin-bottom: 60px; -} - -.warranty-card { - background: white; - padding: 30px; - border-radius: 12px; - text-align: center; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); - transition: transform 0.3s ease; - flex: 1; - min-width: 250px; - max-width: 280px; - display: flex; - flex-direction: column; - align-items: center; -} - -.warranty-card:hover { - transform: translateY(-5px); -} - -.warranty-icon { - font-size: 48px; - color: #617365; - margin-bottom: 20px; -} - -.warranty-card h3 { - font-family: 'Anek Kannada', sans-serif; - font-size: 20px; - margin-bottom: 15px; - color: #453227; -} - -.warranty-period { - font-size: 24px; - font-weight: bold; - color: #617365; - margin-top: auto; -} - -.coverage-section { - display: flex; - flex-wrap: wrap; - gap: 40px; - margin-bottom: 60px; -} - -.coverage-covered, -.coverage-not-covered { - flex: 1; - min-width: 300px; -} - -.coverage-section h2 { - font-family: 'Anek Kannada', sans-serif; - font-size: 24px; - margin-bottom: 25px; - color: #453227; -} - -.coverage-list { - display: flex; - flex-direction: column; - gap: 20px; -} - -.coverage-item { - display: flex; - align-items: flex-start; - gap: 15px; - padding: 20px; - border-radius: 8px; - background: white; - box-shadow: 0 3px 10px rgba(0,0,0,0.1); -} - -.coverage-item.covered i { - color: #28a745; - font-size: 20px; - margin-top: 2px; - flex-shrink: 0; -} - -.coverage-item.not-covered i { - color: #dc3545; - font-size: 20px; - margin-top: 2px; - flex-shrink: 0; -} - -.coverage-text { - flex: 1; -} - -.coverage-item h4 { - font-family: 'Anek Kannada', sans-serif; - font-size: 16px; - margin-bottom: 5px; - color: #333; -} - -.card { - min-height: 250px; - display: flex; - align-items: center; - justify-content: center; - color: @color-text-light; - text-align: center; - - &--green { - background: @color-primary; - flex: 0 1 450px; - max-width: 450px; - } - - &--beige { - background: @color-beige; - color: @color-text-dark; - flex: 0 1 925px; - max-width: 925px; - } -} - -.design-section { - display: flex; - justify-content: center; - margin-bottom: 40px; - .card { width: 100%; } -} - -// ======================= -// === АДАПТИВНОСТЬ === -// ======================= -@media (max-width: 1240px) { - .catalog-wrapper { gap: 20px; } - .catalog-sidebar { flex: 0 0 200px; } - .products-container { - gap: 15px; - display: flex; - flex-wrap: wrap; - } - - .product-card.small1 { - margin-top: 100px; - } - - .product-card.small, - .product-card.small1, - .product-card.large, - .product-card.wide, - .product-card.wide1, - .product-card.wide2, - .product-card.wide2_1, - .product-card.wide4 { - flex: 0 0 calc(33.333% - 10px); - max-width: calc(33.333% - 10px); - height: 180px; - margin: 0; - - .product-image-container { - height: 180px; - } - } - - .product-card.wide3 { - flex: 0 0 calc(25% - 10px); - max-width: calc(25% - 10px); - height: 300px; - margin: 0; - - .product-image-container { - height: 350px; - } - } - - .product-card.tall { - flex: 0 0 calc(25% - 10px); - max-width: calc(25% - 10px); - height: 300px; - margin: 0; - - .product-image-container { - height: 300px; - } - } - - .product-card.full-width { - flex: 0 0 100%; - max-width: 100%; - height: 300px; - margin: 0; - - .product-image-container { - height: 300px; - } - } - - .product-card.small { order: 1; } - .product-card.large { order: 2; } - .product-card.wide { order: 3; } - - .product-card.small1 { order: 11; } - .product-card.wide2 { order: 12; } - .product-card.wide2_1 { order: 13; } - - .product-card.wide3 { order: 21; } - .product-card.tall { order: 22; } - - .product-card.wide3 { order: 31; } - - .product-card.full-width { order: 41; flex-basis: 100%; } - - .main__content { - gap: 20px; - .products { - flex: 0 0 35%; - .products__image { - width: 250px; - height: 180px; - } - } - .order { - flex: 0 0 60%; - padding: 30px; - - .order__title { - font-size: 24px; - } - - .order__section-title { - font-size: 16px; - } - } - } - - .solutions-slider { - &__slide { - .solution-text-overlay { - top: 10%; - left: 5%; - h2 { - font-size: 26px; - margin-bottom: 5px; - line-height: 1.2; - } - p { - font-size: 18px; - line-height: 1.2; - } - } - .solution-image-link { - bottom: 70px; - padding: 10px 25px; - font-size: 14px; - } - } - } - - .product__image { - width: 350px; - height: 250px; - } - - .product__thumbnail img { - width: 170px; - height: 120px; - } -} - -@media (max-width: 1024px) { - .main__content { - gap: 25px; - .products { - flex: 0 0 30%; - .products__image { - width: 200px; - height: 150px; - } - - .products__name { - font-size: 16px; - } - - .products__price { - font-size: 16px; - } - } - .order { - flex: 0 0 60%; - padding: 25px; - - .order__title { - font-size: 22px; - } - - .form__input { - padding: 12px 14px; - font-size: 14px; - } - - .promo__btn { - padding: 10px 40px; - font-size: 16px; - } - } - } -} - -@media (max-width: 768px) { - .container { padding: 0 15px; } - - .delivery-section { - flex-direction: column; - align-items: center; - } - - .delivery-card { - min-width: 100%; - max-width: 100%; - } - - .delivery-content h1 { - font-size: 32px; - } - - .warranty-overview { - flex-direction: column; - align-items: center; - } - - .warranty-card { - max-width: 100%; - width: 100%; - } - - .coverage-section { - flex-direction: column; - } - - .warranty-content h1 { - font-size: 32px; - } - - .header__top .container, - .header__bottom .container, - .hero__content, - .advantages__header, - .about__content, - .advantages__items, - .promo-images, - .stats__items, - .faq__items, - .catalog-wrapper, - .main__content { - flex-direction: column; - gap: 30px; - } - - .search-catalog { - order: 3; - width: 100%; - max-width: 100%; - } - - .nav-list { - flex-wrap: wrap; - justify-content: center; - gap: 15px; - } - - .hero { - &__image-block { - flex: none; - max-width: 400px; - height: 400px; - } - &__circle { - width: 380px; - height: 380px; - } - &__text-block { - flex: none; - padding-left: 0; - text-align: center; - h1 { font-size: 32px; } - .hero__usp-text { - padding-left: 0; - justify-content: center; - &::before { display: none; } - } - .btn.primary-btn { margin-left: 0; } - } - } - - .advantages__header h2, - .faq h2 { font-size: 28px; } - - .faq-item, - .stat-item { - flex: none; - .flex-center(); - text-align: center; - } - - .stats .container { justify-content: center; } - .catalog-dropdown__menu { width: 200px; } - - .catalog-sidebar { width: 100%; flex: none; } - .products-container { gap: 15px; } - - .product-card.small, - .product-card.small1, - .product-card.large, - .product-card.wide, - .product-card.wide1, - .product-card.wide2, - .product-card.wide2_1, - .product-card.wide3, - .product-card.wide4, - .product-card.tall, - .product-card.full-width { - flex: 0 0 100%; - max-width: 100%; - height: 250px; - margin: 0; - - .product-image-container { - height: 200px; - } - } - - .main__content { - flex-direction: column; - gap: 20px; - - .products, - .order { - flex: 0 0 100%; - width: 100%; - } - - .products { - .products__item { - flex-direction: column; - text-align: center; - gap: 15px; - } - - .products__image { - width: 100%; - height: 200px; - justify-content: center; - } - - .products__details { - min-height: auto; - align-items: center; - } - - .products__controls { - justify-content: center; - margin-top: 15px; - } - - .products__cart-icon { - margin-left: 0; - } - } - - .order { - padding: 20px; - - .order__title { - font-size: 20px; - text-align: center; - } - - .order__total { - text-align: center; - } - - .form__radio-group { - flex-direction: column; - gap: 15px; - } - - .form__radio-label { - flex: none; - justify-content: flex-start; - } - - .promo { - flex-direction: column; - gap: 10px; - - &__btn { - width: 100%; - padding: 12px; - } - } - - .order-btn { - padding: 12px; - font-size: 16px; - } - - .services { - flex-direction: column; - align-items: center; - } - } - } - - .product-image-container { height: 200px; } - .product-card.tall .product-image-container, - .product-card.large .product-image-container { height: 250px; } - - .profile-page-main { - .profile-container { - flex-direction: column; - min-height: auto; - max-width: 100%; - box-shadow: none; - } - .profile-left-col { - flex: none; - width: 100%; - height: 100px; - .flex-center(); - padding: 0; - } - .profile-right-col { - flex: none; - width: 100%; - padding: 30px 20px; - } - .profile-form-block { max-width: 100%; } - } - - .form__row { flex-direction: column; } - .form__input--half { flex: 0 0 100%; max-width: 100%; } - .services { flex-direction: column; align-items: center; } - - .services-section { - padding: 40px 0; - } - - .service-card { - padding: 30px 20px; - min-height: 180px; - - &--green, - &--beige { - max-width: 100%; - } - - &__title { - font-size: 20px; - } - - &__text { - font-size: 14px; - } - } - .solutions-slider { - margin: 20px auto; - &__slide { - .solution-text-overlay { - top: 8%; - left: 4%; - h2 { - font-size: 20px; - margin-bottom: 3px; - line-height: 1.1; - } - p { - font-size: 15px; - line-height: 1.1; - } - } - .solution-image-link { - bottom: 90px; - padding: 8px 20px; - font-size: 13px; - } - } - } -} - -// Стили для ошибок полей -.error-input { - border-color: #ff4444 !important; - box-shadow: 0 0 0 1px #ff4444; -} - -.field-error { - color: #ff4444; - font-size: 12px; - margin-top: 5px; - margin-bottom: 10px; -} - -// Стили для сообщений -.message { - padding: 15px; - margin: 20px 0; - border-radius: 5px; - display: none; -} - -.message.error { - background-color: #ffebee; - color: #c62828; - border: 1px solid #ffcdd2; -} - -.message.success { - background-color: #e8f5e9; - color: #2e7d32; - border: 1px solid #c8e6c9; -} - -// Добавьте в конец файла -.access-denied { - text-align: center; - padding: 80px 20px; - background: white; - border-radius: 10px; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); - margin: 50px 0; - - h2 { - color: #dc3545; - margin-bottom: 30px; - font-size: 28px; - } - - p { - color: #666; - margin-bottom: 40px; - font-size: 18px; - line-height: 1.6; - } - - .btn { - margin: 5px; - min-width: 200px; - } -} -// ======================= -// === ПРОФИЛЬ ПОЛЬЗОВАТЕЛЯ === -// ======================= - -.user-profile-dropdown { - position: relative; - display: inline-block; - - &__toggle { - display: flex; - align-items: center; - gap: 8px; - cursor: pointer; - padding: 8px 12px; - border-radius: 4px; - transition: all 0.3s ease; - - &:hover { - background-color: rgba(0, 0, 0, 0.05); - } - - .user-avatar { - width: 32px; - height: 32px; - border-radius: 50%; - background-color: @color-primary; - color: @color-text-light; - .flex-center(); - font-weight: bold; - } - - .user-info { - display: flex; - flex-direction: column; - - .user-email { - font-size: 12px; - color: #666; - max-width: 150px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .user-status { - font-size: 10px; - padding: 2px 6px; - border-radius: 10px; - text-transform: uppercase; - - &.admin { - background-color: #617365; - color: white; - } - - &.user { - background-color: #28a745; - color: white; - } - } - } - } - - &__menu { - .menu-base(); - width: 220px; - top: 100%; - right: 0; - - .user-details { - padding: 15px; - border-bottom: 1px solid #eee; - - .user-name { - font-weight: bold; - margin-bottom: 5px; - } - - .user-registered { - font-size: 11px; - color: #999; - } - } - - ul { - padding: 10px 0; - - li { - padding: 8px 15px; - cursor: pointer; - display: flex; - align-items: center; - gap: 10px; - transition: background-color 0.3s ease; - - &:hover { - background-color: #f5f5f5; - } - - &.logout { - color: #dc3545; - border-top: 1px solid #eee; - margin-top: 5px; - padding-top: 12px; - - &:hover { - background-color: #ffe6e6; - } - } - } - } - } - - &:hover &__menu { - display: block; - } -} - -// ======================= -// === КАРТОЧКА ТОВАРА === -// ======================= - -.product-image-container { - position: relative; - overflow: hidden; - margin-bottom: 0; - padding: 0; - height: 250px; - .flex-center(); - - &:hover { - .product-overlay-info { - opacity: 1; - transform: translateY(0); - } - } -} - -.product-overlay-info { - position: absolute; - bottom: 0; - left: 0; - right: 0; - background: linear-gradient(to top, rgba(0,0,0,0.8), transparent); - color: white; - padding: 15px; - opacity: 0; - transform: translateY(10px); - transition: all 0.3s ease; - - .product-overlay-name { - font-weight: bold; - font-size: 14px; - margin-bottom: 5px; - } - - .product-overlay-price { - font-size: 16px; - font-weight: bold; - - .old-price { - text-decoration: line-through; - font-size: 12px; - color: #ccc; - margin-right: 5px; - } - - .current-price { - color: #ffd700; - } - } - - .product-overlay-category { - font-size: 11px; - opacity: 0.8; - margin-top: 3px; - } - - .product-overlay-stock { - font-size: 11px; - margin-top: 5px; - - &.out-of-stock { - color: #ff6b6b; - } - - i { - margin-right: 5px; - } - } -} - -.product-card-details { - padding: 15px; - background: white; - flex-grow: 1; - display: flex; - flex-direction: column; - - .product-card-name { - font-weight: bold; - font-size: 16px; - margin-bottom: 8px; - color: @color-text-dark; - } - - .product-card-description { - font-size: 13px; - color: #777; - margin-bottom: 10px; - flex-grow: 1; - } - - .product-card-attributes { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-bottom: 10px; - - .attribute { - font-size: 11px; - background: #f5f5f5; - padding: 3px 8px; - border-radius: 12px; - color: #666; - - i { - margin-right: 3px; - } - } - } - - .product-card-price { - margin-bottom: 10px; - - .old-price { - text-decoration: line-through; - font-size: 14px; - color: #999; - margin-right: 8px; - } - - .current-price { - font-size: 18px; - font-weight: bold; - color: @color-button; - } - } - - .add-to-cart-btn { - width: 100%; - padding: 8px; - font-size: 14px; - } - - .admin-actions { - display: flex; - gap: 5px; - margin-top: 10px; - - .admin-btn { - flex: 1; - font-size: 12px; - padding: 6px; - - &.delete-btn { - background: #dc3545; - - &:hover { - background: #c82333; - } - } - } - } -} - -// ======================= -// === ПРОФИЛЬ ПОЛЬЗОВАТЕЛЯ === -// ======================= - -.user-profile-dropdown { - position: relative; - display: inline-block; - - .user-profile-toggle { - display: flex; - align-items: center; - gap: 10px; - cursor: pointer; - padding: 8px 12px; - border-radius: 4px; - transition: all 0.3s ease; - - &:hover { - background-color: rgba(0, 0, 0, 0.05); - - .dropdown-arrow { - transform: rotate(180deg); - } - } - - .user-avatar { - width: 36px; - height: 36px; - border-radius: 50%; - background: linear-gradient(135deg, #617365 0%, #453227 100%); - color: @color-text-light; - .flex-center(); - font-weight: bold; - font-size: 16px; - box-shadow: 0 2px 5px rgba(0,0,0,0.2); - } - - .user-info { - display: flex; - flex-direction: column; - - .user-email { - font-size: 12px; - color: #666; - max-width: 120px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .user-status { - font-size: 10px; - padding: 2px 8px; - border-radius: 12px; - text-transform: uppercase; - font-weight: bold; - text-align: center; - margin-top: 2px; - - &.admin { - background-color: #617365; - color: white; - border: 1px solid #617365; - } - - &.user { - background-color: #28a745; - color: white; - border: 1px solid #28a745; - } - } - } - - .dropdown-arrow { - font-size: 10px; - color: #666; - transition: transform 0.3s ease; - } - } - - .user-profile-menu { - .menu-base(); - width: 280px; - top: 100%; - right: 0; - margin-top: 10px; - padding: 0; - overflow: hidden; - - .user-profile-header { - padding: 20px; - background: linear-gradient(135deg, #617365 0%, #453227 100%); - color: white; - - .user-profile-name { - font-weight: bold; - margin-bottom: 8px; - display: flex; - align-items: center; - gap: 10px; - font-size: 16px; - } - - .user-profile-details { - small { - display: block; - opacity: 0.8; - margin-bottom: 5px; - font-size: 11px; - - i { - margin-right: 5px; - width: 14px; - text-align: center; - } - } - } - } - - .user-profile-links { - list-style: none; - padding: 10px 0; - - li { - border-bottom: 1px solid #f0f0f0; - - &:last-child { - border-bottom: none; - } - - a { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 20px; - color: #333; - transition: all 0.3s ease; - - &:hover { - background-color: #f8f9fa; - color: @color-primary; - text-decoration: none; - - i { - transform: scale(1.1); - } - } - - i { - width: 20px; - text-align: center; - font-size: 14px; - color: #617365; - transition: transform 0.3s ease; - } - - span { - flex-grow: 1; - } - } - } - - .logout-item { - border-top: 2px solid #f0f0f0; - margin-top: 5px; - - a { - color: #dc3545; - - &:hover { - background-color: #ffe6e6; - color: #c82333; - - i { - color: #dc3545; - } - } - } - } - } - } - - &:hover .user-profile-menu { - display: block; - animation: fadeIn 0.3s ease; - } -} - -@keyframes fadeIn { - from { - opacity: 0; - transform: translateY(-10px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -// Для мобильных устройств -@media (max-width: 768px) { - .user-profile-dropdown { - .user-profile-toggle { - .user-info { - display: none; - } - - .dropdown-arrow { - display: none; - } - } - - .user-profile-menu { - width: 250px; - right: -50px; - } - } -} -// Добавьте в конец файла -.unavailable-product { - position: relative; - opacity: 0.6; - filter: grayscale(0.7); - - &::before { - content: "ТОВАР ЗАКОНЧИЛСЯ"; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background: rgba(0, 0, 0, 0.85); - color: white; - padding: 15px 25px; - border-radius: 5px; - font-weight: bold; - font-size: 16px; - text-align: center; - z-index: 100; - white-space: nowrap; - pointer-events: none; - box-shadow: 0 4px 12px rgba(0,0,0,0.3); - } - - .product-name-overlay { - .name, .price { - color: #999 !important; - text-shadow: none !important; - } - } - - .add-to-cart-btn { - display: none !important; - } - - &:hover { - transform: none !important; - cursor: not-allowed; - } -} - -.out-of-stock-badge { - position: absolute; - top: 10px; - left: 10px; - background: #6c757d; - color: white; - padding: 5px 10px; - border-radius: 4px; - font-size: 12px; - font-weight: bold; - z-index: 10; -} - -// Для админ-таблицы -.admin-table tr.unavailable { - background-color: #f8f9fa !important; - opacity: 0.7; - - td { - color: #999; - } -} - -.status-unavailable { - background-color: #6c757d !important; - color: white !important; -} \ No newline at end of file diff --git a/OLD_CODE/config/check_auth.js b/OLD_CODE/config/check_auth.js deleted file mode 100644 index a4e0551..0000000 --- a/OLD_CODE/config/check_auth.js +++ /dev/null @@ -1,107 +0,0 @@ - -$(document).ready(function() { - - checkAuthStatus(); - - $('#loginForm').on('submit', function(e) { - e.preventDefault(); - - const email = $('#login-email').val(); - const password = $('#login-password').val(); - const remember = $('#remember').is(':checked'); - - $.ajax({ - url: 'login_handler.php', - method: 'POST', - data: { - email: email, - password: password - }, - success: function(response) { - try { - const result = JSON.parse(response); - if (result.success) { - - if (remember) { - localStorage.setItem('rememberedEmail', email); - } else { - localStorage.removeItem('rememberedEmail'); - } - - window.location.href = result.redirect || 'catalog.php'; - } else { - showMessage('error', result.message || 'Ошибка авторизации'); - } - } catch(e) { - showMessage('error', 'Ошибка обработки ответа'); - } - }, - error: function() { - showMessage('error', 'Ошибка сервера'); - } - }); - }); - - function checkAuthStatus() { - $.ajax({ - url: 'check_auth_status.php', - method: 'GET', - success: function(response) { - try { - const result = JSON.parse(response); - if (result.loggedIn) { - updateUserProfile(result.user); - } - } catch(e) { - console.error('Ошибка проверки авторизации', e); - } - } - }); - } - - function updateUserProfile(user) { - - if ($('#userEmail').length) { - $('#userEmail').text(user.email); - } - if ($('#userName').length) { - $('#userName').text(user.full_name); - } - } - - function showMessage(type, text) { - const $message = $('#' + type + 'Message'); - if ($message.length) { - $message.text(text).fadeIn(); - setTimeout(() => $message.fadeOut(), 5000); - } else { - alert(text); - } - } - - function checkAuth(redirectUrl) { - $.ajax({ - url: 'check_auth_status.php', - method: 'GET', - success: function(response) { - try { - const result = JSON.parse(response); - if (result.loggedIn) { - window.location.href = redirectUrl; - } else { - - showLoginModal(redirectUrl); - } - } catch(e) { - showLoginModal(redirectUrl); - } - } - }); - return false; - } - - function showLoginModal(redirectUrl) { - - window.location.href = 'вход.php?redirect=' + encodeURIComponent(redirectUrl); - } -}); diff --git a/OLD_CODE/config/database.php b/OLD_CODE/config/database.php deleted file mode 100644 index 7e3062f..0000000 --- a/OLD_CODE/config/database.php +++ /dev/null @@ -1,32 +0,0 @@ -connection = new PDO( - "pgsql:host=185.130.224.177;port=5481;dbname=postgres", - "admin", - "38feaad2840ccfda0e71243a6faaecfd" - ); - $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $this->connection->exec("SET NAMES 'utf8'"); - } catch(PDOException $e) { - die("Ошибка подключения: " . $e->getMessage()); - } - } - - public static function getInstance() { - if (self::$instance == null) { - self::$instance = new Database(); - } - return self::$instance; - } - - public function getConnection() { - return $this->connection; - } -} -?> \ No newline at end of file diff --git a/OLD_CODE/img b/OLD_CODE/img deleted file mode 120000 index 14d6a13..0000000 --- a/OLD_CODE/img +++ /dev/null @@ -1 +0,0 @@ -assets/img \ No newline at end of file diff --git a/OLD_CODE/img2 b/OLD_CODE/img2 deleted file mode 120000 index 14d6a13..0000000 --- a/OLD_CODE/img2 +++ /dev/null @@ -1 +0,0 @@ -assets/img \ No newline at end of file diff --git a/OLD_CODE/includes/auth.php b/OLD_CODE/includes/auth.php deleted file mode 100644 index 5326642..0000000 --- a/OLD_CODE/includes/auth.php +++ /dev/null @@ -1,127 +0,0 @@ -getConnection(); - - try { - $stmt = $db->prepare(" - SELECT user_id, email, password_hash, full_name, phone, city, is_admin, is_active - FROM users WHERE email = ? - "); - $stmt->execute([$email]); - $user = $stmt->fetch(); - - if (!$user) { - return ['success' => false, 'message' => 'Пользователь не найден']; - } - - if (!$user['is_active']) { - return ['success' => false, 'message' => 'Аккаунт заблокирован']; - } - - if (!password_verify($password, $user['password_hash'])) { - return ['success' => false, 'message' => 'Неверный пароль']; - } - - $_SESSION['user_id'] = $user['user_id']; - $_SESSION['user_email'] = $user['email']; - $_SESSION['full_name'] = $user['full_name']; - $_SESSION['user_phone'] = $user['phone'] ?? ''; - $_SESSION['user_city'] = $user['city'] ?? ''; - $_SESSION['isLoggedIn'] = true; - $_SESSION['isAdmin'] = (bool)$user['is_admin']; - $_SESSION['login_time'] = time(); - - $updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?"); - $updateStmt->execute([$user['user_id']]); - - return ['success' => true, 'user' => $user]; - - } catch (PDOException $e) { - return ['success' => false, 'message' => 'Ошибка базы данных']; - } -} - -function registerUser(array $data): array { - $db = Database::getInstance()->getConnection(); - - $email = trim($data['email'] ?? ''); - $password = $data['password'] ?? ''; - $fullName = trim($data['full_name'] ?? ''); - $phone = trim($data['phone'] ?? ''); - $city = trim($data['city'] ?? ''); - - if (empty($email) || empty($password) || empty($fullName)) { - return ['success' => false, 'message' => 'Заполните все обязательные поля']; - } - - if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { - return ['success' => false, 'message' => 'Некорректный email']; - } - - if (strlen($password) < 6) { - return ['success' => false, 'message' => 'Пароль должен содержать минимум 6 символов']; - } - - try { - - $checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?"); - $checkStmt->execute([$email]); - - if ($checkStmt->fetch()) { - return ['success' => false, 'message' => 'Пользователь с таким email уже существует']; - } - - $passwordHash = password_hash($password, PASSWORD_DEFAULT); - - $stmt = $db->prepare(" - INSERT INTO users (email, password_hash, full_name, phone, city, is_active) - VALUES (?, ?, ?, ?, ?, TRUE) - RETURNING user_id - "); - $stmt->execute([$email, $passwordHash, $fullName, $phone, $city]); - $userId = $stmt->fetchColumn(); - - $_SESSION['user_id'] = $userId; - $_SESSION['user_email'] = $email; - $_SESSION['full_name'] = $fullName; - $_SESSION['user_phone'] = $phone; - $_SESSION['user_city'] = $city; - $_SESSION['isLoggedIn'] = true; - $_SESSION['isAdmin'] = false; - $_SESSION['login_time'] = time(); - - return ['success' => true, 'user_id' => $userId]; - - } catch (PDOException $e) { - return ['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]; - } -} - -function logoutUser(): void { - $_SESSION = []; - - if (ini_get("session.use_cookies")) { - $params = session_get_cookie_params(); - setcookie(session_name(), '', time() - 42000, - $params["path"], $params["domain"], - $params["secure"], $params["httponly"] - ); - } - - session_destroy(); -} - -function checkAdminAccess(): bool { - if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) { - return false; - } - - if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) { - return false; - } - - return true; -} diff --git a/OLD_CODE/includes/footer.php b/OLD_CODE/includes/footer.php deleted file mode 100644 index 98e1481..0000000 --- a/OLD_CODE/includes/footer.php +++ /dev/null @@ -1,49 +0,0 @@ - - - diff --git a/OLD_CODE/includes/functions.php b/OLD_CODE/includes/functions.php deleted file mode 100644 index 58d16bb..0000000 --- a/OLD_CODE/includes/functions.php +++ /dev/null @@ -1,97 +0,0 @@ - $_SESSION['user_id'] ?? 0, - 'email' => $_SESSION['user_email'] ?? '', - 'full_name' => $_SESSION['full_name'] ?? '', - 'is_admin' => isAdmin() - ]; -} - -function formatPrice(float $price): string { - return number_format($price, 0, '', ' ') . ' ₽'; -} - -function e(string $str): string { - return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); -} - -function generateOrderNumber(): string { - return 'AET-' . date('Ymd') . '-' . strtoupper(substr(uniqid(), -6)); -} - -function generateSKU(string $productName): string { - $prefix = strtoupper(substr(preg_replace('/[^a-zA-Z0-9]/', '', transliterate($productName)), 0, 6)); - return $prefix . '-' . rand(100, 999); -} - -function transliterate(string $str): string { - $converter = [ - 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', - 'е' => 'e', 'ё' => 'e', 'ж' => 'zh', 'з' => 'z', 'и' => 'i', - 'й' => 'y', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', - 'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', - 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c', 'ч' => 'ch', - 'ш' => 'sh', 'щ' => 'sch', 'ь' => '', 'ы' => 'y', 'ъ' => '', - 'э' => 'e', 'ю' => 'yu', 'я' => 'ya', - 'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', - 'Е' => 'E', 'Ё' => 'E', 'Ж' => 'Zh', 'З' => 'Z', 'И' => 'I', - 'Й' => 'Y', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N', - 'О' => 'O', 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', - 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C', 'Ч' => 'Ch', - 'Ш' => 'Sh', 'Щ' => 'Sch', 'Ь' => '', 'Ы' => 'Y', 'Ъ' => '', - 'Э' => 'E', 'Ю' => 'Yu', 'Я' => 'Ya', - ]; - return strtr($str, $converter); -} - -function createSlug(string $str): string { - $slug = transliterate($str); - $slug = strtolower($slug); - $slug = preg_replace('/[^a-z0-9]+/', '-', $slug); - $slug = trim($slug, '-'); - return $slug; -} - -function setFlashMessage(string $type, string $message): void { - $_SESSION['flash_message'] = [ - 'type' => $type, - 'message' => $message - ]; -} - -function getFlashMessage(): ?array { - if (isset($_SESSION['flash_message'])) { - $message = $_SESSION['flash_message']; - unset($_SESSION['flash_message']); - return $message; - } - return null; -} diff --git a/OLD_CODE/includes/header.php b/OLD_CODE/includes/header.php deleted file mode 100644 index 3f0ac92..0000000 --- a/OLD_CODE/includes/header.php +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - AETERNA - <?= $pageTitle ?? 'Мебель и Интерьер' ?> - - - - - - - - - - -
-
-
- - -
-
- Все категории - -
- -
- -
- - - - - 0 - - - - - - Войти - -
-
-
- - -
- - diff --git a/OLD_CODE/migrations/001_initial_schema.sql b/OLD_CODE/migrations/001_initial_schema.sql deleted file mode 100644 index c57629b..0000000 --- a/OLD_CODE/migrations/001_initial_schema.sql +++ /dev/null @@ -1,73 +0,0 @@ --- 001_initial_schema.sql --- Создание базовых таблиц для AETERNA - --- Таблица пользователей -CREATE TABLE IF NOT EXISTS users ( - user_id SERIAL PRIMARY KEY, - email VARCHAR(255) UNIQUE NOT NULL, - password_hash VARCHAR(255) NOT NULL, - full_name VARCHAR(100) NOT NULL, - phone VARCHAR(20), - city VARCHAR(100), - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - last_login TIMESTAMP, - is_active BOOLEAN DEFAULT TRUE, - is_admin BOOLEAN DEFAULT FALSE -); - --- Таблица категорий -CREATE TABLE IF NOT EXISTS categories ( - category_id SERIAL PRIMARY KEY, - name VARCHAR(100) NOT NULL, - slug VARCHAR(100) UNIQUE NOT NULL, - parent_id INTEGER REFERENCES categories(category_id) ON DELETE SET NULL, - description TEXT, - sort_order INTEGER DEFAULT 0, - is_active BOOLEAN DEFAULT TRUE, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); - --- Таблица подкатегорий -CREATE TABLE IF NOT EXISTS subcategories ( - subcategory_id SERIAL PRIMARY KEY, - category_id INTEGER REFERENCES categories(category_id) ON DELETE CASCADE, - name VARCHAR(100) NOT NULL, - slug VARCHAR(100) UNIQUE NOT NULL, - description TEXT, - sort_order INTEGER DEFAULT 0, - is_active BOOLEAN DEFAULT TRUE, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); - --- Таблица товаров -CREATE TABLE IF NOT EXISTS products ( - product_id SERIAL PRIMARY KEY, - category_id INTEGER REFERENCES categories(category_id) ON DELETE SET NULL, - name VARCHAR(200) NOT NULL, - slug VARCHAR(200) UNIQUE NOT NULL, - description TEXT, - price DECIMAL(10, 2) NOT NULL, - old_price DECIMAL(10, 2), - sku VARCHAR(50) UNIQUE, - stock_quantity INTEGER DEFAULT 0, - is_available BOOLEAN DEFAULT TRUE, - is_featured BOOLEAN DEFAULT FALSE, - rating DECIMAL(3, 2) DEFAULT 0, - review_count INTEGER DEFAULT 0, - image_url VARCHAR(500), - color VARCHAR(50), - material VARCHAR(100), - card_size VARCHAR(20) DEFAULT 'small', - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); - --- Индексы для быстрого поиска -CREATE INDEX IF NOT EXISTS idx_products_category ON products(category_id); -CREATE INDEX IF NOT EXISTS idx_products_available ON products(is_available); -CREATE INDEX IF NOT EXISTS idx_products_price ON products(price); -CREATE INDEX IF NOT EXISTS idx_categories_parent ON categories(parent_id); -CREATE INDEX IF NOT EXISTS idx_categories_active ON categories(is_active); - diff --git a/OLD_CODE/migrations/002_add_cart_orders.sql b/OLD_CODE/migrations/002_add_cart_orders.sql deleted file mode 100644 index e4bf13c..0000000 --- a/OLD_CODE/migrations/002_add_cart_orders.sql +++ /dev/null @@ -1,70 +0,0 @@ --- 002_add_cart_orders.sql --- Таблицы для корзины и заказов - --- Таблица корзины -CREATE TABLE IF NOT EXISTS cart ( - cart_id SERIAL PRIMARY KEY, - user_id INTEGER REFERENCES users(user_id) ON DELETE CASCADE, - product_id INTEGER REFERENCES products(product_id) ON DELETE CASCADE, - quantity INTEGER DEFAULT 1 CHECK (quantity > 0), - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - UNIQUE(user_id, product_id) -); - --- Таблица заказов -CREATE TABLE IF NOT EXISTS orders ( - order_id SERIAL PRIMARY KEY, - order_number VARCHAR(50) UNIQUE NOT NULL, - user_id INTEGER REFERENCES users(user_id) ON DELETE SET NULL, - - -- Контактная информация - customer_name VARCHAR(100) NOT NULL, - customer_email VARCHAR(255) NOT NULL, - customer_phone VARCHAR(20) NOT NULL, - - -- Адрес доставки - delivery_address TEXT NOT NULL, - delivery_region VARCHAR(100), - postal_code VARCHAR(20), - - -- Способы - delivery_method VARCHAR(50) DEFAULT 'courier', - payment_method VARCHAR(50) DEFAULT 'card', - - -- Суммы - subtotal DECIMAL(10, 2) NOT NULL, - discount_amount DECIMAL(10, 2) DEFAULT 0, - delivery_price DECIMAL(10, 2) DEFAULT 0, - final_amount DECIMAL(10, 2) NOT NULL, - - -- Промокод - promo_code VARCHAR(50), - - -- Статус и даты - status VARCHAR(30) DEFAULT 'pending', - notes TEXT, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - completed_at TIMESTAMP -); - --- Таблица позиций заказа -CREATE TABLE IF NOT EXISTS order_items ( - item_id SERIAL PRIMARY KEY, - order_id INTEGER REFERENCES orders(order_id) ON DELETE CASCADE, - product_id INTEGER REFERENCES products(product_id) ON DELETE SET NULL, - product_name VARCHAR(200) NOT NULL, - product_price DECIMAL(10, 2) NOT NULL, - quantity INTEGER NOT NULL CHECK (quantity > 0), - total_price DECIMAL(10, 2) NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); - --- Индексы -CREATE INDEX IF NOT EXISTS idx_cart_user ON cart(user_id); -CREATE INDEX IF NOT EXISTS idx_orders_user ON orders(user_id); -CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status); -CREATE INDEX IF NOT EXISTS idx_orders_created ON orders(created_at); -CREATE INDEX IF NOT EXISTS idx_order_items_order ON order_items(order_id); - diff --git a/OLD_CODE/migrations/003_add_product_fields.sql b/OLD_CODE/migrations/003_add_product_fields.sql deleted file mode 100644 index 3fbb9ba..0000000 --- a/OLD_CODE/migrations/003_add_product_fields.sql +++ /dev/null @@ -1,57 +0,0 @@ --- 003_add_product_fields.sql --- Добавление дополнительных полей (если таблицы уже существуют) - --- Добавляем поля в products если их нет -DO $$ -BEGIN - -- color - IF NOT EXISTS (SELECT 1 FROM information_schema.columns - WHERE table_name = 'products' AND column_name = 'color') THEN - ALTER TABLE products ADD COLUMN color VARCHAR(50); - END IF; - - -- material - IF NOT EXISTS (SELECT 1 FROM information_schema.columns - WHERE table_name = 'products' AND column_name = 'material') THEN - ALTER TABLE products ADD COLUMN material VARCHAR(100); - END IF; - - -- card_size - IF NOT EXISTS (SELECT 1 FROM information_schema.columns - WHERE table_name = 'products' AND column_name = 'card_size') THEN - ALTER TABLE products ADD COLUMN card_size VARCHAR(20) DEFAULT 'small'; - END IF; -END $$; - --- Добавляем поля в users если их нет -DO $$ -BEGIN - -- city - IF NOT EXISTS (SELECT 1 FROM information_schema.columns - WHERE table_name = 'users' AND column_name = 'city') THEN - ALTER TABLE users ADD COLUMN city VARCHAR(100); - END IF; - - -- last_login - IF NOT EXISTS (SELECT 1 FROM information_schema.columns - WHERE table_name = 'users' AND column_name = 'last_login') THEN - ALTER TABLE users ADD COLUMN last_login TIMESTAMP; - END IF; -END $$; - --- Добавляем поля в categories если их нет -DO $$ -BEGIN - -- updated_at - IF NOT EXISTS (SELECT 1 FROM information_schema.columns - WHERE table_name = 'categories' AND column_name = 'updated_at') THEN - ALTER TABLE categories ADD COLUMN updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP; - END IF; - - -- created_at - IF NOT EXISTS (SELECT 1 FROM information_schema.columns - WHERE table_name = 'categories' AND column_name = 'created_at') THEN - ALTER TABLE categories ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP; - END IF; -END $$; - diff --git a/OLD_CODE/migrations/004_grant_admin_to_admin_mail.sql b/OLD_CODE/migrations/004_grant_admin_to_admin_mail.sql deleted file mode 100644 index 2ccf98c..0000000 --- a/OLD_CODE/migrations/004_grant_admin_to_admin_mail.sql +++ /dev/null @@ -1,50 +0,0 @@ --- 004_grant_admin_to_admin_mail.sql --- Миграция: Назначение прав администратора пользователю admin@mail.ru - --- Обновляем пользователя admin@mail.ru, давая ему права администратора -UPDATE users -SET is_admin = TRUE, - is_active = TRUE, - updated_at = CURRENT_TIMESTAMP -WHERE email = 'admin@mail.ru'; - --- Проверяем результат -DO $$ -DECLARE - updated_count INTEGER; - user_info RECORD; -BEGIN - GET DIAGNOSTICS updated_count = ROW_COUNT; - - IF updated_count > 0 THEN - -- Получаем информацию об обновленном пользователе - SELECT user_id, email, full_name, is_admin, is_active - INTO user_info - FROM users - WHERE email = 'admin@mail.ru'; - - RAISE NOTICE 'Пользователь % (ID: %) успешно получил права администратора', - user_info.email, user_info.user_id; - RAISE NOTICE 'ФИО: %, Админ: %, Активен: %', - user_info.full_name, user_info.is_admin, user_info.is_active; - ELSE - -- Если пользователь не найден, создаем его с правами админа - INSERT INTO users (email, password_hash, full_name, phone, city, is_admin, is_active) - VALUES ( - 'admin@mail.ru', - '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', -- admin123 - 'Администратор', - '+79129991223', - 'Москва', - TRUE, - TRUE - ) - ON CONFLICT (email) DO UPDATE - SET is_admin = TRUE, - is_active = TRUE, - updated_at = CURRENT_TIMESTAMP; - - RAISE NOTICE 'Пользователь admin@mail.ru создан/обновлен с правами администратора'; - END IF; -END $$; - diff --git a/OLD_CODE/migrations/grant_admin.php b/OLD_CODE/migrations/grant_admin.php deleted file mode 100644 index 40d7258..0000000 --- a/OLD_CODE/migrations/grant_admin.php +++ /dev/null @@ -1,85 +0,0 @@ -getConnection(); - echo "[OK] Подключение к базе данных успешно\n\n"; - - $email = 'admin@mail.ru'; - - $checkStmt = $db->prepare("SELECT user_id, email, full_name, is_admin, is_active FROM users WHERE email = ?"); - $checkStmt->execute([$email]); - $user = $checkStmt->fetch(PDO::FETCH_ASSOC); - - if ($user) { - echo "[INFO] Найден пользователь:\n"; - echo " Email: {$user['email']}\n"; - echo " ФИО: {$user['full_name']}\n"; - echo " Админ: " . ($user['is_admin'] ? 'ДА' : 'НЕТ') . "\n"; - echo " Активен: " . ($user['is_active'] ? 'ДА' : 'НЕТ') . "\n\n"; - - if ($user['is_admin']) { - echo "[INFO] Пользователь уже имеет права администратора\n"; - } else { - - $updateStmt = $db->prepare(" - UPDATE users - SET is_admin = TRUE, - is_active = TRUE, - updated_at = CURRENT_TIMESTAMP - WHERE email = ? - "); - $updateStmt->execute([$email]); - - echo "[SUCCESS] Права администратора успешно назначены!\n"; - } - } else { - echo "[WARN] Пользователь с email $email не найден\n"; - echo "[INFO] Создаю нового пользователя с правами администратора...\n"; - - $password_hash = password_hash('admin123', PASSWORD_DEFAULT); - - $insertStmt = $db->prepare(" - INSERT INTO users (email, password_hash, full_name, phone, city, is_admin, is_active) - VALUES (?, ?, ?, ?, ?, CAST(? AS boolean), TRUE) - RETURNING user_id - "); - - $insertStmt->execute([ - $email, - $password_hash, - 'Администратор', - '+79129991223', - 'Москва', - 'true' - ]); - - $user_id = $insertStmt->fetchColumn(); - echo "[SUCCESS] Пользователь создан с ID: $user_id\n"; - echo "[INFO] Email: $email\n"; - echo "[INFO] Пароль по умолчанию: admin123\n"; - echo "[WARN] Рекомендуется сменить пароль после первого входа!\n"; - } - - $verifyStmt = $db->prepare("SELECT user_id, email, full_name, is_admin, is_active FROM users WHERE email = ?"); - $verifyStmt->execute([$email]); - $finalUser = $verifyStmt->fetch(PDO::FETCH_ASSOC); - - echo "\n===========================================\n"; - echo " Итоговый статус:\n"; - echo "===========================================\n"; - echo " Email: {$finalUser['email']}\n"; - echo " ФИО: {$finalUser['full_name']}\n"; - echo " Админ: " . ($finalUser['is_admin'] ? 'ДА ✓' : 'НЕТ ✗') . "\n"; - echo " Активен: " . ($finalUser['is_active'] ? 'ДА ✓' : 'НЕТ ✗') . "\n"; - echo "===========================================\n"; - -} catch (PDOException $e) { - echo "[ERROR] Ошибка: " . $e->getMessage() . "\n"; - exit(1); -} diff --git a/OLD_CODE/migrations/migrate.php b/OLD_CODE/migrations/migrate.php deleted file mode 100644 index 7f009a7..0000000 --- a/OLD_CODE/migrations/migrate.php +++ /dev/null @@ -1,95 +0,0 @@ -getConnection(); - echo "[OK] Подключение к базе данных успешно\n\n"; - - $db->exec(" - CREATE TABLE IF NOT EXISTS migrations ( - id SERIAL PRIMARY KEY, - filename VARCHAR(255) NOT NULL UNIQUE, - applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP - ) - "); - echo "[OK] Таблица migrations готова\n"; - - $stmt = $db->query("SELECT filename FROM migrations ORDER BY filename"); - $applied = $stmt->fetchAll(PDO::FETCH_COLUMN); - echo "[INFO] Уже применено миграций: " . count($applied) . "\n\n"; - - $migrationFiles = glob(__DIR__ . '/*.sql'); - sort($migrationFiles); - - $newMigrations = 0; - - foreach ($migrationFiles as $file) { - $filename = basename($file); - - if ($filename === 'seed_data.sql') { - continue; - } - - if (in_array($filename, $applied)) { - echo "[SKIP] $filename (уже применена)\n"; - continue; - } - - echo "[RUN] Применяю $filename... "; - - $sql = file_get_contents($file); - - try { - $db->exec($sql); - - $stmt = $db->prepare("INSERT INTO migrations (filename) VALUES (?)"); - $stmt->execute([$filename]); - - echo "OK\n"; - $newMigrations++; - } catch (PDOException $e) { - echo "ОШИБКА!\n"; - echo " Причина: " . $e->getMessage() . "\n"; - echo "\n[!] Миграция остановлена из-за ошибки\n"; - exit(1); - } - } - - echo "\n-------------------------------------------\n"; - - if ($newMigrations > 0) { - echo "[SUCCESS] Применено новых миграций: $newMigrations\n"; - } else { - echo "[INFO] Все миграции уже применены\n"; - } - - $seedFile = __DIR__ . '/seed_data.sql'; - if (file_exists($seedFile)) { - echo "\n[?] Хотите загрузить начальные данные (seed_data.sql)?\n"; - echo " Запустите: php migrations/migrate.php --seed\n"; - - if (isset($argv[1]) && $argv[1] === '--seed') { - echo "\n[RUN] Загружаю seed_data.sql... "; - try { - $sql = file_get_contents($seedFile); - $db->exec($sql); - echo "OK\n"; - } catch (PDOException $e) { - echo "ОШИБКА: " . $e->getMessage() . "\n"; - } - } - } - - echo "\n===========================================\n"; - echo " Миграции завершены!\n"; - echo "===========================================\n"; - -} catch (PDOException $e) { - echo "[ERROR] Ошибка подключения к БД: " . $e->getMessage() . "\n"; - exit(1); -} diff --git a/OLD_CODE/migrations/seed_data.sql b/OLD_CODE/migrations/seed_data.sql deleted file mode 100644 index ca1af50..0000000 --- a/OLD_CODE/migrations/seed_data.sql +++ /dev/null @@ -1,65 +0,0 @@ --- seed_data.sql --- Начальные данные для AETERNA - --- Администратор (пароль: admin123) -INSERT INTO users (email, password_hash, full_name, phone, city, is_admin, is_active) -VALUES ( - 'admin@aeterna.ru', - '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', -- admin123 - 'Администратор AETERNA', - '+79129991223', - 'Москва', - TRUE, - TRUE -) ON CONFLICT (email) DO NOTHING; - --- Тестовый пользователь (пароль: user123) -INSERT INTO users (email, password_hash, full_name, phone, city, is_admin, is_active) -VALUES ( - 'user@test.com', - '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', -- user123 - 'Тестовый Пользователь', - '+79111234567', - 'Санкт-Петербург', - FALSE, - TRUE -) ON CONFLICT (email) DO NOTHING; - --- Категории -INSERT INTO categories (name, slug, description, sort_order, is_active) VALUES - ('Диваны', 'divany', 'Прямые и угловые диваны для гостиной', 1, TRUE), - ('Кресла', 'kresla', 'Кресла для гостиной и офиса', 2, TRUE), - ('Кровати', 'krovati', 'Односпальные и двуспальные кровати', 3, TRUE), - ('Столы', 'stoly', 'Обеденные и рабочие столы', 4, TRUE), - ('Стулья', 'stulya', 'Стулья для кухни и офиса', 5, TRUE), - ('Светильники', 'svetilniki', 'Торшеры, люстры и настольные лампы', 6, TRUE) -ON CONFLICT (slug) DO NOTHING; - --- Товары -INSERT INTO products (category_id, name, slug, description, price, old_price, sku, stock_quantity, is_available, image_url, color, material, card_size) VALUES - (1, 'Светильник MINNIGHT', 'svetilnik-minnight', 'Настольный светильник в современном стиле', 7999, 9999, 'LAMP-MIN-001', 15, TRUE, 'img2/1_2.png', 'Черный', 'Металл', 'small'), - (3, 'Кровать MODER', 'krovat-moder', 'Двуспальная кровать с мягким изголовьем', 45999, 55999, 'BED-MOD-001', 5, TRUE, 'img2/3_3.png', 'Серый', 'Дерево/Ткань', 'large'), - (6, 'Торшер MARCIA', 'torsher-marcia', 'Напольный торшер с регулируемой высотой', 11999, 14999, 'LAMP-MAR-001', 8, TRUE, 'img2/2_2.png', 'Золотой', 'Металл', 'tall'), - (6, 'Светильник POLET', 'svetilnik-polet', 'Подвесной светильник для гостиной', 5499, NULL, 'LAMP-POL-001', 20, TRUE, 'img2/4.jpg', 'Белый', 'Стекло', 'wide'), - (4, 'Стол NORD', 'stol-nord', 'Обеденный стол в скандинавском стиле', 23999, 28999, 'TABLE-NOR-001', 7, TRUE, 'img2/5_5.png', 'Натуральный', 'Дерево', 'small1'), - (1, 'Диван ROYALTY', 'divan-royalty', 'Роскошный угловой диван с велюровой обивкой', 78999, 95999, 'SOFA-ROY-001', 3, TRUE, 'img2/6_6.png', 'Зеленый', 'Велюр', 'wide2'), - (2, 'Кресло MINIMAL', 'kreslo-minimal', 'Кресло в минималистичном стиле', 29999, 35999, 'ARM-MIN-001', 10, TRUE, 'img2/7_7.png', 'Бежевый', 'Ткань', 'wide3'), - (4, 'Стол LONKI', 'stol-lonki', 'Журнальный столик с мраморной столешницей', 34999, NULL, 'TABLE-LON-001', 12, TRUE, 'img2/8_8.png', 'Белый мрамор', 'Мрамор/Металл', 'wide2_1'), - (1, 'Диван HEMMINS', 'divan-hemmins', 'Большой модульный диван для всей семьи', 89999, 110000, 'SOFA-HEM-001', 2, TRUE, 'img2/9_9.png', 'Темно-серый', 'Ткань', 'full-width') -ON CONFLICT (slug) DO NOTHING; - --- Выводим статистику -DO $$ -DECLARE - users_count INTEGER; - categories_count INTEGER; - products_count INTEGER; -BEGIN - SELECT COUNT(*) INTO users_count FROM users; - SELECT COUNT(*) INTO categories_count FROM categories; - SELECT COUNT(*) INTO products_count FROM products; - - RAISE NOTICE 'Загружено: % пользователей, % категорий, % товаров', - users_count, categories_count, products_count; -END $$; - diff --git a/OLD_CODE/mixins.less b/OLD_CODE/mixins.less deleted file mode 100644 index 934de15..0000000 --- a/OLD_CODE/mixins.less +++ /dev/null @@ -1,85 +0,0 @@ -// =================================== -// === ПЕРЕМЕННЫЕ И МИКСИНЫ AETERNA === -// =================================== -@color-primary: #617365; -@color-secondary: #D1D1D1; -@color-accent: #453227; -@color-text-dark: #333; -@color-text-light: #fff; -@color-button: @color-accent; -@color-beige: #A2A09A; - -@font-logo: 'Anek Kannada', sans-serif; -@font-main: 'Anonymous Pro', monospace; -@font-heading: 'Playfair Display', serif; - -@shadow-light: 0 5px 15px rgba(0, 0, 0, 0.2); -@shadow-dark: 2px 2px 4px rgba(0, 0, 0, 0.3); - -.flex-center(@gap: 0) { - display: flex; - align-items: center; - justify-content: center; - gap: @gap; -} - -.flex-between() { - display: flex; - align-items: center; - justify-content: space-between; -} - -.flex-column() { - display: flex; - flex-direction: column; -} - -.icon-base(@size: 18px, @hover-scale: 1.1) { - cursor: pointer; - transition: all 0.3s ease; - font-size: @size; - &:hover { - transform: scale(@hover-scale); - } -} - -.image-overlay() { - position: absolute; - inset: 0; - .flex-center(15px); - flex-direction: column; - text-align: center; - background-color: rgba(0, 0, 0, 0.4); - padding: 20px; - color: @color-text-light; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7); - transition: all 0.3s ease; -} - -.menu-base() { - position: absolute; - top: 100%; - left: 0; - width: 250px; - background: white; - border-radius: 8px; - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); - padding: 15px; - z-index: 1000; - margin-top: 5px; - display: none; -} - -.input-base() { - width: 100%; - padding: 12px 15px; - border: 1px solid #ccc; - background-color: #fff; - font-family: @font-main; - font-size: 14px; - outline: none; - transition: border-color 0.3s ease; - &:focus { - border-color: @color-primary; - } -} \ No newline at end of file diff --git a/OLD_CODE/public/admin/index.php b/OLD_CODE/public/admin/index.php deleted file mode 100644 index 72dc1ac..0000000 --- a/OLD_CODE/public/admin/index.php +++ /dev/null @@ -1,797 +0,0 @@ -alert('Требуется авторизация администратора'); window.location.href = '../login.php';"; - exit(); -} - -$db = Database::getInstance()->getConnection(); - -$action = $_GET['action'] ?? 'dashboard'; -$message = $_GET['message'] ?? ''; -$error = $_GET['error'] ?? ''; - -if ($_SERVER['REQUEST_METHOD'] === 'POST') { - $post_action = $_POST['action'] ?? ''; - - try { - if ($post_action === 'add_category') { - $name = trim($_POST['name'] ?? ''); - $slug = strtolower(preg_replace('/[^a-z0-9]+/i', '-', $name)); - $parent_id = !empty($_POST['parent_id']) ? (int)$_POST['parent_id'] : NULL; - $description = trim($_POST['description'] ?? ''); - $sort_order = (int)($_POST['sort_order'] ?? 0); - $is_active = isset($_POST['is_active']) ? 1 : 0; - - if (empty($name)) { - throw new Exception('Название категории обязательно'); - } - - $stmt = $db->prepare(" - INSERT INTO categories (name, slug, parent_id, description, sort_order, is_active) - VALUES (?, ?, ?, ?, ?, ?) - "); - - $result = $stmt->execute([$name, $slug, $parent_id, $description, $sort_order, $is_active]); - - if ($result) { - header('Location: index.php?action=categories&message=Категория+успешно+добавлена'); - exit(); - } - } - - if ($post_action === 'edit_category' && isset($_POST['category_id'])) { - $category_id = (int)$_POST['category_id']; - $name = trim($_POST['name'] ?? ''); - $parent_id = !empty($_POST['parent_id']) ? (int)$_POST['parent_id'] : NULL; - $description = trim($_POST['description'] ?? ''); - $sort_order = (int)($_POST['sort_order'] ?? 0); - $is_active = isset($_POST['is_active']) ? 1 : 0; - - if (empty($name)) { - throw new Exception('Название категории обязательно'); - } - - $slug = strtolower(preg_replace('/[^a-z0-9]+/i', '-', $name)); - - $stmt = $db->prepare(" - UPDATE categories SET - name = ?, - slug = ?, - parent_id = ?, - description = ?, - sort_order = ?, - is_active = ?, - updated_at = CURRENT_TIMESTAMP - WHERE category_id = ? - "); - - $stmt->execute([$name, $slug, $parent_id, $description, $sort_order, $is_active, $category_id]); - - header('Location: index.php?action=categories&message=Категория+обновлена'); - exit(); - } - - if ($post_action === 'add_product') { - $name = trim($_POST['name'] ?? ''); - $slug = strtolower(preg_replace('/[^a-z0-9]+/i', '-', $name)); - $category_id = (int)($_POST['category_id'] ?? 0); - $description = trim($_POST['description'] ?? ''); - $price = (float)($_POST['price'] ?? 0); - $old_price = !empty($_POST['old_price']) ? (float)$_POST['old_price'] : NULL; - $sku = trim($_POST['sku'] ?? ''); - $stock_quantity = (int)($_POST['stock_quantity'] ?? 0); - $is_available = isset($_POST['is_available']) ? 1 : 0; - $is_featured = isset($_POST['is_featured']) ? 1 : 0; - $image_url = trim($_POST['image_url'] ?? ''); - $color = trim($_POST['color'] ?? ''); - $material = trim($_POST['material'] ?? ''); - $card_size = trim($_POST['card_size'] ?? 'small'); - - if ($category_id <= 0) { - $_SESSION['error'] = 'Выберите корректную категорию'; - header('Location: index.php?action=add_product'); - exit(); - } - - $check_category = $db->prepare("SELECT COUNT(*) FROM categories WHERE category_id = ?"); - $check_category->execute([$category_id]); - if ($check_category->fetchColumn() == 0) { - $_SESSION['error'] = 'Выбранная категория не существует'; - header('Location: index.php?action=add_product'); - exit(); - } - - if (empty($name)) throw new Exception('Название товара обязательно'); - if ($price <= 0) throw new Exception('Цена должна быть больше 0'); - - if (empty($sku)) { - $sku = 'PROD-' . strtoupper(substr(preg_replace('/[^a-z0-9]/i', '', $name), 0, 6)) . '-' . rand(100, 999); - } - - $stmt = $db->prepare(" - INSERT INTO products ( - category_id, name, slug, description, price, old_price, - sku, stock_quantity, is_available, is_featured, image_url, - color, material, card_size - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - "); - - $result = $stmt->execute([ - $category_id, $name, $slug, $description, $price, $old_price, - $sku, $stock_quantity, $is_available, $is_featured, $image_url, - $color, $material, $card_size - ]); - - if ($result) { - $_SESSION['message'] = 'Товар успешно добавлен'; - header('Location: index.php?action=products'); - exit(); - } - } - - if ($post_action === 'edit_product' && isset($_POST['product_id'])) { - $product_id = (int)$_POST['product_id']; - $name = trim($_POST['name'] ?? ''); - $category_id = (int)($_POST['category_id'] ?? 1); - $description = trim($_POST['description'] ?? ''); - $price = (float)($_POST['price'] ?? 0); - $old_price = !empty($_POST['old_price']) ? (float)$_POST['old_price'] : NULL; - $stock_quantity = (int)($_POST['stock_quantity'] ?? 0); - $is_available = isset($_POST['is_available']) ? 1 : 0; - $image_url = trim($_POST['image_url'] ?? ''); - $color = trim($_POST['color'] ?? ''); - $material = trim($_POST['material'] ?? ''); - - if ($category_id <= 0) { - - $firstCat = $db->query("SELECT category_id FROM categories LIMIT 1")->fetchColumn(); - $category_id = $firstCat ?: 1; - } - - $stmt = $db->prepare(" - UPDATE products SET - name = ?, - category_id = ?, - description = ?, - price = ?, - old_price = ?, - stock_quantity = ?, - is_available = ?, - image_url = ?, - color = ?, - material = ?, - updated_at = CURRENT_TIMESTAMP - WHERE product_id = ? - "); - - $stmt->execute([ - $name, $category_id, $description, $price, $old_price, - $stock_quantity, $is_available, $image_url, $color, $material, $product_id - ]); - - header('Location: index.php?action=products&message=Товар+обновлен'); - exit(); - } - - if ($post_action === 'delete_category' && isset($_POST['category_id'])) { - $categoryId = intval($_POST['category_id']); - - $checkProducts = $db->prepare("SELECT COUNT(*) FROM products WHERE category_id = ?"); - $checkProducts->execute([$categoryId]); - $productCount = $checkProducts->fetchColumn(); - - $checkChildren = $db->prepare("SELECT COUNT(*) FROM categories WHERE parent_id = ?"); - $checkChildren->execute([$categoryId]); - $childCount = $checkChildren->fetchColumn(); - - if ($productCount > 0) { - - $stmt = $db->prepare("UPDATE categories SET is_active = FALSE WHERE category_id = ?"); - $stmt->execute([$categoryId]); - - header('Location: index.php?action=categories&message=Категория+скрыта+(содержит+товары)'); - exit(); - } elseif ($childCount > 0) { - - $stmt = $db->prepare("UPDATE categories SET is_active = FALSE WHERE category_id = ?"); - $stmt->execute([$categoryId]); - - header('Location: index.php?action=categories&message=Категория+скрыта+(имеет+дочерние+категории)'); - exit(); - } else { - - $stmt = $db->prepare("DELETE FROM categories WHERE category_id = ?"); - $stmt->execute([$categoryId]); - - header('Location: index.php?action=categories&message=Категория+удалена'); - exit(); - } - } - } catch (PDOException $e) { - header('Location: index.php?action=' . $action . '&error=' . urlencode('Ошибка БД: ' . $e->getMessage())); - exit(); - } catch (Exception $e) { - header('Location: index.php?action=' . $action . '&error=' . urlencode($e->getMessage())); - exit(); - } - } - -try { - - $stats = [ - 'total_products' => $db->query("SELECT COUNT(*) FROM products")->fetchColumn(), - 'active_products' => $db->query("SELECT COUNT(*) FROM products WHERE is_available = TRUE")->fetchColumn(), - 'total_orders' => $db->query("SELECT COUNT(*) FROM orders")->fetchColumn(), - 'total_users' => $db->query("SELECT COUNT(*) FROM users")->fetchColumn(), - 'revenue' => $db->query("SELECT COALESCE(SUM(final_amount), 0) FROM orders WHERE status = 'completed'")->fetchColumn() - ]; - - $allCategories = $db->query("SELECT * FROM categories WHERE is_active = TRUE ORDER BY name")->fetchAll(); - - $parentCategories = $db->query("SELECT * FROM categories WHERE parent_id IS NULL AND is_active = TRUE ORDER BY name")->fetchAll(); - - switch ($action) { - case 'products': - $showAll = isset($_GET['show_all']) && $_GET['show_all'] == '1'; - $sql = $showAll - ? "SELECT p.*, c.name as category_name FROM products p LEFT JOIN categories c ON p.category_id = c.category_id ORDER BY p.created_at DESC" - : "SELECT p.*, c.name as category_name FROM products p LEFT JOIN categories c ON p.category_id = c.category_id WHERE p.is_available = TRUE ORDER BY p.created_at DESC"; - $data = $db->query($sql)->fetchAll(); - break; - - case 'categories': - $data = $db->query(" - SELECT c1.*, c2.name as parent_name, - (SELECT COUNT(*) FROM products p WHERE p.category_id = c1.category_id) as product_count - FROM categories c1 - LEFT JOIN categories c2 ON c1.parent_id = c2.category_id - ORDER BY c1.sort_order, c1.name - ")->fetchAll(); - break; - - case 'orders': - $data = $db->query(" - SELECT o.*, u.email as user_email - FROM orders o - LEFT JOIN users u ON o.user_id = u.user_id - ORDER BY o.created_at DESC - LIMIT 50 - ")->fetchAll(); - break; - - case 'users': - $data = $db->query("SELECT * FROM users ORDER BY created_at DESC LIMIT 50")->fetchAll(); - break; - - case 'add_product': - case 'edit_product': - if ($action === 'edit_product' && isset($_GET['id'])) { - $productId = (int)$_GET['id']; - $stmt = $db->prepare("SELECT * FROM products WHERE product_id = ?"); - $stmt->execute([$productId]); - $edit_data = $stmt->fetch(); - } - break; - - case 'add_category': - case 'edit_category': - if ($action === 'edit_category' && isset($_GET['id'])) { - $categoryId = (int)$_GET['id']; - $stmt = $db->prepare("SELECT * FROM categories WHERE category_id = ?"); - $stmt->execute([$categoryId]); - $edit_data = $stmt->fetch(); - } - break; - - } - -} catch (PDOException $e) { - $error = "Ошибка базы данных: " . $e->getMessage(); -} -?> - - - - - - AETERNA - Админ-панель - - - - -
-

Админ-панель AETERNA

-
- - В каталог - Выйти -
-
- -
- - Дашборд - - - Товары - - - Категории - - - Заказы - - - Пользователи - -
- -
- -
- -
- - - -
- -
- - - - -

Статистика

-
-
-

-

Всего товаров

-
-
-

-

Активных товаров

-
-
-

-

Заказов

-
-
-

-

Пользователей

-
-
- -
- - Добавить новый товар - - - Добавить категорию - -
- - - -
-

Управление товарами

-
- - Добавить товар - - - Только активные - - Показать все - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
IDНазваниеКатегорияЦенаНа складеСтатусДействия
- 0): ?> - ✓ Доступен - - ✗ Недоступен - - ⚠ Нет на складе - - - - - - -
- - - - -
- -
- - - - -
- -
- - - -
-

Управление категориями

- - Добавить категорию - -
- - - - - - - - - - - - - - - - - - - - - - - - -
IDНазваниеSlugРодительскаяТоваровДействия
- - - Редактировать - - - -
- - - -
-

- -
- - - - - - -
- - -
- -
- - -
- -
- - -
- -
-
- - -
-
- - -
-
- -
-
- - -
-
- - -
-
- -
- - -
- -
-
- - -
-
- - -
-
- -
- -
- -
- -
- - - Отмена -
-
- - - -
-

- -
- - - - - - -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- -
- - - Отмена -
-
- - - -

Заказы

- - - - - - - - - - - - - - - - - - - - - - - -
№ заказаКлиентСуммаСтатусДатаДействия
- - - -
- - - -

Пользователи

- - - - - - - - - - - - - - - - - - - - - -
IDEmailФИОДата регистрацииСтатус
- - ✓ Активен - - ✗ Неактивен - -
- - -
- - - \ No newline at end of file diff --git a/OLD_CODE/public/api/add_to_cart.php b/OLD_CODE/public/api/add_to_cart.php deleted file mode 100644 index a452dcc..0000000 --- a/OLD_CODE/public/api/add_to_cart.php +++ /dev/null @@ -1,112 +0,0 @@ - false, 'message' => 'Требуется авторизация']); - exit(); -} - -if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['product_id'])) { - $product_id = intval($_POST['product_id']); - $quantity = intval($_POST['quantity'] ?? 1); - $user_id = $_SESSION['user_id'] ?? 0; - - if ($user_id == 0) { - echo json_encode(['success' => false, 'message' => 'Пользователь не найден']); - exit(); - } - - $db = Database::getInstance()->getConnection(); - - try { - - $checkStock = $db->prepare(" - SELECT stock_quantity, name, price - FROM products - WHERE product_id = ? AND is_available = TRUE - "); - $checkStock->execute([$product_id]); - $product = $checkStock->fetch(); - - if (!$product) { - echo json_encode(['success' => false, 'message' => 'Товар не найден']); - exit(); - } - - if ($product['stock_quantity'] < $quantity) { - echo json_encode(['success' => false, 'message' => 'Недостаточно товара на складе']); - exit(); - } - - $checkCart = $db->prepare(" - SELECT cart_id, quantity - FROM cart - WHERE user_id = ? AND product_id = ? - "); - $checkCart->execute([$user_id, $product_id]); - $cartItem = $checkCart->fetch(); - - if ($cartItem) { - - $newQuantity = $cartItem['quantity'] + $quantity; - - if ($newQuantity > $product['stock_quantity']) { - echo json_encode(['success' => false, 'message' => 'Превышено доступное количество']); - exit(); - } - - $updateStmt = $db->prepare(" - UPDATE cart - SET quantity = ?, updated_at = CURRENT_TIMESTAMP - WHERE cart_id = ? - "); - $updateStmt->execute([$newQuantity, $cartItem['cart_id']]); - } else { - - $insertStmt = $db->prepare(" - INSERT INTO cart (user_id, product_id, quantity) - VALUES (?, ?, ?) - "); - $insertStmt->execute([$user_id, $product_id, $quantity]); - } - - if (!isset($_SESSION['cart'])) { - $_SESSION['cart'] = []; - } - - if (isset($_SESSION['cart'][$product_id])) { - $_SESSION['cart'][$product_id]['quantity'] += $quantity; - } else { - $_SESSION['cart'][$product_id] = [ - 'quantity' => $quantity, - 'name' => $product['name'], - 'price' => $product['price'], - 'added_at' => time() - ]; - } - - $cartCountStmt = $db->prepare(" - SELECT SUM(quantity) as total - FROM cart - WHERE user_id = ? - "); - $cartCountStmt->execute([$user_id]); - $cart_count = $cartCountStmt->fetchColumn() ?: 0; - - echo json_encode([ - 'success' => true, - 'cart_count' => $cart_count, - 'message' => 'Товар добавлен в корзину' - ]); - - } catch (PDOException $e) { - echo json_encode([ - 'success' => false, - 'message' => 'Ошибка базы данных: ' . $e->getMessage() - ]); - } -} else { - echo json_encode(['success' => false, 'message' => 'Неверный запрос']); -} -?> \ No newline at end of file diff --git a/OLD_CODE/public/api/auth.php b/OLD_CODE/public/api/auth.php deleted file mode 100644 index 4aac5e4..0000000 --- a/OLD_CODE/public/api/auth.php +++ /dev/null @@ -1,68 +0,0 @@ - false, 'message' => 'Заполните все поля']); - exit(); - } - - $db = Database::getInstance()->getConnection(); - - try { - - $stmt = $db->prepare(" - SELECT user_id, email, password_hash, full_name, phone, city, is_admin, is_active - FROM users - WHERE email = ? - "); - $stmt->execute([$email]); - $user = $stmt->fetch(PDO::FETCH_ASSOC); - - if (!$user) { - echo json_encode(['success' => false, 'message' => 'Пользователь не найден']); - exit(); - } - - if (!$user['is_active']) { - echo json_encode(['success' => false, 'message' => 'Аккаунт заблокирован']); - exit(); - } - - if (empty($user['password_hash'])) { - echo json_encode(['success' => false, 'message' => 'Ошибка: пароль не найден в базе данных']); - exit(); - } - - if (!password_verify($password, $user['password_hash'])) { - echo json_encode(['success' => false, 'message' => 'Неверный пароль']); - exit(); - } - - $_SESSION['user_id'] = $user['user_id']; - $_SESSION['user_email'] = $user['email']; - $_SESSION['full_name'] = $user['full_name']; - $_SESSION['user_phone'] = $user['phone'] ?? ''; - $_SESSION['user_city'] = $user['city'] ?? ''; - $_SESSION['isLoggedIn'] = true; - $_SESSION['isAdmin'] = (bool)$user['is_admin']; - $_SESSION['login_time'] = time(); - - $updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?"); - $updateStmt->execute([$user['user_id']]); - - echo json_encode(['success' => true, 'redirect' => 'catalog.php']); - - } catch (PDOException $e) { - echo json_encode(['success' => false, 'message' => 'Ошибка базы данных']); - } - -} else { - echo json_encode(['success' => false, 'message' => 'Неверный запрос']); -} -?> \ No newline at end of file diff --git a/OLD_CODE/public/api/cart.php b/OLD_CODE/public/api/cart.php deleted file mode 100644 index cd68d7b..0000000 --- a/OLD_CODE/public/api/cart.php +++ /dev/null @@ -1,127 +0,0 @@ - false, 'message' => 'Требуется авторизация']); - exit(); -} - -$userId = $_SESSION['user_id'] ?? 0; -$action = $_GET['action'] ?? $_POST['action'] ?? ''; - -$db = Database::getInstance()->getConnection(); - -try { - switch ($action) { - case 'add': - $productId = (int)($_POST['product_id'] ?? 0); - $quantity = (int)($_POST['quantity'] ?? 1); - - if ($productId <= 0) { - echo json_encode(['success' => false, 'message' => 'Неверный ID товара']); - exit(); - } - - $checkProduct = $db->prepare("SELECT product_id, stock_quantity FROM products WHERE product_id = ? AND is_available = TRUE"); - $checkProduct->execute([$productId]); - $product = $checkProduct->fetch(); - - if (!$product) { - echo json_encode(['success' => false, 'message' => 'Товар не найден']); - exit(); - } - - $checkCart = $db->prepare("SELECT cart_id, quantity FROM cart WHERE user_id = ? AND product_id = ?"); - $checkCart->execute([$userId, $productId]); - $cartItem = $checkCart->fetch(); - - if ($cartItem) { - - $newQuantity = $cartItem['quantity'] + $quantity; - $stmt = $db->prepare("UPDATE cart SET quantity = ?, updated_at = CURRENT_TIMESTAMP WHERE cart_id = ?"); - $stmt->execute([$newQuantity, $cartItem['cart_id']]); - } else { - - $stmt = $db->prepare("INSERT INTO cart (user_id, product_id, quantity) VALUES (?, ?, ?)"); - $stmt->execute([$userId, $productId, $quantity]); - } - - echo json_encode(['success' => true, 'message' => 'Товар добавлен в корзину']); - break; - - case 'update': - $productId = (int)($_POST['product_id'] ?? 0); - $quantity = (int)($_POST['quantity'] ?? 1); - - if ($quantity <= 0) { - - $stmt = $db->prepare("DELETE FROM cart WHERE user_id = ? AND product_id = ?"); - $stmt->execute([$userId, $productId]); - } else { - $stmt = $db->prepare("UPDATE cart SET quantity = ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ? AND product_id = ?"); - $stmt->execute([$quantity, $userId, $productId]); - } - - echo json_encode(['success' => true, 'message' => 'Корзина обновлена']); - break; - - case 'remove': - $productId = (int)($_POST['product_id'] ?? 0); - - $stmt = $db->prepare("DELETE FROM cart WHERE user_id = ? AND product_id = ?"); - $stmt->execute([$userId, $productId]); - - echo json_encode(['success' => true, 'message' => 'Товар удален из корзины']); - break; - - case 'get': - $stmt = $db->prepare(" - SELECT c.cart_id, c.product_id, c.quantity, p.name, p.price, p.image_url, p.stock_quantity - FROM cart c - JOIN products p ON c.product_id = p.product_id - WHERE c.user_id = ? AND p.is_available = TRUE - ORDER BY c.created_at DESC - "); - $stmt->execute([$userId]); - $items = $stmt->fetchAll(); - - $total = 0; - foreach ($items as &$item) { - $item['subtotal'] = $item['price'] * $item['quantity']; - $total += $item['subtotal']; - } - - echo json_encode([ - 'success' => true, - 'items' => $items, - 'total' => $total, - 'count' => array_sum(array_column($items, 'quantity')) - ]); - break; - - case 'count': - $stmt = $db->prepare("SELECT COALESCE(SUM(quantity), 0) FROM cart WHERE user_id = ?"); - $stmt->execute([$userId]); - $count = $stmt->fetchColumn(); - - echo json_encode(['success' => true, 'count' => (int)$count]); - break; - - case 'clear': - $stmt = $db->prepare("DELETE FROM cart WHERE user_id = ?"); - $stmt->execute([$userId]); - - echo json_encode(['success' => true, 'message' => 'Корзина очищена']); - break; - - default: - echo json_encode(['success' => false, 'message' => 'Неизвестное действие']); - } - -} catch (PDOException $e) { - echo json_encode(['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]); -} diff --git a/OLD_CODE/public/api/get_cart.php b/OLD_CODE/public/api/get_cart.php deleted file mode 100644 index 2d43ea4..0000000 --- a/OLD_CODE/public/api/get_cart.php +++ /dev/null @@ -1,61 +0,0 @@ - false, 'message' => 'Требуется авторизация']); - exit(); -} - -$user_id = $_SESSION['user_id'] ?? 0; - -if ($user_id == 0) { - echo json_encode(['success' => false, 'message' => 'Пользователь не найден']); - exit(); -} - -$db = Database::getInstance()->getConnection(); - -try { - - $stmt = $db->prepare(" - SELECT - c.cart_id, - c.product_id, - c.quantity, - p.name, - p.price, - p.image_url, - p.stock_quantity - FROM cart c - JOIN products p ON c.product_id = p.product_id - WHERE c.user_id = ? AND p.is_available = TRUE - ORDER BY c.created_at DESC - "); - $stmt->execute([$user_id]); - $cart_items = $stmt->fetchAll(); - - $_SESSION['cart'] = []; - foreach ($cart_items as $item) { - $_SESSION['cart'][$item['product_id']] = [ - 'quantity' => $item['quantity'], - 'name' => $item['name'], - 'price' => $item['price'], - 'added_at' => time() - ]; - } - - echo json_encode([ - 'success' => true, - 'cart_items' => $cart_items, - 'total_items' => count($cart_items) - ]); - -} catch (PDOException $e) { - echo json_encode([ - 'success' => false, - 'message' => 'Ошибка базы данных: ' . $e->getMessage() - ]); -} -?> \ No newline at end of file diff --git a/OLD_CODE/public/api/get_cart_count.php b/OLD_CODE/public/api/get_cart_count.php deleted file mode 100644 index f1d59c2..0000000 --- a/OLD_CODE/public/api/get_cart_count.php +++ /dev/null @@ -1,22 +0,0 @@ - false, 'cart_count' => 0]); - exit(); -} - -$user_id = $_SESSION['user_id'] ?? 0; -$db = Database::getInstance()->getConnection(); - -try { - $stmt = $db->prepare("SELECT SUM(quantity) as total FROM cart WHERE user_id = ?"); - $stmt->execute([$user_id]); - $cart_count = $stmt->fetchColumn() ?: 0; - - echo json_encode(['success' => true, 'cart_count' => $cart_count]); -} catch (PDOException $e) { - echo json_encode(['success' => false, 'cart_count' => 0]); -} \ No newline at end of file diff --git a/OLD_CODE/public/api/get_product.php b/OLD_CODE/public/api/get_product.php deleted file mode 100644 index 0cd3ca6..0000000 --- a/OLD_CODE/public/api/get_product.php +++ /dev/null @@ -1,32 +0,0 @@ - false, 'message' => 'Доступ запрещен']); - exit(); -} - -if (!isset($_GET['id'])) { - echo json_encode(['success' => false, 'message' => 'ID не указан']); - exit(); -} - -try { - $db = Database::getInstance()->getConnection(); - $product_id = $_GET['id']; - - $stmt = $db->prepare("SELECT * FROM products WHERE product_id = ?"); - $stmt->execute([$product_id]); - $product = $stmt->fetch(); - - if ($product) { - echo json_encode($product); - } else { - echo json_encode(['success' => false, 'message' => 'Товар не найден']); - } - -} catch (PDOException $e) { - echo json_encode(['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]); -} -?> \ No newline at end of file diff --git a/OLD_CODE/public/api/process_order.php b/OLD_CODE/public/api/process_order.php deleted file mode 100644 index 8c94036..0000000 --- a/OLD_CODE/public/api/process_order.php +++ /dev/null @@ -1,124 +0,0 @@ -getConnection(); - - try { - $db->beginTransaction(); - - $customer_name = $_POST['full_name'] ?? ''; - $customer_email = $_POST['email'] ?? ''; - $customer_phone = $_POST['phone'] ?? ''; - $delivery_address = $_POST['address'] ?? ''; - $region = $_POST['region'] ?? ''; - $payment_method = $_POST['payment'] ?? 'card'; - $delivery_method = $_POST['delivery'] ?? 'courier'; - $notes = $_POST['notes'] ?? ''; - $discount_amount = floatval($_POST['discount'] ?? 0); - $delivery_cost = floatval($_POST['delivery_price'] ?? 2000); - - $order_number = 'ORD-' . date('Ymd-His') . '-' . rand(1000, 9999); - - $cartStmt = $db->prepare(" - SELECT - c.product_id, - c.quantity, - p.name, - p.price, - p.stock_quantity - FROM cart c - JOIN products p ON c.product_id = p.product_id - WHERE c.user_id = ? - "); - $cartStmt->execute([$user_id]); - $cart_items = $cartStmt->fetchAll(); - - if (empty($cart_items)) { - throw new Exception('Корзина пуста'); - } - - $total_amount = 0; - foreach ($cart_items as $item) { - $total_amount += $item['price'] * $item['quantity']; - } - - $final_amount = $total_amount - $discount_amount + $delivery_cost; - - $orderStmt = $db->prepare(" - INSERT INTO orders ( - user_id, order_number, total_amount, discount_amount, - delivery_cost, final_amount, status, payment_method, - delivery_method, delivery_address, customer_name, - customer_email, customer_phone, notes - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - RETURNING order_id - "); - - $orderStmt->execute([ - $user_id, $order_number, $total_amount, $discount_amount, - $delivery_cost, $final_amount, 'pending', $payment_method, - $delivery_method, $delivery_address, $customer_name, - $customer_email, $customer_phone, $notes - ]); - - $order_id = $orderStmt->fetchColumn(); - - foreach ($cart_items as $item) { - - $itemStmt = $db->prepare(" - INSERT INTO order_items ( - order_id, product_id, product_name, - quantity, unit_price, total_price - ) VALUES (?, ?, ?, ?, ?, ?) - "); - - $item_total = $item['price'] * $item['quantity']; - $itemStmt->execute([ - $order_id, $item['product_id'], $item['name'], - $item['quantity'], $item['price'], $item_total - ]); - - $updateStmt = $db->prepare(" - UPDATE products - SET stock_quantity = stock_quantity - ?, - updated_at = CURRENT_TIMESTAMP - WHERE product_id = ? - "); - $updateStmt->execute([$item['quantity'], $item['product_id']]); - } - - $clearCartStmt = $db->prepare("DELETE FROM cart WHERE user_id = ?"); - $clearCartStmt->execute([$user_id]); - - unset($_SESSION['cart']); - - $db->commit(); - - header('Location: order_success.php?id=' . $order_id); - exit(); - - } catch (Exception $e) { - $db->rollBack(); - header('Location: checkout.php?error=' . urlencode($e->getMessage())); - exit(); - } -} else { - header('Location: checkout.php'); - exit(); -} -?> \ No newline at end of file diff --git a/OLD_CODE/public/api/register_handler.php b/OLD_CODE/public/api/register_handler.php deleted file mode 100644 index d1cfb81..0000000 --- a/OLD_CODE/public/api/register_handler.php +++ /dev/null @@ -1,162 +0,0 @@ - $full_name, - 'city' => $city, - 'email' => $email, - 'phone' => $phone - ]; - header('Location: ../register.php'); - exit(); - } - - $db = Database::getInstance()->getConnection(); - - try { - - $checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?"); - $checkStmt->execute([$email]); - - if ($checkStmt->fetch()) { - $_SESSION['registration_errors'] = ['Пользователь с таким email уже существует']; - $_SESSION['old_data'] = [ - 'fio' => $full_name, - 'city' => $city, - 'email' => $email, - 'phone' => $phone - ]; - header('Location: ../register.php'); - exit(); - } - - $password_hash = password_hash($password, PASSWORD_DEFAULT); - - $is_admin = false; - $admin_emails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru']; - if (in_array(strtolower($email), $admin_emails)) { - $is_admin = true; - } - - $stmt = $db->prepare(" - INSERT INTO users (email, password_hash, full_name, phone, city, is_admin, is_active) - VALUES (?, ?, ?, ?, ?, CAST(? AS boolean), TRUE) - RETURNING user_id - "); - - $stmt->execute([ - $email, - $password_hash, - $full_name, - $phone, - $city, - $is_admin ? 'true' : 'false' - ]); - - $user_id = $stmt->fetchColumn(); - - if (!$user_id) { - throw new Exception('Ошибка при создании пользователя: user_id не получен'); - } - - $verifyStmt = $db->prepare("SELECT user_id, email, password_hash FROM users WHERE user_id = ?"); - $verifyStmt->execute([$user_id]); - $verifyUser = $verifyStmt->fetch(PDO::FETCH_ASSOC); - - if (!$verifyUser) { - throw new Exception('Ошибка: пользователь не найден после создания'); - } - - if (empty($verifyUser['password_hash'])) { - throw new Exception('Ошибка: пароль не сохранен'); - } - - $_SESSION['user_id'] = $user_id; - $_SESSION['user_email'] = $email; - $_SESSION['full_name'] = $full_name; - $_SESSION['user_phone'] = $phone; - $_SESSION['user_city'] = $city; - $_SESSION['isLoggedIn'] = true; - $_SESSION['isAdmin'] = (bool)$is_admin; - $_SESSION['login_time'] = time(); - - $updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?"); - $updateStmt->execute([$user_id]); - - $_SESSION['registration_success'] = 'Регистрация прошла успешно! ' . - ($is_admin ? 'Вы зарегистрированы как администратор.' : 'Добро пожаловать в AETERNA!'); - - header('Location: ../catalog.php'); - exit(); - - } catch (PDOException $e) { - - error_log("Registration DB Error: " . $e->getMessage()); - error_log("SQL State: " . $e->getCode()); - error_log("Email: " . $email); - - $_SESSION['registration_errors'] = ['Ошибка базы данных: ' . $e->getMessage()]; - $_SESSION['old_data'] = [ - 'fio' => $full_name, - 'city' => $city, - 'email' => $email, - 'phone' => $phone - ]; - header('Location: ../register.php'); - exit(); - } catch (Exception $e) { - error_log("Registration Error: " . $e->getMessage()); - - $_SESSION['registration_errors'] = [$e->getMessage()]; - header('Location: ../register.php'); - exit(); - } - -} else { - - header('Location: register.php'); - exit(); -} -?> \ No newline at end of file diff --git a/OLD_CODE/public/api/update_cart.php b/OLD_CODE/public/api/update_cart.php deleted file mode 100644 index 0063946..0000000 --- a/OLD_CODE/public/api/update_cart.php +++ /dev/null @@ -1,31 +0,0 @@ - false, 'message' => 'Требуется авторизация']); - exit(); -} - -if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['product_id'])) { - $product_id = intval($_POST['product_id']); - $quantity = intval($_POST['quantity'] ?? 1); - $user_id = $_SESSION['user_id'] ?? 0; - - $db = Database::getInstance()->getConnection(); - - try { - $stmt = $db->prepare(" - UPDATE cart - SET quantity = ?, updated_at = CURRENT_TIMESTAMP - WHERE user_id = ? AND product_id = ? - "); - $stmt->execute([$quantity, $user_id, $product_id]); - - echo json_encode(['success' => true]); - - } catch (PDOException $e) { - echo json_encode(['success' => false, 'message' => 'Ошибка базы данных']); - } -} -?> \ No newline at end of file diff --git a/OLD_CODE/public/assets/img/1 — копия.jpg b/OLD_CODE/public/assets/img/1 — копия.jpg deleted file mode 100644 index 68992d6..0000000 Binary files a/OLD_CODE/public/assets/img/1 — копия.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/1.jpg b/OLD_CODE/public/assets/img/1.jpg deleted file mode 100644 index 1df7668..0000000 Binary files a/OLD_CODE/public/assets/img/1.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/100.jpg b/OLD_CODE/public/assets/img/100.jpg deleted file mode 100644 index 646480d..0000000 Binary files a/OLD_CODE/public/assets/img/100.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/11.jpg b/OLD_CODE/public/assets/img/11.jpg deleted file mode 100644 index 3a8270e..0000000 Binary files a/OLD_CODE/public/assets/img/11.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/111.jpg b/OLD_CODE/public/assets/img/111.jpg deleted file mode 100644 index 33dc453..0000000 Binary files a/OLD_CODE/public/assets/img/111.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/11_1.png b/OLD_CODE/public/assets/img/11_1.png deleted file mode 100644 index 4735774..0000000 Binary files a/OLD_CODE/public/assets/img/11_1.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/1_1.jpg b/OLD_CODE/public/assets/img/1_1.jpg deleted file mode 100644 index 3f9e1a1..0000000 Binary files a/OLD_CODE/public/assets/img/1_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/1_2.jpg b/OLD_CODE/public/assets/img/1_2.jpg deleted file mode 100644 index 2d7a54a..0000000 Binary files a/OLD_CODE/public/assets/img/1_2.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/1_2.png b/OLD_CODE/public/assets/img/1_2.png deleted file mode 100644 index 9a8a6c0..0000000 Binary files a/OLD_CODE/public/assets/img/1_2.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/2.jpg b/OLD_CODE/public/assets/img/2.jpg deleted file mode 100644 index 417df4a..0000000 Binary files a/OLD_CODE/public/assets/img/2.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/22.jpg b/OLD_CODE/public/assets/img/22.jpg deleted file mode 100644 index f59b320..0000000 Binary files a/OLD_CODE/public/assets/img/22.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/25.jpg b/OLD_CODE/public/assets/img/25.jpg deleted file mode 100644 index 03eddcf..0000000 Binary files a/OLD_CODE/public/assets/img/25.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/2_2.jpg b/OLD_CODE/public/assets/img/2_2.jpg deleted file mode 100644 index 76ba9ba..0000000 Binary files a/OLD_CODE/public/assets/img/2_2.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/2_2.png b/OLD_CODE/public/assets/img/2_2.png deleted file mode 100644 index 8fa6e8c..0000000 Binary files a/OLD_CODE/public/assets/img/2_2.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/3.jpg b/OLD_CODE/public/assets/img/3.jpg deleted file mode 100644 index 973449d..0000000 Binary files a/OLD_CODE/public/assets/img/3.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/3_3.jpg b/OLD_CODE/public/assets/img/3_3.jpg deleted file mode 100644 index 7e56605..0000000 Binary files a/OLD_CODE/public/assets/img/3_3.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/3_3.png b/OLD_CODE/public/assets/img/3_3.png deleted file mode 100644 index ba16e91..0000000 Binary files a/OLD_CODE/public/assets/img/3_3.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/4.jpg b/OLD_CODE/public/assets/img/4.jpg deleted file mode 100644 index da2945c..0000000 Binary files a/OLD_CODE/public/assets/img/4.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/44.jpg b/OLD_CODE/public/assets/img/44.jpg deleted file mode 100644 index e38c994..0000000 Binary files a/OLD_CODE/public/assets/img/44.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/444 b/OLD_CODE/public/assets/img/444 deleted file mode 100644 index dc6e3fa..0000000 Binary files a/OLD_CODE/public/assets/img/444 and /dev/null differ diff --git a/OLD_CODE/public/assets/img/444 (1).png b/OLD_CODE/public/assets/img/444 (1).png deleted file mode 100644 index ddf7e92..0000000 Binary files a/OLD_CODE/public/assets/img/444 (1).png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/444.jpg b/OLD_CODE/public/assets/img/444.jpg deleted file mode 100644 index dc6e3fa..0000000 Binary files a/OLD_CODE/public/assets/img/444.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/444.png b/OLD_CODE/public/assets/img/444.png deleted file mode 100644 index cd53804..0000000 Binary files a/OLD_CODE/public/assets/img/444.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/4_1.jpg b/OLD_CODE/public/assets/img/4_1.jpg deleted file mode 100644 index 69f2236..0000000 Binary files a/OLD_CODE/public/assets/img/4_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/5.jpg b/OLD_CODE/public/assets/img/5.jpg deleted file mode 100644 index 456cec1..0000000 Binary files a/OLD_CODE/public/assets/img/5.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/5_5.jpg b/OLD_CODE/public/assets/img/5_5.jpg deleted file mode 100644 index 9ced54f..0000000 Binary files a/OLD_CODE/public/assets/img/5_5.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/5_5.png b/OLD_CODE/public/assets/img/5_5.png deleted file mode 100644 index 369b63b..0000000 Binary files a/OLD_CODE/public/assets/img/5_5.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/6.jpg b/OLD_CODE/public/assets/img/6.jpg deleted file mode 100644 index 550e17d..0000000 Binary files a/OLD_CODE/public/assets/img/6.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/6_6.jpg b/OLD_CODE/public/assets/img/6_6.jpg deleted file mode 100644 index 0aa5c4b..0000000 Binary files a/OLD_CODE/public/assets/img/6_6.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/6_6.png b/OLD_CODE/public/assets/img/6_6.png deleted file mode 100644 index af949f9..0000000 Binary files a/OLD_CODE/public/assets/img/6_6.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/7.jpg b/OLD_CODE/public/assets/img/7.jpg deleted file mode 100644 index 17150c7..0000000 Binary files a/OLD_CODE/public/assets/img/7.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/77.jpg b/OLD_CODE/public/assets/img/77.jpg deleted file mode 100644 index d9bf304..0000000 Binary files a/OLD_CODE/public/assets/img/77.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/777 (1).png b/OLD_CODE/public/assets/img/777 (1).png deleted file mode 100644 index 6b01d3f..0000000 Binary files a/OLD_CODE/public/assets/img/777 (1).png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/777.jpg b/OLD_CODE/public/assets/img/777.jpg deleted file mode 100644 index 908d164..0000000 Binary files a/OLD_CODE/public/assets/img/777.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/777.png b/OLD_CODE/public/assets/img/777.png deleted file mode 100644 index 41d57c8..0000000 Binary files a/OLD_CODE/public/assets/img/777.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/7_7.jpg b/OLD_CODE/public/assets/img/7_7.jpg deleted file mode 100644 index 5ee1524..0000000 Binary files a/OLD_CODE/public/assets/img/7_7.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/7_7.png b/OLD_CODE/public/assets/img/7_7.png deleted file mode 100644 index d50782e..0000000 Binary files a/OLD_CODE/public/assets/img/7_7.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/8.jpg b/OLD_CODE/public/assets/img/8.jpg deleted file mode 100644 index 8b41c63..0000000 Binary files a/OLD_CODE/public/assets/img/8.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/88.jpg b/OLD_CODE/public/assets/img/88.jpg deleted file mode 100644 index 713eeec..0000000 Binary files a/OLD_CODE/public/assets/img/88.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/888 (1).png b/OLD_CODE/public/assets/img/888 (1).png deleted file mode 100644 index 127e80d..0000000 Binary files a/OLD_CODE/public/assets/img/888 (1).png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/888.jpg b/OLD_CODE/public/assets/img/888.jpg deleted file mode 100644 index e8f33f7..0000000 Binary files a/OLD_CODE/public/assets/img/888.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/888.png b/OLD_CODE/public/assets/img/888.png deleted file mode 100644 index 35e3403..0000000 Binary files a/OLD_CODE/public/assets/img/888.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/8_8.png b/OLD_CODE/public/assets/img/8_8.png deleted file mode 100644 index 9f86b2c..0000000 Binary files a/OLD_CODE/public/assets/img/8_8.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/9.jpg b/OLD_CODE/public/assets/img/9.jpg deleted file mode 100644 index 0b772e3..0000000 Binary files a/OLD_CODE/public/assets/img/9.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/99.jpg b/OLD_CODE/public/assets/img/99.jpg deleted file mode 100644 index ed309ba..0000000 Binary files a/OLD_CODE/public/assets/img/99.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/99.png b/OLD_CODE/public/assets/img/99.png deleted file mode 100644 index 8fd29b2..0000000 Binary files a/OLD_CODE/public/assets/img/99.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/99_1.jpg b/OLD_CODE/public/assets/img/99_1.jpg deleted file mode 100644 index 0247358..0000000 Binary files a/OLD_CODE/public/assets/img/99_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/99_2.jpg b/OLD_CODE/public/assets/img/99_2.jpg deleted file mode 100644 index 468fd51..0000000 Binary files a/OLD_CODE/public/assets/img/99_2.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/99_3.png b/OLD_CODE/public/assets/img/99_3.png deleted file mode 100644 index ae2cd8e..0000000 Binary files a/OLD_CODE/public/assets/img/99_3.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/9_9.jpg b/OLD_CODE/public/assets/img/9_9.jpg deleted file mode 100644 index a77f2ae..0000000 Binary files a/OLD_CODE/public/assets/img/9_9.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/9_9.png b/OLD_CODE/public/assets/img/9_9.png deleted file mode 100644 index 733a453..0000000 Binary files a/OLD_CODE/public/assets/img/9_9.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/black.png b/OLD_CODE/public/assets/img/black.png deleted file mode 100644 index a10af51..0000000 Binary files a/OLD_CODE/public/assets/img/black.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/black1.png b/OLD_CODE/public/assets/img/black1.png deleted file mode 100644 index f529bd3..0000000 Binary files a/OLD_CODE/public/assets/img/black1.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/black2.png b/OLD_CODE/public/assets/img/black2.png deleted file mode 100644 index 75758a2..0000000 Binary files a/OLD_CODE/public/assets/img/black2.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/brown.png b/OLD_CODE/public/assets/img/brown.png deleted file mode 100644 index 9ef4db4..0000000 Binary files a/OLD_CODE/public/assets/img/brown.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/brown1.png b/OLD_CODE/public/assets/img/brown1.png deleted file mode 100644 index 0b178f1..0000000 Binary files a/OLD_CODE/public/assets/img/brown1.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/brown2.png b/OLD_CODE/public/assets/img/brown2.png deleted file mode 100644 index 346b22f..0000000 Binary files a/OLD_CODE/public/assets/img/brown2.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/chair.PNG b/OLD_CODE/public/assets/img/chair.PNG deleted file mode 100644 index 12af9db..0000000 Binary files a/OLD_CODE/public/assets/img/chair.PNG and /dev/null differ diff --git a/OLD_CODE/public/assets/img/gray.png b/OLD_CODE/public/assets/img/gray.png deleted file mode 100644 index 55ab5bb..0000000 Binary files a/OLD_CODE/public/assets/img/gray.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/gray1.png b/OLD_CODE/public/assets/img/gray1.png deleted file mode 100644 index 3137e25..0000000 Binary files a/OLD_CODE/public/assets/img/gray1.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/gray2.png b/OLD_CODE/public/assets/img/gray2.png deleted file mode 100644 index 95b8781..0000000 Binary files a/OLD_CODE/public/assets/img/gray2.png and /dev/null differ diff --git a/OLD_CODE/public/assets/img/диван.jpg b/OLD_CODE/public/assets/img/диван.jpg deleted file mode 100644 index 578d1a3..0000000 Binary files a/OLD_CODE/public/assets/img/диван.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/диван_1.jpg b/OLD_CODE/public/assets/img/диван_1.jpg deleted file mode 100644 index 3618723..0000000 Binary files a/OLD_CODE/public/assets/img/диван_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/кресло.jpg b/OLD_CODE/public/assets/img/кресло.jpg deleted file mode 100644 index 6d1c12b..0000000 Binary files a/OLD_CODE/public/assets/img/кресло.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/кресло_1.jpg b/OLD_CODE/public/assets/img/кресло_1.jpg deleted file mode 100644 index e59b3b1..0000000 Binary files a/OLD_CODE/public/assets/img/кресло_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/слайдер_1.jpg b/OLD_CODE/public/assets/img/слайдер_1.jpg deleted file mode 100644 index 255440e..0000000 Binary files a/OLD_CODE/public/assets/img/слайдер_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/слайдер_2.jpg b/OLD_CODE/public/assets/img/слайдер_2.jpg deleted file mode 100644 index 9cb6403..0000000 Binary files a/OLD_CODE/public/assets/img/слайдер_2.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/слайдер_3.jpg b/OLD_CODE/public/assets/img/слайдер_3.jpg deleted file mode 100644 index dc65d0b..0000000 Binary files a/OLD_CODE/public/assets/img/слайдер_3.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/слайдер_4.jpg b/OLD_CODE/public/assets/img/слайдер_4.jpg deleted file mode 100644 index f6d8d38..0000000 Binary files a/OLD_CODE/public/assets/img/слайдер_4.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/слайдер_5.jpg b/OLD_CODE/public/assets/img/слайдер_5.jpg deleted file mode 100644 index a9cfbb6..0000000 Binary files a/OLD_CODE/public/assets/img/слайдер_5.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/слайдер_6.jpg b/OLD_CODE/public/assets/img/слайдер_6.jpg deleted file mode 100644 index 0dc28a0..0000000 Binary files a/OLD_CODE/public/assets/img/слайдер_6.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/спальня.jpg b/OLD_CODE/public/assets/img/спальня.jpg deleted file mode 100644 index f403324..0000000 Binary files a/OLD_CODE/public/assets/img/спальня.jpg and /dev/null differ diff --git a/OLD_CODE/public/assets/img/стили_оформления.css b/OLD_CODE/public/assets/img/стили_оформления.css deleted file mode 100644 index 2e1d09c..0000000 --- a/OLD_CODE/public/assets/img/стили_оформления.css +++ /dev/null @@ -1,61 +0,0 @@ - -.error-message { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; -} - -.form__input.error { - border-color: #ff0000; -} - -.form__group { - position: relative; - margin-bottom: 15px; -} - -.page-messages { - position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - z-index: 1000; - width: 90%; - max-width: 500px; -} - -.message { - padding: 15px; - margin: 10px 0; - border-radius: 5px; - text-align: center; - font-weight: bold; - display: none; -} - -.message.error { - background-color: #ffebee; - color: #c62828; - border: 1px solid #ffcdd2; -} - -.message.success { - background-color: #e8f5e9; - color: #453227; - border: 1px solid #c8e6c9; -} - -.message.warning { - background-color: #fff3e0; - color: #ef6c00; - border: 1px solid #ffe0b2; -} - -.privacy-error { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; - text-align: center; -} diff --git a/OLD_CODE/public/assets/js/checkout.js b/OLD_CODE/public/assets/js/checkout.js deleted file mode 100644 index 45a09f5..0000000 --- a/OLD_CODE/public/assets/js/checkout.js +++ /dev/null @@ -1,306 +0,0 @@ - -$(document).ready(function() { - - let cart = { - items: [ - { id: 1, name: 'Кресло OPPORTUNITY', price: 16999, quantity: 1 }, - { id: 2, name: 'Кресло GOLDEN', price: 19999, quantity: 1 }, - { id: 3, name: 'Светильник POLET', price: 7999, quantity: 1 } - ], - delivery: 2000, - discount: 0 - }; - - function updateTotal() { - let productsTotal = 0; - let totalCount = 0; - - $('.products__item').each(function() { - const $item = $(this); - const price = parseInt($item.data('price')); - const quantity = parseInt($item.find('.products__qty-value').text()); - - productsTotal += price * quantity; - totalCount += quantity; - }); - - $('.products-total').text(productsTotal + ' ₽'); - $('.summary-count').text(totalCount); - $('.total-count').text(totalCount + ' шт.'); - $('.cart-count').text(totalCount); - - const finalTotal = productsTotal + cart.delivery - cart.discount; - $('.final-total').text(finalTotal + ' ₽'); - } - - function validateEmail(email) { - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - return emailRegex.test(email); - } - - function validateFullName(name) { - - const nameRegex = /^[a-zA-Zа-яА-ЯёЁ\s\-']+$/; - - const words = name.trim().split(/\s+/); - - return nameRegex.test(name) && words.length >= 2; - } - - function validatePhone(phone) { - const phoneRegex = /^\+7\d{10}$/; - return phoneRegex.test(phone); - } - - function showMessage(messageId, duration = 5000) { - $('.message').hide(); - - $(messageId).fadeIn(300); - - if (duration > 0) { - setTimeout(() => { - $(messageId).fadeOut(300); - }, duration); - } - } - - function showPrivacyError(show) { - if (show) { - $('#privacy-error').show(); - } else { - $('#privacy-error').hide(); - } - } - - function showFieldError(fieldId, message) { - $(fieldId).removeClass('error-input'); - $(fieldId + '-error').remove(); - - if (message) { - $(fieldId).addClass('error-input'); - $(fieldId).after('
' + message + '
'); - } - } - - $('#fullname').on('blur', function() { - const value = $(this).val().trim(); - if (value) { - if (!validateFullName(value)) { - showFieldError('#fullname', 'ФИО должно содержать только буквы и состоять минимум из 2 слов'); - } else { - showFieldError('#fullname', ''); - } - } else { - showFieldError('#fullname', ''); - } - }); - - $('#email').on('blur', function() { - const value = $(this).val().trim(); - if (value) { - if (!validateEmail(value)) { - showFieldError('#email', 'Введите корректный email адрес (например: example@mail.ru)'); - } else { - showFieldError('#email', ''); - } - } else { - showFieldError('#email', ''); - } - }); - - $('#phone').on('blur', function() { - const value = $(this).val().trim(); - if (value) { - if (!validatePhone(value)) { - showFieldError('#phone', 'Введите номер в формате +7XXXXXXXXXX (10 цифр после +7)'); - } else { - showFieldError('#phone', ''); - } - } else { - showFieldError('#phone', ''); - } - }); - - $('#region').on('blur', function() { - const value = $(this).val().trim(); - if (!value) { - showFieldError('#region', 'Укажите регион доставки'); - } else { - showFieldError('#region', ''); - } - }); - - $('#address').on('blur', function() { - const value = $(this).val().trim(); - if (!value) { - showFieldError('#address', 'Укажите адрес доставки (улица, дом, квартира)'); - } else { - showFieldError('#address', ''); - } - }); - - $('.form__input').on('input', function() { - const fieldId = '#' + $(this).attr('id'); - showFieldError(fieldId, ''); - }); - - $('.products__qty-btn.plus').click(function() { - const $qtyValue = $(this).siblings('.products__qty-value'); - let quantity = parseInt($qtyValue.text()); - $qtyValue.text(quantity + 1); - updateTotal(); - }); - - $('.products__qty-btn.minus').click(function() { - const $qtyValue = $(this).siblings('.products__qty-value'); - let quantity = parseInt($qtyValue.text()); - if (quantity > 1) { - $qtyValue.text(quantity - 1); - updateTotal(); - } - }); - - $('.remove-from-cart').click(function() { - const $productItem = $(this).closest('.products__item'); - $productItem.fadeOut(300, function() { - $(this).remove(); - updateTotal(); - - if ($('.products__item').length === 0) { - $('.products__list').html('
Корзина пуста
'); - } - }); - }); - - $('.promo__btn').click(function() { - const promoCode = $('.promo__input').val().toUpperCase(); - - if (promoCode === 'SALE10') { - cart.discount = Math.round(parseInt($('.products-total').text()) * 0.1); - $('.discount-total').text(cart.discount + ' ₽'); - showMessage('#form-error', 3000); - $('#form-error').text('Промокод применен! Скидка 10%').removeClass('error').addClass('success'); - } else if (promoCode === 'FREE') { - cart.delivery = 0; - $('.delivery-price').text('0 ₽'); - showMessage('#form-error', 3000); - $('#form-error').text('Промокод применен! Бесплатная доставка').removeClass('error').addClass('success'); - } else if (promoCode) { - showMessage('#form-error', 3000); - $('#form-error').text('Промокод недействителен').removeClass('success').addClass('error'); - } - - updateTotal(); - }); - - $('input[name="delivery"]').change(function() { - if ($(this).val() === 'pickup') { - cart.delivery = 0; - $('.delivery-price').text('0 ₽'); - } else { - cart.delivery = 2000; - $('.delivery-price').text('2000 ₽'); - } - updateTotal(); - }); - - function validateForm() { - let isValid = true; - let errorMessages = []; - - $('.field-error').remove(); - $('.form__input').removeClass('error-input'); - - const requiredFields = [ - { - id: '#fullname', - value: $('#fullname').val().trim(), - validator: validateFullName, - required: true, - message: 'ФИО должно содержать только буквы и состоять минимум из 2 слов' - }, - { - id: '#phone', - value: $('#phone').val().trim(), - validator: validatePhone, - required: true, - message: 'Введите корректный номер телефона в формате +7XXXXXXXXXX' - }, - { - id: '#email', - value: $('#email').val().trim(), - validator: validateEmail, - required: true, - message: 'Введите корректный email адрес' - }, - { - id: '#region', - value: $('#region').val().trim(), - validator: (val) => val.length > 0, - required: true, - message: 'Поле "Регион" обязательно для заполнения' - }, - { - id: '#address', - value: $('#address').val().trim(), - validator: (val) => val.length > 0, - required: true, - message: 'Поле "Адрес" обязательно для заполнения' - } - ]; - - requiredFields.forEach(field => { - if (field.required && (!field.value || !field.validator(field.value))) { - isValid = false; - errorMessages.push(field.message); - showFieldError(field.id, field.message); - } - }); - - if (!$('#privacy-checkbox').is(':checked')) { - isValid = false; - showPrivacyError(true); - errorMessages.push('Необходимо согласие на обработку персональных данных'); - } else { - showPrivacyError(false); - } - - if (!isValid && errorMessages.length > 0) { - showMessage('#form-error', 5000); - $('#form-error').text('Исправьте следующие ошибки: ' + errorMessages.join('; ')).removeClass('success').addClass('error'); - - $('html, body').animate({ - scrollTop: $('.error-input').first().offset().top - 100 - }, 500); - } - - return isValid; - } - - $('#submit-order').click(function() { - if (!validateForm()) { - return; - } - - $(this).prop('disabled', true).text('ОБРАБОТКА...'); - - setTimeout(() => { - showMessage('#order-success', 5000); - $(this).prop('disabled', false).text('ОФОРМИТЬ ЗАКАЗ'); - - }, 2000); - }); - - $('#phone').on('input', function() { - let phone = $(this).val().replace(/\D/g, ''); - if (phone.length > 0) { - if (phone[0] !== '7' && phone[0] !== '8') { - phone = '7' + phone; - } - phone = '+7' + phone.substring(1, 11); - $(this).val(phone); - } - }); - - updateTotal(); -}); diff --git a/OLD_CODE/public/assets/js/profile.js b/OLD_CODE/public/assets/js/profile.js deleted file mode 100644 index 0224b62..0000000 --- a/OLD_CODE/public/assets/js/profile.js +++ /dev/null @@ -1,348 +0,0 @@ -$(document).ready(function() { - - function showMessage(type, text) { - const messageId = type + 'Message'; - const $message = $('#' + messageId); - $message.text(text).fadeIn(300); - setTimeout(() => { - $message.fadeOut(300); - }, 5000); - } - - function isAdminEmail(email) { - const adminEmails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru']; - return adminEmails.includes(email.toLowerCase()); - } - - function validateFIO(fio) { - const words = fio.trim().split(/\s+/); - - const hasNoDigits = !/\d/.test(fio); - return words.length >= 2 && words.every(word => word.length >= 2) && hasNoDigits; - } - - function validateCity(city) { - return city.trim().length >= 2 && /^[а-яА-ЯёЁ\s-]+$/.test(city); - } - - function validateEmail(email) { - const localPart = email.split('@')[0]; - - if (/[а-яА-ЯёЁ]/.test(localPart)) { - showError('email', 'В тексте перед знаком "@" не должно быть кириллических символов'); - return false; - } - - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - if (!emailRegex.test(email)) { - showError('email', 'Введите корректный email адрес'); - return false; - } - - hideError('email'); - return true; - } - - function validatePhone(phone) { - const phoneRegex = /^(\+7|8)[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/; - return phoneRegex.test(phone.replace(/\s/g, '')); - } - - function validatePassword(password) { - return password.length >= 6; - } - - function showError(fieldId, message) { - $('#' + fieldId).addClass('error'); - $('#' + fieldId + '-error').text(message).show(); - } - - function hideError(fieldId) { - $('#' + fieldId).removeClass('error'); - $('#' + fieldId + '-error').hide(); - } - - function validateForm() { - let isValid = true; - - const fio = $('#fio').val(); - if (!validateFIO(fio)) { - if (/\d/.test(fio)) { - showError('fio', 'ФИО не должно содержать цифры'); - } else { - showError('fio', 'ФИО должно содержать минимум 2 слова (каждое от 2 символов)'); - } - isValid = false; - } else { - hideError('fio'); - } - - const city = $('#city').val(); - if (!validateCity(city)) { - showError('city', 'Укажите корректное название города (только русские буквы)'); - isValid = false; - } else { - hideError('city'); - } - - const email = $('#email').val(); - if (!validateEmail(email)) { - showError('email', 'Введите корректный email адрес'); - isValid = false; - } else { - hideError('email'); - } - - const phone = $('#phone').val(); - if (!validatePhone(phone)) { - showError('phone', 'Введите номер в формате: +7(912)999-12-23'); - isValid = false; - } else { - hideError('phone'); - } - - const password = $('#password').val(); - if (!validatePassword(password)) { - showError('password', 'Пароль должен содержать минимум 6 символов'); - isValid = false; - } else { - hideError('password'); - } - - const confirmPassword = $('#confirm-password').val(); - if (password !== confirmPassword) { - showError('confirm-password', 'Пароли не совпадают'); - isValid = false; - } else { - hideError('confirm-password'); - } - - if (!$('#privacy').is(':checked')) { - $('#privacy-error').show(); - isValid = false; - } else { - $('#privacy-error').hide(); - } - - return isValid; - } - - $('input').on('blur', function() { - const fieldId = $(this).attr('id'); - const value = $(this).val(); - - switch(fieldId) { - case 'fio': - if (!validateFIO(value)) { - if (/\d/.test(value)) { - showError(fieldId, 'ФИО не должно содержать цифры'); - } else { - showError(fieldId, 'ФИО должно содержать минимум 2 слова'); - } - } else { - hideError(fieldId); - } - break; - case 'city': - if (!validateCity(value)) { - showError(fieldId, 'Укажите корректное название города'); - } else { - hideError(fieldId); - } - break; - case 'email': - if (!validateEmail(value)) { - showError(fieldId, 'Введите корректный email адрес'); - } else { - hideError(fieldId); - } - break; - case 'phone': - if (!validatePhone(value)) { - showError(fieldId, 'Введите номер в формате: +7(912)999-12-23'); - } else { - hideError(fieldId); - } - break; - case 'password': - if (!validatePassword(value)) { - showError(fieldId, 'Пароль должен содержать минимум 6 символов'); - } else { - hideError(fieldId); - } - break; - case 'confirm-password': - const password = $('#password').val(); - if (value !== password) { - showError(fieldId, 'Пароли не совпадают'); - } else { - hideError(fieldId); - } - break; - } - }); - - $('#registrationForm').on('submit', function(e) { - e.preventDefault(); - - if (validateForm()) { - const email = $('#email').val(); - const isAdmin = isAdminEmail(email); - - const userData = { - email: email, - fio: $('#fio').val(), - phone: $('#phone').val(), - isAdmin: isAdmin, - registered: new Date().toISOString() - }; - - localStorage.setItem('userData', JSON.stringify(userData)); - localStorage.setItem('isLoggedIn', 'true'); - localStorage.setItem('isAdmin', isAdmin.toString()); - - showMessage('success', 'Регистрация прошла успешно! ' + - (isAdmin ? 'Вы зарегистрированы как администратор.' : 'Добро пожаловать в AETERNA!')); - - setTimeout(() => { - - window.location.href = 'cite_mebel.php'; - }, 2000); - } else { - showMessage('error', 'Пожалуйста, исправьте ошибки в форме'); - } - }); - - $('a[href^="#"]').on('click', function(event) { - var target = $(this.getAttribute('href')); - if (target.length) { - event.preventDefault(); - $('html, body').stop().animate({ - scrollTop: target.offset().top - }, 1000); - } - }); - - $('.login-btn').on('click', function() { - showMessage('warning', 'Переход к форме входа...'); - setTimeout(() => { - window.location.href = 'вход.php'; - }, 1000); - }); - - $('.password-link').on('click', function(e) { - e.preventDefault(); - showMessage('warning', 'Функция смены пароля будет доступна после регистрации'); - }); - - $('#phone').on('input', function() { - let value = $(this).val().replace(/\D/g, ''); - if (value.startsWith('7') || value.startsWith('8')) { - value = value.substring(1); - } - if (value.length > 0) { - value = '+7(' + value; - if (value.length > 6) value = value.substring(0, 6) + ')' + value.substring(6); - if (value.length > 10) value = value.substring(0, 10) + '-' + value.substring(10); - if (value.length > 13) value = value.substring(0, 13) + '-' + value.substring(13); - if (value.length > 16) value = value.substring(0, 16); - } - $(this).val(value); - }); - - $('#fio').on('input', function() { - let value = $(this).val(); - - value = value.replace(/\d/g, ''); - $(this).val(value); - }); -}); - -$(document).ready(function() { - - if (localStorage.getItem('isLoggedIn') === 'true') { - const userData = JSON.parse(localStorage.getItem('userData') || '{}'); - if (userData.email) { - $('#login-email').val(userData.email); - } - } - - function checkAdminPassword(email, password) { - - const adminAccounts = { - 'admin@aeterna.ru': 'admin123', - 'administrator@aeterna.ru': 'admin123', - 'aeterna@mail.ru': 'admin123' - }; - - return adminAccounts[email.toLowerCase()] === password; - } - - $('#loginForm').on('submit', function(e) { - e.preventDefault(); - - let isValid = true; - const email = $('#login-email').val(); - const password = $('#login-password').val(); - - if (!isValidEmail(email)) { - $('#email-error').show(); - isValid = false; - } else { - $('#email-error').hide(); - } - - if (password.length < 6) { - $('#password-error').show(); - isValid = false; - } else { - $('#password-error').hide(); - } - - if (isValid) { - - showMessage('success', 'Вы успешно вошли в систему!'); - - setTimeout(function() { - window.location.href = 'cite_mebel.php'; - }, 1500); - } - }); - - function showMessage(type, text) { - const messageId = type + 'Message'; - const $message = $('#' + messageId); - - $message.text(text).show(); - - setTimeout(function() { - $message.fadeOut(); - }, 3000); - } - - $('input').on('focus', function() { - $(this).next('.error-message').hide(); - }); - - $('#remember').on('change', function() { - if ($(this).is(':checked')) { - const email = $('#login-email').val(); - if (email) { - localStorage.setItem('rememberedEmail', email); - } - } else { - localStorage.removeItem('rememberedEmail'); - } - }); - - const rememberedEmail = localStorage.getItem('rememberedEmail'); - if (rememberedEmail) { - $('#login-email').val(rememberedEmail); - $('#remember').prop('checked', true); - } - - $('.forgot-password').on('click', function(e) { - e.preventDefault(); - showMessage('info', 'Для восстановления пароля обратитесь к администратору'); - }); -}); diff --git a/OLD_CODE/public/assets/less/checkout.less b/OLD_CODE/public/assets/less/checkout.less deleted file mode 100644 index a6fe073..0000000 --- a/OLD_CODE/public/assets/less/checkout.less +++ /dev/null @@ -1,137 +0,0 @@ -.error-message { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; -} - -.form__input.error { - border-color: #ff0000; -} - -.form__group { - position: relative; - margin-bottom: 15px; -} - -.page-messages { - position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - z-index: 1000; - width: 90%; - max-width: 500px; -} - -.message { - padding: 15px; - margin: 10px 0; - border-radius: 5px; - text-align: center; - font-weight: bold; - display: none; -} - -.message.error { - background-color: #ffebee; - color: #c62828; - border: 1px solid #ffcdd2; -} - -.message.success { - background-color: #e8f5e9; - color: #453227; - border: 1px solid #c8e6c9; -} - -.message.warning { - background-color: #fff3e0; - color: #ef6c00; - border: 1px solid #ffe0b2; -} - -.privacy-error { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; - text-align: center; -} - -.input-group { - position: relative; - margin-bottom: 20px; -} - -.profile-form input.error { - border-color: #ff0000; - background-color: #fff5f5; -} - -.privacy-checkbox { - margin: 20px 0; - text-align: center; -} - -.privacy-checkbox label { - display: flex; - align-items: center; - justify-content: center; - gap: 8px; - cursor: pointer; - font-size: 14px; -} - -.privacy-checkbox input[type="checkbox"] { - margin: 0; -} - -.profile-page-main { - padding: 40px 0; - min-height: calc(100vh - 200px); -} - -.profile-container { - margin: 0 auto; - position: relative; - z-index: 1; -} - -.input-hint { - font-size: 12px; - color: #666; - margin-top: 5px; -} - -.form-options { - display: flex; - justify-content: space-between; - align-items: center; - margin: 20px 0; -} - -.remember-me { - display: flex; - align-items: center; - gap: 8px; - font-size: 14px; - color: #453227; -} - -.remember-me input[type="checkbox"] { - width: 16px; - height: 16px; - cursor: pointer; -} - -.forgot-password { - font-size: 14px; - color: #453227; - text-decoration: underline; -} - -.forgot-password:hover { - color: #617365; - text-decoration: none; -} \ No newline at end of file diff --git a/OLD_CODE/public/assets/less/mixins.less b/OLD_CODE/public/assets/less/mixins.less deleted file mode 100644 index 10638f0..0000000 --- a/OLD_CODE/public/assets/less/mixins.less +++ /dev/null @@ -1,85 +0,0 @@ -// =================================== -// === ПЕРЕМЕННЫЕ И МИКСИНЫ AETERNA === -// =================================== -@color-primary: #617365; -@color-secondary: #D1D1D1; -@color-accent: #453227; -@color-text-dark: #333; -@color-text-light: #fff; -@color-button: @color-accent; -@color-beige: #A2A09A; - -@font-logo: 'Anek Kannada', sans-serif; -@font-main: 'Anonymous Pro', monospace; -@font-heading: 'Playfair Display', serif; - -@shadow-light: 0 5px 15px rgba(0, 0, 0, 0.2); -@shadow-dark: 2px 2px 4px rgba(0, 0, 0, 0.3); - -.flex-center(@gap: 0) { - display: flex; - align-items: center; - justify-content: center; - gap: @gap; -} - -.flex-between() { - display: flex; - align-items: center; - justify-content: space-between; -} - -.flex-column() { - display: flex; - flex-direction: column; -} - -.icon-base(@size: 18px, @hover-scale: 1.1) { - cursor: pointer; - transition: all 0.3s ease; - font-size: @size; - &:hover { - transform: scale(@hover-scale); - } -} - -.image-overlay() { - position: absolute; - inset: 0; - .flex-center(15px); - flex-direction: column; - text-align: center; - background-color: rgba(0, 0, 0, 0.4); - padding: 20px; - color: @color-text-light; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7); - transition: all 0.3s ease; -} - -.menu-base() { - position: absolute; - top: 100%; - left: 0; - width: 250px; - background: white; - border-radius: 8px; - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); - padding: 15px; - z-index: 1000; - margin-top: 5px; - display: none; -} - -.input-base() { - width: 100%; - padding: 12px 15px; - border: 1px solid #ccc; - background-color: #fff; - font-family: @font-main; - font-size: 14px; - outline: none; - transition: border-color 0.3s ease; - &:focus { - border-color: @color-primary; - } -} diff --git a/OLD_CODE/public/assets/less/style.less b/OLD_CODE/public/assets/less/style.less deleted file mode 100644 index 667a7f4..0000000 --- a/OLD_CODE/public/assets/less/style.less +++ /dev/null @@ -1,3177 +0,0 @@ -@import "mixins.less"; -// ======================= -// === БАЗОВЫЕ СТИЛИ === -// ======================= -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -html, body { - height: 100%; -} - -html { - scroll-behavior: smooth; -} - -body { - font-family: @font-main; - background-color: @color-secondary; - color: @color-text-dark; - line-height: 1.6; - display: flex; - flex-direction: column; - min-height: 100vh; -} - -.container { - max-width: 1210px; - margin: 0 auto; - padding: 0 20px; -} - -ul { - list-style: none; -} - -a { - text-decoration: none; - color: inherit; - transition: all 0.3s ease; -} - -h1, h2, h3, h4, h5, h6 { - font-family: @font-heading; - margin: 0; -} - -p, li, span { - font-family: @font-main; -} - -// ======================= -// === КОМПОНЕНТЫ === -// ======================= - -.logo, .footer-logo { - font: bold 32px/1 @font-logo; - letter-spacing: 2px; - text-shadow: @shadow-dark; - flex-shrink: 0; -} - -.btn { - padding: 12px 30px; - border: none; - cursor: pointer; - font-size: 14px; - text-transform: uppercase; - transition: all 0.3s ease; - font-family: @font-main; - - &.primary-btn { - background-color: @color-button; - color: @color-text-light; - - &:hover { - background-color: lighten(@color-button, 10%); - transform: translateY(-2px); - box-shadow: @shadow-light; - } - } -} - -.number-circle { - .flex-center(); - width: 28px; - height: 28px; - border-radius: 50%; - background-color: @color-button; - color: @color-text-light; - font-size: 16px; - font-weight: bold; - flex-shrink: 0; -} - -.breadcrumbs { - font-size: 14px; - margin-bottom: 20px; - color: #666; - - a { - color: #666; - opacity: 0.7; - &:hover { opacity: 1; } - } - - .current-page { - font-weight: bold; - color: @color-text-dark; - } -} - -// ======================= -// === ШАПКА САЙТА === -// ======================= -.header { - background-color: @color-secondary; - border-bottom: 1px solid rgba(0, 0, 0, 0.05); - z-index: 1000; - - &__top, &__bottom { - padding: 15px 0; - .container { - .flex-between(); - gap: 20px; - } - } - - &__bottom { - padding: 10px 0; - border-top: 1px solid rgba(0, 0, 0, 0.05); - - .catalog-link.active-catalog { - background-color: rgba(0, 0, 0, 0.08); - pointer-events: none; - } - } - - .search-catalog { - .flex-center(); - border: 2px solid @color-text-dark; - background-color: #fff; - max-width: 600px; - width: 100%; - margin: 0 auto; - overflow: hidden; - - .catalog-dropdown { - position: relative; - background-color: #f8f8f8; - padding: 10px 15px 10px 25px; - font-size: 18px; - cursor: pointer; - border-right: 1px solid @color-text-dark; - .flex-center(10px); - width: 200px; - flex-shrink: 0; - - &__menu { - .menu-base(); - li { - padding: 8px 0; - cursor: pointer; - transition: color 0.3s; - border-bottom: 1px solid #f0f0f0; - &:last-child { border-bottom: none; } - &:hover { color: @color-accent; } - } - } - &:hover &__menu { display: block; } - } - - .search-box { - .flex-center(); - padding: 0 15px; - flex-grow: 1; - position: relative; - font-size: 15px; - - input { - border: none; - padding: 10px 30px 10px 0; - outline: none; - font-size: 16px; - width: 100%; - text-align: left; - } - - .search-icon { - font-size: 20px; - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; - } - }} - - &__icons--top { - .flex-center(15px); - flex-shrink: 0; - .icon { .icon-base(); font-size: 20px;} - } - - .nav-list { - .flex-center(30px); - font-size: 18px; - a { - text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); - &:hover { text-shadow: @shadow-dark; } - &.active { - border-bottom: 2px solid @color-button; - padding-bottom: 5px; - text-shadow: @shadow-dark; - } - &[href="#footer"] { - cursor: pointer; - } - } - } - - .catalog-link { - .flex-center(10px); - border-radius: 4px; - white-space: nowrap; - font-size: 18px; - padding: 10px 18px; - &:hover { background-color: rgba(0, 0, 0, 0.05); } - } - - .header-phone { - font-weight: bold; - color: @color-button; - flex-shrink: 0; - } -} - -// ======================= -// === ОСНОВНЫЕ СЕКЦИИ === -// ======================= -.hero { - padding: 15px 0; - - &__content { - .flex-center(50px); - min-height: 60vh; - align-items: center; - } - - &__image-block { - position: relative; - flex: 0 0 40%; - max-width: 600px; - height: 600px; - .flex-center(); - - .hero__circle { - position: absolute; - width: 450px; - height: 450px; - background-color: @color-primary; - border-radius: 50%; - z-index: 1; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - - .hero__img { - position: relative; - width: 100%; - height: 100%; - object-fit: contain; - z-index: 2; - } - } - - &__text-block { - flex: 0 0 60%; - padding-left: 50px; - - h1 { - font-size: 42px; - font-weight: normal; - margin-bottom: 25px; - line-height: 1.3; - } - - .hero__usp-text { - position: relative; - padding-left: 50px; - margin-bottom: 35px; - line-height: 1.7; - .flex-center(); - justify-content: flex-start; - min-height: 40px; - font-size: 16px; - - &::before { - content: "✓"; - position: absolute; - left: 0; - top: 50%; - transform: translateY(-50%); - width: 32px; - height: 32px; - border: 2px solid @color-button; - background-color: transparent; - color: @color-button; - border-radius: 50%; - .flex-center(); - font-size: 16px; - font-weight: bold; - } - } - - .btn.primary-btn { - margin: 25px 0 0 50px; - padding: 14px 35px; - font-size: 15px; - } - } -} - -.advantages { - padding: 30px 0 40px; - - &__header { - display: flex; - align-items: center; - gap: 50px; - margin-bottom: 40px; - h2 { - font-size: 32px; - font-weight: normal; - flex: 0 0 30%; - } - } - - &__items { - flex: 0 0 70%; - display: flex; - gap: 30px; - } - - .advantage-item { - flex: 1; - text-align: left; - position: relative; - padding-top: 30px; - - &__number { - .number-circle(); - position: absolute; - top: 0; - left: 0; - } - - h4 { - font-weight: 600; - margin-bottom: 10px; - } - } -} - -.promo-images { - display: flex; - gap: 20px; - margin-top: 50px; - - .promo-image-col { - position: relative; - overflow: hidden; - border-radius: 8px; - flex: 1; - transition: all 0.3s ease; - - &:hover { - transform: translateY(-5px); - box-shadow: @shadow-light; - .image-overlay-text { background-color: rgba(0, 0, 0, 0.6); } - img { transform: scale(1.05); } - .image-overlay-text h4, - .image-overlay-text .overlay-link { transform: translateY(0); } - } - - img { - width: 100%; - height: 350px; - object-fit: cover; - display: block; - transition: transform 0.5s ease; - } - - .image-overlay-text { - .image-overlay(); - h4 { - font-size: 24px; - text-transform: uppercase; - line-height: 1.2; - margin-bottom: 15px; - transform: translateY(20px); - transition: transform 0.3s ease; - } - } - - .overlay-link { - display: inline-block; - text-transform: uppercase; - font-weight: bold; - border-radius: 3px; - margin-top: 15px; - padding: 10px 25px; - background-color: @color-button; - color: @color-text-light; - font-size: 12px; - transform: translateY(20px); - transition: all 0.3s ease; - - &:hover { - background-color: lighten(@color-button, 10%); - transform: translateY(-2px); - box-shadow: @shadow-light; - } - } - } -} - -.about { - padding: 40px 0 80px; - - &__content { - display: flex; - align-items: flex-start; - gap: 50px; - } - - &__column { - display: flex; - flex-direction: column; - gap: 20px; - &--left { flex: 0 0 40%; margin-bottom: 30px; } - &--right { - flex: 0 0 60%; - .about__caption { - padding-right: 50px; - } - } - } - - &__text-block { - margin-bottom: 30px; - h2 { margin-bottom: 15px; } - } - - &__img { - width: 93%; - object-fit: cover; - display: block; - &--small { height: 300px; } - &--large { height: 450px; } - } - - .text-justified { - text-align: justify; - color: #555; - } -} - -.solutions { - padding: 0; - background-color: @color-secondary; - - &-slider { - position: relative; - width: 100%; - max-width: 1200px; - margin: 40px auto; - border-radius: 8px; - overflow: hidden; - - &__slides { - display: flex; - width: 200%; - height: 100%; - animation: slideLeftRight 10s infinite ease-in-out; - } - - &__slide { - width: 50%; - flex-shrink: 0; - position: relative; - overflow: hidden; - transition: transform 0.5s ease, box-shadow 0.5s ease; - - &:hover { - transform: scale(1.02); - box-shadow: 0 10px 25px rgba(0,0,0,0.3); - .solution-img { - transform: scale(1.05); - filter: brightness(0.8); - } - .solution-text-overlay { - opacity: 1; - transform: translateY(-5px); - } - .solution-image-link { - transform: translateX(-50%) translateY(-6px); - background-color: rgba(255,255,255,0.9); - color: @color-text-dark; - } - } - } - - .solution-img { - width: 100%; - height: auto; - object-fit: cover; - display: block; - } - - .solution-text-overlay { - position: absolute; - top: 15%; - left: 8%; - color: #493131; - text-shadow: 2px 2px 4px rgba(0,0,0,0.6); - z-index: 2; - opacity: 0.9; - transition: opacity 0.5s ease, transform 0.5s ease; - h2 { - font-size: 35px; - text-transform: uppercase; - margin-bottom: 10px; - } - p { - font-size: 25px; - text-transform: uppercase; - } - } - - .solution-image-link { - position: absolute; - bottom: 40px; - left: 50%; - transform: translateX(-50%); - padding: 12px 30px; - border: 2px solid @color-text-light; - color: #493131; - text-transform: uppercase; - font-size: 16px; - font-weight: bold; - background: transparent; - transition: 0.4s ease; - z-index: 2; - &:hover { - background: @color-text-light; - color: @color-text-dark; - transform: translateX(-50%) translateY(-2px); - } - } - } -} - -@keyframes slideLeftRight { - 0%, 40% { transform: translateX(0); } - 50%, 90% { transform: translateX(-50%); } - 100% { transform: translateX(0); } -} - -.stats { - padding: 0; - margin-top: 20px; - - .container { - display: flex; - justify-content: flex-end; - } - - &__items { - display: flex; - gap: 20px; - .stat-item { - text-align: left; - .stat-number { - font-size: 36px; - font-weight: bold; - color: @color-text-dark; - margin-bottom: 5px; - } - .stat-label { color: @color-text-dark; } - } - } -} - -.faq { - padding: 50px 0; - - h2 { - text-align: left; - font-size: 32px; - font-weight: normal; - margin-bottom: 40px; - } - - &__items { - display: flex; - flex-wrap: wrap; - gap: 40px 60px; - margin-bottom: 40px; - } - - .faq-item { - flex: 0 0 calc(50% - 30px); - .flex-center(15px); - align-items: flex-start; - &__content h4 { - font-weight: 600; - margin-bottom: 10px; - } - } - - .btn.primary-btn { - display: block; - width: 100%; - margin: 20px auto 80px; - } -} - -// ======================= -// === СТИЛИ КАТАЛОГА === -// ======================= -.catalog-main { - padding: 30px 0 60px; - background-color: lighten(@color-secondary, 5%); -} - -.catalog-wrapper { - display: flex; - gap: 20px; -} - -.catalog-sidebar { - flex: 0 0 250px; - background-color: #fff; - padding: 20px; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); - height: fit-content; -} - -.filter-group { - margin-bottom: 30px; -} - -.filter-title { - font-size: 16px; - font-weight: bold; - margin-bottom: 15px; - text-transform: uppercase; -} - -.filter-list li { - padding: 5px 0; - font-size: 16px; - a { - color: #555; - transition: color 0.2s; - &:hover { color: @color-accent; } - &.active-category { - font-weight: bold; - color: @color-primary; - } - } -} - -.price-range { - display: flex; - flex-direction: column; - gap: 15px; - width: 100%; - - .range-slider { - width: 100%; - - input[type="range"] { - -webkit-appearance: none; - appearance: none; - width: 100%; - height: 5px; - background: @color-primary; - border-radius: 5px; - outline: none; - margin: 0; - - &::-webkit-slider-thumb { - -webkit-appearance: none; - appearance: none; - width: 20px; - height: 20px; - background: @color-accent; - border: 2px solid #fff; - border-radius: 50%; - cursor: pointer; - box-shadow: 0 2px 4px rgba(0,0,0,0.2); - transition: all 0.3s ease; - - &:hover { - transform: scale(1.1); - background: lighten(@color-accent, 10%); - } - } - - &::-moz-range-thumb { - width: 20px; - height: 20px; - background: @color-accent; - border: 2px solid #fff; - border-radius: 50%; - cursor: pointer; - box-shadow: 0 2px 4px rgba(0,0,0,0.2); - transition: all 0.3s ease; - - &:hover { - transform: scale(1.1); - background: lighten(@color-accent, 10%); - } - } - } - } - - .price-display { - font-size: 14px; - font-weight: bold; - text-align: center; - color: @color-text-dark; - padding: 10px; - background: #f8f8f8; - border-radius: 4px; - } -} - -.filter-options { - list-style: none; - li { - display: flex; - align-items: center; - padding: 4px 0; - font-size: 14px; - } - label { - margin-left: 10px; - cursor: pointer; - color: #555; - } - input[type="checkbox"] { - width: 15px; - height: 15px; - cursor: pointer; - accent-color: @color-primary; - &:checked + label { - font-weight: bold; - color: @color-primary; - } - } -} - -.filter-apply-btn { - width: 100%; - margin-top: 20px; -} - -.catalog-products { - flex-grow: 1; -} - -.products-container { - display: flex; - flex-wrap: wrap; - gap: 20px; -} - -.product-card { - background-color: #fff; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); - display: flex; - flex-direction: column; - position: relative; - transition: transform 0.3s ease; - box-sizing: border-box; - - &:hover { - transform: translateY(-5px); - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); - .product-img { transform: scale(1.05); } - } -} - -.product-image-container { - position: relative; - overflow: hidden; - margin-bottom: 0; - padding: 0; - height: 250px; - .flex-center(); -} - -.product-img { - width: 100%; - height: 100%; - object-fit: contain; - display: block; - transition: transform 0.3s ease; - margin: 0; -} - -.product-img1 { - width: 100%; - height: 100%; - object-fit: cover; - display: block; - transition: transform 0.3s ease; - margin: 0; -} - -.product-discount { - position: absolute; - top: 10px; - right: 10px; - background-color: @color-button; - color: @color-text-light; - padding: 3px 8px; - font-size: 12px; - font-weight: bold; - z-index: 10; -} - -.product-wishlist-icon { - position: absolute; - top: 10px; - left: 10px; - color: #333; - font-size: 18px; - cursor: pointer; - transition: color 0.3s ease; - z-index: 10; - &:hover { color: @color-accent; } -} - -.product-name { - font-size: 16px; - font-weight: bold; - margin-bottom: 5px; -} - -.product-details { - font-size: 13px; - color: #777; - margin-bottom: 10px; - flex-grow: 1; -} - -.product-price { - font-size: 18px; - font-weight: bold; - color: @color-button; -} - -.product-card.small { flex: 0 0 300px; max-width: 300px; height: 200px; } -.product-card.small1 { flex: 0 0 320px; max-width: 320px; height: 250px;width: 320px; } -.product-card.large { flex: 0 0 580px; max-width: 580px; height: 380px; } -.product-card.wide { flex: 0 0 240px; max-width: 240px; height: 250px; } -.product-card.wide1 { flex: 0 0 350px; max-width: 350px; height: 250px; } -.product-card.wide2 { flex: 0 0 560px; max-width: 560px; height: 260px; } -.product-card.wide2_1 { flex: 0 0 560px; max-width: 560px; height: 260px; margin: -280px 0 0; } -.product-card.wide3 { - flex: 0 0 320px; max-width: 320px; height: 540px; - .product-image-container { height: 580px; } -} -.product-card.wide4 { - flex: 0 0 545px; max-width: 545px; margin: -270px 0 0; height: 250px; - .product-image-container { padding: 0; justify-content: flex-start; } - .product-img { margin-left: 0; align-self: flex-start; object-position: left center; } -} -.product-card.tall { flex: 0 0 300px; max-width: 300px; margin: -180px 0 0; height: 430px; } -.product-card.full-width { flex: 0 0 100%; margin: -20px 0 0; max-width: 900px; height: 300px;} - -.product-card.full-width { - flex: 0 0 100%; - max-width: 100%; - height: 300px; - - .product-image-container { - height: 100%; - padding: 0; - margin: 0; - - .product-img1 { - width: 100%; - height: 100%; - object-fit: cover; - margin: 0; - padding: 0; - } - } -} - -.product-card.tall .product-image-container, -.product-card.large .product-image-container { height: 430px; } - -// ======================= -// === СТРАНИЦА ТОВАРА === -// ======================= -.product__section { - display: flex; - gap: 0; - margin: 30px 0; -} - -.product__gallery, .product__info { - flex: 1; -} - -.product__main-image { - margin-bottom: 15px; -} - -.product__image { - width: 500px; - height: 300px; - border-radius: 4px; -} - -.product__thumbnails { - display: flex; - gap: 10px; -} - -.product__thumbnail { - border: none; - background: none; - cursor: pointer; - padding: 0; -} - -.product__thumbnail img { - width: 245px; - height: 150px; - object-fit: cover; - border-radius: 4px; -} - -.product__title { - font-size: 30px; - margin-bottom: 35px; -} - -.product__rating { - display: flex; - align-items: center; - gap: 10px; - margin-bottom: 30px; -} - -.product__color-selector { - display: flex; - gap: 10px; - margin-bottom: 40px; -} - -.product__color-option { - width: 45px; - height: 45px; - border-radius: 50%; - border: 2px solid transparent; - cursor: pointer; - transition: transform 0.3s ease; - - &:hover{ - transform: translateY(-2px); - } -} - -.product__color-option.active { - border-color: @color-primary; -} - -.product__description { - margin-bottom: 65px; - line-height: 1.5; -} - -.product__details-link { - display: inline-block; - margin-bottom: 20px; - color: @color-primary; - font-weight: bold; -} - -.product__purchase { - display: flex; - justify-content: space-between; - margin-bottom: 35px; -} - -.product__price { - font-size: 24px; - font-weight: bold; -} - -.product__quantity { - display: flex; - align-items: center; - gap: 10px; -} - -.product__qty-btn { - width: 30px; - height: 30px; - background: @color-button; - color: @color-text-light; - border: none; - border-radius: 50%; - cursor: pointer; - font-weight: bold; - transition: all 0.3s ease; - - &:hover { - background: lighten(@color-button, 10%); - transform: scale(1.1); - } -} - -.product__qty-value { - font-weight: bold; - min-width: 30px; - text-align: center; -} - -.product__actions { - display: flex; - gap: 15px; -} - -.product__btn { - flex: 1; - padding: 12px 20px; - border: none; - border-radius: 4px; - font-weight: bold; - cursor: pointer; - transition: all 0.3s ease; - - &:hover { - transform: translateY(-2px); - box-shadow: @shadow-light; - } -} - -.product__btn.primary { - background: @color-button; - color: @color-text-light; - - &:hover { - background: lighten(@color-button, 10%); - } -} - -.product__btn.secondary { - background: transparent; - border: 1px solid @color-button; - color: @color-button; - - &:hover { - background: @color-button; - color: @color-text-light; - } -} - -.similar { - margin: 60px 0; -} - -.similar__title { - margin-bottom: 30px; - font-size: 28px; - font-weight: bold; -} - -.similar__grid { - display: flex; - gap: 25px; - flex-wrap: wrap; - justify-content: space-between; -} - -.similar__card { - flex: 0 0 calc(33.333% - 17px); - min-width: 320px; - background: @color-secondary; - border-radius: 12px; - overflow: hidden; - transition: all 0.3s ease; - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); - - &:hover { - transform: translateY(-8px); - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); - } -} - -.similar__card-image { - height: 300px; - overflow: hidden; - background: white; - - img { - width: 100%; - height: 100%; - object-fit: contain; - transition: transform 0.3s ease; - - &:hover { - transform: scale(1.05); - } - } -} - -.similar__card-content { - padding: 25px; -} - -.similar__card-title { - font-weight: bold; - margin-bottom: 10px; - font-size: 20px; - color: @color-text-dark; -} - -.similar__card-description { - font-size: 15px; - margin-bottom: 15px; - color: #666; - line-height: 1.5; -} - -.similar__card-price { - font-weight: bold; - font-size: 22px; - color: @color-button; -} - -@media (max-width: 1024px) { - .similar { - &__card { - flex: 0 0 calc(50% - 13px); - min-width: 280px; - } - } -} - -@media (max-width: 768px) { - .similar { - &__grid { - justify-content: center; - } - - &__card { - flex: 0 0 100%; - max-width: 400px; - } - } -} - -// ======================= -// === КОРЗИНА И ЗАКАЗ === -// ======================= -.main__content { - display: flex; - gap: 40px; - margin: 30px 0; - - .products { - flex: 1; - } - - .order { - flex: 0 0 65%; - padding: 40px; - - &__header { - .flex-between(); - margin-bottom: 20px; - } - - &__title { - font-family: @font-logo; - font-size: 28px; - color: @color-text-dark; - margin: 0; - } - - &__total { - font-weight: bold; - color: @color-text-dark; - } - - &__section { - margin-bottom: 25px; - } - - &__section-title { - font-family: @font-logo; - margin-bottom: 15px; - font-size: 18px; - color: @color-text-dark; - } - } -} - -.products { - &__title { - font-family: @font-logo; - margin-bottom: 20px; - font-size: 24px; - color: @color-text-dark; - } - - &__list { - .flex-column(); - gap: 20px; - } - - &__item { - background-color: @color-secondary; - border-radius: 8px; - padding: 20px; - display: flex; - gap: 15px; - border: 1px solid @color-secondary; - transition: transform 0.3s ease; - align-items: flex-start; - position: relative; - - &:hover { - transform: translateY(-2px); - } - } - - &__image { - width: 300px; - height: 200px; - border-radius: 4px; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: flex-start; - } - - .product-img { - width: 100%; - height: 100%; - object-fit: cover; - display: block; - transition: transform 0.3s ease; - margin: 0; - } - - &__details { - flex: 1; - .flex-column(); - justify-content: space-between; - align-items: flex-start; - min-height: 200px; - } - - &__name { - font-weight: bold; - margin-bottom: 5px; - color: @color-accent; - font-size: 18px; - font-family: @font-main; - } - - &__price { - font-weight: bold; - font-size: 18px; - margin-bottom: 15px; - color: @color-text-dark; - } - - &__controls { - display: flex; - align-items: center; - gap: 15px; - margin-top: auto; - width: 100%; - justify-content: space-between; - } - - &__quantity { - display: flex; - align-items: center; - gap: 10px; - } - - &__qty-btn { - width: 30px; - height: 30px; - background-color: @color-text-dark; - color: @color-text-light; - border: none; - border-radius: 50%; - cursor: pointer; - .flex-center(); - font-family: @font-main; - font-weight: bold; - transition: all 0.3s ease; - - &:hover { - transform: scale(1.1); - } - } - - &__qty-value { - font-weight: bold; - min-width: 30px; - text-align: center; - font-size: 16px; - } - - &__cart-icon { - background-color: transparent; - color: @color-text-dark; - width: 40px; - height: 40px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: all 0.3s ease; - border: 2px solid @color-text-dark; - margin-left: 20px; - - &:hover { - transform: scale(1.1); - } - - i { font-size: 18px; } - } -} - -.form { - &__group { margin-bottom: 15px; } - &__label { - display: block; - margin-bottom: 5px; - font-weight: bold; - color: #000000; - } - &__input { - width: 100%; - padding: 14px 16px; - border: 2px solid #ccc; - font-family: @font-main; - font-size: 15px; - transition: border-color 0.3s ease; - - &:focus { - border-color: @color-primary; - } - - &:hover { - border-color: darken(#ccc, 10%); - } - &::placeholder { - font-style: italic; - color: #999; - } - } - &__row { - display: flex; - gap: 20px; - justify-content: space-between; - } - &__input--half { - width: 100%; - } - &__radio-group { - display: flex; - justify-content: space-between; - margin-bottom: 20px; - margin-top: 20px; - } - &__radio-label { - display: flex; - align-items: center; - cursor: pointer; - color: @color-text-dark; - position: relative; - padding-left: 30px; - flex: 1; - - &:hover { - .form__custom-radio { - border-color: lighten(@color-accent, 10%); - } - } - } - &__radio-input { - position: absolute; - opacity: 0; - cursor: pointer; - } - &__custom-radio { - position: absolute; - left: 0; - height: 20px; - width: 20px; - background-color: @color-secondary; - border: 2px solid @color-accent; - border-radius: 50%; - transition: border-color 0.3s ease; - } - &__radio-input:checked ~ &__custom-radio { - background-color: @color-accent; - - &:after { - content: ""; - position: absolute; - display: block; - top: 4px; - left: 4px; - width: 8px; - height: 8px; - border-radius: 50%; - background: white; - } - } -} - -.divider { - height: 1px; - background-color: #999; - margin: 20px 0; -} - -.promo { - display: flex; - margin-bottom: 20px; - - &__input { - flex: 1; - padding: 10px; - border: 1px solid #000; - background-color: @color-secondary; - font-family: @font-main; - height: auto; - min-height: 48px; - - &:hover { - border-color: @color-primary; - } - - &::placeholder { - font-style: italic; - color: #999; - } - } - - &__btn { - background-color: @color-accent; - color: @color-secondary; - border: none; - padding: 10px 60px; - cursor: pointer; - font-family: @font-main; - font-size: 18px; - transition: all 0.3s ease; - - &:hover { - background-color: lighten(@color-accent, 10%); - transform: translateY(-2px); - } - } -} - -.summary { - margin-bottom: 20px; - - &__item { - display: flex; - justify-content: space-between; - margin-bottom: 10px; - color: @color-text-dark; - - &.total { - font-weight: bold; - font-size: 18px; - padding-top: 10px; - margin-top: 10px; - } - } -} - -.order-btn { - width: 100%; - background-color: @color-accent; - color: @color-secondary; - border: none; - padding: 15px; - border-radius: 4px; - font-size: 18px; - cursor: pointer; - margin-bottom: 10px; - font-family: @font-main; - transition: all 0.3s ease; - - &:hover { - background-color: lighten(@color-accent, 10%); - transform: translateY(-2px); - } -} - -.privacy { - display: flex; - gap: 8px; - font-size: 16px; - color: #666; - margin-bottom: 20px; - - input[type="checkbox"] { - width: 18px; - height: 18px; - cursor: pointer; - } -} - -.services { - display: flex; - flex-direction: row; - justify-content: center; - flex-wrap: wrap; - gap: 24px; - margin-bottom: 24px; - - &__title { - font-family: @font-logo; - margin-bottom: 10px; - font-size: 18px; - color: @color-text-dark; - display: block; - width: 100%; - } - - &__item { - display: flex; - justify-content: space-between; - margin-bottom: 8px; - color: @color-text-dark; - width: 100%; - } -} - -.cart-icon { - position: relative; -} - -.cart-count { - position: absolute; - top: -8px; - right: -8px; - background: @color-accent; - color: @color-text-light; - border-radius: 50%; - width: 18px; - height: 18px; - font-size: 12px; - display: flex; - align-items: center; - justify-content: center; -} - -.form__input.error { - border-color: #ff4444; - box-shadow: 0 0 5px rgba(255, 68, 68, 0.3); -} - -.empty-cart { - text-align: center; - padding: 40px; - color: #666; - font-size: 18px; -} - -// ======================= -// === АВТОРИЗАЦИЯ === -// ======================= -.profile-page-main { - .flex-center(); - min-height: 80vh; - padding: 40px 0; - background-color: lighten(@color-secondary, 5%); - z-index: 1; - - .profile-container { - display: flex; - width: 100%; - max-width: 1000px; - min-height: 600px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); - background-color: @color-text-light; - } - - .profile-left-col { - flex: 0 0 35%; - background-color: @color-primary; - color: @color-text-light; - display: flex; - justify-content: flex-start; - align-items: flex-start; - padding: 40px; - .logo { - font-size: 32px; - font-weight: normal; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4); - color: @color-text-light; - } - } - - .profile-right-col { - flex: 0 0 65%; - .flex-center(); - padding: 40px; - .profile-form-block { - width: 100%; - max-width: 400px; - h2 { - font-size: 28px; - font-weight: normal; - margin-bottom: 40px; - text-align: left; - color: @color-text-dark; - } - } - } - - .profile-form { - .input-group { - margin-bottom: 20px; - label { - display: block; - font-size: 12px; - font-weight: bold; - color: @color-text-dark; - margin-bottom: 5px; - text-transform: uppercase; - } - } - - input[type="text"], - input[type="email"], - input[type="tel"] { - .input-base(); - } - - .password-link { - display: block; - text-align: left; - font-size: 13px; - color: @color-text-dark; - text-decoration: underline; - margin: 10px 0 20px; - &:hover { - color: @color-accent; - text-decoration: none; - } - } - - .save-btn { - padding: 15px 30px; - border: none; - cursor: pointer; - font-size: 15px; - text-transform: uppercase; - transition: all 0.3s ease; - font-family: @font-main; - width: 100%; - margin-top: 20px; - background-color: @color-primary; - color: @color-text-light; - - &:hover { - background-color: lighten(@color-primary, 10%); - transform: translateY(-2px); - box-shadow: @shadow-light; - } - } - - .auth-actions { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 25px; - padding-top: 20px; - border-top: 1px solid #eee; - - .auth-text { - font-size: 13px; - color: @color-text-dark; - } - - .login-btn { - background-color: transparent; - color: @color-accent; - border: 1px solid @color-accent; - padding: 10px 25px; - font-size: 13px; - cursor: pointer; - transition: all 0.3s ease; - - &:hover { - background-color: @color-primary; - color: @color-text-light; - } - } - } - } -} - -// ======================= -// === СЕКЦИЯ УСЛУГ === -// ======================= -.services-section { - padding: 60px 0; - background-color: @color-secondary; -} - -.services__wrapper { - display: flex; - flex-direction: column; - gap: 30px; -} - -.services__top-row { - display: flex; - gap: 30px; - justify-content: center; - - @media (max-width: 768px) { - flex-direction: column; - align-items: center; - } -} - -.service-card { - border-radius: 8px; - padding: 40px; - min-height: 200px; - text-align: center; - transition: all 0.3s ease; - - &:hover { - transform: translateY(-5px); - box-shadow: @shadow-light; - } - - &--green { - background: @color-primary; - color: @color-text-light; - flex: 1; - max-width: 450px; - } - - &--beige { - background: @color-beige; - color: @color-text-light; - width: 100%; - max-width: 930px; - margin: 0 auto; - } - - &__title { - font-family: @font-logo; - font-size: 24px; - font-weight: bold; - margin-bottom: 15px; - text-transform: uppercase; - } - - &__text { - font-family: @font-main; - font-size: 16px; - line-height: 1.6; - margin: 0; - } -} - -// ======================= -// === ФУТЕР === -// ======================= -.footer { - background-color: @color-primary; - color: black; - padding: 40px 0 10px; - position: relative; - z-index: 1000; - - &::before { - content: ''; - display: block; - position: absolute; - top: -80px; - left: 0; - width: 100%; - height: 1px; - visibility: hidden; - } - - &__content { - display: flex; - gap: 20px; - padding-bottom: 30px; - border-bottom: 1px solid rgba(255, 255, 255, 0.2); - } - - &__col { - flex: 1; - &--logo { flex: 1.5; } - h5 { - margin-bottom: 15px; - font-size: 14px; - text-transform: uppercase; - } - ul li { - margin-bottom: 8px; - a:hover { text-decoration: underline; } - } - .social-icons, - .payment-icons { - .flex-center(15px); - justify-content: flex-start; - margin-top: 10px; - } - .social-icons .icon { - .icon-base(20px, 1.1); - color: black; - &:hover { color: @color-accent; } - } - .payment-icons .pay-icon { - .icon-base(24px, 1.05); - color: black; - } - } - - .copyright { - text-align: center; - font-size: 12px; - padding-top: 20px; - color: rgba(255, 255, 255, 0.6); - } -} - -// ======================= -// === ДОСТАВКА === -// ======================= -.delivery-content { - max-width: 1200px; - margin: 0 auto; - padding: 40px 20px; -} - -.delivery-content h1 { - font-family: @font-logo; - font-size: 42px; - text-align: center; - margin-bottom: 50px; - color: #453227; -} - -.delivery-section { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 30px; - margin-bottom: 60px; -} - -.delivery-card { - background: white; - padding: 30px; - border-radius: 12px; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); - text-align: center; - transition: transform 0.3s ease; - flex: 1; - min-width: 350px; - max-width: 400px; -} - -.delivery-card:hover { - transform: translateY(-5px); -} - -.delivery-icon { - font-size: 48px; - color: #617365; - margin-bottom: 20px; -} - -.delivery-card h3 { - font-family: @font-logo; - font-size: 24px; - margin-bottom: 20px; - color: #453227; -} - -.delivery-details { - text-align: left; -} - -.detail-item { - display: flex; - justify-content: space-between; - margin-bottom: 12px; - padding-bottom: 12px; - border-bottom: 1px solid #f0f0f0; -} - -.detail-label { - font-weight: bold; - color: #333; -} - -.detail-value { - color: #617365; - text-align: right; -} - -// ======================= -// === ГАРАНТИЯ === -// ======================= -.warranty-content { - max-width: 1200px; - margin: 0 auto; - padding: 40px 20px; -} - -.warranty-content h1 { - font-family: 'Anek Kannada', sans-serif; - font-size: 42px; - text-align: center; - margin-bottom: 50px; - color: #453227; -} - -.warranty-overview { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 25px; - margin-bottom: 60px; -} - -.warranty-card { - background: white; - padding: 30px; - border-radius: 12px; - text-align: center; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); - transition: transform 0.3s ease; - flex: 1; - min-width: 250px; - max-width: 280px; - display: flex; - flex-direction: column; - align-items: center; -} - -.warranty-card:hover { - transform: translateY(-5px); -} - -.warranty-icon { - font-size: 48px; - color: #617365; - margin-bottom: 20px; -} - -.warranty-card h3 { - font-family: 'Anek Kannada', sans-serif; - font-size: 20px; - margin-bottom: 15px; - color: #453227; -} - -.warranty-period { - font-size: 24px; - font-weight: bold; - color: #617365; - margin-top: auto; -} - -.coverage-section { - display: flex; - flex-wrap: wrap; - gap: 40px; - margin-bottom: 60px; -} - -.coverage-covered, -.coverage-not-covered { - flex: 1; - min-width: 300px; -} - -.coverage-section h2 { - font-family: 'Anek Kannada', sans-serif; - font-size: 24px; - margin-bottom: 25px; - color: #453227; -} - -.coverage-list { - display: flex; - flex-direction: column; - gap: 20px; -} - -.coverage-item { - display: flex; - align-items: flex-start; - gap: 15px; - padding: 20px; - border-radius: 8px; - background: white; - box-shadow: 0 3px 10px rgba(0,0,0,0.1); -} - -.coverage-item.covered i { - color: #28a745; - font-size: 20px; - margin-top: 2px; - flex-shrink: 0; -} - -.coverage-item.not-covered i { - color: #dc3545; - font-size: 20px; - margin-top: 2px; - flex-shrink: 0; -} - -.coverage-text { - flex: 1; -} - -.coverage-item h4 { - font-family: 'Anek Kannada', sans-serif; - font-size: 16px; - margin-bottom: 5px; - color: #333; -} - -.card { - min-height: 250px; - display: flex; - align-items: center; - justify-content: center; - color: @color-text-light; - text-align: center; - - &--green { - background: @color-primary; - flex: 0 1 450px; - max-width: 450px; - } - - &--beige { - background: @color-beige; - color: @color-text-dark; - flex: 0 1 925px; - max-width: 925px; - } -} - -.design-section { - display: flex; - justify-content: center; - margin-bottom: 40px; - .card { width: 100%; } -} - -// ======================= -// === АДАПТИВНОСТЬ === -// ======================= -@media (max-width: 1240px) { - .catalog-wrapper { gap: 20px; } - .catalog-sidebar { flex: 0 0 200px; } - .products-container { - gap: 15px; - display: flex; - flex-wrap: wrap; - } - - .product-card.small1 { - margin-top: 100px; - } - - .product-card.small, - .product-card.small1, - .product-card.large, - .product-card.wide, - .product-card.wide1, - .product-card.wide2, - .product-card.wide2_1, - .product-card.wide4 { - flex: 0 0 calc(33.333% - 10px); - max-width: calc(33.333% - 10px); - height: 180px; - margin: 0; - - .product-image-container { - height: 180px; - } - } - - .product-card.wide3 { - flex: 0 0 calc(25% - 10px); - max-width: calc(25% - 10px); - height: 300px; - margin: 0; - - .product-image-container { - height: 350px; - } - } - - .product-card.tall { - flex: 0 0 calc(25% - 10px); - max-width: calc(25% - 10px); - height: 300px; - margin: 0; - - .product-image-container { - height: 300px; - } - } - - .product-card.full-width { - flex: 0 0 100%; - max-width: 100%; - height: 300px; - margin: 0; - - .product-image-container { - height: 300px; - } - } - - .product-card.small { order: 1; } - .product-card.large { order: 2; } - .product-card.wide { order: 3; } - - .product-card.small1 { order: 11; } - .product-card.wide2 { order: 12; } - .product-card.wide2_1 { order: 13; } - - .product-card.wide3 { order: 21; } - .product-card.tall { order: 22; } - - .product-card.wide3 { order: 31; } - - .product-card.full-width { order: 41; flex-basis: 100%; } - - .main__content { - gap: 20px; - .products { - flex: 0 0 35%; - .products__image { - width: 250px; - height: 180px; - } - } - .order { - flex: 0 0 60%; - padding: 30px; - - .order__title { - font-size: 24px; - } - - .order__section-title { - font-size: 16px; - } - } - } - - .solutions-slider { - &__slide { - .solution-text-overlay { - top: 10%; - left: 5%; - h2 { - font-size: 26px; - margin-bottom: 5px; - line-height: 1.2; - } - p { - font-size: 18px; - line-height: 1.2; - } - } - .solution-image-link { - bottom: 70px; - padding: 10px 25px; - font-size: 14px; - } - } - } - - .product__image { - width: 350px; - height: 250px; - } - - .product__thumbnail img { - width: 170px; - height: 120px; - } -} - -@media (max-width: 1024px) { - .main__content { - gap: 25px; - .products { - flex: 0 0 30%; - .products__image { - width: 200px; - height: 150px; - } - - .products__name { - font-size: 16px; - } - - .products__price { - font-size: 16px; - } - } - .order { - flex: 0 0 60%; - padding: 25px; - - .order__title { - font-size: 22px; - } - - .form__input { - padding: 12px 14px; - font-size: 14px; - } - - .promo__btn { - padding: 10px 40px; - font-size: 16px; - } - } - } -} - -@media (max-width: 768px) { - .container { padding: 0 15px; } - - .delivery-section { - flex-direction: column; - align-items: center; - } - - .delivery-card { - min-width: 100%; - max-width: 100%; - } - - .delivery-content h1 { - font-size: 32px; - } - - .warranty-overview { - flex-direction: column; - align-items: center; - } - - .warranty-card { - max-width: 100%; - width: 100%; - } - - .coverage-section { - flex-direction: column; - } - - .warranty-content h1 { - font-size: 32px; - } - - .header__top .container, - .header__bottom .container, - .hero__content, - .advantages__header, - .about__content, - .advantages__items, - .promo-images, - .stats__items, - .faq__items, - .catalog-wrapper, - .main__content { - flex-direction: column; - gap: 30px; - } - - .search-catalog { - order: 3; - width: 100%; - max-width: 100%; - } - - .nav-list { - flex-wrap: wrap; - justify-content: center; - gap: 15px; - } - - .hero { - &__image-block { - flex: none; - max-width: 400px; - height: 400px; - } - &__circle { - width: 380px; - height: 380px; - } - &__text-block { - flex: none; - padding-left: 0; - text-align: center; - h1 { font-size: 32px; } - .hero__usp-text { - padding-left: 0; - justify-content: center; - &::before { display: none; } - } - .btn.primary-btn { margin-left: 0; } - } - } - - .advantages__header h2, - .faq h2 { font-size: 28px; } - - .faq-item, - .stat-item { - flex: none; - .flex-center(); - text-align: center; - } - - .stats .container { justify-content: center; } - .catalog-dropdown__menu { width: 200px; } - - .catalog-sidebar { width: 100%; flex: none; } - .products-container { gap: 15px; } - - .product-card.small, - .product-card.small1, - .product-card.large, - .product-card.wide, - .product-card.wide1, - .product-card.wide2, - .product-card.wide2_1, - .product-card.wide3, - .product-card.wide4, - .product-card.tall, - .product-card.full-width { - flex: 0 0 100%; - max-width: 100%; - height: 250px; - margin: 0; - - .product-image-container { - height: 200px; - } - } - - .main__content { - flex-direction: column; - gap: 20px; - - .products, - .order { - flex: 0 0 100%; - width: 100%; - } - - .products { - .products__item { - flex-direction: column; - text-align: center; - gap: 15px; - } - - .products__image { - width: 100%; - height: 200px; - justify-content: center; - } - - .products__details { - min-height: auto; - align-items: center; - } - - .products__controls { - justify-content: center; - margin-top: 15px; - } - - .products__cart-icon { - margin-left: 0; - } - } - - .order { - padding: 20px; - - .order__title { - font-size: 20px; - text-align: center; - } - - .order__total { - text-align: center; - } - - .form__radio-group { - flex-direction: column; - gap: 15px; - } - - .form__radio-label { - flex: none; - justify-content: flex-start; - } - - .promo { - flex-direction: column; - gap: 10px; - - &__btn { - width: 100%; - padding: 12px; - } - } - - .order-btn { - padding: 12px; - font-size: 16px; - } - - .services { - flex-direction: column; - align-items: center; - } - } - } - - .product-image-container { height: 200px; } - .product-card.tall .product-image-container, - .product-card.large .product-image-container { height: 250px; } - - .profile-page-main { - .profile-container { - flex-direction: column; - min-height: auto; - max-width: 100%; - box-shadow: none; - } - .profile-left-col { - flex: none; - width: 100%; - height: 100px; - .flex-center(); - padding: 0; - } - .profile-right-col { - flex: none; - width: 100%; - padding: 30px 20px; - } - .profile-form-block { max-width: 100%; } - } - - .form__row { flex-direction: column; } - .form__input--half { flex: 0 0 100%; max-width: 100%; } - .services { flex-direction: column; align-items: center; } - - .services-section { - padding: 40px 0; - } - - .service-card { - padding: 30px 20px; - min-height: 180px; - - &--green, - &--beige { - max-width: 100%; - } - - &__title { - font-size: 20px; - } - - &__text { - font-size: 14px; - } - } - .solutions-slider { - margin: 20px auto; - &__slide { - .solution-text-overlay { - top: 8%; - left: 4%; - h2 { - font-size: 20px; - margin-bottom: 3px; - line-height: 1.1; - } - p { - font-size: 15px; - line-height: 1.1; - } - } - .solution-image-link { - bottom: 90px; - padding: 8px 20px; - font-size: 13px; - } - } - } -} - -// Стили для ошибок полей -.error-input { - border-color: #ff4444 !important; - box-shadow: 0 0 0 1px #ff4444; -} - -.field-error { - color: #ff4444; - font-size: 12px; - margin-top: 5px; - margin-bottom: 10px; -} - -// Стили для сообщений -.message { - padding: 15px; - margin: 20px 0; - border-radius: 5px; - display: none; -} - -.message.error { - background-color: #ffebee; - color: #c62828; - border: 1px solid #ffcdd2; -} - -.message.success { - background-color: #e8f5e9; - color: #2e7d32; - border: 1px solid #c8e6c9; -} - -// Добавьте в конец файла -.access-denied { - text-align: center; - padding: 80px 20px; - background: white; - border-radius: 10px; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); - margin: 50px 0; - - h2 { - color: #dc3545; - margin-bottom: 30px; - font-size: 28px; - } - - p { - color: #666; - margin-bottom: 40px; - font-size: 18px; - line-height: 1.6; - } - - .btn { - margin: 5px; - min-width: 200px; - } -} -// ======================= -// === ПРОФИЛЬ ПОЛЬЗОВАТЕЛЯ === -// ======================= - -.user-profile-dropdown { - position: relative; - display: inline-block; - - &__toggle { - display: flex; - align-items: center; - gap: 8px; - cursor: pointer; - padding: 8px 12px; - border-radius: 4px; - transition: all 0.3s ease; - - &:hover { - background-color: rgba(0, 0, 0, 0.05); - } - - .user-avatar { - width: 32px; - height: 32px; - border-radius: 50%; - background-color: @color-primary; - color: @color-text-light; - .flex-center(); - font-weight: bold; - } - - .user-info { - display: flex; - flex-direction: column; - - .user-email { - font-size: 12px; - color: #666; - max-width: 150px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .user-status { - font-size: 10px; - padding: 2px 6px; - border-radius: 10px; - text-transform: uppercase; - - &.admin { - background-color: #617365; - color: white; - } - - &.user { - background-color: #28a745; - color: white; - } - } - } - } - - &__menu { - .menu-base(); - width: 220px; - top: 100%; - right: 0; - - .user-details { - padding: 15px; - border-bottom: 1px solid #eee; - - .user-name { - font-weight: bold; - margin-bottom: 5px; - } - - .user-registered { - font-size: 11px; - color: #999; - } - } - - ul { - padding: 10px 0; - - li { - padding: 8px 15px; - cursor: pointer; - display: flex; - align-items: center; - gap: 10px; - transition: background-color 0.3s ease; - - &:hover { - background-color: #f5f5f5; - } - - &.logout { - color: #dc3545; - border-top: 1px solid #eee; - margin-top: 5px; - padding-top: 12px; - - &:hover { - background-color: #ffe6e6; - } - } - } - } - } - - &:hover &__menu { - display: block; - } -} - -// ======================= -// === КАРТОЧКА ТОВАРА === -// ======================= - -.product-image-container { - position: relative; - overflow: hidden; - margin-bottom: 0; - padding: 0; - height: 250px; - .flex-center(); - - &:hover { - .product-overlay-info { - opacity: 1; - transform: translateY(0); - } - } -} - -.product-overlay-info { - position: absolute; - bottom: 0; - left: 0; - right: 0; - background: linear-gradient(to top, rgba(0,0,0,0.8), transparent); - color: white; - padding: 15px; - opacity: 0; - transform: translateY(10px); - transition: all 0.3s ease; - - .product-overlay-name { - font-weight: bold; - font-size: 14px; - margin-bottom: 5px; - } - - .product-overlay-price { - font-size: 16px; - font-weight: bold; - - .old-price { - text-decoration: line-through; - font-size: 12px; - color: #ccc; - margin-right: 5px; - } - - .current-price { - color: #ffd700; - } - } - - .product-overlay-category { - font-size: 11px; - opacity: 0.8; - margin-top: 3px; - } - - .product-overlay-stock { - font-size: 11px; - margin-top: 5px; - - &.out-of-stock { - color: #ff6b6b; - } - - i { - margin-right: 5px; - } - } -} - -.product-card-details { - padding: 15px; - background: white; - flex-grow: 1; - display: flex; - flex-direction: column; - - .product-card-name { - font-weight: bold; - font-size: 16px; - margin-bottom: 8px; - color: @color-text-dark; - } - - .product-card-description { - font-size: 13px; - color: #777; - margin-bottom: 10px; - flex-grow: 1; - } - - .product-card-attributes { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-bottom: 10px; - - .attribute { - font-size: 11px; - background: #f5f5f5; - padding: 3px 8px; - border-radius: 12px; - color: #666; - - i { - margin-right: 3px; - } - } - } - - .product-card-price { - margin-bottom: 10px; - - .old-price { - text-decoration: line-through; - font-size: 14px; - color: #999; - margin-right: 8px; - } - - .current-price { - font-size: 18px; - font-weight: bold; - color: @color-button; - } - } - - .add-to-cart-btn { - width: 100%; - padding: 8px; - font-size: 14px; - } - - .admin-actions { - display: flex; - gap: 5px; - margin-top: 10px; - - .admin-btn { - flex: 1; - font-size: 12px; - padding: 6px; - - &.delete-btn { - background: #dc3545; - - &:hover { - background: #c82333; - } - } - } - } -} - -// ======================= -// === ПРОФИЛЬ ПОЛЬЗОВАТЕЛЯ === -// ======================= - -.user-profile-dropdown { - position: relative; - display: inline-block; - - .user-profile-toggle { - display: flex; - align-items: center; - gap: 10px; - cursor: pointer; - padding: 8px 12px; - border-radius: 4px; - transition: all 0.3s ease; - - &:hover { - background-color: rgba(0, 0, 0, 0.05); - - .dropdown-arrow { - transform: rotate(180deg); - } - } - - .user-avatar { - width: 36px; - height: 36px; - border-radius: 50%; - background: linear-gradient(135deg, #617365 0%, #453227 100%); - color: @color-text-light; - .flex-center(); - font-weight: bold; - font-size: 16px; - box-shadow: 0 2px 5px rgba(0,0,0,0.2); - } - - .user-info { - display: flex; - flex-direction: column; - - .user-email { - font-size: 12px; - color: #666; - max-width: 120px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .user-status { - font-size: 10px; - padding: 2px 8px; - border-radius: 12px; - text-transform: uppercase; - font-weight: bold; - text-align: center; - margin-top: 2px; - - &.admin { - background-color: #617365; - color: white; - border: 1px solid #617365; - } - - &.user { - background-color: #28a745; - color: white; - border: 1px solid #28a745; - } - } - } - - .dropdown-arrow { - font-size: 10px; - color: #666; - transition: transform 0.3s ease; - } - } - - .user-profile-menu { - .menu-base(); - width: 280px; - top: 100%; - right: 0; - margin-top: 10px; - padding: 0; - overflow: hidden; - - .user-profile-header { - padding: 20px; - background: linear-gradient(135deg, #617365 0%, #453227 100%); - color: white; - - .user-profile-name { - font-weight: bold; - margin-bottom: 8px; - display: flex; - align-items: center; - gap: 10px; - font-size: 16px; - } - - .user-profile-details { - small { - display: block; - opacity: 0.8; - margin-bottom: 5px; - font-size: 11px; - - i { - margin-right: 5px; - width: 14px; - text-align: center; - } - } - } - } - - .user-profile-links { - list-style: none; - padding: 10px 0; - - li { - border-bottom: 1px solid #f0f0f0; - - &:last-child { - border-bottom: none; - } - - a { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 20px; - color: #333; - transition: all 0.3s ease; - - &:hover { - background-color: #f8f9fa; - color: @color-primary; - text-decoration: none; - - i { - transform: scale(1.1); - } - } - - i { - width: 20px; - text-align: center; - font-size: 14px; - color: #617365; - transition: transform 0.3s ease; - } - - span { - flex-grow: 1; - } - } - } - - .logout-item { - border-top: 2px solid #f0f0f0; - margin-top: 5px; - - a { - color: #dc3545; - - &:hover { - background-color: #ffe6e6; - color: #c82333; - - i { - color: #dc3545; - } - } - } - } - } - } - - &:hover .user-profile-menu { - display: block; - animation: fadeIn 0.3s ease; - } -} - -@keyframes fadeIn { - from { - opacity: 0; - transform: translateY(-10px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -// Для мобильных устройств -@media (max-width: 768px) { - .user-profile-dropdown { - .user-profile-toggle { - .user-info { - display: none; - } - - .dropdown-arrow { - display: none; - } - } - - .user-profile-menu { - width: 250px; - right: -50px; - } - } -} -// Добавьте в конец файла -.unavailable-product { - position: relative; - opacity: 0.6; - filter: grayscale(0.7); - - &::before { - content: "ТОВАР ЗАКОНЧИЛСЯ"; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background: rgba(0, 0, 0, 0.85); - color: white; - padding: 15px 25px; - border-radius: 5px; - font-weight: bold; - font-size: 16px; - text-align: center; - z-index: 100; - white-space: nowrap; - pointer-events: none; - box-shadow: 0 4px 12px rgba(0,0,0,0.3); - } - - .product-name-overlay { - .name, .price { - color: #999 !important; - text-shadow: none !important; - } - } - - .add-to-cart-btn { - display: none !important; - } - - &:hover { - transform: none !important; - cursor: not-allowed; - } -} - -.out-of-stock-badge { - position: absolute; - top: 10px; - left: 10px; - background: #6c757d; - color: white; - padding: 5px 10px; - border-radius: 4px; - font-size: 12px; - font-weight: bold; - z-index: 10; -} - -// Для админ-таблицы -.admin-table tr.unavailable { - background-color: #f8f9fa !important; - opacity: 0.7; - - td { - color: #999; - } -} - -.status-unavailable { - background-color: #6c757d !important; - color: white !important; -} \ No newline at end of file diff --git a/OLD_CODE/public/catalog.php b/OLD_CODE/public/catalog.php deleted file mode 100644 index 5b13ae1..0000000 --- a/OLD_CODE/public/catalog.php +++ /dev/null @@ -1,1306 +0,0 @@ -getConnection(); - -$category_id = $_GET['category'] ?? 0; -$search = $_GET['search'] ?? ''; -$min_price = $_GET['min_price'] ?? 0; -$max_price = $_GET['max_price'] ?? 1000000; -$colors = isset($_GET['colors']) ? (array)$_GET['colors'] : []; -$materials = isset($_GET['materials']) ? (array)$_GET['materials'] : []; -$show_all = isset($_GET['show_all']) && $_GET['show_all'] == '1'; - -$success_message = $_GET['success'] ?? ''; -$error_message = $_GET['error'] ?? ''; - -try { - - $user_id = $_SESSION['user_id'] ?? 0; - $userStmt = $db->prepare("SELECT * FROM users WHERE user_id = ?"); - $userStmt->execute([$user_id]); - $user = $userStmt->fetch(); - - $isAdmin = isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true; - $userEmail = $_SESSION['user_email'] ?? ''; - $fullName = $_SESSION['full_name'] ?? $userEmail; - $loginTime = $_SESSION['login_time'] ?? time(); - - try { - $categoriesStmt = $db->prepare(" - SELECT * FROM categories - WHERE is_active = TRUE - ORDER BY sort_order, name - "); - $categoriesStmt->execute(); - $categories = $categoriesStmt->fetchAll(); - } catch (PDOException $e) { - $categories = []; - error_log("Ошибка получения категорий: " . $e->getMessage()); - } - - $subcategories = []; - if ($category_id > 0) { - $subStmt = $db->prepare(" - SELECT * FROM subcategories - WHERE category_id = ? AND is_active = TRUE - ORDER BY sort_order, name - "); - $subStmt->execute([$category_id]); - $subcategories = $subStmt->fetchAll(); - } - - $checkColumns = $db->query(" - SELECT column_name - FROM information_schema.columns - WHERE table_name = 'products' - AND column_name IN ('color', 'material') - "); - $existingColumns = $checkColumns->fetchAll(PDO::FETCH_COLUMN); - - $hasColorColumn = in_array('color', $existingColumns); - $hasMaterialColumn = in_array('material', $existingColumns); - - $availableColors = []; - if ($hasColorColumn) { - $colorsStmt = $db->query(" - SELECT DISTINCT color FROM products - WHERE color IS NOT NULL AND color != '' AND is_available = TRUE - ORDER BY color - "); - $availableColors = $colorsStmt->fetchAll(PDO::FETCH_COLUMN); - } - - $availableMaterials = []; - if ($hasMaterialColumn) { - $materialsStmt = $db->query(" - SELECT DISTINCT material FROM products - WHERE material IS NOT NULL AND material != '' AND is_available = TRUE - ORDER BY material - "); - $availableMaterials = $materialsStmt->fetchAll(PDO::FETCH_COLUMN); - } - - $sql = "SELECT p.*, c.name as category_name - FROM products p - LEFT JOIN categories c ON p.category_id = c.category_id - WHERE 1=1"; - - $params = []; - - if (!$show_all && !$isAdmin) { - $sql .= " AND p.is_available = TRUE"; - } - - if ($category_id > 0) { - $sql .= " AND p.category_id = ?"; - $params[] = $category_id; - } - - if ($min_price > 0 || $max_price < 1000000) { - $sql .= " AND p.price BETWEEN ? AND ?"; - $params[] = $min_price; - $params[] = $max_price; - } - - if ($hasColorColumn && !empty($colors)) { - $placeholders = implode(',', array_fill(0, count($colors), '?')); - $sql .= " AND p.color IN ($placeholders)"; - $params = array_merge($params, $colors); - } - - if ($hasMaterialColumn && !empty($materials)) { - $placeholders = implode(',', array_fill(0, count($materials), '?')); - $sql .= " AND p.material IN ($placeholders)"; - $params = array_merge($params, $materials); - } - - if (!empty($search)) { - $sql .= " AND (p.name LIKE ? OR p.description LIKE ?)"; - $params[] = "%$search%"; - $params[] = "%$search%"; - } - - $sql .= " ORDER BY p.product_id ASC LIMIT 50"; - - $stmt = $db->prepare($sql); - $stmt->execute($params); - $filteredProducts = $stmt->fetchAll(); - - $originalSizes = [ - 1 => 'small', - 2 => 'large', - 3 => 'tall align-right', - 4 => 'wide', - 5 => 'small1', - 6 => 'wide2', - 7 => 'wide3', - 8 => 'wide2_1', - 9 => 'full-width' - ]; - - $imgClasses = ['small1', 'wide2', 'wide3', 'wide2_1']; - -} catch (PDOException $e) { - die("Ошибка базы данных: " . $e->getMessage()); -} -?> - - - - - - AETERNA - Каталог - - - - - - - -
- -
-
-
- - -
-
- Все категории - -
- -
- -
- - - 0 - - - -
-
-
- - -
- -
-
- - - -
- 'Категория успешно добавлена!', - 'category_updated' => 'Категория успешно обновлена!', - 'category_deleted' => 'Категория успешно удалена!', - 'product_added' => 'Товар успешно добавлен!', - 'product_updated' => 'Товар успешно обновлен!', - 'product_deleted' => 'Товар успешно удален!' - ]; - echo $messages[$success_message] ?? 'Операция выполнена успешно!'; - ?> -
- - - -
- Ошибка: -
- - - - - - -
-

- Настройки отображения -

- - - Скрыть недоступные товары - - - - Показать все товары - - - - Недоступные товары отмечены серым цветом - -
- - -
- Добро пожаловать, ! - - - Администратор - - - - - Показаны все товары - - -
- -
- - -
-
-

- Каталог мебели - - ( товаров) - -

- - -

- Результаты поиска по запросу: "" - - Очистить поиск - -

- - - -
- - - Показаны все товары, включая недоступные. Недоступные товары отмечены серым цветом. - -
- -
- -
- ['name' => 'Светильник MINNIGHT', 'price' => 7999, 'image' => 'img2/1_2.png', 'size' => 'small'], - 2 => ['name' => 'Кровать MODER', 'price' => 45999, 'image' => 'img2/3_3.png', 'size' => 'large'], - 3 => ['name' => 'Торшер MARCIA', 'price' => 11999, 'image' => 'img2/2_2.png', 'size' => 'tall align-right'], - 4 => ['name' => 'Светильник POLET', 'price' => 5499, 'image' => 'img2/4.jpg', 'size' => 'wide'], - 5 => ['name' => 'Стол NORD', 'price' => 23999, 'image' => 'img2/5_5.png', 'size' => 'small1'], - 6 => ['name' => 'Диван ROYALTY', 'price' => 78999, 'image' => 'img2/6_6.png', 'size' => 'wide2'], - 7 => ['name' => 'Кресло MINIMAL', 'price' => 29999, 'image' => 'img2/7_7.png', 'size' => 'wide3'], - 8 => ['name' => 'Стол LONKI', 'price' => 34999, 'image' => 'img2/8_8.png', 'size' => 'wide2_1'], - 9 => ['name' => 'Диван HEMMINS', 'price' => 89999, 'image' => 'img2/9_9.png', 'size' => 'full-width'] - ]; - - if (empty($filteredProducts)) { - foreach ($originalProducts as $id => $product): ?> -
-
- <?= $product['name'] ?> - -
-
-
-
- - -
-
- -
-
- <?= htmlspecialchars($product['name']) ?> - -
-
-
-
- - -
-
- -
-
-
-
-
- - - - - - \ No newline at end of file diff --git a/OLD_CODE/public/check_auth.js b/OLD_CODE/public/check_auth.js deleted file mode 100644 index a4e0551..0000000 --- a/OLD_CODE/public/check_auth.js +++ /dev/null @@ -1,107 +0,0 @@ - -$(document).ready(function() { - - checkAuthStatus(); - - $('#loginForm').on('submit', function(e) { - e.preventDefault(); - - const email = $('#login-email').val(); - const password = $('#login-password').val(); - const remember = $('#remember').is(':checked'); - - $.ajax({ - url: 'login_handler.php', - method: 'POST', - data: { - email: email, - password: password - }, - success: function(response) { - try { - const result = JSON.parse(response); - if (result.success) { - - if (remember) { - localStorage.setItem('rememberedEmail', email); - } else { - localStorage.removeItem('rememberedEmail'); - } - - window.location.href = result.redirect || 'catalog.php'; - } else { - showMessage('error', result.message || 'Ошибка авторизации'); - } - } catch(e) { - showMessage('error', 'Ошибка обработки ответа'); - } - }, - error: function() { - showMessage('error', 'Ошибка сервера'); - } - }); - }); - - function checkAuthStatus() { - $.ajax({ - url: 'check_auth_status.php', - method: 'GET', - success: function(response) { - try { - const result = JSON.parse(response); - if (result.loggedIn) { - updateUserProfile(result.user); - } - } catch(e) { - console.error('Ошибка проверки авторизации', e); - } - } - }); - } - - function updateUserProfile(user) { - - if ($('#userEmail').length) { - $('#userEmail').text(user.email); - } - if ($('#userName').length) { - $('#userName').text(user.full_name); - } - } - - function showMessage(type, text) { - const $message = $('#' + type + 'Message'); - if ($message.length) { - $message.text(text).fadeIn(); - setTimeout(() => $message.fadeOut(), 5000); - } else { - alert(text); - } - } - - function checkAuth(redirectUrl) { - $.ajax({ - url: 'check_auth_status.php', - method: 'GET', - success: function(response) { - try { - const result = JSON.parse(response); - if (result.loggedIn) { - window.location.href = redirectUrl; - } else { - - showLoginModal(redirectUrl); - } - } catch(e) { - showLoginModal(redirectUrl); - } - } - }); - return false; - } - - function showLoginModal(redirectUrl) { - - window.location.href = 'вход.php?redirect=' + encodeURIComponent(redirectUrl); - } -}); diff --git a/OLD_CODE/public/checkout.php b/OLD_CODE/public/checkout.php deleted file mode 100644 index 25f26c9..0000000 --- a/OLD_CODE/public/checkout.php +++ /dev/null @@ -1,496 +0,0 @@ -getConnection(); - -$cart_items = []; -$total_amount = 0; -$total_quantity = 0; - -try { - $stmt = $db->prepare(" - SELECT - c.cart_id, - c.product_id, - c.quantity, - p.name, - p.price, - p.image_url, - p.stock_quantity - FROM cart c - JOIN products p ON c.product_id = p.product_id - WHERE c.user_id = ? AND p.is_available = TRUE - ORDER BY c.created_at DESC - "); - $stmt->execute([$user_id]); - $cart_items = $stmt->fetchAll(); - - foreach ($cart_items as $item) { - $total_amount += $item['price'] * $item['quantity']; - $total_quantity += $item['quantity']; - } - -} catch (PDOException $e) { - $error = "Ошибка загрузки корзины: " . $e->getMessage(); -} -?> - - - - - - AETERNA - Оформление заказа - - - - - - - - - -
-
-
- -

Товары в корзине

- - -
- -

Ваша корзина пуста

- -
- -
- -
-
- <?= htmlspecialchars($item['name']) ?> -
-
-
-
-
-
- - - -
- -
-
-
- -
- -
- - -
-
-
-

Оформление заказа

-
Товары,
-
- -
-

СПОСОБ ДОСТАВКИ

-
- - -
- -
- - -
-
-
- -
-
- -
-
-
- -
-

СПОСОБ ОПЛАТЫ

-
- - -
- -
-
- -
-
- -
-
-
- -
-
- -
- -
- - -
- -
-
- Товары, шт. - -
-
- Скидка - 0 ₽ - -
-
- Доставка - 2000 ₽ - -
-
- ИТОГО: - -
-
- - - - - - -
-

УСЛУГИ

-
- Доставка - 2000 ₽ -
-
- Сборка - 1000 ₽ -
-
-
-
- -
-
- -
- - -
- - - - - - - - \ No newline at end of file diff --git a/OLD_CODE/public/config/check_auth.js b/OLD_CODE/public/config/check_auth.js deleted file mode 100644 index a4e0551..0000000 --- a/OLD_CODE/public/config/check_auth.js +++ /dev/null @@ -1,107 +0,0 @@ - -$(document).ready(function() { - - checkAuthStatus(); - - $('#loginForm').on('submit', function(e) { - e.preventDefault(); - - const email = $('#login-email').val(); - const password = $('#login-password').val(); - const remember = $('#remember').is(':checked'); - - $.ajax({ - url: 'login_handler.php', - method: 'POST', - data: { - email: email, - password: password - }, - success: function(response) { - try { - const result = JSON.parse(response); - if (result.success) { - - if (remember) { - localStorage.setItem('rememberedEmail', email); - } else { - localStorage.removeItem('rememberedEmail'); - } - - window.location.href = result.redirect || 'catalog.php'; - } else { - showMessage('error', result.message || 'Ошибка авторизации'); - } - } catch(e) { - showMessage('error', 'Ошибка обработки ответа'); - } - }, - error: function() { - showMessage('error', 'Ошибка сервера'); - } - }); - }); - - function checkAuthStatus() { - $.ajax({ - url: 'check_auth_status.php', - method: 'GET', - success: function(response) { - try { - const result = JSON.parse(response); - if (result.loggedIn) { - updateUserProfile(result.user); - } - } catch(e) { - console.error('Ошибка проверки авторизации', e); - } - } - }); - } - - function updateUserProfile(user) { - - if ($('#userEmail').length) { - $('#userEmail').text(user.email); - } - if ($('#userName').length) { - $('#userName').text(user.full_name); - } - } - - function showMessage(type, text) { - const $message = $('#' + type + 'Message'); - if ($message.length) { - $message.text(text).fadeIn(); - setTimeout(() => $message.fadeOut(), 5000); - } else { - alert(text); - } - } - - function checkAuth(redirectUrl) { - $.ajax({ - url: 'check_auth_status.php', - method: 'GET', - success: function(response) { - try { - const result = JSON.parse(response); - if (result.loggedIn) { - window.location.href = redirectUrl; - } else { - - showLoginModal(redirectUrl); - } - } catch(e) { - showLoginModal(redirectUrl); - } - } - }); - return false; - } - - function showLoginModal(redirectUrl) { - - window.location.href = 'вход.php?redirect=' + encodeURIComponent(redirectUrl); - } -}); diff --git a/OLD_CODE/public/config/database.php b/OLD_CODE/public/config/database.php deleted file mode 100644 index 7e3062f..0000000 --- a/OLD_CODE/public/config/database.php +++ /dev/null @@ -1,32 +0,0 @@ -connection = new PDO( - "pgsql:host=185.130.224.177;port=5481;dbname=postgres", - "admin", - "38feaad2840ccfda0e71243a6faaecfd" - ); - $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $this->connection->exec("SET NAMES 'utf8'"); - } catch(PDOException $e) { - die("Ошибка подключения: " . $e->getMessage()); - } - } - - public static function getInstance() { - if (self::$instance == null) { - self::$instance = new Database(); - } - return self::$instance; - } - - public function getConnection() { - return $this->connection; - } -} -?> \ No newline at end of file diff --git a/OLD_CODE/public/delivery.php b/OLD_CODE/public/delivery.php deleted file mode 100644 index 13ca5b9..0000000 --- a/OLD_CODE/public/delivery.php +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - AETERNA - Доставка и оплата - - - - - - - - - - - -
-
- - -
-

ДОСТАВКА И ОПЛАТА

- -
-
-
- -
-

Курьерская доставка

-
-
- Бесплатная доставка: - при заказе от 30 000 ₽ -
-
- В пределах МКАД: - 1 500 ₽ -
-
- За МКАД: - 1 500 ₽ + 50 ₽/км -
-
- Время доставки: - с 9:00 до 21:00 -
-
-
- -
-
- -
-

Самовывоз из шоурума

-
-
- Адрес: - г. Москва, ул. Дизайнерская, 15 -
-
- Стоимость: - Бесплатно -
-
- Время получения: - в течение 2 часов после подтверждения -
-
- Парковка: - Бесплатная для клиентов -
-
-
- -
-
- -
-

Доставка по России

-
-
- Стоимость: - рассчитывается индивидуально -
-
- Сроки: - от 3 до 14 дней -
-
- Транспортные компании: - СДЭК, Boxberry, Деловые Линии -
-
-
-
- -
-
-
- - - - \ No newline at end of file diff --git a/OLD_CODE/public/footer.php b/OLD_CODE/public/footer.php deleted file mode 100644 index 98e1481..0000000 --- a/OLD_CODE/public/footer.php +++ /dev/null @@ -1,49 +0,0 @@ - - - diff --git a/OLD_CODE/public/header_common.php b/OLD_CODE/public/header_common.php deleted file mode 100644 index 8654ef6..0000000 --- a/OLD_CODE/public/header_common.php +++ /dev/null @@ -1,159 +0,0 @@ - -
-
-
- - -
-
- Все категории - -
- -
- -
- - - - - 0 - - - - - - Войти - -
-
-
- - -
- - - - diff --git a/OLD_CODE/public/img/1 — копия.jpg b/OLD_CODE/public/img/1 — копия.jpg deleted file mode 100644 index 68992d6..0000000 Binary files a/OLD_CODE/public/img/1 — копия.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/1.jpg b/OLD_CODE/public/img/1.jpg deleted file mode 100644 index 1df7668..0000000 Binary files a/OLD_CODE/public/img/1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/100.jpg b/OLD_CODE/public/img/100.jpg deleted file mode 100644 index 646480d..0000000 Binary files a/OLD_CODE/public/img/100.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/11.jpg b/OLD_CODE/public/img/11.jpg deleted file mode 100644 index 3a8270e..0000000 Binary files a/OLD_CODE/public/img/11.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/111.jpg b/OLD_CODE/public/img/111.jpg deleted file mode 100644 index 33dc453..0000000 Binary files a/OLD_CODE/public/img/111.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/11_1.png b/OLD_CODE/public/img/11_1.png deleted file mode 100644 index 4735774..0000000 Binary files a/OLD_CODE/public/img/11_1.png and /dev/null differ diff --git a/OLD_CODE/public/img/1_1.jpg b/OLD_CODE/public/img/1_1.jpg deleted file mode 100644 index 3f9e1a1..0000000 Binary files a/OLD_CODE/public/img/1_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/1_2.jpg b/OLD_CODE/public/img/1_2.jpg deleted file mode 100644 index 2d7a54a..0000000 Binary files a/OLD_CODE/public/img/1_2.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/1_2.png b/OLD_CODE/public/img/1_2.png deleted file mode 100644 index 9a8a6c0..0000000 Binary files a/OLD_CODE/public/img/1_2.png and /dev/null differ diff --git a/OLD_CODE/public/img/2.jpg b/OLD_CODE/public/img/2.jpg deleted file mode 100644 index 417df4a..0000000 Binary files a/OLD_CODE/public/img/2.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/22.jpg b/OLD_CODE/public/img/22.jpg deleted file mode 100644 index f59b320..0000000 Binary files a/OLD_CODE/public/img/22.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/25.jpg b/OLD_CODE/public/img/25.jpg deleted file mode 100644 index 03eddcf..0000000 Binary files a/OLD_CODE/public/img/25.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/2_2.jpg b/OLD_CODE/public/img/2_2.jpg deleted file mode 100644 index 76ba9ba..0000000 Binary files a/OLD_CODE/public/img/2_2.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/2_2.png b/OLD_CODE/public/img/2_2.png deleted file mode 100644 index 8fa6e8c..0000000 Binary files a/OLD_CODE/public/img/2_2.png and /dev/null differ diff --git a/OLD_CODE/public/img/3.jpg b/OLD_CODE/public/img/3.jpg deleted file mode 100644 index 973449d..0000000 Binary files a/OLD_CODE/public/img/3.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/3_3.jpg b/OLD_CODE/public/img/3_3.jpg deleted file mode 100644 index 7e56605..0000000 Binary files a/OLD_CODE/public/img/3_3.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/3_3.png b/OLD_CODE/public/img/3_3.png deleted file mode 100644 index ba16e91..0000000 Binary files a/OLD_CODE/public/img/3_3.png and /dev/null differ diff --git a/OLD_CODE/public/img/4.jpg b/OLD_CODE/public/img/4.jpg deleted file mode 100644 index da2945c..0000000 Binary files a/OLD_CODE/public/img/4.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/44.jpg b/OLD_CODE/public/img/44.jpg deleted file mode 100644 index e38c994..0000000 Binary files a/OLD_CODE/public/img/44.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/444 b/OLD_CODE/public/img/444 deleted file mode 100644 index dc6e3fa..0000000 Binary files a/OLD_CODE/public/img/444 and /dev/null differ diff --git a/OLD_CODE/public/img/444 (1).png b/OLD_CODE/public/img/444 (1).png deleted file mode 100644 index ddf7e92..0000000 Binary files a/OLD_CODE/public/img/444 (1).png and /dev/null differ diff --git a/OLD_CODE/public/img/444.jpg b/OLD_CODE/public/img/444.jpg deleted file mode 100644 index dc6e3fa..0000000 Binary files a/OLD_CODE/public/img/444.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/444.png b/OLD_CODE/public/img/444.png deleted file mode 100644 index cd53804..0000000 Binary files a/OLD_CODE/public/img/444.png and /dev/null differ diff --git a/OLD_CODE/public/img/4_1.jpg b/OLD_CODE/public/img/4_1.jpg deleted file mode 100644 index 69f2236..0000000 Binary files a/OLD_CODE/public/img/4_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/5.jpg b/OLD_CODE/public/img/5.jpg deleted file mode 100644 index 456cec1..0000000 Binary files a/OLD_CODE/public/img/5.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/5_5.jpg b/OLD_CODE/public/img/5_5.jpg deleted file mode 100644 index 9ced54f..0000000 Binary files a/OLD_CODE/public/img/5_5.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/5_5.png b/OLD_CODE/public/img/5_5.png deleted file mode 100644 index 369b63b..0000000 Binary files a/OLD_CODE/public/img/5_5.png and /dev/null differ diff --git a/OLD_CODE/public/img/6.jpg b/OLD_CODE/public/img/6.jpg deleted file mode 100644 index 550e17d..0000000 Binary files a/OLD_CODE/public/img/6.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/6_6.jpg b/OLD_CODE/public/img/6_6.jpg deleted file mode 100644 index 0aa5c4b..0000000 Binary files a/OLD_CODE/public/img/6_6.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/6_6.png b/OLD_CODE/public/img/6_6.png deleted file mode 100644 index af949f9..0000000 Binary files a/OLD_CODE/public/img/6_6.png and /dev/null differ diff --git a/OLD_CODE/public/img/7.jpg b/OLD_CODE/public/img/7.jpg deleted file mode 100644 index 17150c7..0000000 Binary files a/OLD_CODE/public/img/7.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/77.jpg b/OLD_CODE/public/img/77.jpg deleted file mode 100644 index d9bf304..0000000 Binary files a/OLD_CODE/public/img/77.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/777 (1).png b/OLD_CODE/public/img/777 (1).png deleted file mode 100644 index 6b01d3f..0000000 Binary files a/OLD_CODE/public/img/777 (1).png and /dev/null differ diff --git a/OLD_CODE/public/img/777.jpg b/OLD_CODE/public/img/777.jpg deleted file mode 100644 index 908d164..0000000 Binary files a/OLD_CODE/public/img/777.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/777.png b/OLD_CODE/public/img/777.png deleted file mode 100644 index 41d57c8..0000000 Binary files a/OLD_CODE/public/img/777.png and /dev/null differ diff --git a/OLD_CODE/public/img/7_7.jpg b/OLD_CODE/public/img/7_7.jpg deleted file mode 100644 index 5ee1524..0000000 Binary files a/OLD_CODE/public/img/7_7.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/7_7.png b/OLD_CODE/public/img/7_7.png deleted file mode 100644 index d50782e..0000000 Binary files a/OLD_CODE/public/img/7_7.png and /dev/null differ diff --git a/OLD_CODE/public/img/8.jpg b/OLD_CODE/public/img/8.jpg deleted file mode 100644 index 8b41c63..0000000 Binary files a/OLD_CODE/public/img/8.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/88.jpg b/OLD_CODE/public/img/88.jpg deleted file mode 100644 index 713eeec..0000000 Binary files a/OLD_CODE/public/img/88.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/888 (1).png b/OLD_CODE/public/img/888 (1).png deleted file mode 100644 index 127e80d..0000000 Binary files a/OLD_CODE/public/img/888 (1).png and /dev/null differ diff --git a/OLD_CODE/public/img/888.jpg b/OLD_CODE/public/img/888.jpg deleted file mode 100644 index e8f33f7..0000000 Binary files a/OLD_CODE/public/img/888.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/888.png b/OLD_CODE/public/img/888.png deleted file mode 100644 index 35e3403..0000000 Binary files a/OLD_CODE/public/img/888.png and /dev/null differ diff --git a/OLD_CODE/public/img/8_8.png b/OLD_CODE/public/img/8_8.png deleted file mode 100644 index 9f86b2c..0000000 Binary files a/OLD_CODE/public/img/8_8.png and /dev/null differ diff --git a/OLD_CODE/public/img/9.jpg b/OLD_CODE/public/img/9.jpg deleted file mode 100644 index 0b772e3..0000000 Binary files a/OLD_CODE/public/img/9.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/99.jpg b/OLD_CODE/public/img/99.jpg deleted file mode 100644 index ed309ba..0000000 Binary files a/OLD_CODE/public/img/99.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/99.png b/OLD_CODE/public/img/99.png deleted file mode 100644 index 8fd29b2..0000000 Binary files a/OLD_CODE/public/img/99.png and /dev/null differ diff --git a/OLD_CODE/public/img/99_1.jpg b/OLD_CODE/public/img/99_1.jpg deleted file mode 100644 index 0247358..0000000 Binary files a/OLD_CODE/public/img/99_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/99_2.jpg b/OLD_CODE/public/img/99_2.jpg deleted file mode 100644 index 468fd51..0000000 Binary files a/OLD_CODE/public/img/99_2.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/99_3.png b/OLD_CODE/public/img/99_3.png deleted file mode 100644 index ae2cd8e..0000000 Binary files a/OLD_CODE/public/img/99_3.png and /dev/null differ diff --git a/OLD_CODE/public/img/9_9.jpg b/OLD_CODE/public/img/9_9.jpg deleted file mode 100644 index a77f2ae..0000000 Binary files a/OLD_CODE/public/img/9_9.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/9_9.png b/OLD_CODE/public/img/9_9.png deleted file mode 100644 index 733a453..0000000 Binary files a/OLD_CODE/public/img/9_9.png and /dev/null differ diff --git a/OLD_CODE/public/img/black.png b/OLD_CODE/public/img/black.png deleted file mode 100644 index a10af51..0000000 Binary files a/OLD_CODE/public/img/black.png and /dev/null differ diff --git a/OLD_CODE/public/img/black1.png b/OLD_CODE/public/img/black1.png deleted file mode 100644 index f529bd3..0000000 Binary files a/OLD_CODE/public/img/black1.png and /dev/null differ diff --git a/OLD_CODE/public/img/black2.png b/OLD_CODE/public/img/black2.png deleted file mode 100644 index 75758a2..0000000 Binary files a/OLD_CODE/public/img/black2.png and /dev/null differ diff --git a/OLD_CODE/public/img/brown.png b/OLD_CODE/public/img/brown.png deleted file mode 100644 index 9ef4db4..0000000 Binary files a/OLD_CODE/public/img/brown.png and /dev/null differ diff --git a/OLD_CODE/public/img/brown1.png b/OLD_CODE/public/img/brown1.png deleted file mode 100644 index 0b178f1..0000000 Binary files a/OLD_CODE/public/img/brown1.png and /dev/null differ diff --git a/OLD_CODE/public/img/brown2.png b/OLD_CODE/public/img/brown2.png deleted file mode 100644 index 346b22f..0000000 Binary files a/OLD_CODE/public/img/brown2.png and /dev/null differ diff --git a/OLD_CODE/public/img/chair.PNG b/OLD_CODE/public/img/chair.PNG deleted file mode 100644 index 12af9db..0000000 Binary files a/OLD_CODE/public/img/chair.PNG and /dev/null differ diff --git a/OLD_CODE/public/img/gray.png b/OLD_CODE/public/img/gray.png deleted file mode 100644 index 55ab5bb..0000000 Binary files a/OLD_CODE/public/img/gray.png and /dev/null differ diff --git a/OLD_CODE/public/img/gray1.png b/OLD_CODE/public/img/gray1.png deleted file mode 100644 index 3137e25..0000000 Binary files a/OLD_CODE/public/img/gray1.png and /dev/null differ diff --git a/OLD_CODE/public/img/gray2.png b/OLD_CODE/public/img/gray2.png deleted file mode 100644 index 95b8781..0000000 Binary files a/OLD_CODE/public/img/gray2.png and /dev/null differ diff --git a/OLD_CODE/public/img/диван.jpg b/OLD_CODE/public/img/диван.jpg deleted file mode 100644 index 578d1a3..0000000 Binary files a/OLD_CODE/public/img/диван.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/диван_1.jpg b/OLD_CODE/public/img/диван_1.jpg deleted file mode 100644 index 3618723..0000000 Binary files a/OLD_CODE/public/img/диван_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/кресло.jpg b/OLD_CODE/public/img/кресло.jpg deleted file mode 100644 index 6d1c12b..0000000 Binary files a/OLD_CODE/public/img/кресло.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/кресло_1.jpg b/OLD_CODE/public/img/кресло_1.jpg deleted file mode 100644 index e59b3b1..0000000 Binary files a/OLD_CODE/public/img/кресло_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/слайдер_1.jpg b/OLD_CODE/public/img/слайдер_1.jpg deleted file mode 100644 index 255440e..0000000 Binary files a/OLD_CODE/public/img/слайдер_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/слайдер_2.jpg b/OLD_CODE/public/img/слайдер_2.jpg deleted file mode 100644 index 9cb6403..0000000 Binary files a/OLD_CODE/public/img/слайдер_2.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/слайдер_3.jpg b/OLD_CODE/public/img/слайдер_3.jpg deleted file mode 100644 index dc65d0b..0000000 Binary files a/OLD_CODE/public/img/слайдер_3.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/слайдер_4.jpg b/OLD_CODE/public/img/слайдер_4.jpg deleted file mode 100644 index f6d8d38..0000000 Binary files a/OLD_CODE/public/img/слайдер_4.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/слайдер_5.jpg b/OLD_CODE/public/img/слайдер_5.jpg deleted file mode 100644 index a9cfbb6..0000000 Binary files a/OLD_CODE/public/img/слайдер_5.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/слайдер_6.jpg b/OLD_CODE/public/img/слайдер_6.jpg deleted file mode 100644 index 0dc28a0..0000000 Binary files a/OLD_CODE/public/img/слайдер_6.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/спальня.jpg b/OLD_CODE/public/img/спальня.jpg deleted file mode 100644 index f403324..0000000 Binary files a/OLD_CODE/public/img/спальня.jpg and /dev/null differ diff --git a/OLD_CODE/public/img/стили_оформления.css b/OLD_CODE/public/img/стили_оформления.css deleted file mode 100644 index 2e1d09c..0000000 --- a/OLD_CODE/public/img/стили_оформления.css +++ /dev/null @@ -1,61 +0,0 @@ - -.error-message { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; -} - -.form__input.error { - border-color: #ff0000; -} - -.form__group { - position: relative; - margin-bottom: 15px; -} - -.page-messages { - position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - z-index: 1000; - width: 90%; - max-width: 500px; -} - -.message { - padding: 15px; - margin: 10px 0; - border-radius: 5px; - text-align: center; - font-weight: bold; - display: none; -} - -.message.error { - background-color: #ffebee; - color: #c62828; - border: 1px solid #ffcdd2; -} - -.message.success { - background-color: #e8f5e9; - color: #453227; - border: 1px solid #c8e6c9; -} - -.message.warning { - background-color: #fff3e0; - color: #ef6c00; - border: 1px solid #ffe0b2; -} - -.privacy-error { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; - text-align: center; -} diff --git a/OLD_CODE/public/img2/1 — копия.jpg b/OLD_CODE/public/img2/1 — копия.jpg deleted file mode 100644 index 68992d6..0000000 Binary files a/OLD_CODE/public/img2/1 — копия.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/1.jpg b/OLD_CODE/public/img2/1.jpg deleted file mode 100644 index 1df7668..0000000 Binary files a/OLD_CODE/public/img2/1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/100.jpg b/OLD_CODE/public/img2/100.jpg deleted file mode 100644 index 646480d..0000000 Binary files a/OLD_CODE/public/img2/100.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/11.jpg b/OLD_CODE/public/img2/11.jpg deleted file mode 100644 index 3a8270e..0000000 Binary files a/OLD_CODE/public/img2/11.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/111.jpg b/OLD_CODE/public/img2/111.jpg deleted file mode 100644 index 33dc453..0000000 Binary files a/OLD_CODE/public/img2/111.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/11_1.png b/OLD_CODE/public/img2/11_1.png deleted file mode 100644 index 4735774..0000000 Binary files a/OLD_CODE/public/img2/11_1.png and /dev/null differ diff --git a/OLD_CODE/public/img2/1_1.jpg b/OLD_CODE/public/img2/1_1.jpg deleted file mode 100644 index 3f9e1a1..0000000 Binary files a/OLD_CODE/public/img2/1_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/1_2.jpg b/OLD_CODE/public/img2/1_2.jpg deleted file mode 100644 index 2d7a54a..0000000 Binary files a/OLD_CODE/public/img2/1_2.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/1_2.png b/OLD_CODE/public/img2/1_2.png deleted file mode 100644 index 9a8a6c0..0000000 Binary files a/OLD_CODE/public/img2/1_2.png and /dev/null differ diff --git a/OLD_CODE/public/img2/2.jpg b/OLD_CODE/public/img2/2.jpg deleted file mode 100644 index 417df4a..0000000 Binary files a/OLD_CODE/public/img2/2.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/22.jpg b/OLD_CODE/public/img2/22.jpg deleted file mode 100644 index f59b320..0000000 Binary files a/OLD_CODE/public/img2/22.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/25.jpg b/OLD_CODE/public/img2/25.jpg deleted file mode 100644 index 03eddcf..0000000 Binary files a/OLD_CODE/public/img2/25.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/2_2.jpg b/OLD_CODE/public/img2/2_2.jpg deleted file mode 100644 index 76ba9ba..0000000 Binary files a/OLD_CODE/public/img2/2_2.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/2_2.png b/OLD_CODE/public/img2/2_2.png deleted file mode 100644 index 8fa6e8c..0000000 Binary files a/OLD_CODE/public/img2/2_2.png and /dev/null differ diff --git a/OLD_CODE/public/img2/3.jpg b/OLD_CODE/public/img2/3.jpg deleted file mode 100644 index 973449d..0000000 Binary files a/OLD_CODE/public/img2/3.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/3_3.jpg b/OLD_CODE/public/img2/3_3.jpg deleted file mode 100644 index 7e56605..0000000 Binary files a/OLD_CODE/public/img2/3_3.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/3_3.png b/OLD_CODE/public/img2/3_3.png deleted file mode 100644 index ba16e91..0000000 Binary files a/OLD_CODE/public/img2/3_3.png and /dev/null differ diff --git a/OLD_CODE/public/img2/4.jpg b/OLD_CODE/public/img2/4.jpg deleted file mode 100644 index da2945c..0000000 Binary files a/OLD_CODE/public/img2/4.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/44.jpg b/OLD_CODE/public/img2/44.jpg deleted file mode 100644 index e38c994..0000000 Binary files a/OLD_CODE/public/img2/44.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/444 b/OLD_CODE/public/img2/444 deleted file mode 100644 index dc6e3fa..0000000 Binary files a/OLD_CODE/public/img2/444 and /dev/null differ diff --git a/OLD_CODE/public/img2/444 (1).png b/OLD_CODE/public/img2/444 (1).png deleted file mode 100644 index ddf7e92..0000000 Binary files a/OLD_CODE/public/img2/444 (1).png and /dev/null differ diff --git a/OLD_CODE/public/img2/444.jpg b/OLD_CODE/public/img2/444.jpg deleted file mode 100644 index dc6e3fa..0000000 Binary files a/OLD_CODE/public/img2/444.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/444.png b/OLD_CODE/public/img2/444.png deleted file mode 100644 index cd53804..0000000 Binary files a/OLD_CODE/public/img2/444.png and /dev/null differ diff --git a/OLD_CODE/public/img2/4_1.jpg b/OLD_CODE/public/img2/4_1.jpg deleted file mode 100644 index 69f2236..0000000 Binary files a/OLD_CODE/public/img2/4_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/5.jpg b/OLD_CODE/public/img2/5.jpg deleted file mode 100644 index 456cec1..0000000 Binary files a/OLD_CODE/public/img2/5.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/5_5.jpg b/OLD_CODE/public/img2/5_5.jpg deleted file mode 100644 index 9ced54f..0000000 Binary files a/OLD_CODE/public/img2/5_5.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/5_5.png b/OLD_CODE/public/img2/5_5.png deleted file mode 100644 index 369b63b..0000000 Binary files a/OLD_CODE/public/img2/5_5.png and /dev/null differ diff --git a/OLD_CODE/public/img2/6.jpg b/OLD_CODE/public/img2/6.jpg deleted file mode 100644 index 550e17d..0000000 Binary files a/OLD_CODE/public/img2/6.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/6_6.jpg b/OLD_CODE/public/img2/6_6.jpg deleted file mode 100644 index 0aa5c4b..0000000 Binary files a/OLD_CODE/public/img2/6_6.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/6_6.png b/OLD_CODE/public/img2/6_6.png deleted file mode 100644 index af949f9..0000000 Binary files a/OLD_CODE/public/img2/6_6.png and /dev/null differ diff --git a/OLD_CODE/public/img2/7.jpg b/OLD_CODE/public/img2/7.jpg deleted file mode 100644 index 17150c7..0000000 Binary files a/OLD_CODE/public/img2/7.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/77.jpg b/OLD_CODE/public/img2/77.jpg deleted file mode 100644 index d9bf304..0000000 Binary files a/OLD_CODE/public/img2/77.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/777 (1).png b/OLD_CODE/public/img2/777 (1).png deleted file mode 100644 index 6b01d3f..0000000 Binary files a/OLD_CODE/public/img2/777 (1).png and /dev/null differ diff --git a/OLD_CODE/public/img2/777.jpg b/OLD_CODE/public/img2/777.jpg deleted file mode 100644 index 908d164..0000000 Binary files a/OLD_CODE/public/img2/777.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/777.png b/OLD_CODE/public/img2/777.png deleted file mode 100644 index 41d57c8..0000000 Binary files a/OLD_CODE/public/img2/777.png and /dev/null differ diff --git a/OLD_CODE/public/img2/7_7.jpg b/OLD_CODE/public/img2/7_7.jpg deleted file mode 100644 index 5ee1524..0000000 Binary files a/OLD_CODE/public/img2/7_7.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/7_7.png b/OLD_CODE/public/img2/7_7.png deleted file mode 100644 index d50782e..0000000 Binary files a/OLD_CODE/public/img2/7_7.png and /dev/null differ diff --git a/OLD_CODE/public/img2/8.jpg b/OLD_CODE/public/img2/8.jpg deleted file mode 100644 index 8b41c63..0000000 Binary files a/OLD_CODE/public/img2/8.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/88.jpg b/OLD_CODE/public/img2/88.jpg deleted file mode 100644 index 713eeec..0000000 Binary files a/OLD_CODE/public/img2/88.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/888 (1).png b/OLD_CODE/public/img2/888 (1).png deleted file mode 100644 index 127e80d..0000000 Binary files a/OLD_CODE/public/img2/888 (1).png and /dev/null differ diff --git a/OLD_CODE/public/img2/888.jpg b/OLD_CODE/public/img2/888.jpg deleted file mode 100644 index e8f33f7..0000000 Binary files a/OLD_CODE/public/img2/888.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/888.png b/OLD_CODE/public/img2/888.png deleted file mode 100644 index 35e3403..0000000 Binary files a/OLD_CODE/public/img2/888.png and /dev/null differ diff --git a/OLD_CODE/public/img2/8_8.png b/OLD_CODE/public/img2/8_8.png deleted file mode 100644 index 9f86b2c..0000000 Binary files a/OLD_CODE/public/img2/8_8.png and /dev/null differ diff --git a/OLD_CODE/public/img2/9.jpg b/OLD_CODE/public/img2/9.jpg deleted file mode 100644 index 0b772e3..0000000 Binary files a/OLD_CODE/public/img2/9.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/99.jpg b/OLD_CODE/public/img2/99.jpg deleted file mode 100644 index ed309ba..0000000 Binary files a/OLD_CODE/public/img2/99.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/99.png b/OLD_CODE/public/img2/99.png deleted file mode 100644 index 8fd29b2..0000000 Binary files a/OLD_CODE/public/img2/99.png and /dev/null differ diff --git a/OLD_CODE/public/img2/99_1.jpg b/OLD_CODE/public/img2/99_1.jpg deleted file mode 100644 index 0247358..0000000 Binary files a/OLD_CODE/public/img2/99_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/99_2.jpg b/OLD_CODE/public/img2/99_2.jpg deleted file mode 100644 index 468fd51..0000000 Binary files a/OLD_CODE/public/img2/99_2.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/99_3.png b/OLD_CODE/public/img2/99_3.png deleted file mode 100644 index ae2cd8e..0000000 Binary files a/OLD_CODE/public/img2/99_3.png and /dev/null differ diff --git a/OLD_CODE/public/img2/9_9.jpg b/OLD_CODE/public/img2/9_9.jpg deleted file mode 100644 index a77f2ae..0000000 Binary files a/OLD_CODE/public/img2/9_9.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/9_9.png b/OLD_CODE/public/img2/9_9.png deleted file mode 100644 index 733a453..0000000 Binary files a/OLD_CODE/public/img2/9_9.png and /dev/null differ diff --git a/OLD_CODE/public/img2/black.png b/OLD_CODE/public/img2/black.png deleted file mode 100644 index a10af51..0000000 Binary files a/OLD_CODE/public/img2/black.png and /dev/null differ diff --git a/OLD_CODE/public/img2/black1.png b/OLD_CODE/public/img2/black1.png deleted file mode 100644 index f529bd3..0000000 Binary files a/OLD_CODE/public/img2/black1.png and /dev/null differ diff --git a/OLD_CODE/public/img2/black2.png b/OLD_CODE/public/img2/black2.png deleted file mode 100644 index 75758a2..0000000 Binary files a/OLD_CODE/public/img2/black2.png and /dev/null differ diff --git a/OLD_CODE/public/img2/brown.png b/OLD_CODE/public/img2/brown.png deleted file mode 100644 index 9ef4db4..0000000 Binary files a/OLD_CODE/public/img2/brown.png and /dev/null differ diff --git a/OLD_CODE/public/img2/brown1.png b/OLD_CODE/public/img2/brown1.png deleted file mode 100644 index 0b178f1..0000000 Binary files a/OLD_CODE/public/img2/brown1.png and /dev/null differ diff --git a/OLD_CODE/public/img2/brown2.png b/OLD_CODE/public/img2/brown2.png deleted file mode 100644 index 346b22f..0000000 Binary files a/OLD_CODE/public/img2/brown2.png and /dev/null differ diff --git a/OLD_CODE/public/img2/chair.PNG b/OLD_CODE/public/img2/chair.PNG deleted file mode 100644 index 12af9db..0000000 Binary files a/OLD_CODE/public/img2/chair.PNG and /dev/null differ diff --git a/OLD_CODE/public/img2/gray.png b/OLD_CODE/public/img2/gray.png deleted file mode 100644 index 55ab5bb..0000000 Binary files a/OLD_CODE/public/img2/gray.png and /dev/null differ diff --git a/OLD_CODE/public/img2/gray1.png b/OLD_CODE/public/img2/gray1.png deleted file mode 100644 index 3137e25..0000000 Binary files a/OLD_CODE/public/img2/gray1.png and /dev/null differ diff --git a/OLD_CODE/public/img2/gray2.png b/OLD_CODE/public/img2/gray2.png deleted file mode 100644 index 95b8781..0000000 Binary files a/OLD_CODE/public/img2/gray2.png and /dev/null differ diff --git a/OLD_CODE/public/img2/диван.jpg b/OLD_CODE/public/img2/диван.jpg deleted file mode 100644 index 578d1a3..0000000 Binary files a/OLD_CODE/public/img2/диван.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/диван_1.jpg b/OLD_CODE/public/img2/диван_1.jpg deleted file mode 100644 index 3618723..0000000 Binary files a/OLD_CODE/public/img2/диван_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/кресло.jpg b/OLD_CODE/public/img2/кресло.jpg deleted file mode 100644 index 6d1c12b..0000000 Binary files a/OLD_CODE/public/img2/кресло.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/кресло_1.jpg b/OLD_CODE/public/img2/кресло_1.jpg deleted file mode 100644 index e59b3b1..0000000 Binary files a/OLD_CODE/public/img2/кресло_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/слайдер_1.jpg b/OLD_CODE/public/img2/слайдер_1.jpg deleted file mode 100644 index 255440e..0000000 Binary files a/OLD_CODE/public/img2/слайдер_1.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/слайдер_2.jpg b/OLD_CODE/public/img2/слайдер_2.jpg deleted file mode 100644 index 9cb6403..0000000 Binary files a/OLD_CODE/public/img2/слайдер_2.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/слайдер_3.jpg b/OLD_CODE/public/img2/слайдер_3.jpg deleted file mode 100644 index dc65d0b..0000000 Binary files a/OLD_CODE/public/img2/слайдер_3.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/слайдер_4.jpg b/OLD_CODE/public/img2/слайдер_4.jpg deleted file mode 100644 index f6d8d38..0000000 Binary files a/OLD_CODE/public/img2/слайдер_4.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/слайдер_5.jpg b/OLD_CODE/public/img2/слайдер_5.jpg deleted file mode 100644 index a9cfbb6..0000000 Binary files a/OLD_CODE/public/img2/слайдер_5.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/слайдер_6.jpg b/OLD_CODE/public/img2/слайдер_6.jpg deleted file mode 100644 index 0dc28a0..0000000 Binary files a/OLD_CODE/public/img2/слайдер_6.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/спальня.jpg b/OLD_CODE/public/img2/спальня.jpg deleted file mode 100644 index f403324..0000000 Binary files a/OLD_CODE/public/img2/спальня.jpg and /dev/null differ diff --git a/OLD_CODE/public/img2/стили_оформления.css b/OLD_CODE/public/img2/стили_оформления.css deleted file mode 100644 index 2e1d09c..0000000 --- a/OLD_CODE/public/img2/стили_оформления.css +++ /dev/null @@ -1,61 +0,0 @@ - -.error-message { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; -} - -.form__input.error { - border-color: #ff0000; -} - -.form__group { - position: relative; - margin-bottom: 15px; -} - -.page-messages { - position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - z-index: 1000; - width: 90%; - max-width: 500px; -} - -.message { - padding: 15px; - margin: 10px 0; - border-radius: 5px; - text-align: center; - font-weight: bold; - display: none; -} - -.message.error { - background-color: #ffebee; - color: #c62828; - border: 1px solid #ffcdd2; -} - -.message.success { - background-color: #e8f5e9; - color: #453227; - border: 1px solid #c8e6c9; -} - -.message.warning { - background-color: #fff3e0; - color: #ef6c00; - border: 1px solid #ffe0b2; -} - -.privacy-error { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; - text-align: center; -} diff --git a/OLD_CODE/public/includes/auth.php b/OLD_CODE/public/includes/auth.php deleted file mode 100644 index 5326642..0000000 --- a/OLD_CODE/public/includes/auth.php +++ /dev/null @@ -1,127 +0,0 @@ -getConnection(); - - try { - $stmt = $db->prepare(" - SELECT user_id, email, password_hash, full_name, phone, city, is_admin, is_active - FROM users WHERE email = ? - "); - $stmt->execute([$email]); - $user = $stmt->fetch(); - - if (!$user) { - return ['success' => false, 'message' => 'Пользователь не найден']; - } - - if (!$user['is_active']) { - return ['success' => false, 'message' => 'Аккаунт заблокирован']; - } - - if (!password_verify($password, $user['password_hash'])) { - return ['success' => false, 'message' => 'Неверный пароль']; - } - - $_SESSION['user_id'] = $user['user_id']; - $_SESSION['user_email'] = $user['email']; - $_SESSION['full_name'] = $user['full_name']; - $_SESSION['user_phone'] = $user['phone'] ?? ''; - $_SESSION['user_city'] = $user['city'] ?? ''; - $_SESSION['isLoggedIn'] = true; - $_SESSION['isAdmin'] = (bool)$user['is_admin']; - $_SESSION['login_time'] = time(); - - $updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?"); - $updateStmt->execute([$user['user_id']]); - - return ['success' => true, 'user' => $user]; - - } catch (PDOException $e) { - return ['success' => false, 'message' => 'Ошибка базы данных']; - } -} - -function registerUser(array $data): array { - $db = Database::getInstance()->getConnection(); - - $email = trim($data['email'] ?? ''); - $password = $data['password'] ?? ''; - $fullName = trim($data['full_name'] ?? ''); - $phone = trim($data['phone'] ?? ''); - $city = trim($data['city'] ?? ''); - - if (empty($email) || empty($password) || empty($fullName)) { - return ['success' => false, 'message' => 'Заполните все обязательные поля']; - } - - if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { - return ['success' => false, 'message' => 'Некорректный email']; - } - - if (strlen($password) < 6) { - return ['success' => false, 'message' => 'Пароль должен содержать минимум 6 символов']; - } - - try { - - $checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?"); - $checkStmt->execute([$email]); - - if ($checkStmt->fetch()) { - return ['success' => false, 'message' => 'Пользователь с таким email уже существует']; - } - - $passwordHash = password_hash($password, PASSWORD_DEFAULT); - - $stmt = $db->prepare(" - INSERT INTO users (email, password_hash, full_name, phone, city, is_active) - VALUES (?, ?, ?, ?, ?, TRUE) - RETURNING user_id - "); - $stmt->execute([$email, $passwordHash, $fullName, $phone, $city]); - $userId = $stmt->fetchColumn(); - - $_SESSION['user_id'] = $userId; - $_SESSION['user_email'] = $email; - $_SESSION['full_name'] = $fullName; - $_SESSION['user_phone'] = $phone; - $_SESSION['user_city'] = $city; - $_SESSION['isLoggedIn'] = true; - $_SESSION['isAdmin'] = false; - $_SESSION['login_time'] = time(); - - return ['success' => true, 'user_id' => $userId]; - - } catch (PDOException $e) { - return ['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]; - } -} - -function logoutUser(): void { - $_SESSION = []; - - if (ini_get("session.use_cookies")) { - $params = session_get_cookie_params(); - setcookie(session_name(), '', time() - 42000, - $params["path"], $params["domain"], - $params["secure"], $params["httponly"] - ); - } - - session_destroy(); -} - -function checkAdminAccess(): bool { - if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) { - return false; - } - - if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) { - return false; - } - - return true; -} diff --git a/OLD_CODE/public/includes/footer.php b/OLD_CODE/public/includes/footer.php deleted file mode 100644 index 98e1481..0000000 --- a/OLD_CODE/public/includes/footer.php +++ /dev/null @@ -1,49 +0,0 @@ - - - diff --git a/OLD_CODE/public/includes/functions.php b/OLD_CODE/public/includes/functions.php deleted file mode 100644 index 58d16bb..0000000 --- a/OLD_CODE/public/includes/functions.php +++ /dev/null @@ -1,97 +0,0 @@ - $_SESSION['user_id'] ?? 0, - 'email' => $_SESSION['user_email'] ?? '', - 'full_name' => $_SESSION['full_name'] ?? '', - 'is_admin' => isAdmin() - ]; -} - -function formatPrice(float $price): string { - return number_format($price, 0, '', ' ') . ' ₽'; -} - -function e(string $str): string { - return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); -} - -function generateOrderNumber(): string { - return 'AET-' . date('Ymd') . '-' . strtoupper(substr(uniqid(), -6)); -} - -function generateSKU(string $productName): string { - $prefix = strtoupper(substr(preg_replace('/[^a-zA-Z0-9]/', '', transliterate($productName)), 0, 6)); - return $prefix . '-' . rand(100, 999); -} - -function transliterate(string $str): string { - $converter = [ - 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', - 'е' => 'e', 'ё' => 'e', 'ж' => 'zh', 'з' => 'z', 'и' => 'i', - 'й' => 'y', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', - 'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', - 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c', 'ч' => 'ch', - 'ш' => 'sh', 'щ' => 'sch', 'ь' => '', 'ы' => 'y', 'ъ' => '', - 'э' => 'e', 'ю' => 'yu', 'я' => 'ya', - 'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', - 'Е' => 'E', 'Ё' => 'E', 'Ж' => 'Zh', 'З' => 'Z', 'И' => 'I', - 'Й' => 'Y', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N', - 'О' => 'O', 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', - 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C', 'Ч' => 'Ch', - 'Ш' => 'Sh', 'Щ' => 'Sch', 'Ь' => '', 'Ы' => 'Y', 'Ъ' => '', - 'Э' => 'E', 'Ю' => 'Yu', 'Я' => 'Ya', - ]; - return strtr($str, $converter); -} - -function createSlug(string $str): string { - $slug = transliterate($str); - $slug = strtolower($slug); - $slug = preg_replace('/[^a-z0-9]+/', '-', $slug); - $slug = trim($slug, '-'); - return $slug; -} - -function setFlashMessage(string $type, string $message): void { - $_SESSION['flash_message'] = [ - 'type' => $type, - 'message' => $message - ]; -} - -function getFlashMessage(): ?array { - if (isset($_SESSION['flash_message'])) { - $message = $_SESSION['flash_message']; - unset($_SESSION['flash_message']); - return $message; - } - return null; -} diff --git a/OLD_CODE/public/includes/header.php b/OLD_CODE/public/includes/header.php deleted file mode 100644 index 702bf53..0000000 --- a/OLD_CODE/public/includes/header.php +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - AETERNA - <?= $pageTitle ?? 'Мебель и Интерьер' ?> - - - - - - - - - - -
-
-
- - -
-
- Все категории - -
- -
- -
- - - - - 0 - - - - - - Войти - -
-
-
- - -
- - diff --git a/OLD_CODE/public/index.php b/OLD_CODE/public/index.php deleted file mode 100644 index 7d3550f..0000000 --- a/OLD_CODE/public/index.php +++ /dev/null @@ -1,759 +0,0 @@ - - - - - - AETERNA - Мебель и Интерьер - - - - - - - - -
-
-
- - -
-
- Все категории - -
- -
- - -
-
- - -
- -
-
-
-
-
- Кресло и торшер -
-
-

ДОБАВЬТЕ ИЗЫСКАННОСТИ В СВОЙ ИНТЕРЬЕР

-

Мы создаем мебель, которая сочетает в себе безупречный дизайн, натуральные материалы, продуманный функционал, чтобы ваш день начинался и заканчивался с комфортом.

- - - ПЕРЕЙТИ В КАТАЛОГ - - ПЕРЕЙТИ В КАТАЛОГ - -
-
-
- -
-
-
-

ПОЧЕМУ
ВЫБИРАЮТ НАС?

-
-
- 1 -

ГАРАНТИЯ ВЫСОЧАЙШЕГО КАЧЕСТВА

-

Собственное производство и строгий контроль на всех этапах.

-
-
- 2 -

ИСПОЛЬЗОВАНИЕ НАДЕЖНЫХ МАТЕРИАЛОВ

-

Гарантия безопасности и долговечности.

-
-
- 3 -

ИНДИВИДУАЛЬНЫЙ ПОДХОД И ГИБКОСТЬ УСЛОВИЙ

-

Реализуем проекты любой сложности по вашим техническим заданиям.

-
-
-
- -
-
- Кровать и тумба -
-

НОВИНКИ В КАТЕГОРИЯХ
МЯГКАЯ МЕБЕЛЬ

- ПЕРЕЙТИ -
-
-
- Диван в гостиной -
-

РАСПРОДАЖА
ПРЕДМЕТЫ ДЕКОРА

- ПЕРЕЙТИ -
-
-
-
-
- -
-
-
-
-

О НАС

-

Компания AETERNA - российский производитель качественной корпусной и мягкой мебели для дома и офиса. С 2015 года мы успешно реализуем проекты любой сложности, сочетая современные технологии, проверенные материалы и классическое мастерство.

-
- Фиолетовое кресло -
- -
- Белый диван с подушками -

Наша сеть включает 30+ российских фабрик, отобранных по строгим стандартам качества. Мы сотрудничаем исключительно с лидерами рынка, чья продукция доказала свое превосходство временем.

-
-
-
- -
-
-
-
-
- Готовое решение для гостиной -
-

ГОТОВОЕ РЕШЕНИЕ
ДЛЯ ВАШЕЙ ГОСТИНОЙ


-

УСПЕЙТЕ ЗАКАЗАТЬ СЕЙЧАС

-
- Подробнее -
- -
- Готовое решение для спальни -
-

ГОТОВОЕ РЕШЕНИЕ
ДЛЯ ВАШЕЙ СПАЛЬНИ


-

УСПЕЙТЕ ЗАКАЗАТЬ СЕЙЧАС

-
- Подробнее -
-
-
-
-
- -
-
-
-
-
10+
-
Лет работы
-
-
-
30 000+
-
Довольных покупателей
-
-
-
4500+
-
Реализованных заказов
-
-
-
-
- -
-
-

ОТВЕТЫ НА ВОПРОСЫ

-
-
- 1 -
-

Сколько времени занимает доставка?

-

Доставка готовых позиций занимает 1-3 дня. Мебель на заказ изготавливается от 14 до 45 рабочих дней, в зависимости от сложности. Точные сроки озвучит ваш менеджер при оформлении заказа.

-
-
-
- 2 -
-

Нужно ли вносить предоплату?

-

Да, для запуска заказа в производство необходима предоплата в размере 50-70% от стоимости, в зависимости от изделия. Оставшаяся сумма оплачивается при доставке и приемке мебели.

-
-
-
- 3 -
-

Предоставляется ли рассрочка или кредит?

-

Да, мы сотрудничаем с несколькими банками и предлагаем рассрочку на 6 или 12 месяцев без первоначального взноса, а также кредит на более длительный срок. Все условия уточняйте у вашего менеджера.

-
-
-
- 4 -
-

Что делать, если мебель пришла с дефектом?

-

В этом случае необходимо в течение 7 дней со дня доставки сообщить нам о проблеме, прислать фото/видео дефекта. Мы оперативно решим вопрос о бесплатной замене или ремонте изделия.

-
-
-
- -
-
-
- - - - - - - - - - - - - -
-

Быстрый вход:

- -
- - - - \ No newline at end of file diff --git a/OLD_CODE/public/login.php b/OLD_CODE/public/login.php deleted file mode 100644 index 0d6eeaf..0000000 --- a/OLD_CODE/public/login.php +++ /dev/null @@ -1,294 +0,0 @@ - - - - - - AETERNA - Вход - - - - - - - - - - - - -
-
-
- - -
-
- Все категории -
-
    -
  • Диваны
  • -
  • Кровати
  • -
  • Шкафы
  • -
  • Стулья
  • -
  • Столы
  • -
  • Комоды
  • -
  • Тумбы
  • -
  • Полки
  • -
  • Стенки
  • -
  • Аксессуары
  • -
-
-
- -
- -
- - -
-
-
- - -
- -
-
-
- -
- -
-
-

ВХОД В АККАУНТ

-
-
- - -
- Введите корректный email адрес -
-
- -
- - -
Неверный пароль
-
- -
- - Забыли пароль? -
- - - -
- Нет аккаунта? - -
-
-
-
-
-
- -
-
-
-
-
- - - - - - - diff --git a/OLD_CODE/public/logout.php b/OLD_CODE/public/logout.php deleted file mode 100644 index 02ef1c7..0000000 --- a/OLD_CODE/public/logout.php +++ /dev/null @@ -1,17 +0,0 @@ -getConnection(); - -try { - - $productStmt = $db->prepare(" - SELECT - p.*, - c.name as category_name, - c.slug as category_slug - FROM products p - LEFT JOIN categories c ON p.category_id = c.category_id - WHERE p.product_id = ? AND p.is_available = TRUE - "); - $productStmt->execute([$product_id]); - $product = $productStmt->fetch(); - - if (!$product) { - header('Location: catalog.php?error=product_not_found'); - exit(); - } - - $similarStmt = $db->prepare(" - SELECT * FROM products - WHERE category_id = ? - AND product_id != ? - AND is_available = TRUE - ORDER BY RANDOM() - LIMIT 3 - "); - $similarStmt->execute([$product['category_id'], $product_id]); - $similarProducts = $similarStmt->fetchAll(); - - $reviewsStmt = $db->prepare(" - SELECT rating, comment, created_at - FROM reviews - WHERE product_id = ? - ORDER BY created_at DESC - LIMIT 5 - "); - $reviewsStmt->execute([$product_id]); - $reviews = $reviewsStmt->fetchAll(); - -} catch (PDOException $e) { - die("Ошибка базы данных: " . $e->getMessage()); -} - -?> - - - - - - AETERNA - <?= htmlspecialchars($product['name']) ?> - - - - - - - -
-
-
- - -
-
- Все категории - -
- -
- -
- - - -
-
-
- - -
- -
- - -
- - -
-

- -
-
- = 0.5; - - for ($i = 1; $i <= 5; $i++) { - if ($i <= $fullStars) { - echo ''; - } elseif ($i == $fullStars + 1 && $hasHalfStar) { - echo ''; - } else { - echo ''; - } - } - ?> -
- - ( отзывов) -
- -
- - ₽ - - $product['price']): ?> - - ₽ - - - -% - - -
- -
- 10) { - echo ' В наличии'; - } elseif ($product['stock_quantity'] > 0) { - echo ' Осталось мало: ' . $product['stock_quantity'] . ' шт.'; - } else { - echo ' Нет в наличии'; - } - ?> -
- -
-
- Артикул: - -
-
- Категория: - -
-
- На складе: - шт. -
-
- -

- -

- - 0): ?> -
-
- - - -
- -
- - -
-
- -
- -
- - - -
- - Редактировать - - -
- -
-
- - -
-

Похожие товары

-
- -
-
- <?= htmlspecialchars($similar['name']) ?> -
-
-

-

- ₽ -

- - Подробнее - -
-
- -
-
- -
- - - - - - \ No newline at end of file diff --git a/OLD_CODE/public/register.php b/OLD_CODE/public/register.php deleted file mode 100644 index 0afc144..0000000 --- a/OLD_CODE/public/register.php +++ /dev/null @@ -1,741 +0,0 @@ -getConnection(); - - try { - - $checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?"); - $checkStmt->execute([$email]); - - if (!$checkStmt->fetch()) { - - $password_hash = password_hash($password, PASSWORD_DEFAULT); - $is_admin = ($_GET['quick_register'] == 'admin'); - - $stmt = $db->prepare(" - INSERT INTO users (email, password_hash, full_name, phone, city, is_admin) - VALUES (?, ?, ?, ?, ?, ?) - RETURNING user_id - "); - - $stmt->execute([$email, $password_hash, $full_name, $phone, $city, $is_admin]); - $user_id = $stmt->fetchColumn(); - } else { - - $stmt = $db->prepare("SELECT user_id, is_admin FROM users WHERE email = ?"); - $stmt->execute([$email]); - $user = $stmt->fetch(); - $user_id = $user['user_id']; - $is_admin = $user['is_admin']; - } - - $_SESSION['user_id'] = $user_id; - $_SESSION['user_email'] = $email; - $_SESSION['full_name'] = $full_name; - $_SESSION['user_phone'] = $phone; - $_SESSION['user_city'] = $city; - $_SESSION['isLoggedIn'] = true; - $_SESSION['isAdmin'] = $is_admin; - $_SESSION['login_time'] = time(); - - header('Location: catalog.php'); - exit(); - - } catch (Exception $e) { - $registration_errors[] = 'Ошибка быстрой регистрации: ' . $e->getMessage(); - } -} -?> - - - - - - AETERNA - Регистрация - - - - - - - - - -
-
-
- - -
-
- Все категории - -
- -
- - -
-
- - -
- -
- -
-

Ошибки регистрации:

-
    - -
  • - -
-
- - - -
- -
- - -
- Для доступа к каталогу и оформления заказов необходимо зарегистрироваться -
- -
-
- -
-

Присоединяйтесь к нам

-

- Создайте аккаунт чтобы получить доступ ко всем функциям: -

-
    -
  • Доступ к каталогу товаров
  • -
  • Добавление товаров в корзину
  • -
  • Оформление заказов
  • -
  • История покупок
  • -
  • Специальные предложения
  • -
-
-
- -
-
-

РЕГИСТРАЦИЯ

-
-
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - -
- - - Уже есть аккаунт? Войти - - - - -
- После регистрации вы будете перенаправлены в каталог -
-
-
-
-
-
- -
- - - -
- - - -
- - -
- - - - - \ No newline at end of file diff --git a/OLD_CODE/public/services.php b/OLD_CODE/public/services.php deleted file mode 100644 index ec1a30d..0000000 --- a/OLD_CODE/public/services.php +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - AETERNA - Услуги - - - - - - - - - - -
-
-
-
-
-

ДОСТАВКА

-

Стоимость доставки зависит от таких факторов, как: вес, адрес, удаленность от города, дата

-
-
-

СБОРКА

-

Стоимость сборки рассчитывается индивидуально, так как на цену влияет несколько факторов

-
-
- -
-

ДИЗАЙН‑ПРОЕКТ

-

Предоставляем услугу по составлению дизайн‑проекта. Учитываем индивидуальные пожелания каждого клиента. Работаем с интерьерами различной сложности.

-
-
-
-
-
- - - - - \ No newline at end of file diff --git a/OLD_CODE/public/style_for_cite.less b/OLD_CODE/public/style_for_cite.less deleted file mode 100644 index 3a52d85..0000000 --- a/OLD_CODE/public/style_for_cite.less +++ /dev/null @@ -1,3178 +0,0 @@ -@import "mixins.less"; -@import "стили_оформления.less"; -// ======================= -// === БАЗОВЫЕ СТИЛИ === -// ======================= -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -html, body { - height: 100%; -} - -html { - scroll-behavior: smooth; -} - -body { - font-family: @font-main; - background-color: @color-secondary; - color: @color-text-dark; - line-height: 1.6; - display: flex; - flex-direction: column; - min-height: 100vh; -} - -.container { - max-width: 1210px; - margin: 0 auto; - padding: 0 20px; -} - -ul { - list-style: none; -} - -a { - text-decoration: none; - color: inherit; - transition: all 0.3s ease; -} - -h1, h2, h3, h4, h5, h6 { - font-family: @font-heading; - margin: 0; -} - -p, li, span { - font-family: @font-main; -} - -// ======================= -// === КОМПОНЕНТЫ === -// ======================= - -.logo, .footer-logo { - font: bold 32px/1 @font-logo; - letter-spacing: 2px; - text-shadow: @shadow-dark; - flex-shrink: 0; -} - -.btn { - padding: 12px 30px; - border: none; - cursor: pointer; - font-size: 14px; - text-transform: uppercase; - transition: all 0.3s ease; - font-family: @font-main; - - &.primary-btn { - background-color: @color-button; - color: @color-text-light; - - &:hover { - background-color: lighten(@color-button, 10%); - transform: translateY(-2px); - box-shadow: @shadow-light; - } - } -} - -.number-circle { - .flex-center(); - width: 28px; - height: 28px; - border-radius: 50%; - background-color: @color-button; - color: @color-text-light; - font-size: 16px; - font-weight: bold; - flex-shrink: 0; -} - -.breadcrumbs { - font-size: 14px; - margin-bottom: 20px; - color: #666; - - a { - color: #666; - opacity: 0.7; - &:hover { opacity: 1; } - } - - .current-page { - font-weight: bold; - color: @color-text-dark; - } -} - -// ======================= -// === ШАПКА САЙТА === -// ======================= -.header { - background-color: @color-secondary; - border-bottom: 1px solid rgba(0, 0, 0, 0.05); - z-index: 1000; - - &__top, &__bottom { - padding: 15px 0; - .container { - .flex-between(); - gap: 20px; - } - } - - &__bottom { - padding: 10px 0; - border-top: 1px solid rgba(0, 0, 0, 0.05); - - .catalog-link.active-catalog { - background-color: rgba(0, 0, 0, 0.08); - pointer-events: none; - } - } - - .search-catalog { - .flex-center(); - border: 2px solid @color-text-dark; - background-color: #fff; - max-width: 600px; - width: 100%; - margin: 0 auto; - overflow: hidden; - - .catalog-dropdown { - position: relative; - background-color: #f8f8f8; - padding: 10px 15px 10px 25px; - font-size: 18px; - cursor: pointer; - border-right: 1px solid @color-text-dark; - .flex-center(10px); - width: 200px; - flex-shrink: 0; - - &__menu { - .menu-base(); - li { - padding: 8px 0; - cursor: pointer; - transition: color 0.3s; - border-bottom: 1px solid #f0f0f0; - &:last-child { border-bottom: none; } - &:hover { color: @color-accent; } - } - } - &:hover &__menu { display: block; } - } - - .search-box { - .flex-center(); - padding: 0 15px; - flex-grow: 1; - position: relative; - font-size: 15px; - - input { - border: none; - padding: 10px 30px 10px 0; - outline: none; - font-size: 16px; - width: 100%; - text-align: left; - } - - .search-icon { - font-size: 20px; - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; - } - }} - - &__icons--top { - .flex-center(15px); - flex-shrink: 0; - .icon { .icon-base(); font-size: 20px;} - } - - .nav-list { - .flex-center(30px); - font-size: 18px; - a { - text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); - &:hover { text-shadow: @shadow-dark; } - &.active { - border-bottom: 2px solid @color-button; - padding-bottom: 5px; - text-shadow: @shadow-dark; - } - &[href="#footer"] { - cursor: pointer; - } - } - } - - .catalog-link { - .flex-center(10px); - border-radius: 4px; - white-space: nowrap; - font-size: 18px; - padding: 10px 18px; - &:hover { background-color: rgba(0, 0, 0, 0.05); } - } - - .header-phone { - font-weight: bold; - color: @color-button; - flex-shrink: 0; - } -} - -// ======================= -// === ОСНОВНЫЕ СЕКЦИИ === -// ======================= -.hero { - padding: 15px 0; - - &__content { - .flex-center(50px); - min-height: 60vh; - align-items: center; - } - - &__image-block { - position: relative; - flex: 0 0 40%; - max-width: 600px; - height: 600px; - .flex-center(); - - .hero__circle { - position: absolute; - width: 450px; - height: 450px; - background-color: @color-primary; - border-radius: 50%; - z-index: 1; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - - .hero__img { - position: relative; - width: 100%; - height: 100%; - object-fit: contain; - z-index: 2; - } - } - - &__text-block { - flex: 0 0 60%; - padding-left: 50px; - - h1 { - font-size: 42px; - font-weight: normal; - margin-bottom: 25px; - line-height: 1.3; - } - - .hero__usp-text { - position: relative; - padding-left: 50px; - margin-bottom: 35px; - line-height: 1.7; - .flex-center(); - justify-content: flex-start; - min-height: 40px; - font-size: 16px; - - &::before { - content: "✓"; - position: absolute; - left: 0; - top: 50%; - transform: translateY(-50%); - width: 32px; - height: 32px; - border: 2px solid @color-button; - background-color: transparent; - color: @color-button; - border-radius: 50%; - .flex-center(); - font-size: 16px; - font-weight: bold; - } - } - - .btn.primary-btn { - margin: 25px 0 0 50px; - padding: 14px 35px; - font-size: 15px; - } - } -} - -.advantages { - padding: 30px 0 40px; - - &__header { - display: flex; - align-items: center; - gap: 50px; - margin-bottom: 40px; - h2 { - font-size: 32px; - font-weight: normal; - flex: 0 0 30%; - } - } - - &__items { - flex: 0 0 70%; - display: flex; - gap: 30px; - } - - .advantage-item { - flex: 1; - text-align: left; - position: relative; - padding-top: 30px; - - &__number { - .number-circle(); - position: absolute; - top: 0; - left: 0; - } - - h4 { - font-weight: 600; - margin-bottom: 10px; - } - } -} - -.promo-images { - display: flex; - gap: 20px; - margin-top: 50px; - - .promo-image-col { - position: relative; - overflow: hidden; - border-radius: 8px; - flex: 1; - transition: all 0.3s ease; - - &:hover { - transform: translateY(-5px); - box-shadow: @shadow-light; - .image-overlay-text { background-color: rgba(0, 0, 0, 0.6); } - img { transform: scale(1.05); } - .image-overlay-text h4, - .image-overlay-text .overlay-link { transform: translateY(0); } - } - - img { - width: 100%; - height: 350px; - object-fit: cover; - display: block; - transition: transform 0.5s ease; - } - - .image-overlay-text { - .image-overlay(); - h4 { - font-size: 24px; - text-transform: uppercase; - line-height: 1.2; - margin-bottom: 15px; - transform: translateY(20px); - transition: transform 0.3s ease; - } - } - - .overlay-link { - display: inline-block; - text-transform: uppercase; - font-weight: bold; - border-radius: 3px; - margin-top: 15px; - padding: 10px 25px; - background-color: @color-button; - color: @color-text-light; - font-size: 12px; - transform: translateY(20px); - transition: all 0.3s ease; - - &:hover { - background-color: lighten(@color-button, 10%); - transform: translateY(-2px); - box-shadow: @shadow-light; - } - } - } -} - -.about { - padding: 40px 0 80px; - - &__content { - display: flex; - align-items: flex-start; - gap: 50px; - } - - &__column { - display: flex; - flex-direction: column; - gap: 20px; - &--left { flex: 0 0 40%; margin-bottom: 30px; } - &--right { - flex: 0 0 60%; - .about__caption { - padding-right: 50px; - } - } - } - - &__text-block { - margin-bottom: 30px; - h2 { margin-bottom: 15px; } - } - - &__img { - width: 93%; - object-fit: cover; - display: block; - &--small { height: 300px; } - &--large { height: 450px; } - } - - .text-justified { - text-align: justify; - color: #555; - } -} - -.solutions { - padding: 0; - background-color: @color-secondary; - - &-slider { - position: relative; - width: 100%; - max-width: 1200px; - margin: 40px auto; - border-radius: 8px; - overflow: hidden; - - &__slides { - display: flex; - width: 200%; - height: 100%; - animation: slideLeftRight 10s infinite ease-in-out; - } - - &__slide { - width: 50%; - flex-shrink: 0; - position: relative; - overflow: hidden; - transition: transform 0.5s ease, box-shadow 0.5s ease; - - &:hover { - transform: scale(1.02); - box-shadow: 0 10px 25px rgba(0,0,0,0.3); - .solution-img { - transform: scale(1.05); - filter: brightness(0.8); - } - .solution-text-overlay { - opacity: 1; - transform: translateY(-5px); - } - .solution-image-link { - transform: translateX(-50%) translateY(-6px); - background-color: rgba(255,255,255,0.9); - color: @color-text-dark; - } - } - } - - .solution-img { - width: 100%; - height: auto; - object-fit: cover; - display: block; - } - - .solution-text-overlay { - position: absolute; - top: 15%; - left: 8%; - color: #493131; - text-shadow: 2px 2px 4px rgba(0,0,0,0.6); - z-index: 2; - opacity: 0.9; - transition: opacity 0.5s ease, transform 0.5s ease; - h2 { - font-size: 35px; - text-transform: uppercase; - margin-bottom: 10px; - } - p { - font-size: 25px; - text-transform: uppercase; - } - } - - .solution-image-link { - position: absolute; - bottom: 40px; - left: 50%; - transform: translateX(-50%); - padding: 12px 30px; - border: 2px solid @color-text-light; - color: #493131; - text-transform: uppercase; - font-size: 16px; - font-weight: bold; - background: transparent; - transition: 0.4s ease; - z-index: 2; - &:hover { - background: @color-text-light; - color: @color-text-dark; - transform: translateX(-50%) translateY(-2px); - } - } - } -} - -@keyframes slideLeftRight { - 0%, 40% { transform: translateX(0); } - 50%, 90% { transform: translateX(-50%); } - 100% { transform: translateX(0); } -} - -.stats { - padding: 0; - margin-top: 20px; - - .container { - display: flex; - justify-content: flex-end; - } - - &__items { - display: flex; - gap: 20px; - .stat-item { - text-align: left; - .stat-number { - font-size: 36px; - font-weight: bold; - color: @color-text-dark; - margin-bottom: 5px; - } - .stat-label { color: @color-text-dark; } - } - } -} - -.faq { - padding: 50px 0; - - h2 { - text-align: left; - font-size: 32px; - font-weight: normal; - margin-bottom: 40px; - } - - &__items { - display: flex; - flex-wrap: wrap; - gap: 40px 60px; - margin-bottom: 40px; - } - - .faq-item { - flex: 0 0 calc(50% - 30px); - .flex-center(15px); - align-items: flex-start; - &__content h4 { - font-weight: 600; - margin-bottom: 10px; - } - } - - .btn.primary-btn { - display: block; - width: 100%; - margin: 20px auto 80px; - } -} - -// ======================= -// === СТИЛИ КАТАЛОГА === -// ======================= -.catalog-main { - padding: 30px 0 60px; - background-color: lighten(@color-secondary, 5%); -} - -.catalog-wrapper { - display: flex; - gap: 20px; -} - -.catalog-sidebar { - flex: 0 0 250px; - background-color: #fff; - padding: 20px; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); - height: fit-content; -} - -.filter-group { - margin-bottom: 30px; -} - -.filter-title { - font-size: 16px; - font-weight: bold; - margin-bottom: 15px; - text-transform: uppercase; -} - -.filter-list li { - padding: 5px 0; - font-size: 16px; - a { - color: #555; - transition: color 0.2s; - &:hover { color: @color-accent; } - &.active-category { - font-weight: bold; - color: @color-primary; - } - } -} - -.price-range { - display: flex; - flex-direction: column; - gap: 15px; - width: 100%; - - .range-slider { - width: 100%; - - input[type="range"] { - -webkit-appearance: none; - appearance: none; - width: 100%; - height: 5px; - background: @color-primary; - border-radius: 5px; - outline: none; - margin: 0; - - &::-webkit-slider-thumb { - -webkit-appearance: none; - appearance: none; - width: 20px; - height: 20px; - background: @color-accent; - border: 2px solid #fff; - border-radius: 50%; - cursor: pointer; - box-shadow: 0 2px 4px rgba(0,0,0,0.2); - transition: all 0.3s ease; - - &:hover { - transform: scale(1.1); - background: lighten(@color-accent, 10%); - } - } - - &::-moz-range-thumb { - width: 20px; - height: 20px; - background: @color-accent; - border: 2px solid #fff; - border-radius: 50%; - cursor: pointer; - box-shadow: 0 2px 4px rgba(0,0,0,0.2); - transition: all 0.3s ease; - - &:hover { - transform: scale(1.1); - background: lighten(@color-accent, 10%); - } - } - } - } - - .price-display { - font-size: 14px; - font-weight: bold; - text-align: center; - color: @color-text-dark; - padding: 10px; - background: #f8f8f8; - border-radius: 4px; - } -} - -.filter-options { - list-style: none; - li { - display: flex; - align-items: center; - padding: 4px 0; - font-size: 14px; - } - label { - margin-left: 10px; - cursor: pointer; - color: #555; - } - input[type="checkbox"] { - width: 15px; - height: 15px; - cursor: pointer; - accent-color: @color-primary; - &:checked + label { - font-weight: bold; - color: @color-primary; - } - } -} - -.filter-apply-btn { - width: 100%; - margin-top: 20px; -} - -.catalog-products { - flex-grow: 1; -} - -.products-container { - display: flex; - flex-wrap: wrap; - gap: 20px; -} - -.product-card { - background-color: #fff; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); - display: flex; - flex-direction: column; - position: relative; - transition: transform 0.3s ease; - box-sizing: border-box; - - &:hover { - transform: translateY(-5px); - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); - .product-img { transform: scale(1.05); } - } -} - -.product-image-container { - position: relative; - overflow: hidden; - margin-bottom: 0; - padding: 0; - height: 250px; - .flex-center(); -} - -.product-img { - width: 100%; - height: 100%; - object-fit: contain; - display: block; - transition: transform 0.3s ease; - margin: 0; -} - -.product-img1 { - width: 100%; - height: 100%; - object-fit: cover; - display: block; - transition: transform 0.3s ease; - margin: 0; -} - -.product-discount { - position: absolute; - top: 10px; - right: 10px; - background-color: @color-button; - color: @color-text-light; - padding: 3px 8px; - font-size: 12px; - font-weight: bold; - z-index: 10; -} - -.product-wishlist-icon { - position: absolute; - top: 10px; - left: 10px; - color: #333; - font-size: 18px; - cursor: pointer; - transition: color 0.3s ease; - z-index: 10; - &:hover { color: @color-accent; } -} - -.product-name { - font-size: 16px; - font-weight: bold; - margin-bottom: 5px; -} - -.product-details { - font-size: 13px; - color: #777; - margin-bottom: 10px; - flex-grow: 1; -} - -.product-price { - font-size: 18px; - font-weight: bold; - color: @color-button; -} - -.product-card.small { flex: 0 0 300px; max-width: 300px; height: 200px; } -.product-card.small1 { flex: 0 0 320px; max-width: 320px; height: 250px;width: 320px; } -.product-card.large { flex: 0 0 580px; max-width: 580px; height: 380px; } -.product-card.wide { flex: 0 0 240px; max-width: 240px; height: 250px; } -.product-card.wide1 { flex: 0 0 350px; max-width: 350px; height: 250px; } -.product-card.wide2 { flex: 0 0 560px; max-width: 560px; height: 260px; } -.product-card.wide2_1 { flex: 0 0 560px; max-width: 560px; height: 260px; margin: -280px 0 0; } -.product-card.wide3 { - flex: 0 0 320px; max-width: 320px; height: 540px; - .product-image-container { height: 580px; } -} -.product-card.wide4 { - flex: 0 0 545px; max-width: 545px; margin: -270px 0 0; height: 250px; - .product-image-container { padding: 0; justify-content: flex-start; } - .product-img { margin-left: 0; align-self: flex-start; object-position: left center; } -} -.product-card.tall { flex: 0 0 300px; max-width: 300px; margin: -180px 0 0; height: 430px; } -.product-card.full-width { flex: 0 0 100%; margin: -20px 0 0; max-width: 900px; height: 300px;} - -.product-card.full-width { - flex: 0 0 100%; - max-width: 100%; - height: 300px; - - .product-image-container { - height: 100%; - padding: 0; - margin: 0; - - .product-img1 { - width: 100%; - height: 100%; - object-fit: cover; - margin: 0; - padding: 0; - } - } -} - -.product-card.tall .product-image-container, -.product-card.large .product-image-container { height: 430px; } - -// ======================= -// === СТРАНИЦА ТОВАРА === -// ======================= -.product__section { - display: flex; - gap: 0; - margin: 30px 0; -} - -.product__gallery, .product__info { - flex: 1; -} - -.product__main-image { - margin-bottom: 15px; -} - -.product__image { - width: 500px; - height: 300px; - border-radius: 4px; -} - -.product__thumbnails { - display: flex; - gap: 10px; -} - -.product__thumbnail { - border: none; - background: none; - cursor: pointer; - padding: 0; -} - -.product__thumbnail img { - width: 245px; - height: 150px; - object-fit: cover; - border-radius: 4px; -} - -.product__title { - font-size: 30px; - margin-bottom: 35px; -} - -.product__rating { - display: flex; - align-items: center; - gap: 10px; - margin-bottom: 30px; -} - -.product__color-selector { - display: flex; - gap: 10px; - margin-bottom: 40px; -} - -.product__color-option { - width: 45px; - height: 45px; - border-radius: 50%; - border: 2px solid transparent; - cursor: pointer; - transition: transform 0.3s ease; - - &:hover{ - transform: translateY(-2px); - } -} - -.product__color-option.active { - border-color: @color-primary; -} - -.product__description { - margin-bottom: 65px; - line-height: 1.5; -} - -.product__details-link { - display: inline-block; - margin-bottom: 20px; - color: @color-primary; - font-weight: bold; -} - -.product__purchase { - display: flex; - justify-content: space-between; - margin-bottom: 35px; -} - -.product__price { - font-size: 24px; - font-weight: bold; -} - -.product__quantity { - display: flex; - align-items: center; - gap: 10px; -} - -.product__qty-btn { - width: 30px; - height: 30px; - background: @color-button; - color: @color-text-light; - border: none; - border-radius: 50%; - cursor: pointer; - font-weight: bold; - transition: all 0.3s ease; - - &:hover { - background: lighten(@color-button, 10%); - transform: scale(1.1); - } -} - -.product__qty-value { - font-weight: bold; - min-width: 30px; - text-align: center; -} - -.product__actions { - display: flex; - gap: 15px; -} - -.product__btn { - flex: 1; - padding: 12px 20px; - border: none; - border-radius: 4px; - font-weight: bold; - cursor: pointer; - transition: all 0.3s ease; - - &:hover { - transform: translateY(-2px); - box-shadow: @shadow-light; - } -} - -.product__btn.primary { - background: @color-button; - color: @color-text-light; - - &:hover { - background: lighten(@color-button, 10%); - } -} - -.product__btn.secondary { - background: transparent; - border: 1px solid @color-button; - color: @color-button; - - &:hover { - background: @color-button; - color: @color-text-light; - } -} - -.similar { - margin: 60px 0; -} - -.similar__title { - margin-bottom: 30px; - font-size: 28px; - font-weight: bold; -} - -.similar__grid { - display: flex; - gap: 25px; - flex-wrap: wrap; - justify-content: space-between; -} - -.similar__card { - flex: 0 0 calc(33.333% - 17px); - min-width: 320px; - background: @color-secondary; - border-radius: 12px; - overflow: hidden; - transition: all 0.3s ease; - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); - - &:hover { - transform: translateY(-8px); - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); - } -} - -.similar__card-image { - height: 300px; - overflow: hidden; - background: white; - - img { - width: 100%; - height: 100%; - object-fit: contain; - transition: transform 0.3s ease; - - &:hover { - transform: scale(1.05); - } - } -} - -.similar__card-content { - padding: 25px; -} - -.similar__card-title { - font-weight: bold; - margin-bottom: 10px; - font-size: 20px; - color: @color-text-dark; -} - -.similar__card-description { - font-size: 15px; - margin-bottom: 15px; - color: #666; - line-height: 1.5; -} - -.similar__card-price { - font-weight: bold; - font-size: 22px; - color: @color-button; -} - -@media (max-width: 1024px) { - .similar { - &__card { - flex: 0 0 calc(50% - 13px); - min-width: 280px; - } - } -} - -@media (max-width: 768px) { - .similar { - &__grid { - justify-content: center; - } - - &__card { - flex: 0 0 100%; - max-width: 400px; - } - } -} - -// ======================= -// === КОРЗИНА И ЗАКАЗ === -// ======================= -.main__content { - display: flex; - gap: 40px; - margin: 30px 0; - - .products { - flex: 1; - } - - .order { - flex: 0 0 65%; - padding: 40px; - - &__header { - .flex-between(); - margin-bottom: 20px; - } - - &__title { - font-family: @font-logo; - font-size: 28px; - color: @color-text-dark; - margin: 0; - } - - &__total { - font-weight: bold; - color: @color-text-dark; - } - - &__section { - margin-bottom: 25px; - } - - &__section-title { - font-family: @font-logo; - margin-bottom: 15px; - font-size: 18px; - color: @color-text-dark; - } - } -} - -.products { - &__title { - font-family: @font-logo; - margin-bottom: 20px; - font-size: 24px; - color: @color-text-dark; - } - - &__list { - .flex-column(); - gap: 20px; - } - - &__item { - background-color: @color-secondary; - border-radius: 8px; - padding: 20px; - display: flex; - gap: 15px; - border: 1px solid @color-secondary; - transition: transform 0.3s ease; - align-items: flex-start; - position: relative; - - &:hover { - transform: translateY(-2px); - } - } - - &__image { - width: 300px; - height: 200px; - border-radius: 4px; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: flex-start; - } - - .product-img { - width: 100%; - height: 100%; - object-fit: cover; - display: block; - transition: transform 0.3s ease; - margin: 0; - } - - &__details { - flex: 1; - .flex-column(); - justify-content: space-between; - align-items: flex-start; - min-height: 200px; - } - - &__name { - font-weight: bold; - margin-bottom: 5px; - color: @color-accent; - font-size: 18px; - font-family: @font-main; - } - - &__price { - font-weight: bold; - font-size: 18px; - margin-bottom: 15px; - color: @color-text-dark; - } - - &__controls { - display: flex; - align-items: center; - gap: 15px; - margin-top: auto; - width: 100%; - justify-content: space-between; - } - - &__quantity { - display: flex; - align-items: center; - gap: 10px; - } - - &__qty-btn { - width: 30px; - height: 30px; - background-color: @color-text-dark; - color: @color-text-light; - border: none; - border-radius: 50%; - cursor: pointer; - .flex-center(); - font-family: @font-main; - font-weight: bold; - transition: all 0.3s ease; - - &:hover { - transform: scale(1.1); - } - } - - &__qty-value { - font-weight: bold; - min-width: 30px; - text-align: center; - font-size: 16px; - } - - &__cart-icon { - background-color: transparent; - color: @color-text-dark; - width: 40px; - height: 40px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: all 0.3s ease; - border: 2px solid @color-text-dark; - margin-left: 20px; - - &:hover { - transform: scale(1.1); - } - - i { font-size: 18px; } - } -} - -.form { - &__group { margin-bottom: 15px; } - &__label { - display: block; - margin-bottom: 5px; - font-weight: bold; - color: #000000; - } - &__input { - width: 100%; - padding: 14px 16px; - border: 2px solid #ccc; - font-family: @font-main; - font-size: 15px; - transition: border-color 0.3s ease; - - &:focus { - border-color: @color-primary; - } - - &:hover { - border-color: darken(#ccc, 10%); - } - &::placeholder { - font-style: italic; - color: #999; - } - } - &__row { - display: flex; - gap: 20px; - justify-content: space-between; - } - &__input--half { - width: 100%; - } - &__radio-group { - display: flex; - justify-content: space-between; - margin-bottom: 20px; - margin-top: 20px; - } - &__radio-label { - display: flex; - align-items: center; - cursor: pointer; - color: @color-text-dark; - position: relative; - padding-left: 30px; - flex: 1; - - &:hover { - .form__custom-radio { - border-color: lighten(@color-accent, 10%); - } - } - } - &__radio-input { - position: absolute; - opacity: 0; - cursor: pointer; - } - &__custom-radio { - position: absolute; - left: 0; - height: 20px; - width: 20px; - background-color: @color-secondary; - border: 2px solid @color-accent; - border-radius: 50%; - transition: border-color 0.3s ease; - } - &__radio-input:checked ~ &__custom-radio { - background-color: @color-accent; - - &:after { - content: ""; - position: absolute; - display: block; - top: 4px; - left: 4px; - width: 8px; - height: 8px; - border-radius: 50%; - background: white; - } - } -} - -.divider { - height: 1px; - background-color: #999; - margin: 20px 0; -} - -.promo { - display: flex; - margin-bottom: 20px; - - &__input { - flex: 1; - padding: 10px; - border: 1px solid #000; - background-color: @color-secondary; - font-family: @font-main; - height: auto; - min-height: 48px; - - &:hover { - border-color: @color-primary; - } - - &::placeholder { - font-style: italic; - color: #999; - } - } - - &__btn { - background-color: @color-accent; - color: @color-secondary; - border: none; - padding: 10px 60px; - cursor: pointer; - font-family: @font-main; - font-size: 18px; - transition: all 0.3s ease; - - &:hover { - background-color: lighten(@color-accent, 10%); - transform: translateY(-2px); - } - } -} - -.summary { - margin-bottom: 20px; - - &__item { - display: flex; - justify-content: space-between; - margin-bottom: 10px; - color: @color-text-dark; - - &.total { - font-weight: bold; - font-size: 18px; - padding-top: 10px; - margin-top: 10px; - } - } -} - -.order-btn { - width: 100%; - background-color: @color-accent; - color: @color-secondary; - border: none; - padding: 15px; - border-radius: 4px; - font-size: 18px; - cursor: pointer; - margin-bottom: 10px; - font-family: @font-main; - transition: all 0.3s ease; - - &:hover { - background-color: lighten(@color-accent, 10%); - transform: translateY(-2px); - } -} - -.privacy { - display: flex; - gap: 8px; - font-size: 16px; - color: #666; - margin-bottom: 20px; - - input[type="checkbox"] { - width: 18px; - height: 18px; - cursor: pointer; - } -} - -.services { - display: flex; - flex-direction: row; - justify-content: center; - flex-wrap: wrap; - gap: 24px; - margin-bottom: 24px; - - &__title { - font-family: @font-logo; - margin-bottom: 10px; - font-size: 18px; - color: @color-text-dark; - display: block; - width: 100%; - } - - &__item { - display: flex; - justify-content: space-between; - margin-bottom: 8px; - color: @color-text-dark; - width: 100%; - } -} - -.cart-icon { - position: relative; -} - -.cart-count { - position: absolute; - top: -8px; - right: -8px; - background: @color-accent; - color: @color-text-light; - border-radius: 50%; - width: 18px; - height: 18px; - font-size: 12px; - display: flex; - align-items: center; - justify-content: center; -} - -.form__input.error { - border-color: #ff4444; - box-shadow: 0 0 5px rgba(255, 68, 68, 0.3); -} - -.empty-cart { - text-align: center; - padding: 40px; - color: #666; - font-size: 18px; -} - -// ======================= -// === АВТОРИЗАЦИЯ === -// ======================= -.profile-page-main { - .flex-center(); - min-height: 80vh; - padding: 40px 0; - background-color: lighten(@color-secondary, 5%); - z-index: 1; - - .profile-container { - display: flex; - width: 100%; - max-width: 1000px; - min-height: 600px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); - background-color: @color-text-light; - } - - .profile-left-col { - flex: 0 0 35%; - background-color: @color-primary; - color: @color-text-light; - display: flex; - justify-content: flex-start; - align-items: flex-start; - padding: 40px; - .logo { - font-size: 32px; - font-weight: normal; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4); - color: @color-text-light; - } - } - - .profile-right-col { - flex: 0 0 65%; - .flex-center(); - padding: 40px; - .profile-form-block { - width: 100%; - max-width: 400px; - h2 { - font-size: 28px; - font-weight: normal; - margin-bottom: 40px; - text-align: left; - color: @color-text-dark; - } - } - } - - .profile-form { - .input-group { - margin-bottom: 20px; - label { - display: block; - font-size: 12px; - font-weight: bold; - color: @color-text-dark; - margin-bottom: 5px; - text-transform: uppercase; - } - } - - input[type="text"], - input[type="email"], - input[type="tel"] { - .input-base(); - } - - .password-link { - display: block; - text-align: left; - font-size: 13px; - color: @color-text-dark; - text-decoration: underline; - margin: 10px 0 20px; - &:hover { - color: @color-accent; - text-decoration: none; - } - } - - .save-btn { - padding: 15px 30px; - border: none; - cursor: pointer; - font-size: 15px; - text-transform: uppercase; - transition: all 0.3s ease; - font-family: @font-main; - width: 100%; - margin-top: 20px; - background-color: @color-primary; - color: @color-text-light; - - &:hover { - background-color: lighten(@color-primary, 10%); - transform: translateY(-2px); - box-shadow: @shadow-light; - } - } - - .auth-actions { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 25px; - padding-top: 20px; - border-top: 1px solid #eee; - - .auth-text { - font-size: 13px; - color: @color-text-dark; - } - - .login-btn { - background-color: transparent; - color: @color-accent; - border: 1px solid @color-accent; - padding: 10px 25px; - font-size: 13px; - cursor: pointer; - transition: all 0.3s ease; - - &:hover { - background-color: @color-primary; - color: @color-text-light; - } - } - } - } -} - -// ======================= -// === СЕКЦИЯ УСЛУГ === -// ======================= -.services-section { - padding: 60px 0; - background-color: @color-secondary; -} - -.services__wrapper { - display: flex; - flex-direction: column; - gap: 30px; -} - -.services__top-row { - display: flex; - gap: 30px; - justify-content: center; - - @media (max-width: 768px) { - flex-direction: column; - align-items: center; - } -} - -.service-card { - border-radius: 8px; - padding: 40px; - min-height: 200px; - text-align: center; - transition: all 0.3s ease; - - &:hover { - transform: translateY(-5px); - box-shadow: @shadow-light; - } - - &--green { - background: @color-primary; - color: @color-text-light; - flex: 1; - max-width: 450px; - } - - &--beige { - background: @color-beige; - color: @color-text-light; - width: 100%; - max-width: 930px; - margin: 0 auto; - } - - &__title { - font-family: @font-logo; - font-size: 24px; - font-weight: bold; - margin-bottom: 15px; - text-transform: uppercase; - } - - &__text { - font-family: @font-main; - font-size: 16px; - line-height: 1.6; - margin: 0; - } -} - -// ======================= -// === ФУТЕР === -// ======================= -.footer { - background-color: @color-primary; - color: black; - padding: 40px 0 10px; - position: relative; - z-index: 1000; - - &::before { - content: ''; - display: block; - position: absolute; - top: -80px; - left: 0; - width: 100%; - height: 1px; - visibility: hidden; - } - - &__content { - display: flex; - gap: 20px; - padding-bottom: 30px; - border-bottom: 1px solid rgba(255, 255, 255, 0.2); - } - - &__col { - flex: 1; - &--logo { flex: 1.5; } - h5 { - margin-bottom: 15px; - font-size: 14px; - text-transform: uppercase; - } - ul li { - margin-bottom: 8px; - a:hover { text-decoration: underline; } - } - .social-icons, - .payment-icons { - .flex-center(15px); - justify-content: flex-start; - margin-top: 10px; - } - .social-icons .icon { - .icon-base(20px, 1.1); - color: black; - &:hover { color: @color-accent; } - } - .payment-icons .pay-icon { - .icon-base(24px, 1.05); - color: black; - } - } - - .copyright { - text-align: center; - font-size: 12px; - padding-top: 20px; - color: rgba(255, 255, 255, 0.6); - } -} - -// ======================= -// === ДОСТАВКА === -// ======================= -.delivery-content { - max-width: 1200px; - margin: 0 auto; - padding: 40px 20px; -} - -.delivery-content h1 { - font-family: @font-logo; - font-size: 42px; - text-align: center; - margin-bottom: 50px; - color: #453227; -} - -.delivery-section { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 30px; - margin-bottom: 60px; -} - -.delivery-card { - background: white; - padding: 30px; - border-radius: 12px; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); - text-align: center; - transition: transform 0.3s ease; - flex: 1; - min-width: 350px; - max-width: 400px; -} - -.delivery-card:hover { - transform: translateY(-5px); -} - -.delivery-icon { - font-size: 48px; - color: #617365; - margin-bottom: 20px; -} - -.delivery-card h3 { - font-family: @font-logo; - font-size: 24px; - margin-bottom: 20px; - color: #453227; -} - -.delivery-details { - text-align: left; -} - -.detail-item { - display: flex; - justify-content: space-between; - margin-bottom: 12px; - padding-bottom: 12px; - border-bottom: 1px solid #f0f0f0; -} - -.detail-label { - font-weight: bold; - color: #333; -} - -.detail-value { - color: #617365; - text-align: right; -} - -// ======================= -// === ГАРАНТИЯ === -// ======================= -.warranty-content { - max-width: 1200px; - margin: 0 auto; - padding: 40px 20px; -} - -.warranty-content h1 { - font-family: 'Anek Kannada', sans-serif; - font-size: 42px; - text-align: center; - margin-bottom: 50px; - color: #453227; -} - -.warranty-overview { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 25px; - margin-bottom: 60px; -} - -.warranty-card { - background: white; - padding: 30px; - border-radius: 12px; - text-align: center; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); - transition: transform 0.3s ease; - flex: 1; - min-width: 250px; - max-width: 280px; - display: flex; - flex-direction: column; - align-items: center; -} - -.warranty-card:hover { - transform: translateY(-5px); -} - -.warranty-icon { - font-size: 48px; - color: #617365; - margin-bottom: 20px; -} - -.warranty-card h3 { - font-family: 'Anek Kannada', sans-serif; - font-size: 20px; - margin-bottom: 15px; - color: #453227; -} - -.warranty-period { - font-size: 24px; - font-weight: bold; - color: #617365; - margin-top: auto; -} - -.coverage-section { - display: flex; - flex-wrap: wrap; - gap: 40px; - margin-bottom: 60px; -} - -.coverage-covered, -.coverage-not-covered { - flex: 1; - min-width: 300px; -} - -.coverage-section h2 { - font-family: 'Anek Kannada', sans-serif; - font-size: 24px; - margin-bottom: 25px; - color: #453227; -} - -.coverage-list { - display: flex; - flex-direction: column; - gap: 20px; -} - -.coverage-item { - display: flex; - align-items: flex-start; - gap: 15px; - padding: 20px; - border-radius: 8px; - background: white; - box-shadow: 0 3px 10px rgba(0,0,0,0.1); -} - -.coverage-item.covered i { - color: #28a745; - font-size: 20px; - margin-top: 2px; - flex-shrink: 0; -} - -.coverage-item.not-covered i { - color: #dc3545; - font-size: 20px; - margin-top: 2px; - flex-shrink: 0; -} - -.coverage-text { - flex: 1; -} - -.coverage-item h4 { - font-family: 'Anek Kannada', sans-serif; - font-size: 16px; - margin-bottom: 5px; - color: #333; -} - -.card { - min-height: 250px; - display: flex; - align-items: center; - justify-content: center; - color: @color-text-light; - text-align: center; - - &--green { - background: @color-primary; - flex: 0 1 450px; - max-width: 450px; - } - - &--beige { - background: @color-beige; - color: @color-text-dark; - flex: 0 1 925px; - max-width: 925px; - } -} - -.design-section { - display: flex; - justify-content: center; - margin-bottom: 40px; - .card { width: 100%; } -} - -// ======================= -// === АДАПТИВНОСТЬ === -// ======================= -@media (max-width: 1240px) { - .catalog-wrapper { gap: 20px; } - .catalog-sidebar { flex: 0 0 200px; } - .products-container { - gap: 15px; - display: flex; - flex-wrap: wrap; - } - - .product-card.small1 { - margin-top: 100px; - } - - .product-card.small, - .product-card.small1, - .product-card.large, - .product-card.wide, - .product-card.wide1, - .product-card.wide2, - .product-card.wide2_1, - .product-card.wide4 { - flex: 0 0 calc(33.333% - 10px); - max-width: calc(33.333% - 10px); - height: 180px; - margin: 0; - - .product-image-container { - height: 180px; - } - } - - .product-card.wide3 { - flex: 0 0 calc(25% - 10px); - max-width: calc(25% - 10px); - height: 300px; - margin: 0; - - .product-image-container { - height: 350px; - } - } - - .product-card.tall { - flex: 0 0 calc(25% - 10px); - max-width: calc(25% - 10px); - height: 300px; - margin: 0; - - .product-image-container { - height: 300px; - } - } - - .product-card.full-width { - flex: 0 0 100%; - max-width: 100%; - height: 300px; - margin: 0; - - .product-image-container { - height: 300px; - } - } - - .product-card.small { order: 1; } - .product-card.large { order: 2; } - .product-card.wide { order: 3; } - - .product-card.small1 { order: 11; } - .product-card.wide2 { order: 12; } - .product-card.wide2_1 { order: 13; } - - .product-card.wide3 { order: 21; } - .product-card.tall { order: 22; } - - .product-card.wide3 { order: 31; } - - .product-card.full-width { order: 41; flex-basis: 100%; } - - .main__content { - gap: 20px; - .products { - flex: 0 0 35%; - .products__image { - width: 250px; - height: 180px; - } - } - .order { - flex: 0 0 60%; - padding: 30px; - - .order__title { - font-size: 24px; - } - - .order__section-title { - font-size: 16px; - } - } - } - - .solutions-slider { - &__slide { - .solution-text-overlay { - top: 10%; - left: 5%; - h2 { - font-size: 26px; - margin-bottom: 5px; - line-height: 1.2; - } - p { - font-size: 18px; - line-height: 1.2; - } - } - .solution-image-link { - bottom: 70px; - padding: 10px 25px; - font-size: 14px; - } - } - } - - .product__image { - width: 350px; - height: 250px; - } - - .product__thumbnail img { - width: 170px; - height: 120px; - } -} - -@media (max-width: 1024px) { - .main__content { - gap: 25px; - .products { - flex: 0 0 30%; - .products__image { - width: 200px; - height: 150px; - } - - .products__name { - font-size: 16px; - } - - .products__price { - font-size: 16px; - } - } - .order { - flex: 0 0 60%; - padding: 25px; - - .order__title { - font-size: 22px; - } - - .form__input { - padding: 12px 14px; - font-size: 14px; - } - - .promo__btn { - padding: 10px 40px; - font-size: 16px; - } - } - } -} - -@media (max-width: 768px) { - .container { padding: 0 15px; } - - .delivery-section { - flex-direction: column; - align-items: center; - } - - .delivery-card { - min-width: 100%; - max-width: 100%; - } - - .delivery-content h1 { - font-size: 32px; - } - - .warranty-overview { - flex-direction: column; - align-items: center; - } - - .warranty-card { - max-width: 100%; - width: 100%; - } - - .coverage-section { - flex-direction: column; - } - - .warranty-content h1 { - font-size: 32px; - } - - .header__top .container, - .header__bottom .container, - .hero__content, - .advantages__header, - .about__content, - .advantages__items, - .promo-images, - .stats__items, - .faq__items, - .catalog-wrapper, - .main__content { - flex-direction: column; - gap: 30px; - } - - .search-catalog { - order: 3; - width: 100%; - max-width: 100%; - } - - .nav-list { - flex-wrap: wrap; - justify-content: center; - gap: 15px; - } - - .hero { - &__image-block { - flex: none; - max-width: 400px; - height: 400px; - } - &__circle { - width: 380px; - height: 380px; - } - &__text-block { - flex: none; - padding-left: 0; - text-align: center; - h1 { font-size: 32px; } - .hero__usp-text { - padding-left: 0; - justify-content: center; - &::before { display: none; } - } - .btn.primary-btn { margin-left: 0; } - } - } - - .advantages__header h2, - .faq h2 { font-size: 28px; } - - .faq-item, - .stat-item { - flex: none; - .flex-center(); - text-align: center; - } - - .stats .container { justify-content: center; } - .catalog-dropdown__menu { width: 200px; } - - .catalog-sidebar { width: 100%; flex: none; } - .products-container { gap: 15px; } - - .product-card.small, - .product-card.small1, - .product-card.large, - .product-card.wide, - .product-card.wide1, - .product-card.wide2, - .product-card.wide2_1, - .product-card.wide3, - .product-card.wide4, - .product-card.tall, - .product-card.full-width { - flex: 0 0 100%; - max-width: 100%; - height: 250px; - margin: 0; - - .product-image-container { - height: 200px; - } - } - - .main__content { - flex-direction: column; - gap: 20px; - - .products, - .order { - flex: 0 0 100%; - width: 100%; - } - - .products { - .products__item { - flex-direction: column; - text-align: center; - gap: 15px; - } - - .products__image { - width: 100%; - height: 200px; - justify-content: center; - } - - .products__details { - min-height: auto; - align-items: center; - } - - .products__controls { - justify-content: center; - margin-top: 15px; - } - - .products__cart-icon { - margin-left: 0; - } - } - - .order { - padding: 20px; - - .order__title { - font-size: 20px; - text-align: center; - } - - .order__total { - text-align: center; - } - - .form__radio-group { - flex-direction: column; - gap: 15px; - } - - .form__radio-label { - flex: none; - justify-content: flex-start; - } - - .promo { - flex-direction: column; - gap: 10px; - - &__btn { - width: 100%; - padding: 12px; - } - } - - .order-btn { - padding: 12px; - font-size: 16px; - } - - .services { - flex-direction: column; - align-items: center; - } - } - } - - .product-image-container { height: 200px; } - .product-card.tall .product-image-container, - .product-card.large .product-image-container { height: 250px; } - - .profile-page-main { - .profile-container { - flex-direction: column; - min-height: auto; - max-width: 100%; - box-shadow: none; - } - .profile-left-col { - flex: none; - width: 100%; - height: 100px; - .flex-center(); - padding: 0; - } - .profile-right-col { - flex: none; - width: 100%; - padding: 30px 20px; - } - .profile-form-block { max-width: 100%; } - } - - .form__row { flex-direction: column; } - .form__input--half { flex: 0 0 100%; max-width: 100%; } - .services { flex-direction: column; align-items: center; } - - .services-section { - padding: 40px 0; - } - - .service-card { - padding: 30px 20px; - min-height: 180px; - - &--green, - &--beige { - max-width: 100%; - } - - &__title { - font-size: 20px; - } - - &__text { - font-size: 14px; - } - } - .solutions-slider { - margin: 20px auto; - &__slide { - .solution-text-overlay { - top: 8%; - left: 4%; - h2 { - font-size: 20px; - margin-bottom: 3px; - line-height: 1.1; - } - p { - font-size: 15px; - line-height: 1.1; - } - } - .solution-image-link { - bottom: 90px; - padding: 8px 20px; - font-size: 13px; - } - } - } -} - -// Стили для ошибок полей -.error-input { - border-color: #ff4444 !important; - box-shadow: 0 0 0 1px #ff4444; -} - -.field-error { - color: #ff4444; - font-size: 12px; - margin-top: 5px; - margin-bottom: 10px; -} - -// Стили для сообщений -.message { - padding: 15px; - margin: 20px 0; - border-radius: 5px; - display: none; -} - -.message.error { - background-color: #ffebee; - color: #c62828; - border: 1px solid #ffcdd2; -} - -.message.success { - background-color: #e8f5e9; - color: #2e7d32; - border: 1px solid #c8e6c9; -} - -// Добавьте в конец файла -.access-denied { - text-align: center; - padding: 80px 20px; - background: white; - border-radius: 10px; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); - margin: 50px 0; - - h2 { - color: #dc3545; - margin-bottom: 30px; - font-size: 28px; - } - - p { - color: #666; - margin-bottom: 40px; - font-size: 18px; - line-height: 1.6; - } - - .btn { - margin: 5px; - min-width: 200px; - } -} -// ======================= -// === ПРОФИЛЬ ПОЛЬЗОВАТЕЛЯ === -// ======================= - -.user-profile-dropdown { - position: relative; - display: inline-block; - - &__toggle { - display: flex; - align-items: center; - gap: 8px; - cursor: pointer; - padding: 8px 12px; - border-radius: 4px; - transition: all 0.3s ease; - - &:hover { - background-color: rgba(0, 0, 0, 0.05); - } - - .user-avatar { - width: 32px; - height: 32px; - border-radius: 50%; - background-color: @color-primary; - color: @color-text-light; - .flex-center(); - font-weight: bold; - } - - .user-info { - display: flex; - flex-direction: column; - - .user-email { - font-size: 12px; - color: #666; - max-width: 150px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .user-status { - font-size: 10px; - padding: 2px 6px; - border-radius: 10px; - text-transform: uppercase; - - &.admin { - background-color: #617365; - color: white; - } - - &.user { - background-color: #28a745; - color: white; - } - } - } - } - - &__menu { - .menu-base(); - width: 220px; - top: 100%; - right: 0; - - .user-details { - padding: 15px; - border-bottom: 1px solid #eee; - - .user-name { - font-weight: bold; - margin-bottom: 5px; - } - - .user-registered { - font-size: 11px; - color: #999; - } - } - - ul { - padding: 10px 0; - - li { - padding: 8px 15px; - cursor: pointer; - display: flex; - align-items: center; - gap: 10px; - transition: background-color 0.3s ease; - - &:hover { - background-color: #f5f5f5; - } - - &.logout { - color: #dc3545; - border-top: 1px solid #eee; - margin-top: 5px; - padding-top: 12px; - - &:hover { - background-color: #ffe6e6; - } - } - } - } - } - - &:hover &__menu { - display: block; - } -} - -// ======================= -// === КАРТОЧКА ТОВАРА === -// ======================= - -.product-image-container { - position: relative; - overflow: hidden; - margin-bottom: 0; - padding: 0; - height: 250px; - .flex-center(); - - &:hover { - .product-overlay-info { - opacity: 1; - transform: translateY(0); - } - } -} - -.product-overlay-info { - position: absolute; - bottom: 0; - left: 0; - right: 0; - background: linear-gradient(to top, rgba(0,0,0,0.8), transparent); - color: white; - padding: 15px; - opacity: 0; - transform: translateY(10px); - transition: all 0.3s ease; - - .product-overlay-name { - font-weight: bold; - font-size: 14px; - margin-bottom: 5px; - } - - .product-overlay-price { - font-size: 16px; - font-weight: bold; - - .old-price { - text-decoration: line-through; - font-size: 12px; - color: #ccc; - margin-right: 5px; - } - - .current-price { - color: #ffd700; - } - } - - .product-overlay-category { - font-size: 11px; - opacity: 0.8; - margin-top: 3px; - } - - .product-overlay-stock { - font-size: 11px; - margin-top: 5px; - - &.out-of-stock { - color: #ff6b6b; - } - - i { - margin-right: 5px; - } - } -} - -.product-card-details { - padding: 15px; - background: white; - flex-grow: 1; - display: flex; - flex-direction: column; - - .product-card-name { - font-weight: bold; - font-size: 16px; - margin-bottom: 8px; - color: @color-text-dark; - } - - .product-card-description { - font-size: 13px; - color: #777; - margin-bottom: 10px; - flex-grow: 1; - } - - .product-card-attributes { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-bottom: 10px; - - .attribute { - font-size: 11px; - background: #f5f5f5; - padding: 3px 8px; - border-radius: 12px; - color: #666; - - i { - margin-right: 3px; - } - } - } - - .product-card-price { - margin-bottom: 10px; - - .old-price { - text-decoration: line-through; - font-size: 14px; - color: #999; - margin-right: 8px; - } - - .current-price { - font-size: 18px; - font-weight: bold; - color: @color-button; - } - } - - .add-to-cart-btn { - width: 100%; - padding: 8px; - font-size: 14px; - } - - .admin-actions { - display: flex; - gap: 5px; - margin-top: 10px; - - .admin-btn { - flex: 1; - font-size: 12px; - padding: 6px; - - &.delete-btn { - background: #dc3545; - - &:hover { - background: #c82333; - } - } - } - } -} - -// ======================= -// === ПРОФИЛЬ ПОЛЬЗОВАТЕЛЯ === -// ======================= - -.user-profile-dropdown { - position: relative; - display: inline-block; - - .user-profile-toggle { - display: flex; - align-items: center; - gap: 10px; - cursor: pointer; - padding: 8px 12px; - border-radius: 4px; - transition: all 0.3s ease; - - &:hover { - background-color: rgba(0, 0, 0, 0.05); - - .dropdown-arrow { - transform: rotate(180deg); - } - } - - .user-avatar { - width: 36px; - height: 36px; - border-radius: 50%; - background: linear-gradient(135deg, #617365 0%, #453227 100%); - color: @color-text-light; - .flex-center(); - font-weight: bold; - font-size: 16px; - box-shadow: 0 2px 5px rgba(0,0,0,0.2); - } - - .user-info { - display: flex; - flex-direction: column; - - .user-email { - font-size: 12px; - color: #666; - max-width: 120px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .user-status { - font-size: 10px; - padding: 2px 8px; - border-radius: 12px; - text-transform: uppercase; - font-weight: bold; - text-align: center; - margin-top: 2px; - - &.admin { - background-color: #617365; - color: white; - border: 1px solid #617365; - } - - &.user { - background-color: #28a745; - color: white; - border: 1px solid #28a745; - } - } - } - - .dropdown-arrow { - font-size: 10px; - color: #666; - transition: transform 0.3s ease; - } - } - - .user-profile-menu { - .menu-base(); - width: 280px; - top: 100%; - right: 0; - margin-top: 10px; - padding: 0; - overflow: hidden; - - .user-profile-header { - padding: 20px; - background: linear-gradient(135deg, #617365 0%, #453227 100%); - color: white; - - .user-profile-name { - font-weight: bold; - margin-bottom: 8px; - display: flex; - align-items: center; - gap: 10px; - font-size: 16px; - } - - .user-profile-details { - small { - display: block; - opacity: 0.8; - margin-bottom: 5px; - font-size: 11px; - - i { - margin-right: 5px; - width: 14px; - text-align: center; - } - } - } - } - - .user-profile-links { - list-style: none; - padding: 10px 0; - - li { - border-bottom: 1px solid #f0f0f0; - - &:last-child { - border-bottom: none; - } - - a { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 20px; - color: #333; - transition: all 0.3s ease; - - &:hover { - background-color: #f8f9fa; - color: @color-primary; - text-decoration: none; - - i { - transform: scale(1.1); - } - } - - i { - width: 20px; - text-align: center; - font-size: 14px; - color: #617365; - transition: transform 0.3s ease; - } - - span { - flex-grow: 1; - } - } - } - - .logout-item { - border-top: 2px solid #f0f0f0; - margin-top: 5px; - - a { - color: #dc3545; - - &:hover { - background-color: #ffe6e6; - color: #c82333; - - i { - color: #dc3545; - } - } - } - } - } - } - - &:hover .user-profile-menu { - display: block; - animation: fadeIn 0.3s ease; - } -} - -@keyframes fadeIn { - from { - opacity: 0; - transform: translateY(-10px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -// Для мобильных устройств -@media (max-width: 768px) { - .user-profile-dropdown { - .user-profile-toggle { - .user-info { - display: none; - } - - .dropdown-arrow { - display: none; - } - } - - .user-profile-menu { - width: 250px; - right: -50px; - } - } -} -// Добавьте в конец файла -.unavailable-product { - position: relative; - opacity: 0.6; - filter: grayscale(0.7); - - &::before { - content: "ТОВАР ЗАКОНЧИЛСЯ"; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background: rgba(0, 0, 0, 0.85); - color: white; - padding: 15px 25px; - border-radius: 5px; - font-weight: bold; - font-size: 16px; - text-align: center; - z-index: 100; - white-space: nowrap; - pointer-events: none; - box-shadow: 0 4px 12px rgba(0,0,0,0.3); - } - - .product-name-overlay { - .name, .price { - color: #999 !important; - text-shadow: none !important; - } - } - - .add-to-cart-btn { - display: none !important; - } - - &:hover { - transform: none !important; - cursor: not-allowed; - } -} - -.out-of-stock-badge { - position: absolute; - top: 10px; - left: 10px; - background: #6c757d; - color: white; - padding: 5px 10px; - border-radius: 4px; - font-size: 12px; - font-weight: bold; - z-index: 10; -} - -// Для админ-таблицы -.admin-table tr.unavailable { - background-color: #f8f9fa !important; - opacity: 0.7; - - td { - color: #999; - } -} - -.status-unavailable { - background-color: #6c757d !important; - color: white !important; -} \ No newline at end of file diff --git a/OLD_CODE/public/uploads/products/.gitkeep b/OLD_CODE/public/uploads/products/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/OLD_CODE/public/uploads/products/product_1765745390_2854.png b/OLD_CODE/public/uploads/products/product_1765745390_2854.png deleted file mode 100644 index 55ab5bb..0000000 Binary files a/OLD_CODE/public/uploads/products/product_1765745390_2854.png and /dev/null differ diff --git a/OLD_CODE/public/uploads/products/product_1765750758_4966.jpg b/OLD_CODE/public/uploads/products/product_1765750758_4966.jpg deleted file mode 100644 index e59b3b1..0000000 Binary files a/OLD_CODE/public/uploads/products/product_1765750758_4966.jpg and /dev/null differ diff --git a/OLD_CODE/public/warranty.php b/OLD_CODE/public/warranty.php deleted file mode 100644 index fb39d60..0000000 --- a/OLD_CODE/public/warranty.php +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - AETERNA - Гарантия - - - - - - - - - - - -
-
- - -
-

ГАРАНТИЙНЫЕ ОБЯЗАТЕЛЬСТВА

- -
-
-
- -
-

Мягкая мебель

-
18 месяцев
-
- -
-
- -
-

Корпусная мебель

-
24 месяца
-
- -
-
- -
-

Элементы освещения

-
12 месяцев
-
- -
-
- -
-

Фурнитура и механизмы

-
36 месяцев
-
-
- -
-
-

Что покрывается гарантией

-
-
- -
-

Производственные дефекты

-

Трещины, сколы, брак материалов

-
-
-
- -
-

Неисправности механизмов

-

Трансформации, выдвижные системы

-
-
-
- -
-

Проблемы с фурнитурой

-

Ручки, петли, направляющие

-
-
-
- -
-

Дефекты покрытия

-

Отслоение шпона, краски, ламинации

-
-
-
-
- -
-

Что не покрывается гарантией

-
-
- -
-

Механические повреждения

-

Царапины, вмятины от неправильной эксплуатации

-
-
-
- -
-

Следы износа

-

Естественное старение материалов

-
-
-
- -
-

Неправильная сборка

-

Последствия самостоятельного ремонта

-
-
-
- -
-

Внешние воздействия

-

Повреждения от жидкостей, солнечных лучей

-
-
-
-
-
-
-
-
- - - - - \ No newline at end of file diff --git a/OLD_CODE/public/стили_оформления.less b/OLD_CODE/public/стили_оформления.less deleted file mode 100644 index a6fe073..0000000 --- a/OLD_CODE/public/стили_оформления.less +++ /dev/null @@ -1,137 +0,0 @@ -.error-message { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; -} - -.form__input.error { - border-color: #ff0000; -} - -.form__group { - position: relative; - margin-bottom: 15px; -} - -.page-messages { - position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - z-index: 1000; - width: 90%; - max-width: 500px; -} - -.message { - padding: 15px; - margin: 10px 0; - border-radius: 5px; - text-align: center; - font-weight: bold; - display: none; -} - -.message.error { - background-color: #ffebee; - color: #c62828; - border: 1px solid #ffcdd2; -} - -.message.success { - background-color: #e8f5e9; - color: #453227; - border: 1px solid #c8e6c9; -} - -.message.warning { - background-color: #fff3e0; - color: #ef6c00; - border: 1px solid #ffe0b2; -} - -.privacy-error { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; - text-align: center; -} - -.input-group { - position: relative; - margin-bottom: 20px; -} - -.profile-form input.error { - border-color: #ff0000; - background-color: #fff5f5; -} - -.privacy-checkbox { - margin: 20px 0; - text-align: center; -} - -.privacy-checkbox label { - display: flex; - align-items: center; - justify-content: center; - gap: 8px; - cursor: pointer; - font-size: 14px; -} - -.privacy-checkbox input[type="checkbox"] { - margin: 0; -} - -.profile-page-main { - padding: 40px 0; - min-height: calc(100vh - 200px); -} - -.profile-container { - margin: 0 auto; - position: relative; - z-index: 1; -} - -.input-hint { - font-size: 12px; - color: #666; - margin-top: 5px; -} - -.form-options { - display: flex; - justify-content: space-between; - align-items: center; - margin: 20px 0; -} - -.remember-me { - display: flex; - align-items: center; - gap: 8px; - font-size: 14px; - color: #453227; -} - -.remember-me input[type="checkbox"] { - width: 16px; - height: 16px; - cursor: pointer; -} - -.forgot-password { - font-size: 14px; - color: #453227; - text-decoration: underline; -} - -.forgot-password:hover { - color: #617365; - text-decoration: none; -} \ No newline at end of file diff --git a/OLD_CODE/setup.sh b/OLD_CODE/setup.sh deleted file mode 100755 index 03cd61a..0000000 --- a/OLD_CODE/setup.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash -# -# AETERNA - Скрипт настройки проекта -# Запуск: ./setup.sh -# - -echo "===========================================" -echo " AETERNA - Настройка проекта" -echo "===========================================" -echo "" - -PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)" -cd "$PROJECT_DIR" - -# Проверяем наличие PHP -if ! command -v php &> /dev/null; then - echo "[ERROR] PHP не установлен!" - exit 1 -fi - -echo "[1/3] Проверка структуры проекта..." -REQUIRED_DIRS=("public" "admin" "api" "includes" "config" "migrations" "assets" "uploads") -for dir in "${REQUIRED_DIRS[@]}"; do - if [ ! -d "$dir" ]; then - mkdir -p "$dir" - echo " Создана папка: $dir" - fi -done -echo " ✓ Структура OK" - -echo "" -echo "[2/3] Запуск миграций базы данных..." -if [ -f "migrations/migrate.php" ]; then - php migrations/migrate.php -else - echo " ⚠ Файл миграций не найден" -fi - -echo "" -echo "[3/3] Загрузка начальных данных..." -echo " Загрузить тестовые данные (админ, категории, товары)? (y/n)" -read -r answer -if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then - php migrations/migrate.php --seed - echo " ✓ Данные загружены" -else - echo " Пропущено" -fi - -echo "" -echo "===========================================" -echo " Готово!" -echo "===========================================" -echo "" -echo "Тестовые аккаунты:" -echo " Админ: admin@aeterna.ru / admin123" -echo " Пользователь: user@test.com / user123" -echo "" -echo "Запуск сервера:" -echo " php -S localhost:8000 -t public" -echo "" diff --git a/OLD_CODE/style_for_cite.less b/OLD_CODE/style_for_cite.less deleted file mode 100644 index 3a52d85..0000000 --- a/OLD_CODE/style_for_cite.less +++ /dev/null @@ -1,3178 +0,0 @@ -@import "mixins.less"; -@import "стили_оформления.less"; -// ======================= -// === БАЗОВЫЕ СТИЛИ === -// ======================= -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -html, body { - height: 100%; -} - -html { - scroll-behavior: smooth; -} - -body { - font-family: @font-main; - background-color: @color-secondary; - color: @color-text-dark; - line-height: 1.6; - display: flex; - flex-direction: column; - min-height: 100vh; -} - -.container { - max-width: 1210px; - margin: 0 auto; - padding: 0 20px; -} - -ul { - list-style: none; -} - -a { - text-decoration: none; - color: inherit; - transition: all 0.3s ease; -} - -h1, h2, h3, h4, h5, h6 { - font-family: @font-heading; - margin: 0; -} - -p, li, span { - font-family: @font-main; -} - -// ======================= -// === КОМПОНЕНТЫ === -// ======================= - -.logo, .footer-logo { - font: bold 32px/1 @font-logo; - letter-spacing: 2px; - text-shadow: @shadow-dark; - flex-shrink: 0; -} - -.btn { - padding: 12px 30px; - border: none; - cursor: pointer; - font-size: 14px; - text-transform: uppercase; - transition: all 0.3s ease; - font-family: @font-main; - - &.primary-btn { - background-color: @color-button; - color: @color-text-light; - - &:hover { - background-color: lighten(@color-button, 10%); - transform: translateY(-2px); - box-shadow: @shadow-light; - } - } -} - -.number-circle { - .flex-center(); - width: 28px; - height: 28px; - border-radius: 50%; - background-color: @color-button; - color: @color-text-light; - font-size: 16px; - font-weight: bold; - flex-shrink: 0; -} - -.breadcrumbs { - font-size: 14px; - margin-bottom: 20px; - color: #666; - - a { - color: #666; - opacity: 0.7; - &:hover { opacity: 1; } - } - - .current-page { - font-weight: bold; - color: @color-text-dark; - } -} - -// ======================= -// === ШАПКА САЙТА === -// ======================= -.header { - background-color: @color-secondary; - border-bottom: 1px solid rgba(0, 0, 0, 0.05); - z-index: 1000; - - &__top, &__bottom { - padding: 15px 0; - .container { - .flex-between(); - gap: 20px; - } - } - - &__bottom { - padding: 10px 0; - border-top: 1px solid rgba(0, 0, 0, 0.05); - - .catalog-link.active-catalog { - background-color: rgba(0, 0, 0, 0.08); - pointer-events: none; - } - } - - .search-catalog { - .flex-center(); - border: 2px solid @color-text-dark; - background-color: #fff; - max-width: 600px; - width: 100%; - margin: 0 auto; - overflow: hidden; - - .catalog-dropdown { - position: relative; - background-color: #f8f8f8; - padding: 10px 15px 10px 25px; - font-size: 18px; - cursor: pointer; - border-right: 1px solid @color-text-dark; - .flex-center(10px); - width: 200px; - flex-shrink: 0; - - &__menu { - .menu-base(); - li { - padding: 8px 0; - cursor: pointer; - transition: color 0.3s; - border-bottom: 1px solid #f0f0f0; - &:last-child { border-bottom: none; } - &:hover { color: @color-accent; } - } - } - &:hover &__menu { display: block; } - } - - .search-box { - .flex-center(); - padding: 0 15px; - flex-grow: 1; - position: relative; - font-size: 15px; - - input { - border: none; - padding: 10px 30px 10px 0; - outline: none; - font-size: 16px; - width: 100%; - text-align: left; - } - - .search-icon { - font-size: 20px; - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; - } - }} - - &__icons--top { - .flex-center(15px); - flex-shrink: 0; - .icon { .icon-base(); font-size: 20px;} - } - - .nav-list { - .flex-center(30px); - font-size: 18px; - a { - text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); - &:hover { text-shadow: @shadow-dark; } - &.active { - border-bottom: 2px solid @color-button; - padding-bottom: 5px; - text-shadow: @shadow-dark; - } - &[href="#footer"] { - cursor: pointer; - } - } - } - - .catalog-link { - .flex-center(10px); - border-radius: 4px; - white-space: nowrap; - font-size: 18px; - padding: 10px 18px; - &:hover { background-color: rgba(0, 0, 0, 0.05); } - } - - .header-phone { - font-weight: bold; - color: @color-button; - flex-shrink: 0; - } -} - -// ======================= -// === ОСНОВНЫЕ СЕКЦИИ === -// ======================= -.hero { - padding: 15px 0; - - &__content { - .flex-center(50px); - min-height: 60vh; - align-items: center; - } - - &__image-block { - position: relative; - flex: 0 0 40%; - max-width: 600px; - height: 600px; - .flex-center(); - - .hero__circle { - position: absolute; - width: 450px; - height: 450px; - background-color: @color-primary; - border-radius: 50%; - z-index: 1; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - - .hero__img { - position: relative; - width: 100%; - height: 100%; - object-fit: contain; - z-index: 2; - } - } - - &__text-block { - flex: 0 0 60%; - padding-left: 50px; - - h1 { - font-size: 42px; - font-weight: normal; - margin-bottom: 25px; - line-height: 1.3; - } - - .hero__usp-text { - position: relative; - padding-left: 50px; - margin-bottom: 35px; - line-height: 1.7; - .flex-center(); - justify-content: flex-start; - min-height: 40px; - font-size: 16px; - - &::before { - content: "✓"; - position: absolute; - left: 0; - top: 50%; - transform: translateY(-50%); - width: 32px; - height: 32px; - border: 2px solid @color-button; - background-color: transparent; - color: @color-button; - border-radius: 50%; - .flex-center(); - font-size: 16px; - font-weight: bold; - } - } - - .btn.primary-btn { - margin: 25px 0 0 50px; - padding: 14px 35px; - font-size: 15px; - } - } -} - -.advantages { - padding: 30px 0 40px; - - &__header { - display: flex; - align-items: center; - gap: 50px; - margin-bottom: 40px; - h2 { - font-size: 32px; - font-weight: normal; - flex: 0 0 30%; - } - } - - &__items { - flex: 0 0 70%; - display: flex; - gap: 30px; - } - - .advantage-item { - flex: 1; - text-align: left; - position: relative; - padding-top: 30px; - - &__number { - .number-circle(); - position: absolute; - top: 0; - left: 0; - } - - h4 { - font-weight: 600; - margin-bottom: 10px; - } - } -} - -.promo-images { - display: flex; - gap: 20px; - margin-top: 50px; - - .promo-image-col { - position: relative; - overflow: hidden; - border-radius: 8px; - flex: 1; - transition: all 0.3s ease; - - &:hover { - transform: translateY(-5px); - box-shadow: @shadow-light; - .image-overlay-text { background-color: rgba(0, 0, 0, 0.6); } - img { transform: scale(1.05); } - .image-overlay-text h4, - .image-overlay-text .overlay-link { transform: translateY(0); } - } - - img { - width: 100%; - height: 350px; - object-fit: cover; - display: block; - transition: transform 0.5s ease; - } - - .image-overlay-text { - .image-overlay(); - h4 { - font-size: 24px; - text-transform: uppercase; - line-height: 1.2; - margin-bottom: 15px; - transform: translateY(20px); - transition: transform 0.3s ease; - } - } - - .overlay-link { - display: inline-block; - text-transform: uppercase; - font-weight: bold; - border-radius: 3px; - margin-top: 15px; - padding: 10px 25px; - background-color: @color-button; - color: @color-text-light; - font-size: 12px; - transform: translateY(20px); - transition: all 0.3s ease; - - &:hover { - background-color: lighten(@color-button, 10%); - transform: translateY(-2px); - box-shadow: @shadow-light; - } - } - } -} - -.about { - padding: 40px 0 80px; - - &__content { - display: flex; - align-items: flex-start; - gap: 50px; - } - - &__column { - display: flex; - flex-direction: column; - gap: 20px; - &--left { flex: 0 0 40%; margin-bottom: 30px; } - &--right { - flex: 0 0 60%; - .about__caption { - padding-right: 50px; - } - } - } - - &__text-block { - margin-bottom: 30px; - h2 { margin-bottom: 15px; } - } - - &__img { - width: 93%; - object-fit: cover; - display: block; - &--small { height: 300px; } - &--large { height: 450px; } - } - - .text-justified { - text-align: justify; - color: #555; - } -} - -.solutions { - padding: 0; - background-color: @color-secondary; - - &-slider { - position: relative; - width: 100%; - max-width: 1200px; - margin: 40px auto; - border-radius: 8px; - overflow: hidden; - - &__slides { - display: flex; - width: 200%; - height: 100%; - animation: slideLeftRight 10s infinite ease-in-out; - } - - &__slide { - width: 50%; - flex-shrink: 0; - position: relative; - overflow: hidden; - transition: transform 0.5s ease, box-shadow 0.5s ease; - - &:hover { - transform: scale(1.02); - box-shadow: 0 10px 25px rgba(0,0,0,0.3); - .solution-img { - transform: scale(1.05); - filter: brightness(0.8); - } - .solution-text-overlay { - opacity: 1; - transform: translateY(-5px); - } - .solution-image-link { - transform: translateX(-50%) translateY(-6px); - background-color: rgba(255,255,255,0.9); - color: @color-text-dark; - } - } - } - - .solution-img { - width: 100%; - height: auto; - object-fit: cover; - display: block; - } - - .solution-text-overlay { - position: absolute; - top: 15%; - left: 8%; - color: #493131; - text-shadow: 2px 2px 4px rgba(0,0,0,0.6); - z-index: 2; - opacity: 0.9; - transition: opacity 0.5s ease, transform 0.5s ease; - h2 { - font-size: 35px; - text-transform: uppercase; - margin-bottom: 10px; - } - p { - font-size: 25px; - text-transform: uppercase; - } - } - - .solution-image-link { - position: absolute; - bottom: 40px; - left: 50%; - transform: translateX(-50%); - padding: 12px 30px; - border: 2px solid @color-text-light; - color: #493131; - text-transform: uppercase; - font-size: 16px; - font-weight: bold; - background: transparent; - transition: 0.4s ease; - z-index: 2; - &:hover { - background: @color-text-light; - color: @color-text-dark; - transform: translateX(-50%) translateY(-2px); - } - } - } -} - -@keyframes slideLeftRight { - 0%, 40% { transform: translateX(0); } - 50%, 90% { transform: translateX(-50%); } - 100% { transform: translateX(0); } -} - -.stats { - padding: 0; - margin-top: 20px; - - .container { - display: flex; - justify-content: flex-end; - } - - &__items { - display: flex; - gap: 20px; - .stat-item { - text-align: left; - .stat-number { - font-size: 36px; - font-weight: bold; - color: @color-text-dark; - margin-bottom: 5px; - } - .stat-label { color: @color-text-dark; } - } - } -} - -.faq { - padding: 50px 0; - - h2 { - text-align: left; - font-size: 32px; - font-weight: normal; - margin-bottom: 40px; - } - - &__items { - display: flex; - flex-wrap: wrap; - gap: 40px 60px; - margin-bottom: 40px; - } - - .faq-item { - flex: 0 0 calc(50% - 30px); - .flex-center(15px); - align-items: flex-start; - &__content h4 { - font-weight: 600; - margin-bottom: 10px; - } - } - - .btn.primary-btn { - display: block; - width: 100%; - margin: 20px auto 80px; - } -} - -// ======================= -// === СТИЛИ КАТАЛОГА === -// ======================= -.catalog-main { - padding: 30px 0 60px; - background-color: lighten(@color-secondary, 5%); -} - -.catalog-wrapper { - display: flex; - gap: 20px; -} - -.catalog-sidebar { - flex: 0 0 250px; - background-color: #fff; - padding: 20px; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); - height: fit-content; -} - -.filter-group { - margin-bottom: 30px; -} - -.filter-title { - font-size: 16px; - font-weight: bold; - margin-bottom: 15px; - text-transform: uppercase; -} - -.filter-list li { - padding: 5px 0; - font-size: 16px; - a { - color: #555; - transition: color 0.2s; - &:hover { color: @color-accent; } - &.active-category { - font-weight: bold; - color: @color-primary; - } - } -} - -.price-range { - display: flex; - flex-direction: column; - gap: 15px; - width: 100%; - - .range-slider { - width: 100%; - - input[type="range"] { - -webkit-appearance: none; - appearance: none; - width: 100%; - height: 5px; - background: @color-primary; - border-radius: 5px; - outline: none; - margin: 0; - - &::-webkit-slider-thumb { - -webkit-appearance: none; - appearance: none; - width: 20px; - height: 20px; - background: @color-accent; - border: 2px solid #fff; - border-radius: 50%; - cursor: pointer; - box-shadow: 0 2px 4px rgba(0,0,0,0.2); - transition: all 0.3s ease; - - &:hover { - transform: scale(1.1); - background: lighten(@color-accent, 10%); - } - } - - &::-moz-range-thumb { - width: 20px; - height: 20px; - background: @color-accent; - border: 2px solid #fff; - border-radius: 50%; - cursor: pointer; - box-shadow: 0 2px 4px rgba(0,0,0,0.2); - transition: all 0.3s ease; - - &:hover { - transform: scale(1.1); - background: lighten(@color-accent, 10%); - } - } - } - } - - .price-display { - font-size: 14px; - font-weight: bold; - text-align: center; - color: @color-text-dark; - padding: 10px; - background: #f8f8f8; - border-radius: 4px; - } -} - -.filter-options { - list-style: none; - li { - display: flex; - align-items: center; - padding: 4px 0; - font-size: 14px; - } - label { - margin-left: 10px; - cursor: pointer; - color: #555; - } - input[type="checkbox"] { - width: 15px; - height: 15px; - cursor: pointer; - accent-color: @color-primary; - &:checked + label { - font-weight: bold; - color: @color-primary; - } - } -} - -.filter-apply-btn { - width: 100%; - margin-top: 20px; -} - -.catalog-products { - flex-grow: 1; -} - -.products-container { - display: flex; - flex-wrap: wrap; - gap: 20px; -} - -.product-card { - background-color: #fff; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); - display: flex; - flex-direction: column; - position: relative; - transition: transform 0.3s ease; - box-sizing: border-box; - - &:hover { - transform: translateY(-5px); - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); - .product-img { transform: scale(1.05); } - } -} - -.product-image-container { - position: relative; - overflow: hidden; - margin-bottom: 0; - padding: 0; - height: 250px; - .flex-center(); -} - -.product-img { - width: 100%; - height: 100%; - object-fit: contain; - display: block; - transition: transform 0.3s ease; - margin: 0; -} - -.product-img1 { - width: 100%; - height: 100%; - object-fit: cover; - display: block; - transition: transform 0.3s ease; - margin: 0; -} - -.product-discount { - position: absolute; - top: 10px; - right: 10px; - background-color: @color-button; - color: @color-text-light; - padding: 3px 8px; - font-size: 12px; - font-weight: bold; - z-index: 10; -} - -.product-wishlist-icon { - position: absolute; - top: 10px; - left: 10px; - color: #333; - font-size: 18px; - cursor: pointer; - transition: color 0.3s ease; - z-index: 10; - &:hover { color: @color-accent; } -} - -.product-name { - font-size: 16px; - font-weight: bold; - margin-bottom: 5px; -} - -.product-details { - font-size: 13px; - color: #777; - margin-bottom: 10px; - flex-grow: 1; -} - -.product-price { - font-size: 18px; - font-weight: bold; - color: @color-button; -} - -.product-card.small { flex: 0 0 300px; max-width: 300px; height: 200px; } -.product-card.small1 { flex: 0 0 320px; max-width: 320px; height: 250px;width: 320px; } -.product-card.large { flex: 0 0 580px; max-width: 580px; height: 380px; } -.product-card.wide { flex: 0 0 240px; max-width: 240px; height: 250px; } -.product-card.wide1 { flex: 0 0 350px; max-width: 350px; height: 250px; } -.product-card.wide2 { flex: 0 0 560px; max-width: 560px; height: 260px; } -.product-card.wide2_1 { flex: 0 0 560px; max-width: 560px; height: 260px; margin: -280px 0 0; } -.product-card.wide3 { - flex: 0 0 320px; max-width: 320px; height: 540px; - .product-image-container { height: 580px; } -} -.product-card.wide4 { - flex: 0 0 545px; max-width: 545px; margin: -270px 0 0; height: 250px; - .product-image-container { padding: 0; justify-content: flex-start; } - .product-img { margin-left: 0; align-self: flex-start; object-position: left center; } -} -.product-card.tall { flex: 0 0 300px; max-width: 300px; margin: -180px 0 0; height: 430px; } -.product-card.full-width { flex: 0 0 100%; margin: -20px 0 0; max-width: 900px; height: 300px;} - -.product-card.full-width { - flex: 0 0 100%; - max-width: 100%; - height: 300px; - - .product-image-container { - height: 100%; - padding: 0; - margin: 0; - - .product-img1 { - width: 100%; - height: 100%; - object-fit: cover; - margin: 0; - padding: 0; - } - } -} - -.product-card.tall .product-image-container, -.product-card.large .product-image-container { height: 430px; } - -// ======================= -// === СТРАНИЦА ТОВАРА === -// ======================= -.product__section { - display: flex; - gap: 0; - margin: 30px 0; -} - -.product__gallery, .product__info { - flex: 1; -} - -.product__main-image { - margin-bottom: 15px; -} - -.product__image { - width: 500px; - height: 300px; - border-radius: 4px; -} - -.product__thumbnails { - display: flex; - gap: 10px; -} - -.product__thumbnail { - border: none; - background: none; - cursor: pointer; - padding: 0; -} - -.product__thumbnail img { - width: 245px; - height: 150px; - object-fit: cover; - border-radius: 4px; -} - -.product__title { - font-size: 30px; - margin-bottom: 35px; -} - -.product__rating { - display: flex; - align-items: center; - gap: 10px; - margin-bottom: 30px; -} - -.product__color-selector { - display: flex; - gap: 10px; - margin-bottom: 40px; -} - -.product__color-option { - width: 45px; - height: 45px; - border-radius: 50%; - border: 2px solid transparent; - cursor: pointer; - transition: transform 0.3s ease; - - &:hover{ - transform: translateY(-2px); - } -} - -.product__color-option.active { - border-color: @color-primary; -} - -.product__description { - margin-bottom: 65px; - line-height: 1.5; -} - -.product__details-link { - display: inline-block; - margin-bottom: 20px; - color: @color-primary; - font-weight: bold; -} - -.product__purchase { - display: flex; - justify-content: space-between; - margin-bottom: 35px; -} - -.product__price { - font-size: 24px; - font-weight: bold; -} - -.product__quantity { - display: flex; - align-items: center; - gap: 10px; -} - -.product__qty-btn { - width: 30px; - height: 30px; - background: @color-button; - color: @color-text-light; - border: none; - border-radius: 50%; - cursor: pointer; - font-weight: bold; - transition: all 0.3s ease; - - &:hover { - background: lighten(@color-button, 10%); - transform: scale(1.1); - } -} - -.product__qty-value { - font-weight: bold; - min-width: 30px; - text-align: center; -} - -.product__actions { - display: flex; - gap: 15px; -} - -.product__btn { - flex: 1; - padding: 12px 20px; - border: none; - border-radius: 4px; - font-weight: bold; - cursor: pointer; - transition: all 0.3s ease; - - &:hover { - transform: translateY(-2px); - box-shadow: @shadow-light; - } -} - -.product__btn.primary { - background: @color-button; - color: @color-text-light; - - &:hover { - background: lighten(@color-button, 10%); - } -} - -.product__btn.secondary { - background: transparent; - border: 1px solid @color-button; - color: @color-button; - - &:hover { - background: @color-button; - color: @color-text-light; - } -} - -.similar { - margin: 60px 0; -} - -.similar__title { - margin-bottom: 30px; - font-size: 28px; - font-weight: bold; -} - -.similar__grid { - display: flex; - gap: 25px; - flex-wrap: wrap; - justify-content: space-between; -} - -.similar__card { - flex: 0 0 calc(33.333% - 17px); - min-width: 320px; - background: @color-secondary; - border-radius: 12px; - overflow: hidden; - transition: all 0.3s ease; - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); - - &:hover { - transform: translateY(-8px); - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); - } -} - -.similar__card-image { - height: 300px; - overflow: hidden; - background: white; - - img { - width: 100%; - height: 100%; - object-fit: contain; - transition: transform 0.3s ease; - - &:hover { - transform: scale(1.05); - } - } -} - -.similar__card-content { - padding: 25px; -} - -.similar__card-title { - font-weight: bold; - margin-bottom: 10px; - font-size: 20px; - color: @color-text-dark; -} - -.similar__card-description { - font-size: 15px; - margin-bottom: 15px; - color: #666; - line-height: 1.5; -} - -.similar__card-price { - font-weight: bold; - font-size: 22px; - color: @color-button; -} - -@media (max-width: 1024px) { - .similar { - &__card { - flex: 0 0 calc(50% - 13px); - min-width: 280px; - } - } -} - -@media (max-width: 768px) { - .similar { - &__grid { - justify-content: center; - } - - &__card { - flex: 0 0 100%; - max-width: 400px; - } - } -} - -// ======================= -// === КОРЗИНА И ЗАКАЗ === -// ======================= -.main__content { - display: flex; - gap: 40px; - margin: 30px 0; - - .products { - flex: 1; - } - - .order { - flex: 0 0 65%; - padding: 40px; - - &__header { - .flex-between(); - margin-bottom: 20px; - } - - &__title { - font-family: @font-logo; - font-size: 28px; - color: @color-text-dark; - margin: 0; - } - - &__total { - font-weight: bold; - color: @color-text-dark; - } - - &__section { - margin-bottom: 25px; - } - - &__section-title { - font-family: @font-logo; - margin-bottom: 15px; - font-size: 18px; - color: @color-text-dark; - } - } -} - -.products { - &__title { - font-family: @font-logo; - margin-bottom: 20px; - font-size: 24px; - color: @color-text-dark; - } - - &__list { - .flex-column(); - gap: 20px; - } - - &__item { - background-color: @color-secondary; - border-radius: 8px; - padding: 20px; - display: flex; - gap: 15px; - border: 1px solid @color-secondary; - transition: transform 0.3s ease; - align-items: flex-start; - position: relative; - - &:hover { - transform: translateY(-2px); - } - } - - &__image { - width: 300px; - height: 200px; - border-radius: 4px; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: flex-start; - } - - .product-img { - width: 100%; - height: 100%; - object-fit: cover; - display: block; - transition: transform 0.3s ease; - margin: 0; - } - - &__details { - flex: 1; - .flex-column(); - justify-content: space-between; - align-items: flex-start; - min-height: 200px; - } - - &__name { - font-weight: bold; - margin-bottom: 5px; - color: @color-accent; - font-size: 18px; - font-family: @font-main; - } - - &__price { - font-weight: bold; - font-size: 18px; - margin-bottom: 15px; - color: @color-text-dark; - } - - &__controls { - display: flex; - align-items: center; - gap: 15px; - margin-top: auto; - width: 100%; - justify-content: space-between; - } - - &__quantity { - display: flex; - align-items: center; - gap: 10px; - } - - &__qty-btn { - width: 30px; - height: 30px; - background-color: @color-text-dark; - color: @color-text-light; - border: none; - border-radius: 50%; - cursor: pointer; - .flex-center(); - font-family: @font-main; - font-weight: bold; - transition: all 0.3s ease; - - &:hover { - transform: scale(1.1); - } - } - - &__qty-value { - font-weight: bold; - min-width: 30px; - text-align: center; - font-size: 16px; - } - - &__cart-icon { - background-color: transparent; - color: @color-text-dark; - width: 40px; - height: 40px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: all 0.3s ease; - border: 2px solid @color-text-dark; - margin-left: 20px; - - &:hover { - transform: scale(1.1); - } - - i { font-size: 18px; } - } -} - -.form { - &__group { margin-bottom: 15px; } - &__label { - display: block; - margin-bottom: 5px; - font-weight: bold; - color: #000000; - } - &__input { - width: 100%; - padding: 14px 16px; - border: 2px solid #ccc; - font-family: @font-main; - font-size: 15px; - transition: border-color 0.3s ease; - - &:focus { - border-color: @color-primary; - } - - &:hover { - border-color: darken(#ccc, 10%); - } - &::placeholder { - font-style: italic; - color: #999; - } - } - &__row { - display: flex; - gap: 20px; - justify-content: space-between; - } - &__input--half { - width: 100%; - } - &__radio-group { - display: flex; - justify-content: space-between; - margin-bottom: 20px; - margin-top: 20px; - } - &__radio-label { - display: flex; - align-items: center; - cursor: pointer; - color: @color-text-dark; - position: relative; - padding-left: 30px; - flex: 1; - - &:hover { - .form__custom-radio { - border-color: lighten(@color-accent, 10%); - } - } - } - &__radio-input { - position: absolute; - opacity: 0; - cursor: pointer; - } - &__custom-radio { - position: absolute; - left: 0; - height: 20px; - width: 20px; - background-color: @color-secondary; - border: 2px solid @color-accent; - border-radius: 50%; - transition: border-color 0.3s ease; - } - &__radio-input:checked ~ &__custom-radio { - background-color: @color-accent; - - &:after { - content: ""; - position: absolute; - display: block; - top: 4px; - left: 4px; - width: 8px; - height: 8px; - border-radius: 50%; - background: white; - } - } -} - -.divider { - height: 1px; - background-color: #999; - margin: 20px 0; -} - -.promo { - display: flex; - margin-bottom: 20px; - - &__input { - flex: 1; - padding: 10px; - border: 1px solid #000; - background-color: @color-secondary; - font-family: @font-main; - height: auto; - min-height: 48px; - - &:hover { - border-color: @color-primary; - } - - &::placeholder { - font-style: italic; - color: #999; - } - } - - &__btn { - background-color: @color-accent; - color: @color-secondary; - border: none; - padding: 10px 60px; - cursor: pointer; - font-family: @font-main; - font-size: 18px; - transition: all 0.3s ease; - - &:hover { - background-color: lighten(@color-accent, 10%); - transform: translateY(-2px); - } - } -} - -.summary { - margin-bottom: 20px; - - &__item { - display: flex; - justify-content: space-between; - margin-bottom: 10px; - color: @color-text-dark; - - &.total { - font-weight: bold; - font-size: 18px; - padding-top: 10px; - margin-top: 10px; - } - } -} - -.order-btn { - width: 100%; - background-color: @color-accent; - color: @color-secondary; - border: none; - padding: 15px; - border-radius: 4px; - font-size: 18px; - cursor: pointer; - margin-bottom: 10px; - font-family: @font-main; - transition: all 0.3s ease; - - &:hover { - background-color: lighten(@color-accent, 10%); - transform: translateY(-2px); - } -} - -.privacy { - display: flex; - gap: 8px; - font-size: 16px; - color: #666; - margin-bottom: 20px; - - input[type="checkbox"] { - width: 18px; - height: 18px; - cursor: pointer; - } -} - -.services { - display: flex; - flex-direction: row; - justify-content: center; - flex-wrap: wrap; - gap: 24px; - margin-bottom: 24px; - - &__title { - font-family: @font-logo; - margin-bottom: 10px; - font-size: 18px; - color: @color-text-dark; - display: block; - width: 100%; - } - - &__item { - display: flex; - justify-content: space-between; - margin-bottom: 8px; - color: @color-text-dark; - width: 100%; - } -} - -.cart-icon { - position: relative; -} - -.cart-count { - position: absolute; - top: -8px; - right: -8px; - background: @color-accent; - color: @color-text-light; - border-radius: 50%; - width: 18px; - height: 18px; - font-size: 12px; - display: flex; - align-items: center; - justify-content: center; -} - -.form__input.error { - border-color: #ff4444; - box-shadow: 0 0 5px rgba(255, 68, 68, 0.3); -} - -.empty-cart { - text-align: center; - padding: 40px; - color: #666; - font-size: 18px; -} - -// ======================= -// === АВТОРИЗАЦИЯ === -// ======================= -.profile-page-main { - .flex-center(); - min-height: 80vh; - padding: 40px 0; - background-color: lighten(@color-secondary, 5%); - z-index: 1; - - .profile-container { - display: flex; - width: 100%; - max-width: 1000px; - min-height: 600px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); - background-color: @color-text-light; - } - - .profile-left-col { - flex: 0 0 35%; - background-color: @color-primary; - color: @color-text-light; - display: flex; - justify-content: flex-start; - align-items: flex-start; - padding: 40px; - .logo { - font-size: 32px; - font-weight: normal; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4); - color: @color-text-light; - } - } - - .profile-right-col { - flex: 0 0 65%; - .flex-center(); - padding: 40px; - .profile-form-block { - width: 100%; - max-width: 400px; - h2 { - font-size: 28px; - font-weight: normal; - margin-bottom: 40px; - text-align: left; - color: @color-text-dark; - } - } - } - - .profile-form { - .input-group { - margin-bottom: 20px; - label { - display: block; - font-size: 12px; - font-weight: bold; - color: @color-text-dark; - margin-bottom: 5px; - text-transform: uppercase; - } - } - - input[type="text"], - input[type="email"], - input[type="tel"] { - .input-base(); - } - - .password-link { - display: block; - text-align: left; - font-size: 13px; - color: @color-text-dark; - text-decoration: underline; - margin: 10px 0 20px; - &:hover { - color: @color-accent; - text-decoration: none; - } - } - - .save-btn { - padding: 15px 30px; - border: none; - cursor: pointer; - font-size: 15px; - text-transform: uppercase; - transition: all 0.3s ease; - font-family: @font-main; - width: 100%; - margin-top: 20px; - background-color: @color-primary; - color: @color-text-light; - - &:hover { - background-color: lighten(@color-primary, 10%); - transform: translateY(-2px); - box-shadow: @shadow-light; - } - } - - .auth-actions { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 25px; - padding-top: 20px; - border-top: 1px solid #eee; - - .auth-text { - font-size: 13px; - color: @color-text-dark; - } - - .login-btn { - background-color: transparent; - color: @color-accent; - border: 1px solid @color-accent; - padding: 10px 25px; - font-size: 13px; - cursor: pointer; - transition: all 0.3s ease; - - &:hover { - background-color: @color-primary; - color: @color-text-light; - } - } - } - } -} - -// ======================= -// === СЕКЦИЯ УСЛУГ === -// ======================= -.services-section { - padding: 60px 0; - background-color: @color-secondary; -} - -.services__wrapper { - display: flex; - flex-direction: column; - gap: 30px; -} - -.services__top-row { - display: flex; - gap: 30px; - justify-content: center; - - @media (max-width: 768px) { - flex-direction: column; - align-items: center; - } -} - -.service-card { - border-radius: 8px; - padding: 40px; - min-height: 200px; - text-align: center; - transition: all 0.3s ease; - - &:hover { - transform: translateY(-5px); - box-shadow: @shadow-light; - } - - &--green { - background: @color-primary; - color: @color-text-light; - flex: 1; - max-width: 450px; - } - - &--beige { - background: @color-beige; - color: @color-text-light; - width: 100%; - max-width: 930px; - margin: 0 auto; - } - - &__title { - font-family: @font-logo; - font-size: 24px; - font-weight: bold; - margin-bottom: 15px; - text-transform: uppercase; - } - - &__text { - font-family: @font-main; - font-size: 16px; - line-height: 1.6; - margin: 0; - } -} - -// ======================= -// === ФУТЕР === -// ======================= -.footer { - background-color: @color-primary; - color: black; - padding: 40px 0 10px; - position: relative; - z-index: 1000; - - &::before { - content: ''; - display: block; - position: absolute; - top: -80px; - left: 0; - width: 100%; - height: 1px; - visibility: hidden; - } - - &__content { - display: flex; - gap: 20px; - padding-bottom: 30px; - border-bottom: 1px solid rgba(255, 255, 255, 0.2); - } - - &__col { - flex: 1; - &--logo { flex: 1.5; } - h5 { - margin-bottom: 15px; - font-size: 14px; - text-transform: uppercase; - } - ul li { - margin-bottom: 8px; - a:hover { text-decoration: underline; } - } - .social-icons, - .payment-icons { - .flex-center(15px); - justify-content: flex-start; - margin-top: 10px; - } - .social-icons .icon { - .icon-base(20px, 1.1); - color: black; - &:hover { color: @color-accent; } - } - .payment-icons .pay-icon { - .icon-base(24px, 1.05); - color: black; - } - } - - .copyright { - text-align: center; - font-size: 12px; - padding-top: 20px; - color: rgba(255, 255, 255, 0.6); - } -} - -// ======================= -// === ДОСТАВКА === -// ======================= -.delivery-content { - max-width: 1200px; - margin: 0 auto; - padding: 40px 20px; -} - -.delivery-content h1 { - font-family: @font-logo; - font-size: 42px; - text-align: center; - margin-bottom: 50px; - color: #453227; -} - -.delivery-section { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 30px; - margin-bottom: 60px; -} - -.delivery-card { - background: white; - padding: 30px; - border-radius: 12px; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); - text-align: center; - transition: transform 0.3s ease; - flex: 1; - min-width: 350px; - max-width: 400px; -} - -.delivery-card:hover { - transform: translateY(-5px); -} - -.delivery-icon { - font-size: 48px; - color: #617365; - margin-bottom: 20px; -} - -.delivery-card h3 { - font-family: @font-logo; - font-size: 24px; - margin-bottom: 20px; - color: #453227; -} - -.delivery-details { - text-align: left; -} - -.detail-item { - display: flex; - justify-content: space-between; - margin-bottom: 12px; - padding-bottom: 12px; - border-bottom: 1px solid #f0f0f0; -} - -.detail-label { - font-weight: bold; - color: #333; -} - -.detail-value { - color: #617365; - text-align: right; -} - -// ======================= -// === ГАРАНТИЯ === -// ======================= -.warranty-content { - max-width: 1200px; - margin: 0 auto; - padding: 40px 20px; -} - -.warranty-content h1 { - font-family: 'Anek Kannada', sans-serif; - font-size: 42px; - text-align: center; - margin-bottom: 50px; - color: #453227; -} - -.warranty-overview { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 25px; - margin-bottom: 60px; -} - -.warranty-card { - background: white; - padding: 30px; - border-radius: 12px; - text-align: center; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); - transition: transform 0.3s ease; - flex: 1; - min-width: 250px; - max-width: 280px; - display: flex; - flex-direction: column; - align-items: center; -} - -.warranty-card:hover { - transform: translateY(-5px); -} - -.warranty-icon { - font-size: 48px; - color: #617365; - margin-bottom: 20px; -} - -.warranty-card h3 { - font-family: 'Anek Kannada', sans-serif; - font-size: 20px; - margin-bottom: 15px; - color: #453227; -} - -.warranty-period { - font-size: 24px; - font-weight: bold; - color: #617365; - margin-top: auto; -} - -.coverage-section { - display: flex; - flex-wrap: wrap; - gap: 40px; - margin-bottom: 60px; -} - -.coverage-covered, -.coverage-not-covered { - flex: 1; - min-width: 300px; -} - -.coverage-section h2 { - font-family: 'Anek Kannada', sans-serif; - font-size: 24px; - margin-bottom: 25px; - color: #453227; -} - -.coverage-list { - display: flex; - flex-direction: column; - gap: 20px; -} - -.coverage-item { - display: flex; - align-items: flex-start; - gap: 15px; - padding: 20px; - border-radius: 8px; - background: white; - box-shadow: 0 3px 10px rgba(0,0,0,0.1); -} - -.coverage-item.covered i { - color: #28a745; - font-size: 20px; - margin-top: 2px; - flex-shrink: 0; -} - -.coverage-item.not-covered i { - color: #dc3545; - font-size: 20px; - margin-top: 2px; - flex-shrink: 0; -} - -.coverage-text { - flex: 1; -} - -.coverage-item h4 { - font-family: 'Anek Kannada', sans-serif; - font-size: 16px; - margin-bottom: 5px; - color: #333; -} - -.card { - min-height: 250px; - display: flex; - align-items: center; - justify-content: center; - color: @color-text-light; - text-align: center; - - &--green { - background: @color-primary; - flex: 0 1 450px; - max-width: 450px; - } - - &--beige { - background: @color-beige; - color: @color-text-dark; - flex: 0 1 925px; - max-width: 925px; - } -} - -.design-section { - display: flex; - justify-content: center; - margin-bottom: 40px; - .card { width: 100%; } -} - -// ======================= -// === АДАПТИВНОСТЬ === -// ======================= -@media (max-width: 1240px) { - .catalog-wrapper { gap: 20px; } - .catalog-sidebar { flex: 0 0 200px; } - .products-container { - gap: 15px; - display: flex; - flex-wrap: wrap; - } - - .product-card.small1 { - margin-top: 100px; - } - - .product-card.small, - .product-card.small1, - .product-card.large, - .product-card.wide, - .product-card.wide1, - .product-card.wide2, - .product-card.wide2_1, - .product-card.wide4 { - flex: 0 0 calc(33.333% - 10px); - max-width: calc(33.333% - 10px); - height: 180px; - margin: 0; - - .product-image-container { - height: 180px; - } - } - - .product-card.wide3 { - flex: 0 0 calc(25% - 10px); - max-width: calc(25% - 10px); - height: 300px; - margin: 0; - - .product-image-container { - height: 350px; - } - } - - .product-card.tall { - flex: 0 0 calc(25% - 10px); - max-width: calc(25% - 10px); - height: 300px; - margin: 0; - - .product-image-container { - height: 300px; - } - } - - .product-card.full-width { - flex: 0 0 100%; - max-width: 100%; - height: 300px; - margin: 0; - - .product-image-container { - height: 300px; - } - } - - .product-card.small { order: 1; } - .product-card.large { order: 2; } - .product-card.wide { order: 3; } - - .product-card.small1 { order: 11; } - .product-card.wide2 { order: 12; } - .product-card.wide2_1 { order: 13; } - - .product-card.wide3 { order: 21; } - .product-card.tall { order: 22; } - - .product-card.wide3 { order: 31; } - - .product-card.full-width { order: 41; flex-basis: 100%; } - - .main__content { - gap: 20px; - .products { - flex: 0 0 35%; - .products__image { - width: 250px; - height: 180px; - } - } - .order { - flex: 0 0 60%; - padding: 30px; - - .order__title { - font-size: 24px; - } - - .order__section-title { - font-size: 16px; - } - } - } - - .solutions-slider { - &__slide { - .solution-text-overlay { - top: 10%; - left: 5%; - h2 { - font-size: 26px; - margin-bottom: 5px; - line-height: 1.2; - } - p { - font-size: 18px; - line-height: 1.2; - } - } - .solution-image-link { - bottom: 70px; - padding: 10px 25px; - font-size: 14px; - } - } - } - - .product__image { - width: 350px; - height: 250px; - } - - .product__thumbnail img { - width: 170px; - height: 120px; - } -} - -@media (max-width: 1024px) { - .main__content { - gap: 25px; - .products { - flex: 0 0 30%; - .products__image { - width: 200px; - height: 150px; - } - - .products__name { - font-size: 16px; - } - - .products__price { - font-size: 16px; - } - } - .order { - flex: 0 0 60%; - padding: 25px; - - .order__title { - font-size: 22px; - } - - .form__input { - padding: 12px 14px; - font-size: 14px; - } - - .promo__btn { - padding: 10px 40px; - font-size: 16px; - } - } - } -} - -@media (max-width: 768px) { - .container { padding: 0 15px; } - - .delivery-section { - flex-direction: column; - align-items: center; - } - - .delivery-card { - min-width: 100%; - max-width: 100%; - } - - .delivery-content h1 { - font-size: 32px; - } - - .warranty-overview { - flex-direction: column; - align-items: center; - } - - .warranty-card { - max-width: 100%; - width: 100%; - } - - .coverage-section { - flex-direction: column; - } - - .warranty-content h1 { - font-size: 32px; - } - - .header__top .container, - .header__bottom .container, - .hero__content, - .advantages__header, - .about__content, - .advantages__items, - .promo-images, - .stats__items, - .faq__items, - .catalog-wrapper, - .main__content { - flex-direction: column; - gap: 30px; - } - - .search-catalog { - order: 3; - width: 100%; - max-width: 100%; - } - - .nav-list { - flex-wrap: wrap; - justify-content: center; - gap: 15px; - } - - .hero { - &__image-block { - flex: none; - max-width: 400px; - height: 400px; - } - &__circle { - width: 380px; - height: 380px; - } - &__text-block { - flex: none; - padding-left: 0; - text-align: center; - h1 { font-size: 32px; } - .hero__usp-text { - padding-left: 0; - justify-content: center; - &::before { display: none; } - } - .btn.primary-btn { margin-left: 0; } - } - } - - .advantages__header h2, - .faq h2 { font-size: 28px; } - - .faq-item, - .stat-item { - flex: none; - .flex-center(); - text-align: center; - } - - .stats .container { justify-content: center; } - .catalog-dropdown__menu { width: 200px; } - - .catalog-sidebar { width: 100%; flex: none; } - .products-container { gap: 15px; } - - .product-card.small, - .product-card.small1, - .product-card.large, - .product-card.wide, - .product-card.wide1, - .product-card.wide2, - .product-card.wide2_1, - .product-card.wide3, - .product-card.wide4, - .product-card.tall, - .product-card.full-width { - flex: 0 0 100%; - max-width: 100%; - height: 250px; - margin: 0; - - .product-image-container { - height: 200px; - } - } - - .main__content { - flex-direction: column; - gap: 20px; - - .products, - .order { - flex: 0 0 100%; - width: 100%; - } - - .products { - .products__item { - flex-direction: column; - text-align: center; - gap: 15px; - } - - .products__image { - width: 100%; - height: 200px; - justify-content: center; - } - - .products__details { - min-height: auto; - align-items: center; - } - - .products__controls { - justify-content: center; - margin-top: 15px; - } - - .products__cart-icon { - margin-left: 0; - } - } - - .order { - padding: 20px; - - .order__title { - font-size: 20px; - text-align: center; - } - - .order__total { - text-align: center; - } - - .form__radio-group { - flex-direction: column; - gap: 15px; - } - - .form__radio-label { - flex: none; - justify-content: flex-start; - } - - .promo { - flex-direction: column; - gap: 10px; - - &__btn { - width: 100%; - padding: 12px; - } - } - - .order-btn { - padding: 12px; - font-size: 16px; - } - - .services { - flex-direction: column; - align-items: center; - } - } - } - - .product-image-container { height: 200px; } - .product-card.tall .product-image-container, - .product-card.large .product-image-container { height: 250px; } - - .profile-page-main { - .profile-container { - flex-direction: column; - min-height: auto; - max-width: 100%; - box-shadow: none; - } - .profile-left-col { - flex: none; - width: 100%; - height: 100px; - .flex-center(); - padding: 0; - } - .profile-right-col { - flex: none; - width: 100%; - padding: 30px 20px; - } - .profile-form-block { max-width: 100%; } - } - - .form__row { flex-direction: column; } - .form__input--half { flex: 0 0 100%; max-width: 100%; } - .services { flex-direction: column; align-items: center; } - - .services-section { - padding: 40px 0; - } - - .service-card { - padding: 30px 20px; - min-height: 180px; - - &--green, - &--beige { - max-width: 100%; - } - - &__title { - font-size: 20px; - } - - &__text { - font-size: 14px; - } - } - .solutions-slider { - margin: 20px auto; - &__slide { - .solution-text-overlay { - top: 8%; - left: 4%; - h2 { - font-size: 20px; - margin-bottom: 3px; - line-height: 1.1; - } - p { - font-size: 15px; - line-height: 1.1; - } - } - .solution-image-link { - bottom: 90px; - padding: 8px 20px; - font-size: 13px; - } - } - } -} - -// Стили для ошибок полей -.error-input { - border-color: #ff4444 !important; - box-shadow: 0 0 0 1px #ff4444; -} - -.field-error { - color: #ff4444; - font-size: 12px; - margin-top: 5px; - margin-bottom: 10px; -} - -// Стили для сообщений -.message { - padding: 15px; - margin: 20px 0; - border-radius: 5px; - display: none; -} - -.message.error { - background-color: #ffebee; - color: #c62828; - border: 1px solid #ffcdd2; -} - -.message.success { - background-color: #e8f5e9; - color: #2e7d32; - border: 1px solid #c8e6c9; -} - -// Добавьте в конец файла -.access-denied { - text-align: center; - padding: 80px 20px; - background: white; - border-radius: 10px; - box-shadow: 0 5px 15px rgba(0,0,0,0.1); - margin: 50px 0; - - h2 { - color: #dc3545; - margin-bottom: 30px; - font-size: 28px; - } - - p { - color: #666; - margin-bottom: 40px; - font-size: 18px; - line-height: 1.6; - } - - .btn { - margin: 5px; - min-width: 200px; - } -} -// ======================= -// === ПРОФИЛЬ ПОЛЬЗОВАТЕЛЯ === -// ======================= - -.user-profile-dropdown { - position: relative; - display: inline-block; - - &__toggle { - display: flex; - align-items: center; - gap: 8px; - cursor: pointer; - padding: 8px 12px; - border-radius: 4px; - transition: all 0.3s ease; - - &:hover { - background-color: rgba(0, 0, 0, 0.05); - } - - .user-avatar { - width: 32px; - height: 32px; - border-radius: 50%; - background-color: @color-primary; - color: @color-text-light; - .flex-center(); - font-weight: bold; - } - - .user-info { - display: flex; - flex-direction: column; - - .user-email { - font-size: 12px; - color: #666; - max-width: 150px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .user-status { - font-size: 10px; - padding: 2px 6px; - border-radius: 10px; - text-transform: uppercase; - - &.admin { - background-color: #617365; - color: white; - } - - &.user { - background-color: #28a745; - color: white; - } - } - } - } - - &__menu { - .menu-base(); - width: 220px; - top: 100%; - right: 0; - - .user-details { - padding: 15px; - border-bottom: 1px solid #eee; - - .user-name { - font-weight: bold; - margin-bottom: 5px; - } - - .user-registered { - font-size: 11px; - color: #999; - } - } - - ul { - padding: 10px 0; - - li { - padding: 8px 15px; - cursor: pointer; - display: flex; - align-items: center; - gap: 10px; - transition: background-color 0.3s ease; - - &:hover { - background-color: #f5f5f5; - } - - &.logout { - color: #dc3545; - border-top: 1px solid #eee; - margin-top: 5px; - padding-top: 12px; - - &:hover { - background-color: #ffe6e6; - } - } - } - } - } - - &:hover &__menu { - display: block; - } -} - -// ======================= -// === КАРТОЧКА ТОВАРА === -// ======================= - -.product-image-container { - position: relative; - overflow: hidden; - margin-bottom: 0; - padding: 0; - height: 250px; - .flex-center(); - - &:hover { - .product-overlay-info { - opacity: 1; - transform: translateY(0); - } - } -} - -.product-overlay-info { - position: absolute; - bottom: 0; - left: 0; - right: 0; - background: linear-gradient(to top, rgba(0,0,0,0.8), transparent); - color: white; - padding: 15px; - opacity: 0; - transform: translateY(10px); - transition: all 0.3s ease; - - .product-overlay-name { - font-weight: bold; - font-size: 14px; - margin-bottom: 5px; - } - - .product-overlay-price { - font-size: 16px; - font-weight: bold; - - .old-price { - text-decoration: line-through; - font-size: 12px; - color: #ccc; - margin-right: 5px; - } - - .current-price { - color: #ffd700; - } - } - - .product-overlay-category { - font-size: 11px; - opacity: 0.8; - margin-top: 3px; - } - - .product-overlay-stock { - font-size: 11px; - margin-top: 5px; - - &.out-of-stock { - color: #ff6b6b; - } - - i { - margin-right: 5px; - } - } -} - -.product-card-details { - padding: 15px; - background: white; - flex-grow: 1; - display: flex; - flex-direction: column; - - .product-card-name { - font-weight: bold; - font-size: 16px; - margin-bottom: 8px; - color: @color-text-dark; - } - - .product-card-description { - font-size: 13px; - color: #777; - margin-bottom: 10px; - flex-grow: 1; - } - - .product-card-attributes { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-bottom: 10px; - - .attribute { - font-size: 11px; - background: #f5f5f5; - padding: 3px 8px; - border-radius: 12px; - color: #666; - - i { - margin-right: 3px; - } - } - } - - .product-card-price { - margin-bottom: 10px; - - .old-price { - text-decoration: line-through; - font-size: 14px; - color: #999; - margin-right: 8px; - } - - .current-price { - font-size: 18px; - font-weight: bold; - color: @color-button; - } - } - - .add-to-cart-btn { - width: 100%; - padding: 8px; - font-size: 14px; - } - - .admin-actions { - display: flex; - gap: 5px; - margin-top: 10px; - - .admin-btn { - flex: 1; - font-size: 12px; - padding: 6px; - - &.delete-btn { - background: #dc3545; - - &:hover { - background: #c82333; - } - } - } - } -} - -// ======================= -// === ПРОФИЛЬ ПОЛЬЗОВАТЕЛЯ === -// ======================= - -.user-profile-dropdown { - position: relative; - display: inline-block; - - .user-profile-toggle { - display: flex; - align-items: center; - gap: 10px; - cursor: pointer; - padding: 8px 12px; - border-radius: 4px; - transition: all 0.3s ease; - - &:hover { - background-color: rgba(0, 0, 0, 0.05); - - .dropdown-arrow { - transform: rotate(180deg); - } - } - - .user-avatar { - width: 36px; - height: 36px; - border-radius: 50%; - background: linear-gradient(135deg, #617365 0%, #453227 100%); - color: @color-text-light; - .flex-center(); - font-weight: bold; - font-size: 16px; - box-shadow: 0 2px 5px rgba(0,0,0,0.2); - } - - .user-info { - display: flex; - flex-direction: column; - - .user-email { - font-size: 12px; - color: #666; - max-width: 120px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .user-status { - font-size: 10px; - padding: 2px 8px; - border-radius: 12px; - text-transform: uppercase; - font-weight: bold; - text-align: center; - margin-top: 2px; - - &.admin { - background-color: #617365; - color: white; - border: 1px solid #617365; - } - - &.user { - background-color: #28a745; - color: white; - border: 1px solid #28a745; - } - } - } - - .dropdown-arrow { - font-size: 10px; - color: #666; - transition: transform 0.3s ease; - } - } - - .user-profile-menu { - .menu-base(); - width: 280px; - top: 100%; - right: 0; - margin-top: 10px; - padding: 0; - overflow: hidden; - - .user-profile-header { - padding: 20px; - background: linear-gradient(135deg, #617365 0%, #453227 100%); - color: white; - - .user-profile-name { - font-weight: bold; - margin-bottom: 8px; - display: flex; - align-items: center; - gap: 10px; - font-size: 16px; - } - - .user-profile-details { - small { - display: block; - opacity: 0.8; - margin-bottom: 5px; - font-size: 11px; - - i { - margin-right: 5px; - width: 14px; - text-align: center; - } - } - } - } - - .user-profile-links { - list-style: none; - padding: 10px 0; - - li { - border-bottom: 1px solid #f0f0f0; - - &:last-child { - border-bottom: none; - } - - a { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 20px; - color: #333; - transition: all 0.3s ease; - - &:hover { - background-color: #f8f9fa; - color: @color-primary; - text-decoration: none; - - i { - transform: scale(1.1); - } - } - - i { - width: 20px; - text-align: center; - font-size: 14px; - color: #617365; - transition: transform 0.3s ease; - } - - span { - flex-grow: 1; - } - } - } - - .logout-item { - border-top: 2px solid #f0f0f0; - margin-top: 5px; - - a { - color: #dc3545; - - &:hover { - background-color: #ffe6e6; - color: #c82333; - - i { - color: #dc3545; - } - } - } - } - } - } - - &:hover .user-profile-menu { - display: block; - animation: fadeIn 0.3s ease; - } -} - -@keyframes fadeIn { - from { - opacity: 0; - transform: translateY(-10px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -// Для мобильных устройств -@media (max-width: 768px) { - .user-profile-dropdown { - .user-profile-toggle { - .user-info { - display: none; - } - - .dropdown-arrow { - display: none; - } - } - - .user-profile-menu { - width: 250px; - right: -50px; - } - } -} -// Добавьте в конец файла -.unavailable-product { - position: relative; - opacity: 0.6; - filter: grayscale(0.7); - - &::before { - content: "ТОВАР ЗАКОНЧИЛСЯ"; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background: rgba(0, 0, 0, 0.85); - color: white; - padding: 15px 25px; - border-radius: 5px; - font-weight: bold; - font-size: 16px; - text-align: center; - z-index: 100; - white-space: nowrap; - pointer-events: none; - box-shadow: 0 4px 12px rgba(0,0,0,0.3); - } - - .product-name-overlay { - .name, .price { - color: #999 !important; - text-shadow: none !important; - } - } - - .add-to-cart-btn { - display: none !important; - } - - &:hover { - transform: none !important; - cursor: not-allowed; - } -} - -.out-of-stock-badge { - position: absolute; - top: 10px; - left: 10px; - background: #6c757d; - color: white; - padding: 5px 10px; - border-radius: 4px; - font-size: 12px; - font-weight: bold; - z-index: 10; -} - -// Для админ-таблицы -.admin-table tr.unavailable { - background-color: #f8f9fa !important; - opacity: 0.7; - - td { - color: #999; - } -} - -.status-unavailable { - background-color: #6c757d !important; - color: white !important; -} \ No newline at end of file diff --git a/OLD_CODE/uploads/products/.gitkeep b/OLD_CODE/uploads/products/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/OLD_CODE/стили_оформления.less b/OLD_CODE/стили_оформления.less deleted file mode 100644 index a6fe073..0000000 --- a/OLD_CODE/стили_оформления.less +++ /dev/null @@ -1,137 +0,0 @@ -.error-message { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; -} - -.form__input.error { - border-color: #ff0000; -} - -.form__group { - position: relative; - margin-bottom: 15px; -} - -.page-messages { - position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - z-index: 1000; - width: 90%; - max-width: 500px; -} - -.message { - padding: 15px; - margin: 10px 0; - border-radius: 5px; - text-align: center; - font-weight: bold; - display: none; -} - -.message.error { - background-color: #ffebee; - color: #c62828; - border: 1px solid #ffcdd2; -} - -.message.success { - background-color: #e8f5e9; - color: #453227; - border: 1px solid #c8e6c9; -} - -.message.warning { - background-color: #fff3e0; - color: #ef6c00; - border: 1px solid #ffe0b2; -} - -.privacy-error { - color: #ff0000; - font-size: 12px; - margin-top: 5px; - display: none; - text-align: center; -} - -.input-group { - position: relative; - margin-bottom: 20px; -} - -.profile-form input.error { - border-color: #ff0000; - background-color: #fff5f5; -} - -.privacy-checkbox { - margin: 20px 0; - text-align: center; -} - -.privacy-checkbox label { - display: flex; - align-items: center; - justify-content: center; - gap: 8px; - cursor: pointer; - font-size: 14px; -} - -.privacy-checkbox input[type="checkbox"] { - margin: 0; -} - -.profile-page-main { - padding: 40px 0; - min-height: calc(100vh - 200px); -} - -.profile-container { - margin: 0 auto; - position: relative; - z-index: 1; -} - -.input-hint { - font-size: 12px; - color: #666; - margin-top: 5px; -} - -.form-options { - display: flex; - justify-content: space-between; - align-items: center; - margin: 20px 0; -} - -.remember-me { - display: flex; - align-items: center; - gap: 8px; - font-size: 14px; - color: #453227; -} - -.remember-me input[type="checkbox"] { - width: 16px; - height: 16px; - cursor: pointer; -} - -.forgot-password { - font-size: 14px; - color: #453227; - text-decoration: underline; -} - -.forgot-password:hover { - color: #617365; - text-decoration: none; -} \ No newline at end of file