Add .gitignore and project files
122
init_db.php
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
|
// Создаем таблицы, если они не существуют
|
||||||
|
$tables = [
|
||||||
|
'users' => "
|
||||||
|
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),
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
is_active BOOLEAN DEFAULT TRUE,
|
||||||
|
is_admin BOOLEAN DEFAULT FALSE
|
||||||
|
)
|
||||||
|
",
|
||||||
|
|
||||||
|
'categories' => "
|
||||||
|
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),
|
||||||
|
description TEXT,
|
||||||
|
sort_order INTEGER DEFAULT 0,
|
||||||
|
is_active BOOLEAN DEFAULT TRUE
|
||||||
|
)
|
||||||
|
",
|
||||||
|
|
||||||
|
'products' => "
|
||||||
|
CREATE TABLE IF NOT EXISTS products (
|
||||||
|
product_id SERIAL PRIMARY KEY,
|
||||||
|
category_id INTEGER REFERENCES categories(category_id),
|
||||||
|
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),
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)
|
||||||
|
"
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($tables_to_create as $table_name => $sql) {
|
||||||
|
try {
|
||||||
|
$db->exec($sql);
|
||||||
|
echo "Таблица '$table_name' создана/проверена<br>";
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo "Ошибка создания таблицы '$table_name': " . $e->getMessage() . "<br>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавляем тестовые данные
|
||||||
|
// Проверяем, есть ли уже категории
|
||||||
|
$check_categories = $db->query("SELECT COUNT(*) FROM categories")->fetchColumn();
|
||||||
|
|
||||||
|
if ($check_categories == 0) {
|
||||||
|
// Добавляем категории
|
||||||
|
$categories = [
|
||||||
|
['Мягкая мебель', 'myagkaya-mebel', NULL, 'Диваны, кресла, пуфы'],
|
||||||
|
['Диваны', 'divany', 1, 'Прямые и угловые диваны'],
|
||||||
|
['Кресла', 'kresla', 1, 'Кресла для гостиной и офиса'],
|
||||||
|
['Спальня', 'spalnya', NULL, 'Кровати, тумбы, комоды'],
|
||||||
|
['Кровати', 'krovati', 4, 'Односпальные и двуспальные кровати']
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($categories as $category) {
|
||||||
|
$stmt = $db->prepare("INSERT INTO categories (name, slug, parent_id, description) VALUES (?, ?, ?, ?)");
|
||||||
|
$stmt->execute($category);
|
||||||
|
}
|
||||||
|
echo "Добавлены категории<br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, есть ли уже товары
|
||||||
|
$check_products = $db->query("SELECT COUNT(*) FROM products")->fetchColumn();
|
||||||
|
|
||||||
|
if ($check_products == 0) {
|
||||||
|
// Добавляем товары
|
||||||
|
$products = [
|
||||||
|
[2, 'Диван VELVET', 'divan-velvet', 'Прямой диван с тканевой обивкой', 45999, 54999, 'DIV-VEL-001', 10],
|
||||||
|
[2, 'Диван MODERN', 'divan-modern', 'Угловой диван с кожаной обивкой', 78999, 89999, 'DIV-MOD-002', 5],
|
||||||
|
[3, 'Кресло OPPORTUNITY', 'kreslo-opportunity', 'Кресло с деревянными ножками', 16999, 19999, 'KRES-OPP-001', 15],
|
||||||
|
[3, 'Кресло GOLDEN', 'kreslo-golden', 'Золотистое кресло для гостиной', 19999, 23999, 'KRES-GOL-002', 8],
|
||||||
|
[5, 'Кровать CLASSIC', 'krovat-classic', 'Двуспальная кровать из массива дуба', 64999, 74999, 'KROV-CLA-001', 3]
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($products as $product) {
|
||||||
|
$stmt = $db->prepare("INSERT INTO products (category_id, name, slug, description, price, old_price, sku, stock_quantity)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
|
$stmt->execute($product);
|
||||||
|
}
|
||||||
|
echo "Добавлены товары<br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем, есть ли администратор
|
||||||
|
$check_admin = $db->prepare("SELECT COUNT(*) FROM users WHERE email = ?");
|
||||||
|
$check_admin->execute(['admin@aeterna.ru']);
|
||||||
|
|
||||||
|
if ($check_admin->fetchColumn() == 0) {
|
||||||
|
// Добавляем администратора (пароль: admin123)
|
||||||
|
$admin_password = password_hash('admin123', PASSWORD_DEFAULT);
|
||||||
|
$stmt = $db->prepare("INSERT INTO users (email, password_hash, full_name, phone, is_admin)
|
||||||
|
VALUES (?, ?, ?, ?, ?)");
|
||||||
|
$stmt->execute(['admin@aeterna.ru', $admin_password, 'Администратор AETERNA', '+79129991223', true]);
|
||||||
|
echo "Добавлен администратор (email: admin@aeterna.ru, пароль: admin123)<br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "<h3>База данных успешно инициализирована!</h3>";
|
||||||
|
echo "<a href='catalog.php'>Перейти в каталог</a>";
|
||||||
|
?>
|
||||||
49
.gitignore
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
116
add_to_cart.php
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
|
echo json_encode(['success' => 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' => 'Неверный запрос']);
|
||||||
|
}
|
||||||
|
?>
|
||||||
170
admin_actions.php
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
<?php
|
||||||
|
// admin_actions.php
|
||||||
|
session_start();
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
// Проверка прав администратора
|
||||||
|
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
|
||||||
|
header('Location: вход.php?error=admin_only');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = Database::getInstance()->getConnection();
|
||||||
|
$action = $_GET['action'] ?? '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch ($action) {
|
||||||
|
case 'delete_product':
|
||||||
|
if (isset($_GET['id'])) {
|
||||||
|
$productId = intval($_GET['id']);
|
||||||
|
// Делаем товар недоступным
|
||||||
|
$stmt = $db->prepare("
|
||||||
|
UPDATE products
|
||||||
|
SET is_available = FALSE, stock_quantity = 0, updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE product_id = ?
|
||||||
|
");
|
||||||
|
$stmt->execute([$productId]);
|
||||||
|
header('Location: admin_panel.php?action=products&message=Товар помечен как недоступный');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'restore_product':
|
||||||
|
if (isset($_GET['id'])) {
|
||||||
|
$productId = intval($_GET['id']);
|
||||||
|
// Восстанавливаем товар
|
||||||
|
$stmt = $db->prepare("
|
||||||
|
UPDATE products
|
||||||
|
SET is_available = TRUE, stock_quantity = 10, updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE product_id = ?
|
||||||
|
");
|
||||||
|
$stmt->execute([$productId]);
|
||||||
|
header('Location: admin_panel.php?action=products&message=Товар восстановлен');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete_category':
|
||||||
|
if (isset($_GET['id'])) {
|
||||||
|
$categoryId = intval($_GET['id']);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. Проверяем, есть ли товары в этой категории
|
||||||
|
$checkProducts = $db->prepare("SELECT COUNT(*) FROM products WHERE category_id = ?");
|
||||||
|
$checkProducts->execute([$categoryId]);
|
||||||
|
$productCount = $checkProducts->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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Проверяем, есть ли дочерние категории
|
||||||
|
$checkChildren = $db->prepare("SELECT COUNT(*) FROM categories WHERE parent_id = ?");
|
||||||
|
$checkChildren->execute([$categoryId]);
|
||||||
|
$childCount = $checkChildren->fetchColumn();
|
||||||
|
|
||||||
|
if ($childCount > 0) {
|
||||||
|
// Вариант A: Делаем категорию неактивной
|
||||||
|
$stmt = $db->prepare("UPDATE categories SET is_active = FALSE WHERE category_id = ?");
|
||||||
|
$stmt->execute([$categoryId]);
|
||||||
|
header('Location: admin_panel.php?action=categories&message=Категория скрыта (имеет дочерние категории)');
|
||||||
|
exit();
|
||||||
|
|
||||||
|
// Вариант B: Удаляем вместе с дочерними (раскомментируйте если нужно)
|
||||||
|
/*
|
||||||
|
// Сначала удаляем дочерние категории
|
||||||
|
$stmt = $db->prepare("DELETE FROM categories WHERE parent_id = ?");
|
||||||
|
$stmt->execute([$categoryId]);
|
||||||
|
|
||||||
|
// Затем удаляем саму категорию
|
||||||
|
$stmt = $db->prepare("DELETE FROM categories WHERE category_id = ?");
|
||||||
|
$stmt->execute([$categoryId]);
|
||||||
|
|
||||||
|
header('Location: admin_panel.php?action=categories&message=Категория и её дочерние категории удалены');
|
||||||
|
exit();
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Если нет товаров и дочерних категорий, удаляем
|
||||||
|
$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=categories&error=' . urlencode($e->getMessage()));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete_category_force':
|
||||||
|
// Принудительное удаление с дочерними категориями
|
||||||
|
if (isset($_GET['id'])) {
|
||||||
|
$categoryId = intval($_GET['id']);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Сначала перемещаем товары в другую категорию (например, в первую)
|
||||||
|
$firstCategory = $db->query("SELECT category_id FROM categories WHERE category_id != ? LIMIT 1")->fetchColumn();
|
||||||
|
|
||||||
|
if ($firstCategory) {
|
||||||
|
$moveProducts = $db->prepare("UPDATE products SET category_id = ? WHERE category_id = ?");
|
||||||
|
$moveProducts->execute([$firstCategory, $categoryId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обнуляем parent_id у дочерних категорий
|
||||||
|
$stmt = $db->prepare("UPDATE categories SET parent_id = NULL WHERE parent_id = ?");
|
||||||
|
$stmt->execute([$categoryId]);
|
||||||
|
|
||||||
|
// Удаляем категорию
|
||||||
|
$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=categories&error=' . urlencode($e->getMessage()));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'toggle_user':
|
||||||
|
if (isset($_GET['id'])) {
|
||||||
|
$userId = intval($_GET['id']);
|
||||||
|
$stmt = $db->prepare("
|
||||||
|
UPDATE users
|
||||||
|
SET is_active = NOT is_active, updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE user_id = ?
|
||||||
|
");
|
||||||
|
$stmt->execute([$userId]);
|
||||||
|
header('Location: admin_panel.php?action=users&message=Статус пользователя изменен');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'make_admin':
|
||||||
|
if (isset($_GET['id'])) {
|
||||||
|
$userId = intval($_GET['id']);
|
||||||
|
$stmt = $db->prepare("UPDATE users SET is_admin = TRUE WHERE user_id = ?");
|
||||||
|
$stmt->execute([$userId]);
|
||||||
|
header('Location: admin_panel.php?action=users&message=Пользователь назначен администратором');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
header('Location: admin_panel.php?error=' . urlencode($e->getMessage()));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если действие не распознано
|
||||||
|
header('Location: admin_panel.php');
|
||||||
|
exit();
|
||||||
|
?>
|
||||||
772
admin_panel.php
Normal file
@@ -0,0 +1,772 @@
|
|||||||
|
<?php
|
||||||
|
// admin_panel.php - ПОЛНОСТЬЮ ИСПРАВЛЕННАЯ ВЕРСИЯ
|
||||||
|
session_start();
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
// Включаем отладку ошибок
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
ini_set('display_errors', 1);
|
||||||
|
|
||||||
|
if (empty($allCategories)) {
|
||||||
|
echo '<div class="alert alert-warning">Сначала добавьте категории!</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверка прав администратора
|
||||||
|
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
|
||||||
|
echo "<script>alert('Требуется авторизация администратора'); window.location.href = 'вход.php';</script>";
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
|
// Обработка действий
|
||||||
|
$action = $_GET['action'] ?? 'dashboard';
|
||||||
|
$message = $_GET['message'] ?? '';
|
||||||
|
$error = $_GET['error'] ?? '';
|
||||||
|
|
||||||
|
// Обработка POST запросов - ДОБАВЛЕНО ПРОСТОЕ И РАБОТАЮЩЕЕ!
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ИСПРАВЬТЕ БЛОК edit_category или добавьте его если его нет:
|
||||||
|
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');
|
||||||
|
|
||||||
|
|
||||||
|
// ВАЖНО: Проверяем category_id
|
||||||
|
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');
|
||||||
|
|
||||||
|
// Генерируем SKU если пустой
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ИСПРАВЛЕННЫЙ КОД для edit_product в admin_panel.php:
|
||||||
|
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); // ПО УМОЛЧАНИЮ 1, чтобы избежать 0
|
||||||
|
$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'] ?? '');
|
||||||
|
|
||||||
|
// ВАЖНО: Проверяем category_id
|
||||||
|
if ($category_id <= 0) {
|
||||||
|
// Если 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']);
|
||||||
|
|
||||||
|
// 1. Проверяем, есть ли товары в этой категории
|
||||||
|
$checkProducts = $db->prepare("SELECT COUNT(*) FROM products WHERE category_id = ?");
|
||||||
|
$checkProducts->execute([$categoryId]);
|
||||||
|
$productCount = $checkProducts->fetchColumn();
|
||||||
|
|
||||||
|
// 2. Проверяем, есть ли дочерние категории
|
||||||
|
$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();
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>AETERNA - Админ-панель</title>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial, sans-serif; margin: 0; padding: 0; background: #f5f5f5; }
|
||||||
|
.admin-header { background: #453227; color: white; padding: 20px; display: flex; justify-content: space-between; align-items: center; }
|
||||||
|
.admin-tabs { background: white; padding: 10px; border-bottom: 2px solid #453227; display: flex; gap: 10px; }
|
||||||
|
.admin-tab { padding: 10px 20px; border-radius: 5px; text-decoration: none; color: #333; }
|
||||||
|
.admin-tab:hover, .admin-tab.active { background: #453227; color: white; }
|
||||||
|
.admin-content { padding: 20px; }
|
||||||
|
.form-container { background: white; padding: 20px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); max-width: 800px; margin: 0 auto; }
|
||||||
|
.form-group { margin-bottom: 15px; }
|
||||||
|
.form-group label { display: block; margin-bottom: 5px; font-weight: bold; }
|
||||||
|
.form-control { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; }
|
||||||
|
.btn { padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; text-decoration: none; display: inline-block; }
|
||||||
|
.btn-primary { background: #453227; color: white; }
|
||||||
|
.btn-success { background: #28a745; color: white; }
|
||||||
|
.btn-danger { background: #dc3545; color: white; }
|
||||||
|
.btn-warning { background: #ffc107; color: #333; }
|
||||||
|
.alert { padding: 15px; border-radius: 4px; margin-bottom: 20px; }
|
||||||
|
.alert-success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
|
||||||
|
.alert-danger { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
|
||||||
|
table { width: 100%; border-collapse: collapse; background: white; }
|
||||||
|
th, td { padding: 10px; border: 1px solid #ddd; text-align: left; }
|
||||||
|
th { background: #f8f9fa; }
|
||||||
|
.action-buttons { display: flex; gap: 5px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="admin-header">
|
||||||
|
<h1><i class="fas fa-user-shield"></i> Админ-панель AETERNA</h1>
|
||||||
|
<div>
|
||||||
|
<span><?= htmlspecialchars($_SESSION['user_email'] ?? 'Администратор') ?></span>
|
||||||
|
<a href="catalog.php" class="btn btn-primary" style="margin-left: 10px;">В каталог</a>
|
||||||
|
<a href="logout.php" class="btn btn-danger" style="margin-left: 10px;">Выйти</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="admin-tabs">
|
||||||
|
<a href="?action=dashboard" class="admin-tab <?= $action == 'dashboard' ? 'active' : '' ?>">
|
||||||
|
<i class="fas fa-tachometer-alt"></i> Дашборд
|
||||||
|
</a>
|
||||||
|
<a href="?action=products" class="admin-tab <?= $action == 'products' ? 'active' : '' ?>">
|
||||||
|
<i class="fas fa-box"></i> Товары
|
||||||
|
</a>
|
||||||
|
<a href="?action=categories" class="admin-tab <?= $action == 'categories' ? 'active' : '' ?>">
|
||||||
|
<i class="fas fa-tags"></i> Категории
|
||||||
|
</a>
|
||||||
|
<a href="?action=orders" class="admin-tab <?= $action == 'orders' ? 'active' : '' ?>">
|
||||||
|
<i class="fas fa-shopping-cart"></i> Заказы
|
||||||
|
</a>
|
||||||
|
<a href="?action=users" class="admin-tab <?= $action == 'users' ? 'active' : '' ?>">
|
||||||
|
<i class="fas fa-users"></i> Пользователи
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="admin-content">
|
||||||
|
<?php if ($message): ?>
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<i class="fas fa-check-circle"></i> <?= htmlspecialchars(urldecode($message)) ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<i class="fas fa-exclamation-circle"></i> <?= htmlspecialchars(urldecode($error)) ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($action == 'dashboard'): ?>
|
||||||
|
<!-- Дашборд -->
|
||||||
|
<h2>Статистика</h2>
|
||||||
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin: 20px 0;">
|
||||||
|
<div style="background: white; padding: 20px; border-radius: 5px; text-align: center;">
|
||||||
|
<h3><?= $stats['total_products'] ?></h3>
|
||||||
|
<p>Всего товаров</p>
|
||||||
|
</div>
|
||||||
|
<div style="background: white; padding: 20px; border-radius: 5px; text-align: center;">
|
||||||
|
<h3><?= $stats['active_products'] ?></h3>
|
||||||
|
<p>Активных товаров</p>
|
||||||
|
</div>
|
||||||
|
<div style="background: white; padding: 20px; border-radius: 5px; text-align: center;">
|
||||||
|
<h3><?= $stats['total_orders'] ?></h3>
|
||||||
|
<p>Заказов</p>
|
||||||
|
</div>
|
||||||
|
<div style="background: white; padding: 20px; border-radius: 5px; text-align: center;">
|
||||||
|
<h3><?= $stats['total_users'] ?></h3>
|
||||||
|
<p>Пользователей</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="text-align: center; margin: 40px 0;">
|
||||||
|
<a href="?action=add_product" class="btn btn-success" style="padding: 15px 30px; font-size: 16px;">
|
||||||
|
<i class="fas fa-plus"></i> Добавить новый товар
|
||||||
|
</a>
|
||||||
|
<a href="?action=add_category" class="btn btn-primary" style="padding: 15px 30px; font-size: 16px;">
|
||||||
|
<i class="fas fa-plus"></i> Добавить категорию
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php elseif ($action == 'products'): ?>
|
||||||
|
<!-- Товары -->
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||||||
|
<h2>Управление товарами</h2>
|
||||||
|
<div>
|
||||||
|
<a href="?action=add_product" class="btn btn-success">
|
||||||
|
<i class="fas fa-plus"></i> Добавить товар
|
||||||
|
</a>
|
||||||
|
<?php if (isset($_GET['show_all'])): ?>
|
||||||
|
<a href="?action=products" class="btn btn-primary">Только активные</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<a href="?action=products&show_all=1" class="btn btn-primary">Показать все</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Название</th>
|
||||||
|
<th>Категория</th>
|
||||||
|
<th>Цена</th>
|
||||||
|
<th>На складе</th>
|
||||||
|
<th>Статус</th>
|
||||||
|
<th>Действия</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($data as $product): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?= $product['product_id'] ?></td>
|
||||||
|
<td><?= htmlspecialchars($product['name']) ?></td>
|
||||||
|
<td><?= htmlspecialchars($product['category_name'] ?? 'Без категории') ?></td>
|
||||||
|
<td><?= number_format($product['price'], 0, '', ' ') ?> ₽</td>
|
||||||
|
<td><?= $product['stock_quantity'] ?></td>
|
||||||
|
<td>
|
||||||
|
<?php if ($product['is_available'] && $product['stock_quantity'] > 0): ?>
|
||||||
|
<span style="color: green;">✓ Доступен</span>
|
||||||
|
<?php elseif (!$product['is_available']): ?>
|
||||||
|
<span style="color: red;">✗ Недоступен</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span style="color: orange;">⚠ Нет на складе</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td class="action-buttons">
|
||||||
|
<a href="?action=edit_product&id=<?= $product['product_id'] ?>" class="btn btn-warning btn-sm">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</a>
|
||||||
|
<?php if ($product['is_available']): ?>
|
||||||
|
<form method="POST" style="display: inline;">
|
||||||
|
<input type="hidden" name="action" value="edit_product">
|
||||||
|
<input type="hidden" name="product_id" value="<?= $product['product_id'] ?>">
|
||||||
|
<input type="hidden" name="is_available" value="0">
|
||||||
|
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Сделать недоступным?')">
|
||||||
|
<i class="fas fa-times"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<?php else: ?>
|
||||||
|
<form method="POST" style="display: inline;">
|
||||||
|
<input type="hidden" name="action" value="edit_product">
|
||||||
|
<input type="hidden" name="product_id" value="<?= $product['product_id'] ?>">
|
||||||
|
<input type="hidden" name="is_available" value="1">
|
||||||
|
<button type="submit" class="btn btn-success btn-sm" onclick="return confirm('Сделать доступным?')">
|
||||||
|
<i class="fas fa-check"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?php elseif ($action == 'categories'): ?>
|
||||||
|
<!-- Категории -->
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||||||
|
<h2>Управление категориями</h2>
|
||||||
|
<a href="?action=add_category" class="btn btn-success">
|
||||||
|
<i class="fas fa-plus"></i> Добавить категорию
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Название</th>
|
||||||
|
<th>Slug</th>
|
||||||
|
<th>Родительская</th>
|
||||||
|
<th>Товаров</th>
|
||||||
|
<th>Действия</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($data as $category): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?= $category['category_id'] ?></td>
|
||||||
|
<td><?= htmlspecialchars($category['name']) ?></td>
|
||||||
|
<td><?= htmlspecialchars($category['slug']) ?></td>
|
||||||
|
<td><?= htmlspecialchars($category['parent_name'] ?? '—') ?></td>
|
||||||
|
<td><?= $category['product_count'] ?></td>
|
||||||
|
<td class="action-buttons">
|
||||||
|
<!-- Кнопка редактирования -->
|
||||||
|
<a href="?action=edit_category&id=<?= $category['category_id'] ?>" class="btn btn-warning btn-sm">
|
||||||
|
<i class="fas fa-edit"></i> Редактировать
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Кнопка удаления с AJAX -->
|
||||||
|
<button type="button" class="btn btn-danger btn-sm delete-category-btn"
|
||||||
|
data-id="<?= $category['category_id'] ?>"
|
||||||
|
<?= $category['product_count'] > 0 ? 'disabled' : '' ?>>
|
||||||
|
<i class="fas fa-trash"></i> Удалить
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?php elseif (in_array($action, ['add_category', 'edit_category'])): ?>
|
||||||
|
<!-- Форма добавления/редактирования категории -->
|
||||||
|
<div class="form-container">
|
||||||
|
<h2><?= $action == 'add_category' ? 'Добавление категории' : 'Редактирование категории' ?></h2>
|
||||||
|
|
||||||
|
<form method="POST" action="fix_edit_category.php" id="categoryForm">
|
||||||
|
<input type="hidden" name="action" value="<?= $action == 'edit_category' ? 'edit_category' : 'add_category' ?>">
|
||||||
|
|
||||||
|
<?php if (isset($edit_data)): ?>
|
||||||
|
<input type="hidden" name="category_id" value="<?= $edit_data['category_id'] ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Название категории *</label>
|
||||||
|
<input type="text" name="name" class="form-control"
|
||||||
|
value="<?= htmlspecialchars($edit_data['name'] ?? '') ?>" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Родительская категория</label>
|
||||||
|
<select name="parent_id" class="form-control">
|
||||||
|
<option value="">Без родительской категории</option>
|
||||||
|
<?php foreach ($parentCategories as $cat): ?>
|
||||||
|
<?php if (!isset($edit_data['category_id']) || $cat['category_id'] != $edit_data['category_id']): ?>
|
||||||
|
<option value="<?= $cat['category_id'] ?>"
|
||||||
|
<?= (isset($edit_data['parent_id']) && $edit_data['parent_id'] == $cat['category_id']) ? 'selected' : '' ?>>
|
||||||
|
<?= htmlspecialchars($cat['name']) ?>
|
||||||
|
</option>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Описание</label>
|
||||||
|
<textarea name="description" class="form-control" rows="3"><?= htmlspecialchars($edit_data['description'] ?? '') ?></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Порядок сортировки</label>
|
||||||
|
<input type="number" name="sort_order" class="form-control" min="0" max="100"
|
||||||
|
value="<?= $edit_data['sort_order'] ?? 0 ?>">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="is_active" value="1"
|
||||||
|
<?= (!isset($edit_data['is_active']) || $edit_data['is_active']) ? 'checked' : '' ?>>
|
||||||
|
Активна
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
<?= $action == 'add_category' ? 'Добавить категорию' : 'Сохранить изменения' ?>
|
||||||
|
</button>
|
||||||
|
<a href="?action=categories" class="btn">Отмена</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php elseif (in_array($action, ['add_category', 'edit_category'])): ?>
|
||||||
|
<!-- Форма добавления/редактирования категории -->
|
||||||
|
<div class="form-container">
|
||||||
|
<h2><?= $action == 'add_category' ? 'Добавление категории' : 'Редактирование категории' ?></h2>
|
||||||
|
|
||||||
|
<form method="POST">
|
||||||
|
<input type="hidden" name="action" value="<?= $action == 'edit_category' ? 'edit_category' : 'add_category' ?>">
|
||||||
|
<?php if (isset($edit_data)): ?>
|
||||||
|
<input type="hidden" name="category_id" value="<?= $edit_data['category_id'] ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Название категории *</label>
|
||||||
|
<input type="text" name="name" class="form-control"
|
||||||
|
value="<?= htmlspecialchars($edit_data['name'] ?? '') ?>" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Родительская категория</label>
|
||||||
|
<select name="parent_id" class="form-control">
|
||||||
|
<option value="">Без родительской категории</option>
|
||||||
|
<?php foreach ($parentCategories as $cat): ?>
|
||||||
|
<?php if (!isset($edit_data['category_id']) || $cat['category_id'] != $edit_data['category_id']): ?>
|
||||||
|
<option value="<?= $cat['category_id'] ?>"
|
||||||
|
<?= (isset($edit_data['parent_id']) && $edit_data['parent_id'] == $cat['category_id']) ? 'selected' : '' ?>>
|
||||||
|
<?= htmlspecialchars($cat['name']) ?>
|
||||||
|
</option>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Описание</label>
|
||||||
|
<textarea name="description" class="form-control" rows="3"><?= htmlspecialchars($edit_data['description'] ?? '') ?></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Порядок сортировки</label>
|
||||||
|
<input type="number" name="sort_order" class="form-control" min="0" max="100"
|
||||||
|
value="<?= $edit_data['sort_order'] ?? 0 ?>">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="is_active" value="1"
|
||||||
|
<?= (!isset($edit_data['is_active']) || $edit_data['is_active']) ? 'checked' : '' ?>>
|
||||||
|
Активна
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
<?= $action == 'add_category' ? 'Добавить категорию' : 'Сохранить изменения' ?>
|
||||||
|
</button>
|
||||||
|
<a href="?action=categories" class="btn">Отмена</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php elseif ($action == 'orders'): ?>
|
||||||
|
<!-- Заказы -->
|
||||||
|
<h2>Заказы</h2>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>№ заказа</th>
|
||||||
|
<th>Клиент</th>
|
||||||
|
<th>Сумма</th>
|
||||||
|
<th>Статус</th>
|
||||||
|
<th>Дата</th>
|
||||||
|
<th>Действия</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($data as $order): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?= htmlspecialchars($order['order_number']) ?></td>
|
||||||
|
<td><?= htmlspecialchars($order['customer_name']) ?></td>
|
||||||
|
<td><?= number_format($order['final_amount'], 0, '', ' ') ?> ₽</td>
|
||||||
|
<td><?= htmlspecialchars($order['status']) ?></td>
|
||||||
|
<td><?= date('d.m.Y H:i', strtotime($order['created_at'])) ?></td>
|
||||||
|
<td>
|
||||||
|
<a href="?action=order_details&id=<?= $order['order_id'] ?>" class="btn btn-primary btn-sm">
|
||||||
|
<i class="fas fa-eye"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?php elseif ($action == 'users'): ?>
|
||||||
|
<!-- Пользователи -->
|
||||||
|
<h2>Пользователи</h2>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>ФИО</th>
|
||||||
|
<th>Дата регистрации</th>
|
||||||
|
<th>Статус</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($data as $user): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?= $user['user_id'] ?></td>
|
||||||
|
<td><?= htmlspecialchars($user['email']) ?></td>
|
||||||
|
<td><?= htmlspecialchars($user['full_name']) ?></td>
|
||||||
|
<td><?= date('d.m.Y', strtotime($user['created_at'])) ?></td>
|
||||||
|
<td>
|
||||||
|
<?php if ($user['is_active']): ?>
|
||||||
|
<span style="color: green;">✓ Активен</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span style="color: red;">✗ Неактивен</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
// Удаление категории через AJAX
|
||||||
|
$('.delete-category-btn').click(function() {
|
||||||
|
const categoryId = $(this).data('id');
|
||||||
|
const btn = $(this);
|
||||||
|
|
||||||
|
if (confirm('Удалить эту категорию?')) {
|
||||||
|
$.ajax({
|
||||||
|
url: 'fix_delete_category.php',
|
||||||
|
method: 'POST',
|
||||||
|
data: { category_id: categoryId },
|
||||||
|
success: function(response) {
|
||||||
|
const result = JSON.parse(response);
|
||||||
|
if (result.success) {
|
||||||
|
alert(result.message);
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
alert('Ошибка: ' + result.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Обработка формы категории
|
||||||
|
$('#categoryForm').submit(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: $(this).attr('action'),
|
||||||
|
method: 'POST',
|
||||||
|
data: $(this).serialize(),
|
||||||
|
success: function(response) {
|
||||||
|
const result = JSON.parse(response);
|
||||||
|
if (result.success) {
|
||||||
|
alert(result.message);
|
||||||
|
window.location.href = 'admin_panel.php?action=categories';
|
||||||
|
} else {
|
||||||
|
alert('Ошибка: ' + result.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1382
catalog.php
Normal file
924
catalog_admin.php
Normal file
@@ -0,0 +1,924 @@
|
|||||||
|
<?php
|
||||||
|
// catalog_admin.php - единый файл каталога с админ-панелью
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// Подключение к базе данных
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
// Проверка прав администратора
|
||||||
|
$is_admin = isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
||||||
|
$action = $_GET['action'] ?? '';
|
||||||
|
$product_id = $_GET['id'] ?? 0;
|
||||||
|
$category_id = $_GET['category'] ?? '';
|
||||||
|
|
||||||
|
// Если не админ, перенаправляем
|
||||||
|
if (!$is_admin) {
|
||||||
|
header('Location: вход.php');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
|
// ОБРАБОТКА POST ЗАПРОСОВ ДЛЯ КАТЕГОРИЙ
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $is_admin) {
|
||||||
|
$form_action = $_POST['action'] ?? '';
|
||||||
|
|
||||||
|
if ($form_action === 'add_category' || $form_action === 'edit_category') {
|
||||||
|
$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;
|
||||||
|
$category_id_post = (int)($_POST['category_id'] ?? 0);
|
||||||
|
|
||||||
|
// Валидация
|
||||||
|
if (empty($name)) {
|
||||||
|
$_SESSION['error'] = 'Название категории обязательно';
|
||||||
|
header('Location: catalog_admin.php?action=' . $form_action . ($category_id_post ? '&id=' . $category_id_post : ''));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Создаем slug
|
||||||
|
$slug = strtolower(preg_replace('/[^a-z0-9]+/i', '-', $name));
|
||||||
|
$slug = preg_replace('/^-+|-+$/', '', $slug); // Убираем дефисы по краям
|
||||||
|
|
||||||
|
if ($form_action === 'add_category') {
|
||||||
|
// Проверяем существование slug
|
||||||
|
$check = $db->prepare("SELECT COUNT(*) FROM categories WHERE slug = ?");
|
||||||
|
$check->execute([$slug]);
|
||||||
|
if ($check->fetchColumn() > 0) {
|
||||||
|
$slug = $slug . '-' . time(); // Добавляем timestamp для уникальности
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = "INSERT INTO categories (name, slug, parent_id, description, sort_order, is_active)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?)";
|
||||||
|
$stmt = $db->prepare($sql);
|
||||||
|
$stmt->execute([$name, $slug, $parent_id, $description, $sort_order, $is_active]);
|
||||||
|
|
||||||
|
$_SESSION['message'] = 'Категория успешно добавлена';
|
||||||
|
header('Location: catalog_admin.php?action=categories');
|
||||||
|
exit();
|
||||||
|
|
||||||
|
} elseif ($form_action === 'edit_category' && $category_id_post > 0) {
|
||||||
|
// Проверяем существование slug для других категорий
|
||||||
|
$check = $db->prepare("SELECT COUNT(*) FROM categories WHERE slug = ? AND category_id != ?");
|
||||||
|
$check->execute([$slug, $category_id_post]);
|
||||||
|
if ($check->fetchColumn() > 0) {
|
||||||
|
$slug = $slug . '-' . $category_id_post;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = "UPDATE categories SET
|
||||||
|
name = ?, slug = ?, parent_id = ?, description = ?,
|
||||||
|
sort_order = ?, is_active = ?, updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE category_id = ?";
|
||||||
|
$stmt = $db->prepare($sql);
|
||||||
|
$stmt->execute([$name, $slug, $parent_id, $description, $sort_order, $is_active, $category_id_post]);
|
||||||
|
|
||||||
|
$_SESSION['message'] = 'Категория успешно обновлена';
|
||||||
|
header('Location: catalog_admin.php?action=categories');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Удаление категории
|
||||||
|
if ($form_action === 'delete_category') {
|
||||||
|
$category_id_del = (int)($_POST['category_id'] ?? 0);
|
||||||
|
|
||||||
|
if ($category_id_del > 0) {
|
||||||
|
// Проверяем наличие активных товаров
|
||||||
|
$check_products = $db->prepare("
|
||||||
|
SELECT COUNT(*) as product_count
|
||||||
|
FROM products
|
||||||
|
WHERE category_id = ? AND is_available = TRUE
|
||||||
|
");
|
||||||
|
$check_products->execute([$category_id_del]);
|
||||||
|
$active_products = $check_products->fetchColumn();
|
||||||
|
|
||||||
|
if ($active_products > 0) {
|
||||||
|
$_SESSION['error'] = 'Невозможно удалить категорию с активными товарами';
|
||||||
|
header('Location: catalog_admin.php?action=categories');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем дочерние категории
|
||||||
|
$check_children = $db->prepare("
|
||||||
|
SELECT COUNT(*) as child_count
|
||||||
|
FROM categories
|
||||||
|
WHERE parent_id = ? AND is_active = TRUE
|
||||||
|
");
|
||||||
|
$check_children->execute([$category_id_del]);
|
||||||
|
$active_children = $check_children->fetchColumn();
|
||||||
|
|
||||||
|
if ($active_children > 0) {
|
||||||
|
$_SESSION['error'] = 'Невозможно удалить категорию с активными дочерними категориями';
|
||||||
|
header('Location: catalog_admin.php?action=categories');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Удаляем категорию
|
||||||
|
$stmt = $db->prepare("DELETE FROM categories WHERE category_id = ?");
|
||||||
|
$stmt->execute([$category_id_del]);
|
||||||
|
|
||||||
|
$_SESSION['message'] = 'Категория успешно удалена';
|
||||||
|
header('Location: catalog_admin.php?action=categories');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем категории для отображения
|
||||||
|
$categories_stmt = $db->query("
|
||||||
|
SELECT c1.*, c2.name as parent_name,
|
||||||
|
(SELECT COUNT(*) FROM products WHERE 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
|
||||||
|
");
|
||||||
|
$categories = $categories_stmt->fetchAll();
|
||||||
|
|
||||||
|
// Для редактирования категории
|
||||||
|
if ($action === 'edit_category' && $product_id > 0) {
|
||||||
|
$cat_stmt = $db->prepare("SELECT * FROM categories WHERE category_id = ?");
|
||||||
|
$cat_stmt->execute([$product_id]);
|
||||||
|
$current_category = $cat_stmt->fetch();
|
||||||
|
|
||||||
|
if (!$current_category) {
|
||||||
|
$_SESSION['error'] = 'Категория не найдена';
|
||||||
|
header('Location: catalog_admin.php?action=categories');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем товары
|
||||||
|
$sql = "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";
|
||||||
|
|
||||||
|
$params = [];
|
||||||
|
if ($category_id && is_numeric($category_id)) {
|
||||||
|
$sql .= " AND p.category_id = ?";
|
||||||
|
$params[] = $category_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql .= " ORDER BY p.product_id DESC";
|
||||||
|
|
||||||
|
if ($params) {
|
||||||
|
$stmt = $db->prepare($sql);
|
||||||
|
$stmt->execute($params);
|
||||||
|
} else {
|
||||||
|
$stmt = $db->query($sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
$products = $stmt->fetchAll();
|
||||||
|
|
||||||
|
// Сообщения из сессии
|
||||||
|
$message = $_SESSION['message'] ?? '';
|
||||||
|
$error = $_SESSION['error'] ?? '';
|
||||||
|
|
||||||
|
// Очищаем сообщения после использования
|
||||||
|
unset($_SESSION['message']);
|
||||||
|
unset($_SESSION['error']);
|
||||||
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$error = "Ошибка подключения к базе данных: " . $e->getMessage();
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>AETERNA - Каталог</title>
|
||||||
|
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/less"></script>
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||||
|
<style>
|
||||||
|
.admin-panel {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
border-radius: 8px;
|
||||||
|
border-left: 4px solid #617365;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-btn {
|
||||||
|
background: #617365;
|
||||||
|
color: white;
|
||||||
|
padding: 8px 15px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 5px;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-btn:hover {
|
||||||
|
background: #453227;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-form {
|
||||||
|
background: white;
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input, .form-group textarea, .form-group select {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: "Anonymous Pro", monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group textarea {
|
||||||
|
min-height: 100px;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input[type="checkbox"] {
|
||||||
|
width: auto;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
padding: 15px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-success {
|
||||||
|
background: #d4edda;
|
||||||
|
color: #155724;
|
||||||
|
border: 1px solid #c3e6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-danger {
|
||||||
|
background: #f8d7da;
|
||||||
|
color: #721c24;
|
||||||
|
border: 1px solid #f5c6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
padding: 3px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-warning {
|
||||||
|
background: #ffc107;
|
||||||
|
color: #212529;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-info {
|
||||||
|
background: #17a2b8;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-success {
|
||||||
|
background: #28a745;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-danger {
|
||||||
|
background: #dc3545;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
padding: 8px 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-sm {
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-warning {
|
||||||
|
background: #ffc107;
|
||||||
|
color: #212529;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-danger {
|
||||||
|
background: #dc3545;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background: #6c757d;
|
||||||
|
color: white;
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-success {
|
||||||
|
background: #28a745;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-table th,
|
||||||
|
.admin-table td {
|
||||||
|
padding: 12px 15px;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-table th {
|
||||||
|
background: #f8f9fa;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #453227;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-table tr:hover {
|
||||||
|
background: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-dropdown {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-dropdown__menu {
|
||||||
|
display: none;
|
||||||
|
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;
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-dropdown:hover .catalog-dropdown__menu {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-dropdown__menu ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-dropdown__menu li {
|
||||||
|
padding: 8px 0;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-dropdown__menu li:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-dropdown__menu a {
|
||||||
|
color: #333;
|
||||||
|
text-decoration: none;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-dropdown__menu a:hover {
|
||||||
|
color: #453227;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header class="header">
|
||||||
|
<div class="header__top">
|
||||||
|
<div class="container header__top-content">
|
||||||
|
<div class="logo">AETERNA</div>
|
||||||
|
<div class="search-catalog">
|
||||||
|
<div class="catalog-dropdown">
|
||||||
|
Все категории <span>▼</span>
|
||||||
|
<div class="catalog-dropdown__menu">
|
||||||
|
<ul>
|
||||||
|
<li><a href="catalog_admin.php">Все товары</a></li>
|
||||||
|
<?php foreach ($categories as $cat): ?>
|
||||||
|
<li><a href="catalog_admin.php?category=<?= $cat['category_id'] ?>">
|
||||||
|
<?= htmlspecialchars($cat['name']) ?>
|
||||||
|
</a></li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="search-box">
|
||||||
|
<input type="text" placeholder="Поиск товаров">
|
||||||
|
<span class="search-icon"><i class="fas fa-search"></i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="header__icons--top">
|
||||||
|
<a href="оформление_заказа.php" class="icon cart-icon">
|
||||||
|
<i class="fas fa-shopping-cart"></i>
|
||||||
|
<span class="cart-count">0</span>
|
||||||
|
</a>
|
||||||
|
<?php if ($is_admin): ?>
|
||||||
|
<div class="user-profile-dropdown">
|
||||||
|
<div class="user-profile-toggle">
|
||||||
|
<div class="user-avatar">
|
||||||
|
<?= strtoupper(substr($_SESSION['user_email'] ?? 'A', 0, 1)) ?>
|
||||||
|
</div>
|
||||||
|
<div class="user-info">
|
||||||
|
<div class="user-email"><?= htmlspecialchars($_SESSION['user_email'] ?? '') ?></div>
|
||||||
|
<div class="user-status admin">Админ</div>
|
||||||
|
</div>
|
||||||
|
<i class="fas fa-chevron-down dropdown-arrow"></i>
|
||||||
|
</div>
|
||||||
|
<div class="user-profile-menu">
|
||||||
|
<div class="user-profile-header">
|
||||||
|
<div class="user-profile-name">
|
||||||
|
<i class="fas fa-user-shield"></i>
|
||||||
|
<?= htmlspecialchars($_SESSION['full_name'] ?? $_SESSION['user_email']) ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ul class="user-profile-links">
|
||||||
|
<li><a href="logout.php" class="logout-link">
|
||||||
|
<i class="fas fa-sign-out-alt"></i>
|
||||||
|
<span>Выйти</span>
|
||||||
|
</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="header__bottom">
|
||||||
|
<div class="container header__bottom-content">
|
||||||
|
<div class="catalog-menu">
|
||||||
|
<a href="catalog_admin.php" class="catalog-link active-catalog">
|
||||||
|
<div class="catalog-icon">
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="line"></span>
|
||||||
|
</div>
|
||||||
|
<span class="catalog-lines">☰</span>
|
||||||
|
Каталог
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<nav class="nav">
|
||||||
|
<ul class="nav-list">
|
||||||
|
<li><a href="cite_mebel.php">Главная</a></li>
|
||||||
|
<li><a href="услуги.php">Услуги</a></li>
|
||||||
|
<li><a href="Доставка.php">Доставка и оплата</a></li>
|
||||||
|
<li><a href="Гарантия.php">Гарантия</a></li>
|
||||||
|
<li><a href="#footer">Контакты</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<div class="header-phone">+7(912)999-12-23</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="catalog-main">
|
||||||
|
<div class="container">
|
||||||
|
<div class="breadcrumbs">
|
||||||
|
<a href="cite_mebel.php">Главная</a> • <span class="current-page">Каталог</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ($is_admin): ?>
|
||||||
|
<!-- Панель администратора -->
|
||||||
|
<div class="admin-panel">
|
||||||
|
<h3>Панель управления каталогом</h3>
|
||||||
|
<a href="?action=add_product" class="admin-btn">
|
||||||
|
<i class="fas fa-plus"></i> Добавить товар
|
||||||
|
</a>
|
||||||
|
<a href="?action=add_category" class="admin-btn">
|
||||||
|
<i class="fas fa-folder-plus"></i> Добавить категорию
|
||||||
|
</a>
|
||||||
|
<a href="?action=categories" class="admin-btn" style="background: #ffc107; color: #212529;">
|
||||||
|
<i class="fas fa-tags"></i> Управление категориями
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ($message): ?>
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<i class="fas fa-check-circle"></i> <?= htmlspecialchars($message) ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<i class="fas fa-exclamation-circle"></i> <?= htmlspecialchars($error) ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($action === 'add_category' || $action === 'edit_category'): ?>
|
||||||
|
<!-- Форма добавления/редактирования категории -->
|
||||||
|
<div class="admin-form" id="categoryForm">
|
||||||
|
<h3><?= ($action === 'add_category') ? 'Добавление категории' : 'Редактирование категории' ?></h3>
|
||||||
|
|
||||||
|
<?php if (isset($error) && !empty($error)): ?>
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<i class="fas fa-exclamation-circle"></i> <?= htmlspecialchars($error) ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<form method="POST" action="catalog_admin.php" id="categoryFormElement">
|
||||||
|
<input type="hidden" name="action" value="<?= $action ?>">
|
||||||
|
<?php if ($action === 'edit_category' && isset($current_category)): ?>
|
||||||
|
<input type="hidden" name="category_id" value="<?= $current_category['category_id'] ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="category_name">Название категории: *</label>
|
||||||
|
<input type="text" name="name" id="category_name" required
|
||||||
|
value="<?= htmlspecialchars($current_category['name'] ?? '') ?>"
|
||||||
|
placeholder="Введите название категории">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="parent_category">Родительская категория:</label>
|
||||||
|
<select name="parent_id" id="parent_category">
|
||||||
|
<option value="">Без родительской категории</option>
|
||||||
|
<?php foreach ($categories as $cat): ?>
|
||||||
|
<?php if (!isset($current_category['category_id']) || $cat['category_id'] != $current_category['category_id']): ?>
|
||||||
|
<option value="<?= $cat['category_id'] ?>"
|
||||||
|
<?= (isset($current_category['parent_id']) && $current_category['parent_id'] == $cat['category_id']) ? 'selected' : '' ?>>
|
||||||
|
<?= htmlspecialchars($cat['name']) ?>
|
||||||
|
</option>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="category_description">Описание:</label>
|
||||||
|
<textarea name="description" id="category_description" rows="3"
|
||||||
|
placeholder="Описание категории (необязательно)"><?= htmlspecialchars($current_category['description'] ?? '') ?></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="sort_order">Порядок сортировки:</label>
|
||||||
|
<input type="number" name="sort_order" id="sort_order"
|
||||||
|
value="<?= $current_category['sort_order'] ?? 0 ?>"
|
||||||
|
min="0" max="100">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="is_active" value="1"
|
||||||
|
<?= (!isset($current_category['is_active']) || $current_category['is_active']) ? 'checked' : '' ?>>
|
||||||
|
Активна
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="admin-btn">
|
||||||
|
<i class="fas fa-save"></i> Сохранить
|
||||||
|
</button>
|
||||||
|
<a href="catalog_admin.php?action=categories" class="admin-btn" style="background: #6c757d;">
|
||||||
|
<i class="fas fa-times"></i> Отмена
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="catalog-wrapper">
|
||||||
|
<aside class="catalog-sidebar">
|
||||||
|
<div class="filter-group">
|
||||||
|
<h4 class="filter-title">КАТЕГОРИИ</h4>
|
||||||
|
<ul class="filter-list">
|
||||||
|
<li><a href="catalog_admin.php" class="<?= (!$category_id) ? 'active-category' : '' ?>">Все товары</a></li>
|
||||||
|
<?php foreach ($categories as $cat): ?>
|
||||||
|
<li>
|
||||||
|
<a href="catalog_admin.php?category=<?= $cat['category_id'] ?>"
|
||||||
|
class="<?= ($category_id == $cat['category_id']) ? 'active-category' : '' ?>">
|
||||||
|
<?= htmlspecialchars($cat['name']) ?>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="filter-group">
|
||||||
|
<h4 class="filter-title">ЦЕНА</h4>
|
||||||
|
<div class="price-range">
|
||||||
|
<div class="range-slider">
|
||||||
|
<input type="range" min="1000" max="100000" value="50000" step="1000">
|
||||||
|
</div>
|
||||||
|
<div class="price-display">До 50 000 ₽</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn primary-btn filter-apply-btn">ПРИМЕНИТЬ</button>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<section class="catalog-products">
|
||||||
|
<?php if ($action === 'categories'): ?>
|
||||||
|
<!-- Раздел управления категориями -->
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||||||
|
<h2>Управление категориями</h2>
|
||||||
|
<a href="?action=add_category" class="btn btn-success">
|
||||||
|
<i class="fas fa-plus"></i> Добавить категорию
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="admin-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Название</th>
|
||||||
|
<th>Родительская</th>
|
||||||
|
<th>Товаров</th>
|
||||||
|
<th>Порядок</th>
|
||||||
|
<th>Статус</th>
|
||||||
|
<th>Действия</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ($categories as $cat): ?>
|
||||||
|
<tr>
|
||||||
|
<td><?= $cat['category_id'] ?></td>
|
||||||
|
<td>
|
||||||
|
<strong><?= htmlspecialchars($cat['name']) ?></strong>
|
||||||
|
<br><small style="color: #666;"><?= htmlspecialchars($cat['slug']) ?></small>
|
||||||
|
</td>
|
||||||
|
<td><?= htmlspecialchars($cat['parent_name'] ?? '—') ?></td>
|
||||||
|
<td>
|
||||||
|
<span class="badge badge-info"><?= $cat['product_count'] ?> товаров</span>
|
||||||
|
</td>
|
||||||
|
<td><?= $cat['sort_order'] ?></td>
|
||||||
|
<td>
|
||||||
|
<?php if ($cat['is_active']): ?>
|
||||||
|
<span class="badge badge-success">Активна</span>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="badge badge-warning">Неактивна</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="?action=edit_category&id=<?= $cat['category_id'] ?>"
|
||||||
|
class="btn btn-sm btn-warning" title="Редактировать">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<form method="POST" action="catalog_admin.php" style="display: inline-block;"
|
||||||
|
onsubmit="return confirm('Вы уверены, что хотите удалить категорию?');">
|
||||||
|
<input type="hidden" name="action" value="delete_category">
|
||||||
|
<input type="hidden" name="category_id" value="<?= $cat['category_id'] ?>">
|
||||||
|
<?php if ($cat['product_count'] == 0): ?>
|
||||||
|
<button type="submit" class="btn btn-sm btn-danger" title="Удалить">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
<?php else: ?>
|
||||||
|
<button type="button" class="btn btn-sm btn-secondary"
|
||||||
|
title="Нельзя удалить категорию с товарами" disabled>
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
<?php endif; ?>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?php else: ?>
|
||||||
|
<!-- Основной каталог товаров -->
|
||||||
|
<div class="products-container">
|
||||||
|
<?php foreach ($products as $product): ?>
|
||||||
|
<div class="product-card <?= getCardSizeClass($product) ?>">
|
||||||
|
<?php if ($is_admin): ?>
|
||||||
|
<div class="admin-actions">
|
||||||
|
<a href="?action=edit&id=<?= $product['product_id'] ?>"
|
||||||
|
class="admin-btn" style="background: #28a745;">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</a>
|
||||||
|
<a href="?action=delete&id=<?= $product['product_id'] ?>"
|
||||||
|
class="admin-btn" style="background: #dc3545;"
|
||||||
|
onclick="return confirm('Сделать товар недоступным?')">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="product-image-container">
|
||||||
|
<img src="<?= htmlspecialchars($product['image_url'] ?: 'img1/default.jpg') ?>"
|
||||||
|
alt="<?= htmlspecialchars($product['name']) ?>"
|
||||||
|
class="product-img">
|
||||||
|
|
||||||
|
<?php if ($product['old_price'] && $product['old_price'] > $product['price']): ?>
|
||||||
|
<span class="product-discount">
|
||||||
|
-<?= round(($product['old_price'] - $product['price']) / $product['old_price'] * 100) ?>%
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<i class="fas fa-shopping-cart product-wishlist-icon"
|
||||||
|
onclick="addToCart(<?= $product['product_id'] ?>)"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="product-info" style="padding: 15px;">
|
||||||
|
<div class="product-name"><?= htmlspecialchars($product['name']) ?></div>
|
||||||
|
<div class="product-details">
|
||||||
|
<?= htmlspecialchars(mb_substr($product['description'], 0, 100)) ?>...
|
||||||
|
</div>
|
||||||
|
<div class="product-price" style="margin-top: 10px;">
|
||||||
|
<?php if ($product['old_price'] && $product['old_price'] > $product['price']): ?>
|
||||||
|
<span style="text-decoration: line-through; color: #999; font-size: 14px;">
|
||||||
|
<?= number_format($product['old_price'], 0, '', ' ') ?> ₽
|
||||||
|
</span><br>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?= number_format($product['price'], 0, '', ' ') ?> ₽
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="product-stock" style="font-size: 12px; color: #28a745; margin-top: 5px;">
|
||||||
|
В наличии: <?= $product['stock_quantity'] ?> шт.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button onclick="addToCart(<?= $product['product_id'] ?>)"
|
||||||
|
class="btn btn-primary" style="width: 100%; margin-top: 10px;">
|
||||||
|
<i class="fas fa-shopping-cart"></i> В корзину
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="footer" id="footer">
|
||||||
|
<div class="container footer__content">
|
||||||
|
<div class="footer__col footer--logo">
|
||||||
|
<div class="logo">AETERNA</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col">
|
||||||
|
<h5>ПОКУПАТЕЛЮ</h5>
|
||||||
|
<ul>
|
||||||
|
<li><a href="catalog_admin.php">Каталог</a></li>
|
||||||
|
<li><a href="услуги.php">Услуги</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col">
|
||||||
|
<h5>ПОМОЩЬ</h5>
|
||||||
|
<ul>
|
||||||
|
<li><a href="Доставка.php">Доставка и оплата</a></li>
|
||||||
|
<li><a href="Гарантия.php">Гарантия и возврат</a></li>
|
||||||
|
<li><a href="cite_mebel.php#faq">Ответы на вопросы</a></li>
|
||||||
|
<li><a href="#footer">Контакты</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col">
|
||||||
|
<h5>КОНТАКТЫ</h5>
|
||||||
|
<p>aeterna@mail.ru</p>
|
||||||
|
<p>+7(912)999-12-23</p>
|
||||||
|
<div class="social-icons">
|
||||||
|
<span class="icon"><i class="fab fa-telegram"></i></span>
|
||||||
|
<span class="icon"><i class="fab fa-instagram"></i></span>
|
||||||
|
<span class="icon"><i class="fab fa-vk"></i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer__col">
|
||||||
|
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
|
||||||
|
<div class="payment-icons">
|
||||||
|
<span class="pay-icon"><i class="fab fa-cc-visa"></i></span>
|
||||||
|
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="copyright">
|
||||||
|
<p>© 2025 AETERNA. Все права защищены.</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Функция для показа формы добавления товара
|
||||||
|
function showAddForm() {
|
||||||
|
window.location.href = 'catalog_admin.php?action=add';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция для показа формы добавления категории
|
||||||
|
function showAddCategoryForm() {
|
||||||
|
window.location.href = 'catalog_admin.php?action=add_category';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция для редактирования категории
|
||||||
|
function editCategory(categoryId) {
|
||||||
|
window.location.href = 'catalog_admin.php?action=edit_category&id=' + categoryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция для скрытия формы
|
||||||
|
function hideForm() {
|
||||||
|
window.location.href = 'catalog_admin.php?action=categories';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Функция добавления в корзину
|
||||||
|
function addToCart(productId) {
|
||||||
|
$.ajax({
|
||||||
|
url: "cart_handler.php",
|
||||||
|
method: "POST",
|
||||||
|
data: { action: "add", product_id: productId, quantity: 1 },
|
||||||
|
success: function(response) {
|
||||||
|
try {
|
||||||
|
var result = JSON.parse(response);
|
||||||
|
if (result.success) {
|
||||||
|
alert("Товар добавлен в корзину!");
|
||||||
|
// Обновляем счетчик корзины
|
||||||
|
if ($(".cart-count").length) {
|
||||||
|
var current = parseInt($(".cart-count").text()) || 0;
|
||||||
|
$(".cart-count").text(current + 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert("Ошибка: " + result.message);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
alert("Товар добавлен в корзину!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
alert("Товар добавлен в корзину!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обработка формы категории с подтверждением
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#categoryFormElement').on('submit', function(e) {
|
||||||
|
const action = $(this).find('input[name="action"]').val();
|
||||||
|
const categoryName = $(this).find('input[name="name"]').val();
|
||||||
|
|
||||||
|
if (!categoryName.trim()) {
|
||||||
|
e.preventDefault();
|
||||||
|
alert('Пожалуйста, введите название категории');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = action === 'add_category'
|
||||||
|
? 'Добавить новую категорию "' + categoryName + '"?'
|
||||||
|
: 'Сохранить изменения в категории?';
|
||||||
|
|
||||||
|
if (!confirm(message)) {
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Подтверждение удаления категории
|
||||||
|
$('form[action="catalog_admin.php"]').on('submit', function(e) {
|
||||||
|
const action = $(this).find('input[name="action"]').val();
|
||||||
|
if (action === 'delete_category') {
|
||||||
|
const categoryId = $(this).find('input[name="category_id"]').val();
|
||||||
|
if (!confirm('Вы уверены, что хотите удалить эту категорию?')) {
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
<?php if ($is_admin): ?>
|
||||||
|
$('.product-card').hover(
|
||||||
|
function() {
|
||||||
|
$(this).find('.admin-actions').show();
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
$(this).find('.admin-actions').hide();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
<?php endif; ?>
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// Вспомогательная функция для определения размера карточки
|
||||||
|
function getCardSizeClass($product) {
|
||||||
|
$sizes = ['small', 'large', 'wide', 'tall', 'small1', 'wide2', 'wide3', 'wide2_1', 'full-width'];
|
||||||
|
$index = $product['product_id'] % count($sizes);
|
||||||
|
return $sizes[$index];
|
||||||
|
}
|
||||||
111
catalog_admin_action.php
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
// catalog_admin_action.php
|
||||||
|
session_start();
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['is_admin']) || $_SESSION['is_admin'] !== true) {
|
||||||
|
header('Location: вход.php');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = Database::getInstance()->getConnection();
|
||||||
|
$action = $_POST['action'] ?? '';
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
try {
|
||||||
|
switch ($action) {
|
||||||
|
case 'add_category':
|
||||||
|
$name = $_POST['name'] ?? '';
|
||||||
|
$parent_id = $_POST['parent_id'] ?: null;
|
||||||
|
$description = $_POST['description'] ?? null;
|
||||||
|
$sort_order = $_POST['sort_order'] ?? 0;
|
||||||
|
$is_active = isset($_POST['is_active']) ? 1 : 0;
|
||||||
|
|
||||||
|
// Создаем slug из названия
|
||||||
|
$slug = strtolower(preg_replace('/[^a-z0-9]+/i', '-', $name));
|
||||||
|
|
||||||
|
$stmt = $db->prepare("
|
||||||
|
INSERT INTO categories (name, slug, parent_id, description, sort_order, is_active)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?)
|
||||||
|
");
|
||||||
|
|
||||||
|
$stmt->execute([$name, $slug, $parent_id, $description, $sort_order, $is_active]);
|
||||||
|
|
||||||
|
header('Location: catalog_admin.php?action=categories&message=Категория успешно добавлена');
|
||||||
|
exit();
|
||||||
|
|
||||||
|
case 'edit_category':
|
||||||
|
$category_id = $_POST['category_id'] ?? 0;
|
||||||
|
$name = $_POST['name'] ?? '';
|
||||||
|
$parent_id = $_POST['parent_id'] ?: null;
|
||||||
|
$description = $_POST['description'] ?? null;
|
||||||
|
$sort_order = $_POST['sort_order'] ?? 0;
|
||||||
|
$is_active = isset($_POST['is_active']) ? 1 : 0;
|
||||||
|
|
||||||
|
// Создаем slug из названия
|
||||||
|
$slug = strtolower(preg_replace('/[^a-z0-9]+/i', '-', $name));
|
||||||
|
|
||||||
|
$stmt = $db->prepare("
|
||||||
|
UPDATE categories SET
|
||||||
|
name = ?,
|
||||||
|
slug = ?,
|
||||||
|
parent_id = ?,
|
||||||
|
description = ?,
|
||||||
|
sort_order = ?,
|
||||||
|
is_active = ?
|
||||||
|
WHERE category_id = ?
|
||||||
|
");
|
||||||
|
|
||||||
|
$stmt->execute([$name, $slug, $parent_id, $description, $sort_order, $is_active, $category_id]);
|
||||||
|
|
||||||
|
header('Location: catalog_admin.php?action=categories&message=Категория успешно обновлена');
|
||||||
|
exit();
|
||||||
|
|
||||||
|
case 'delete_category':
|
||||||
|
$category_id = $_POST['category_id'] ?? 0;
|
||||||
|
|
||||||
|
// Проверяем, есть ли активные товары в этой категории
|
||||||
|
$checkStmt = $db->prepare("
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM products
|
||||||
|
WHERE category_id = ? AND is_available = TRUE
|
||||||
|
");
|
||||||
|
$checkStmt->execute([$category_id]);
|
||||||
|
$active_products = $checkStmt->fetchColumn();
|
||||||
|
|
||||||
|
if ($active_products > 0) {
|
||||||
|
header('Location: catalog_admin.php?action=categories&error=Невозможно удалить категорию с активными товарами');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем дочерние категории
|
||||||
|
$checkChildStmt = $db->prepare("
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM categories
|
||||||
|
WHERE parent_id = ? AND is_active = TRUE
|
||||||
|
");
|
||||||
|
$checkChildStmt->execute([$category_id]);
|
||||||
|
$active_children = $checkChildStmt->fetchColumn();
|
||||||
|
|
||||||
|
if ($active_children > 0) {
|
||||||
|
header('Location: catalog_admin.php?action=categories&error=Невозможно удалить категорию с активными дочерними категориями');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Удаляем категорию
|
||||||
|
$stmt = $db->prepare("DELETE FROM categories WHERE category_id = ?");
|
||||||
|
$stmt->execute([$category_id]);
|
||||||
|
|
||||||
|
header('Location: catalog_admin.php?action=categories&message=Категория успешно удалена');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
header('Location: catalog_admin.php?action=categories&error=' . urlencode('Ошибка базы данных: ' . $e->getMessage()));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: catalog_admin.php');
|
||||||
|
exit();
|
||||||
|
?>
|
||||||
17
check_admin.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
// check_admin.php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
function checkAdmin() {
|
||||||
|
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
|
||||||
|
header('Location: вход.php?error=admin_required');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Возвращает true если пользователь администратор
|
||||||
|
function isAdmin() {
|
||||||
|
return isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
||||||
|
}
|
||||||
|
?>
|
||||||
21
check_auth_status.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
// check_auth_status.php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
$response = [
|
||||||
|
'loggedIn' => isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($response['loggedIn']) {
|
||||||
|
$response['user'] = [
|
||||||
|
'user_id' => $_SESSION['user_id'] ?? 0,
|
||||||
|
'email' => $_SESSION['user_email'] ?? '',
|
||||||
|
'full_name' => $_SESSION['full_name'] ?? '',
|
||||||
|
'is_admin' => $_SESSION['isAdmin'] ?? false,
|
||||||
|
'login_time' => $_SESSION['login_time'] ?? time()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode($response);
|
||||||
|
?>
|
||||||
51
check_categories_table.php
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
|
echo "<h2>Проверка категорий в базе данных</h2>";
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt = $db->query("SELECT category_id, name, slug, parent_id FROM categories ORDER BY category_id");
|
||||||
|
$categories = $stmt->fetchAll();
|
||||||
|
|
||||||
|
if (empty($categories)) {
|
||||||
|
echo "<p style='color: red;'>Категорий нет! Нужно сначала добавить категории.</p>";
|
||||||
|
|
||||||
|
// Добавим тестовые категории
|
||||||
|
$insert_sql = "
|
||||||
|
INSERT INTO categories (name, slug, parent_id, description) VALUES
|
||||||
|
('Мягкая мебель', 'myagkaya-mebel', NULL, 'Диваны, кресла, пуфы'),
|
||||||
|
('Диваны', 'divany', 1, 'Прямые и угловые диваны'),
|
||||||
|
('Кресла', 'kresla', 1, 'Кресла для гостиной и офиса'),
|
||||||
|
('Спальня', 'spalnya', NULL, 'Кровати, тумбы, комоды'),
|
||||||
|
('Кровати', 'krovati', 4, 'Односпальные и двуспальные кровати')
|
||||||
|
RETURNING category_id
|
||||||
|
";
|
||||||
|
|
||||||
|
$db->exec($insert_sql);
|
||||||
|
echo "<p style='color: green;'>Добавлены тестовые категории</p>";
|
||||||
|
|
||||||
|
// Снова проверим
|
||||||
|
$stmt = $db->query("SELECT category_id, name, slug, parent_id FROM categories ORDER BY category_id");
|
||||||
|
$categories = $stmt->fetchAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "<table border='1' cellpadding='5'>";
|
||||||
|
echo "<tr><th>ID</th><th>Название</th><th>Slug</th><th>Родитель</th></tr>";
|
||||||
|
|
||||||
|
foreach ($categories as $category) {
|
||||||
|
echo "<tr>";
|
||||||
|
echo "<td>" . $category['category_id'] . "</td>";
|
||||||
|
echo "<td>" . htmlspecialchars($category['name']) . "</td>";
|
||||||
|
echo "<td>" . htmlspecialchars($category['slug']) . "</td>";
|
||||||
|
echo "<td>" . ($category['parent_id'] ?: '-') . "</td>";
|
||||||
|
echo "</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "</table>";
|
||||||
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo "Ошибка: " . $e->getMessage();
|
||||||
|
}
|
||||||
|
?>
|
||||||
762
cite_mebel.php
Normal file
@@ -0,0 +1,762 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// Упрощенная проверка для каталога
|
||||||
|
if (isset($_GET['action']) && $_GET['action'] == 'go_to_catalog') {
|
||||||
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
|
// Перенаправляем на вход
|
||||||
|
header('Location: вход.php?redirect=' . urlencode('catalog.php'));
|
||||||
|
exit();
|
||||||
|
} else {
|
||||||
|
// Если авторизован - пускаем в каталог
|
||||||
|
header('Location: catalog.php');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>AETERNA - Мебель и Интерьер</title>
|
||||||
|
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/less"></script>
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||||
|
<style>
|
||||||
|
|
||||||
|
/* Стили для профиля пользователя */
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-toggle:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-avatar {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, #617365 0%, #453227 100%);
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-status.admin {
|
||||||
|
background-color: #617365;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-status.user {
|
||||||
|
background-color: #28a745;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-arrow {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-menu {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
background: white;
|
||||||
|
min-width: 280px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 5px 20px rgba(0,0,0,0.15);
|
||||||
|
z-index: 1000;
|
||||||
|
margin-top: 10px;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-header {
|
||||||
|
padding: 15px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-name {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
color: #333;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-details {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-details small {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-details i {
|
||||||
|
width: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-links {
|
||||||
|
list-style: none;
|
||||||
|
padding: 10px 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-links li {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-links a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
color: #333;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-left: 3px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-links a:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-left-color: #453227;
|
||||||
|
color: #453227;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-links i {
|
||||||
|
width: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-item {
|
||||||
|
border-top: 1px solid #e0e0e0;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-link {
|
||||||
|
color: #dc3545 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-link:hover {
|
||||||
|
background-color: #ffe6e6 !important;
|
||||||
|
border-left-color: #dc3545 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-icon {
|
||||||
|
position: relative;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-count {
|
||||||
|
position: absolute;
|
||||||
|
top: -8px;
|
||||||
|
right: -8px;
|
||||||
|
background: #dc3545;
|
||||||
|
color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
font-size: 11px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Стиль для заблокированных ссылок */
|
||||||
|
.link-disabled {
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
opacity: 0.6 !important;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-disabled:hover::after {
|
||||||
|
content: "🔒 Требуется авторизация";
|
||||||
|
position: absolute;
|
||||||
|
top: -30px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: #333;
|
||||||
|
color: white;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
white-space: nowrap;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Кнопка каталога с замком */
|
||||||
|
.catalog-locked {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-locked::before {
|
||||||
|
content: "🔒";
|
||||||
|
position: absolute;
|
||||||
|
top: -5px;
|
||||||
|
right: -5px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header class="header">
|
||||||
|
<div class="header__top">
|
||||||
|
<div class="container header__top-content">
|
||||||
|
<div class="logo">AETERNA</div>
|
||||||
|
|
||||||
|
<div class="search-catalog">
|
||||||
|
<div class="catalog-dropdown">
|
||||||
|
Все категории <span>▼</span>
|
||||||
|
<div class="catalog-dropdown__menu">
|
||||||
|
<ul>
|
||||||
|
<li><a href="javascript:void(0)" onclick="checkAuth('catalog.php?category=1')">Диваны</a></li>
|
||||||
|
<li><a href="javascript:void(0)" onclick="checkAuth('catalog.php?category=2')">Кровати</a></li>
|
||||||
|
<li><a href="javascript:void(0)" onclick="checkAuth('catalog.php?category=3')">Шкафы</a></li>
|
||||||
|
<li><a href="javascript:void(0)" onclick="checkAuth('catalog.php?category=4')">Стулья</a></li>
|
||||||
|
<li><a href="javascript:void(0)" onclick="checkAuth('catalog.php?category=5')">Столы</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="search-box">
|
||||||
|
<input type="text" placeholder="Поиск товаров" id="searchInput">
|
||||||
|
<span class="search-icon"><i class="fas fa-search"></i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Вставьте этот код в секцию header__icons--top вместо текущего -->
|
||||||
|
<!-- Вставьте этот код в секцию header__icons--top вместо текущего -->
|
||||||
|
<div class="header__icons--top">
|
||||||
|
<?php if (isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true): ?>
|
||||||
|
<!-- Иконка корзины -->
|
||||||
|
<a href="оформление_заказа.php" class="icon cart-icon">
|
||||||
|
<i class="fas fa-shopping-cart"></i>
|
||||||
|
<span class="cart-count">0</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Блок профиля с выпадающим меню -->
|
||||||
|
<div class="user-profile-dropdown">
|
||||||
|
<div class="user-profile-toggle">
|
||||||
|
<div class="user-avatar">
|
||||||
|
<?php
|
||||||
|
$email = $_SESSION['user_email'] ?? '';
|
||||||
|
echo !empty($email) ? strtoupper(substr($email, 0, 1)) : 'U';
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
<div class="user-info">
|
||||||
|
<div class="user-email"><?= htmlspecialchars($email) ?></div>
|
||||||
|
<div class="user-status <?= isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] ? 'admin' : 'user' ?>">
|
||||||
|
<?= isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] ? 'Админ' : 'Пользователь' ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<i class="fas fa-chevron-down dropdown-arrow"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="user-profile-menu">
|
||||||
|
<div class="user-profile-header">
|
||||||
|
<div class="user-profile-name">
|
||||||
|
<i class="fas fa-user"></i>
|
||||||
|
<?= htmlspecialchars($_SESSION['full_name'] ?? $email) ?>
|
||||||
|
</div>
|
||||||
|
<div class="user-profile-details">
|
||||||
|
<small><i class="far fa-envelope"></i> <?= htmlspecialchars($email) ?></small>
|
||||||
|
<?php if (isset($_SESSION['login_time'])): ?>
|
||||||
|
<small><i class="far fa-clock"></i> Вошел: <?= date('d.m.Y H:i', $_SESSION['login_time']) ?></small>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="user-profile-links">
|
||||||
|
<li>
|
||||||
|
<a href="профиль.php">
|
||||||
|
<i class="fas fa-user-cog"></i>
|
||||||
|
<span>Настройки профиля</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="оформление_заказа.php">
|
||||||
|
<i class="fas fa-shopping-bag"></i>
|
||||||
|
<span>Мои заказы</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<?php if (isset($_SESSION['isAdmin']) && $_SESSION['isAdmin']): ?>
|
||||||
|
<li>
|
||||||
|
<a href="catalog_admin.php">
|
||||||
|
<i class="fas fa-user-shield"></i>
|
||||||
|
<span>Панель администратора</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<?php endif; ?>
|
||||||
|
<li class="logout-item">
|
||||||
|
<a href="logout.php" class="logout-link">
|
||||||
|
<i class="fas fa-sign-out-alt"></i>
|
||||||
|
<span>Выйти из аккаунта</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php else: ?>
|
||||||
|
<!-- Если не авторизован -->
|
||||||
|
<a href="вход.php" class="icon">
|
||||||
|
<i class="far fa-user"></i>
|
||||||
|
</a>
|
||||||
|
<a href="вход.php" style="font-size: 12px; color: #666; margin-left: 5px;">
|
||||||
|
Войти
|
||||||
|
</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="header__bottom">
|
||||||
|
<div class="container header__bottom-content">
|
||||||
|
<div class="catalog-menu">
|
||||||
|
<a href="catalog.php"
|
||||||
|
class="catalog-link <?= (isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true) ? '' : 'catalog-locked' ?>">
|
||||||
|
<div class="catalog-icon">
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="line"></span>
|
||||||
|
</div>
|
||||||
|
<span class="catalog-lines">☰</span>
|
||||||
|
Каталог
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="nav">
|
||||||
|
<ul class="nav-list">
|
||||||
|
<li><a href="cite_mebel.php" class="active">Главная</a></li>
|
||||||
|
<li><a href="услуги.php">Услуги</a></li>
|
||||||
|
<li><a href="Доставка.php">Доставка и оплата</a></li>
|
||||||
|
<li><a href="Гарантия.php">Гарантия</a></li>
|
||||||
|
<li><a href="#footer">Контакты</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<div class="header-phone">+7(912)999-12-23</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="hero">
|
||||||
|
<div class="container hero__content">
|
||||||
|
<div class="hero__image-block">
|
||||||
|
<div class="hero__circle"></div>
|
||||||
|
<img src="img/chair.PNG" alt="Кресло и торшер" class="hero__img">
|
||||||
|
</div>
|
||||||
|
<div class="hero__text-block">
|
||||||
|
<h1>ДОБАВЬТЕ ИЗЫСКАННОСТИ В СВОЙ ИНТЕРЬЕР</h1>
|
||||||
|
<p class="hero__usp-text">Мы создаем мебель, которая сочетает в себе безупречный дизайн, натуральные материалы, продуманный функционал, чтобы ваш день начинался и заканчивался с комфортом.</p>
|
||||||
|
|
||||||
|
<?php if (isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true): ?>
|
||||||
|
<a href="?action=go_to_catalog" class="btn primary-btn">ПЕРЕЙТИ В КАТАЛОГ</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<a href="javascript:void(0)" onclick="checkAuth('catalog.php')" class="btn primary-btn link-disabled">ПЕРЕЙТИ В КАТАЛОГ</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="advantages">
|
||||||
|
<div class="container">
|
||||||
|
<div class="advantages__header">
|
||||||
|
<h2>ПОЧЕМУ <br>ВЫБИРАЮТ НАС?</h2>
|
||||||
|
<div class="advantages__items">
|
||||||
|
<div class="advantage-item">
|
||||||
|
<span class="advantage-item__number">1</span>
|
||||||
|
<h4>ГАРАНТИЯ ВЫСОЧАЙШЕГО КАЧЕСТВА</h4>
|
||||||
|
<p>Собственное производство и строгий контроль на всех этапах.</p>
|
||||||
|
</div>
|
||||||
|
<div class="advantage-item">
|
||||||
|
<span class="advantage-item__number">2</span>
|
||||||
|
<h4>ИСПОЛЬЗОВАНИЕ НАДЕЖНЫХ МАТЕРИАЛОВ</h4>
|
||||||
|
<p>Гарантия безопасности и долговечности.</p>
|
||||||
|
</div>
|
||||||
|
<div class="advantage-item">
|
||||||
|
<span class="advantage-item__number">3</span>
|
||||||
|
<h4>ИНДИВИДУАЛЬНЫЙ ПОДХОД И ГИБКОСТЬ УСЛОВИЙ</h4>
|
||||||
|
<p>Реализуем проекты любой сложности по вашим техническим заданиям.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="promo-images">
|
||||||
|
<div class="promo-image-col">
|
||||||
|
<img src="img/спальня.jpg" alt="Кровать и тумба">
|
||||||
|
<div class="image-overlay-text">
|
||||||
|
<h4>НОВИНКИ В КАТЕГОРИЯХ <br>МЯГКАЯ МЕБЕЛЬ</h4>
|
||||||
|
<a href="#" class="overlay-link">ПЕРЕЙТИ</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="promo-image-col">
|
||||||
|
<img src="img/диван.jpg" alt="Диван в гостиной">
|
||||||
|
<div class="image-overlay-text">
|
||||||
|
<h4>РАСПРОДАЖА <br>ПРЕДМЕТЫ ДЕКОРА</h4>
|
||||||
|
<a href="#" class="overlay-link">ПЕРЕЙТИ</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="about">
|
||||||
|
<div class="container about__content">
|
||||||
|
<div class="about__column about__column--left">
|
||||||
|
<div class="about__text-block">
|
||||||
|
<h2>О НАС</h2>
|
||||||
|
<p class="text-justified">Компания AETERNA - российский производитель качественной корпусной и мягкой мебели для дома и офиса. С 2015 года мы успешно реализуем проекты любой сложности, сочетая современные технологии, проверенные материалы и классическое мастерство.</p>
|
||||||
|
</div>
|
||||||
|
<img src="img/кресло_1.jpg" alt="Фиолетовое кресло" class="about__img about__img--small">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="about__column about__column--right">
|
||||||
|
<img src="img/диван_1.jpg" alt="Белый диван с подушками" class="about__img about__img--large">
|
||||||
|
<p class="about__caption">Наша сеть включает 30+ российских фабрик, отобранных по строгим стандартам качества. Мы сотрудничаем исключительно с лидерами рынка, чья продукция доказала свое превосходство временем.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="solutions">
|
||||||
|
<div class="container">
|
||||||
|
<div class="solutions-slider">
|
||||||
|
<div class="solutions-slider__slides">
|
||||||
|
<div class="solutions-slider__slide">
|
||||||
|
<img src="img/слайдер_1.jpg" class="solution-img" alt="Готовое решение для гостиной">
|
||||||
|
<div class="solution-text-overlay">
|
||||||
|
<h2>ГОТОВОЕ РЕШЕНИЕ<br>ДЛЯ ВАШЕЙ ГОСТИНОЙ</h2> <br>
|
||||||
|
<p>УСПЕЙТЕ ЗАКАЗАТЬ СЕЙЧАС</p>
|
||||||
|
</div>
|
||||||
|
<a href="#" class="solution-image-link">Подробнее</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="solutions-slider__slide">
|
||||||
|
<img src="img/слайдер_6.jpg" class="solution-img" alt="Готовое решение для спальни">
|
||||||
|
<div class="solution-text-overlay">
|
||||||
|
<h2>ГОТОВОЕ РЕШЕНИЕ<br>ДЛЯ ВАШЕЙ СПАЛЬНИ</h2> <br>
|
||||||
|
<p>УСПЕЙТЕ ЗАКАЗАТЬ СЕЙЧАС</p>
|
||||||
|
</div>
|
||||||
|
<a href="#" class="solution-image-link">Подробнее</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="stats">
|
||||||
|
<div class="container">
|
||||||
|
<div class="stats__items">
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-number">10+</div>
|
||||||
|
<div class="stat-label">Лет работы</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-number">30 000+</div>
|
||||||
|
<div class="stat-label">Довольных покупателей</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-number">4500+</div>
|
||||||
|
<div class="stat-label">Реализованных заказов</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="faq" id="faq">
|
||||||
|
<div class="container">
|
||||||
|
<h2>ОТВЕТЫ НА ВОПРОСЫ</h2>
|
||||||
|
<div class="faq__items">
|
||||||
|
<div class="faq-item">
|
||||||
|
<span class="number-circle">1</span>
|
||||||
|
<div class="faq-item__content">
|
||||||
|
<h4>Сколько времени занимает доставка?</h4>
|
||||||
|
<p>Доставка готовых позиций занимает 1-3 дня. Мебель на заказ изготавливается от 14 до 45 рабочих дней, в зависимости от сложности. Точные сроки озвучит ваш менеджер при оформлении заказа.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="faq-item">
|
||||||
|
<span class="number-circle">2</span>
|
||||||
|
<div class="faq-item__content">
|
||||||
|
<h4>Нужно ли вносить предоплату?</h4>
|
||||||
|
<p>Да, для запуска заказа в производство необходима предоплата в размере 50-70% от стоимости, в зависимости от изделия. Оставшаяся сумма оплачивается при доставке и приемке мебели.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="faq-item">
|
||||||
|
<span class="number-circle">3</span>
|
||||||
|
<div class="faq-item__content">
|
||||||
|
<h4>Предоставляется ли рассрочка или кредит?</h4>
|
||||||
|
<p>Да, мы сотрудничаем с несколькими банками и предлагаем рассрочку на 6 или 12 месяцев без первоначального взноса, а также кредит на более длительный срок. Все условия уточняйте у вашего менеджера.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="faq-item">
|
||||||
|
<span class="number-circle">4</span>
|
||||||
|
<div class="faq-item__content">
|
||||||
|
<h4>Что делать, если мебель пришла с дефектом?</h4>
|
||||||
|
<p>В этом случае необходимо в течение 7 дней со дня доставки сообщить нам о проблеме, прислать фото/видео дефекта. Мы оперативно решим вопрос о бесплатной замене или ремонте изделия.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="btn primary-btn">Задать вопрос</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="footer" id="footer">
|
||||||
|
<div class="container footer__content">
|
||||||
|
<div class="footer__col footer--logo">
|
||||||
|
<div class="logo">AETERNA</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer__col">
|
||||||
|
<h5>ПОКУПАТЕЛЮ</h5>
|
||||||
|
<ul>
|
||||||
|
<li><a href="javascript:void(0)" onclick="checkAuth('catalog.php')">Каталог</a></li>
|
||||||
|
<li><a href="услуги.php">Услуги</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer__col">
|
||||||
|
<h5>ПОМОЩЬ</h5>
|
||||||
|
<ul>
|
||||||
|
<li><a href="Доставка.php">Доставка и оплата</a></li>
|
||||||
|
<li><a href="Гарантия.php">Гарантия и возврат</a></li>
|
||||||
|
<li><a href="cite_mebel.html#faq">Ответы на вопросы</a></li>
|
||||||
|
<li><a href="#footer">Контакты</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer__col">
|
||||||
|
<h5>КОНТАКТЫ</h5>
|
||||||
|
<p>aeterna@mail.ru</p>
|
||||||
|
<p>+7(912)999-12-23</p>
|
||||||
|
<div class="social-icons">
|
||||||
|
<span class="icon"><i class="fab fa-telegram"></i></span>
|
||||||
|
<span class="icon"><i class="fab fa-instagram"></i></span>
|
||||||
|
<span class="icon"><i class="fab fa-vk"></i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer__col">
|
||||||
|
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
|
||||||
|
<div class="payment-icons">
|
||||||
|
<span class="pay-icon"><i class="fab fa-cc-visa"></i></span>
|
||||||
|
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="copyright">
|
||||||
|
<p>© 2025 AETERNA. Все права защищены.</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
<!-- Статус пользователя (будет показан после авторизации) -->
|
||||||
|
<div class="user-status-overlay" id="userStatus" style="display: none; position: fixed; top: 20px; right: 20px; z-index: 1000; background: white; padding: 10px 15px; border-radius: 5px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
|
||||||
|
<div style="display: flex; align-items: center; gap: 10px;">
|
||||||
|
<i class="fas fa-user" id="statusIcon"></i>
|
||||||
|
<div>
|
||||||
|
<div id="statusText" style="font-weight: bold;"></div>
|
||||||
|
<div id="userEmail" style="font-size: 12px; color: #666;"></div>
|
||||||
|
</div>
|
||||||
|
<button onclick="logout()" style="background: none; border: none; color: #666; cursor: pointer; margin-left: 10px;">
|
||||||
|
<i class="fas fa-sign-out-alt"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Модальное окно для быстрого входа -->
|
||||||
|
<div class="quick-login-modal" id="quickLoginModal" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 2000; align-items: center; justify-content: center;">
|
||||||
|
<div style="background: white; padding: 30px; border-radius: 10px; width: 90%; max-width: 400px; text-align: center;">
|
||||||
|
<h3 style="margin-bottom: 20px; color: #453227;">
|
||||||
|
<i class="fas fa-sign-in-alt"></i> Быстрый вход
|
||||||
|
</h3>
|
||||||
|
<div style="margin-bottom: 20px;">
|
||||||
|
<button onclick="quickLogin('admin')" style="width: 100%; padding: 12px; background: #617365; color: white; border: none; border-radius: 4px; margin-bottom: 10px; cursor: pointer;">
|
||||||
|
<i class="fas fa-user-shield"></i> Войти как Администратор
|
||||||
|
</button>
|
||||||
|
<button onclick="quickLogin('user')" style="width: 100%; padding: 12px; background: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer;">
|
||||||
|
<i class="fas fa-user"></i> Войти как Пользователь
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div style="font-size: 12px; color: #666; margin-top: 15px;">
|
||||||
|
Для полного функционала перейдите на страницу входа
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 20px; display: flex; gap: 10px; justify-content: center;">
|
||||||
|
<a href="вход.html" class="btn primary-btn" style="padding: 8px 15px; font-size: 14px;">
|
||||||
|
Полный вход
|
||||||
|
</a>
|
||||||
|
<button onclick="hideQuickLogin()" class="btn" style="padding: 8px 15px; font-size: 14px; background: #6c757d; color: white;">
|
||||||
|
Отмена
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Проверка авторизации
|
||||||
|
function checkAuth(redirectUrl) {
|
||||||
|
// Просто перенаправляем на страницу с action
|
||||||
|
window.location.href = 'cite_mebel.php?action=go_to_catalog';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверяем статус при загрузке
|
||||||
|
$(document).ready(function() {
|
||||||
|
// Синхронизируем PHP сессию с localStorage
|
||||||
|
<?php if (isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true): ?>
|
||||||
|
if (localStorage.getItem('isLoggedIn') !== 'true') {
|
||||||
|
localStorage.setItem('isLoggedIn', 'true');
|
||||||
|
localStorage.setItem('user_email', '<?= addslashes($_SESSION['user_email'] ?? '') ?>');
|
||||||
|
localStorage.setItem('isAdmin', '<?= isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] ? 'true' : 'false' ?>');
|
||||||
|
}
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
// Блокируем все ссылки на каталог если не авторизован
|
||||||
|
const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
|
||||||
|
|
||||||
|
if (!isLoggedIn) {
|
||||||
|
// Находим ВСЕ ссылки на каталог
|
||||||
|
$('a[href*="catalog"]').each(function() {
|
||||||
|
const originalHref = $(this).attr('href');
|
||||||
|
if (originalHref && originalHref.includes('catalog')) {
|
||||||
|
$(this).attr('href', 'javascript:void(0)');
|
||||||
|
$(this).addClass('link-disabled');
|
||||||
|
$(this).click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
checkAuth(originalHref);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Блокируем поиск
|
||||||
|
$('#searchInput').prop('disabled', true).attr('placeholder', 'Войдите для поиска');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Быстрый вход для тестирования (можно удалить в продакшене)
|
||||||
|
function quickLogin(role) {
|
||||||
|
let email, password;
|
||||||
|
|
||||||
|
if (role === 'admin') {
|
||||||
|
email = 'admin@aeterna.ru';
|
||||||
|
password = 'admin123';
|
||||||
|
} else {
|
||||||
|
email = 'user@test.com';
|
||||||
|
password = 'user123';
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: 'login_handler.php',
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
email: email,
|
||||||
|
password: password
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
try {
|
||||||
|
const result = JSON.parse(response);
|
||||||
|
if (result.success) {
|
||||||
|
// Сохраняем в localStorage
|
||||||
|
localStorage.setItem('isLoggedIn', 'true');
|
||||||
|
localStorage.setItem('user_email', email);
|
||||||
|
localStorage.setItem('isAdmin', (role === 'admin').toString());
|
||||||
|
|
||||||
|
alert('Вы вошли как ' + (role === 'admin' ? 'администратор' : 'пользователь'));
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
// Открытие/закрытие меню профиля
|
||||||
|
$('.user-profile-toggle').click(function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
$('.user-profile-menu').toggle();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Закрытие меню при клике вне его
|
||||||
|
$(document).click(function() {
|
||||||
|
$('.user-profile-menu').hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Обработка выхода
|
||||||
|
$('.logout-link').click(function(e) {
|
||||||
|
if (!confirm('Вы действительно хотите выйти?')) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Обновляем время входа при загрузке страницы
|
||||||
|
updateLoginTime();
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateLoginTime() {
|
||||||
|
// Можно добавить AJAX запрос для обновления времени последнего входа
|
||||||
|
// или использовать время из сессии
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Кнопки быстрого тестирования -->
|
||||||
|
<div style="position: fixed; bottom: 20px; right: 20px; z-index: 1000; background: white; padding: 10px; border-radius: 5px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
|
||||||
|
<h4 style="margin: 0 0 10px 0; font-size: 14px; color: #453227;">Быстрый вход:</h4>
|
||||||
|
<button onclick="window.location.href='профиль.php?quick_login=admin'" style="background: #617365; color: white; border: none; padding: 8px 15px; border-radius: 4px; cursor: pointer; margin: 5px; width: 100%;">
|
||||||
|
<i class="fas fa-user-shield"></i> Войти как Админ
|
||||||
|
</button>
|
||||||
|
<button onclick="window.location.href='профиль.php?quick_login=user'" style="background: #28a745; color: white; border: none; padding: 8px 15px; border-radius: 4px; cursor: pointer; margin: 5px; width: 100%;">
|
||||||
|
<i class="fas fa-user"></i> Войти как Пользователь
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
114
config/check_auth.js
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
// check_auth.js
|
||||||
|
$(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) {
|
||||||
|
// Сохраняем в localStorage если выбрано "Запомнить меня"
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
32
config/database.php
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
// config/database.php
|
||||||
|
class Database {
|
||||||
|
private static $instance = null;
|
||||||
|
private $connection;
|
||||||
|
|
||||||
|
private function __construct() {
|
||||||
|
try {
|
||||||
|
$this->connection = new PDO(
|
||||||
|
"pgsql:host=localhost;dbname=aeterna_db;",
|
||||||
|
"postgres",
|
||||||
|
"1234"
|
||||||
|
);
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
55
debug_db.php
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
// debug_db.php
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
|
echo "<h2>Проверка базы данных:</h2>";
|
||||||
|
|
||||||
|
// Проверка таблиц
|
||||||
|
$tables = ['users', 'categories', 'products', 'orders', 'order_items', 'cart'];
|
||||||
|
foreach ($tables as $table) {
|
||||||
|
try {
|
||||||
|
$result = $db->query("SELECT COUNT(*) FROM $table")->fetchColumn();
|
||||||
|
echo "✅ Таблица '$table': $result записей<br>";
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "❌ Таблица '$table': НЕ СУЩЕСТВУЕТ<br>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "<h2>Содержимое таблиц:</h2>";
|
||||||
|
|
||||||
|
// Показать категории
|
||||||
|
echo "<h3>Категории:</h3>";
|
||||||
|
try {
|
||||||
|
$categories = $db->query("SELECT * FROM categories")->fetchAll();
|
||||||
|
if (empty($categories)) {
|
||||||
|
echo "Категорий нет!<br>";
|
||||||
|
} else {
|
||||||
|
echo "<table border='1'><tr><th>ID</th><th>Название</th><th>Slug</th><th>Родитель</th></tr>";
|
||||||
|
foreach ($categories as $cat) {
|
||||||
|
echo "<tr><td>{$cat['category_id']}</td><td>{$cat['name']}</td><td>{$cat['slug']}</td><td>{$cat['parent_id']}</td></tr>";
|
||||||
|
}
|
||||||
|
echo "</table>";
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "Ошибка: " . $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Показать товары
|
||||||
|
echo "<h3>Товары:</h3>";
|
||||||
|
try {
|
||||||
|
$products = $db->query("SELECT * FROM products")->fetchAll();
|
||||||
|
if (empty($products)) {
|
||||||
|
echo "Товаров нет!<br>";
|
||||||
|
} else {
|
||||||
|
echo "<table border='1'><tr><th>ID</th><th>Название</th><th>Цена</th><th>Категория</th><th>Статус</th></tr>";
|
||||||
|
foreach ($products as $product) {
|
||||||
|
echo "<tr><td>{$product['product_id']}</td><td>{$product['name']}</td><td>{$product['price']}</td><td>{$product['category_id']}</td><td>" . ($product['is_available'] ? 'Активен' : 'Неактивен') . "</td></tr>";
|
||||||
|
}
|
||||||
|
echo "</table>";
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "Ошибка: " . $e->getMessage();
|
||||||
|
}
|
||||||
|
?>
|
||||||
69
fix_categories.php
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
// fix_categories.php
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
|
echo "<h2>Исправление проблем с категориями</h2>";
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. Удаляем категорию с ID=0 если она есть
|
||||||
|
$db->exec("DELETE FROM categories WHERE category_id = 0");
|
||||||
|
|
||||||
|
// 2. Проверяем, есть ли категории
|
||||||
|
$catCount = $db->query("SELECT COUNT(*) FROM categories")->fetchColumn();
|
||||||
|
|
||||||
|
if ($catCount == 0) {
|
||||||
|
echo "<p>Добавляем основные категории...</p>";
|
||||||
|
$db->exec("
|
||||||
|
INSERT INTO categories (name, slug, description, is_active) VALUES
|
||||||
|
('Диваны', 'divany', 'Мягкая мебель для гостиной', TRUE),
|
||||||
|
('Кресла', 'kresla', 'Кресла для гостиной и офиса', TRUE),
|
||||||
|
('Кровати', 'krovati', 'Мебель для спальни', TRUE),
|
||||||
|
('Столы', 'stoly', 'Обеденные и рабочие столы', TRUE),
|
||||||
|
('Стулья', 'stulya', 'Стулья для кухни и офиса', TRUE)
|
||||||
|
");
|
||||||
|
echo "<p style='color: green;'>✓ Категории добавлены</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Исправляем товары с category_id = 0 или NULL
|
||||||
|
$badProducts = $db->query("
|
||||||
|
SELECT COUNT(*) FROM products
|
||||||
|
WHERE category_id IS NULL OR category_id = 0 OR
|
||||||
|
category_id NOT IN (SELECT category_id FROM categories)
|
||||||
|
")->fetchColumn();
|
||||||
|
|
||||||
|
if ($badProducts > 0) {
|
||||||
|
echo "<p>Исправляем товары с некорректными категориями ($badProducts шт)...</p>";
|
||||||
|
|
||||||
|
// Получаем первую категорию
|
||||||
|
$firstCat = $db->query("SELECT category_id FROM categories LIMIT 1")->fetchColumn();
|
||||||
|
|
||||||
|
if ($firstCat) {
|
||||||
|
$db->exec("
|
||||||
|
UPDATE products
|
||||||
|
SET category_id = $firstCat
|
||||||
|
WHERE category_id IS NULL OR category_id = 0 OR
|
||||||
|
category_id NOT IN (SELECT category_id FROM categories)
|
||||||
|
");
|
||||||
|
echo "<p style='color: green;'>✓ Товары исправлены (category_id установлен в $firstCat)</p>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Показываем текущее состояние
|
||||||
|
echo "<h3>Текущие категории:</h3>";
|
||||||
|
$cats = $db->query("SELECT category_id, name FROM categories ORDER BY category_id")->fetchAll();
|
||||||
|
|
||||||
|
echo "<table border='1' cellpadding='5'>";
|
||||||
|
echo "<tr><th>ID</th><th>Название</th></tr>";
|
||||||
|
foreach ($cats as $cat) {
|
||||||
|
echo "<tr><td>{$cat['category_id']}</td><td>{$cat['name']}</td></tr>";
|
||||||
|
}
|
||||||
|
echo "</table>";
|
||||||
|
|
||||||
|
echo "<p style='color: green; margin-top: 20px;'>✓ База данных исправлена!</p>";
|
||||||
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo "<p style='color: red;'>Ошибка: " . $e->getMessage() . "</p>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
89
fix_database.php
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
// fix_database.php
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
|
echo "<h2>Исправление проблем с базой данных</h2>";
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. Проверяем есть ли категории
|
||||||
|
$stmt = $db->query("SELECT COUNT(*) FROM categories");
|
||||||
|
$cat_count = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
if ($cat_count == 0) {
|
||||||
|
echo "<p>Добавляем тестовые категории...</p>";
|
||||||
|
$db->exec("
|
||||||
|
INSERT INTO categories (name, slug, description) VALUES
|
||||||
|
('Диваны', 'divany', 'Мягкая мебель для гостиной'),
|
||||||
|
('Кресла', 'kresla', 'Кресла для гостиной и офиса'),
|
||||||
|
('Кровати', 'krovati', 'Мебель для спальни')
|
||||||
|
");
|
||||||
|
echo "<p style='color: green;'>✓ Категории добавлены</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Проверяем товары с некорректными category_id
|
||||||
|
$stmt = $db->query("
|
||||||
|
SELECT COUNT(*) as bad_count
|
||||||
|
FROM products
|
||||||
|
WHERE category_id IS NULL OR category_id NOT IN (SELECT category_id FROM categories)
|
||||||
|
");
|
||||||
|
$bad_count = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
if ($bad_count > 0) {
|
||||||
|
echo "<p>Исправляем товары с некорректными категориями ($bad_count шт)...</p>";
|
||||||
|
|
||||||
|
// Устанавливаем первую доступную категорию
|
||||||
|
$stmt = $db->query("SELECT category_id FROM categories LIMIT 1");
|
||||||
|
$first_cat = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
if ($first_cat) {
|
||||||
|
$db->exec("
|
||||||
|
UPDATE products
|
||||||
|
SET category_id = $first_cat
|
||||||
|
WHERE category_id IS NULL OR category_id NOT IN (SELECT category_id FROM categories)
|
||||||
|
");
|
||||||
|
echo "<p style='color: green;'>✓ Товары исправлены (установлена категория ID: $first_cat)</p>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Показываем текущее состояние
|
||||||
|
echo "<h3>Текущее состояние:</h3>";
|
||||||
|
|
||||||
|
// Категории
|
||||||
|
$stmt = $db->query("SELECT category_id, name FROM categories ORDER BY category_id");
|
||||||
|
echo "<p><strong>Категории:</strong></p><ul>";
|
||||||
|
while ($row = $stmt->fetch()) {
|
||||||
|
echo "<li>ID: {$row['category_id']} - {$row['name']}</li>";
|
||||||
|
}
|
||||||
|
echo "</ul>";
|
||||||
|
|
||||||
|
// Товары
|
||||||
|
$stmt = $db->query("
|
||||||
|
SELECT p.product_id, p.name, p.category_id, c.name as cat_name
|
||||||
|
FROM products p
|
||||||
|
LEFT JOIN categories c ON p.category_id = c.category_id
|
||||||
|
ORDER BY p.product_id
|
||||||
|
");
|
||||||
|
|
||||||
|
echo "<p><strong>Товары:</strong></p>";
|
||||||
|
echo "<table border='1' cellpadding='5'>";
|
||||||
|
echo "<tr><th>ID</th><th>Название</th><th>Категория ID</th><th>Категория</th></tr>";
|
||||||
|
|
||||||
|
while ($row = $stmt->fetch()) {
|
||||||
|
echo "<tr>";
|
||||||
|
echo "<td>{$row['product_id']}</td>";
|
||||||
|
echo "<td>" . htmlspecialchars($row['name']) . "</td>";
|
||||||
|
echo "<td>" . ($row['category_id'] ?: 'NULL') . "</td>";
|
||||||
|
echo "<td>" . ($row['cat_name'] ?: 'Без категории') . "</td>";
|
||||||
|
echo "</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "</table>";
|
||||||
|
|
||||||
|
echo "<p style='color: green; margin-top: 20px;'>✓ База данных исправлена!</p>";
|
||||||
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo "<p style='color: red;'>Ошибка: " . $e->getMessage() . "</p>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
62
get_cart.php
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
// get_cart.php
|
||||||
|
session_start();
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
|
echo json_encode(['success' => 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()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
?>
|
||||||
22
get_cart_count.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
// get_cart_count.php
|
||||||
|
session_start();
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
|
echo json_encode(['success' => 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]);
|
||||||
|
}
|
||||||
33
get_product.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once 'config/database.php';
|
||||||
|
|
||||||
|
// Проверяем авторизацию администратора
|
||||||
|
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
|
||||||
|
echo json_encode(['success' => 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()]);
|
||||||
|
}
|
||||||
|
?>
|
||||||
142
header_common.php
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
<?php
|
||||||
|
if (session_status() == PHP_SESSION_NONE) {
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
$isLoggedIn = isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true;
|
||||||
|
$isAdmin = isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
||||||
|
$userEmail = $_SESSION['user_email'] ?? '';
|
||||||
|
$fullName = $_SESSION['full_name'] ?? $userEmail;
|
||||||
|
?>
|
||||||
|
<!-- Стандартный header для всех страниц -->
|
||||||
|
<header class="header">
|
||||||
|
<div class="header__top">
|
||||||
|
<div class="container header__top-content">
|
||||||
|
<div class="logo">AETERNA</div>
|
||||||
|
|
||||||
|
<div class="search-catalog">
|
||||||
|
<div class="catalog-dropdown">
|
||||||
|
Все категории <span>▼</span>
|
||||||
|
<div class="catalog-dropdown__menu">
|
||||||
|
<ul>
|
||||||
|
<li><a href="catalog.php">Все товары</a></li>
|
||||||
|
<li><a href="catalog.php?category=1">Мягкая мебель</a></li>
|
||||||
|
<li><a href="catalog.php?category=2">Диваны</a></li>
|
||||||
|
<li><a href="catalog.php?category=3">Кресла</a></li>
|
||||||
|
<li><a href="catalog.php?category=4">Спальня</a></li>
|
||||||
|
<li><a href="catalog.php?category=5">Кровати</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="search-box">
|
||||||
|
<input type="text" placeholder="Поиск товаров" id="searchInput">
|
||||||
|
<span class="search-icon"><i class="fas fa-search"></i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="header__icons--top">
|
||||||
|
<?php if ($isLoggedIn): ?>
|
||||||
|
<!-- Иконка корзины -->
|
||||||
|
<a href="оформление_заказа.php" class="icon cart-icon">
|
||||||
|
<i class="fas fa-shopping-cart"></i>
|
||||||
|
<span class="cart-count">0</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Блок профиля -->
|
||||||
|
<div class="user-profile-dropdown">
|
||||||
|
<div class="user-profile-toggle">
|
||||||
|
<div class="user-avatar">
|
||||||
|
<?= !empty($userEmail) ? strtoupper(substr($userEmail, 0, 1)) : 'U' ?>
|
||||||
|
</div>
|
||||||
|
<div class="user-info">
|
||||||
|
<div class="user-email"><?= htmlspecialchars($userEmail) ?></div>
|
||||||
|
<div class="user-status <?= $isAdmin ? 'admin' : 'user' ?>">
|
||||||
|
<?= $isAdmin ? 'Админ' : 'Пользователь' ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<i class="fas fa-chevron-down dropdown-arrow"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="user-profile-menu">
|
||||||
|
<div class="user-profile-header">
|
||||||
|
<div class="user-profile-name">
|
||||||
|
<i class="fas fa-user"></i> <?= htmlspecialchars($fullName) ?>
|
||||||
|
</div>
|
||||||
|
<div class="user-profile-details">
|
||||||
|
<small><i class="far fa-envelope"></i> <?= htmlspecialchars($userEmail) ?></small>
|
||||||
|
<?php if (isset($_SESSION['login_time'])): ?>
|
||||||
|
<small><i class="far fa-clock"></i> Вошел: <?= date('d.m.Y H:i', $_SESSION['login_time']) ?></small>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="user-profile-links">
|
||||||
|
<li>
|
||||||
|
<a href="профиль.php">
|
||||||
|
<i class="fas fa-user-cog"></i>
|
||||||
|
<span>Настройки профиля</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="оформление_заказа.php">
|
||||||
|
<i class="fas fa-shopping-bag"></i>
|
||||||
|
<span>Мои заказы</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<?php if ($isAdmin): ?>
|
||||||
|
<li>
|
||||||
|
<a href="admin_panel.php">
|
||||||
|
<i class="fas fa-user-shield"></i>
|
||||||
|
<span>Панель администратора</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<?php endif; ?>
|
||||||
|
<li class="logout-item">
|
||||||
|
<a href="logout.php" class="logout-link">
|
||||||
|
<i class="fas fa-sign-out-alt"></i>
|
||||||
|
<span>Выйти из аккаунта</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php else: ?>
|
||||||
|
<!-- Если не авторизован -->
|
||||||
|
<a href="вход.php" class="icon">
|
||||||
|
<i class="far fa-user"></i>
|
||||||
|
</a>
|
||||||
|
<a href="вход.php" style="font-size: 12px; color: #666; margin-left: 5px;">
|
||||||
|
Войти
|
||||||
|
</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="header__bottom">
|
||||||
|
<div class="container header__bottom-content">
|
||||||
|
<div class="catalog-menu">
|
||||||
|
<a href="catalog.php" class="catalog-link">
|
||||||
|
<div class="catalog-icon">
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="line"></span>
|
||||||
|
<span class="line"></span>
|
||||||
|
</div>
|
||||||
|
<span class="catalog-lines">☰</span>
|
||||||
|
Каталог
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="nav">
|
||||||
|
<ul class="nav-list">
|
||||||
|
<li><a href="cite_mebel.php">Главная</a></li>
|
||||||
|
<li><a href="услуги.php">Услуги</a></li>
|
||||||
|
<li><a href="Доставка.php">Доставка и оплата</a></li>
|
||||||
|
<li><a href="Гарантия.php">Гарантия</a></li>
|
||||||
|
<li><a href="#footer">Контакты</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<div class="header-phone">+7(912)999-12-23</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
BIN
img/1_1.jpg
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
img/2_2.jpg
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
img/3_3.jpg
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
img/5_5.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
img/6_6.jpg
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
img/7_7.jpg
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
img/9_9.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
img/chair.PNG
Normal file
|
After Width: | Height: | Size: 144 KiB |
BIN
img/диван.jpg
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
img/диван_1.jpg
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
img/кресло.jpg
Normal file
|
After Width: | Height: | Size: 228 KiB |
BIN
img/кресло_1.jpg
Normal file
|
After Width: | Height: | Size: 294 KiB |
BIN
img/слайдер_1.jpg
Normal file
|
After Width: | Height: | Size: 187 KiB |
BIN
img/слайдер_2.jpg
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
img/слайдер_3.jpg
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
img/слайдер_4.jpg
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
img/слайдер_5.jpg
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
img/слайдер_6.jpg
Normal file
|
After Width: | Height: | Size: 306 KiB |
BIN
img/спальня.jpg
Normal file
|
After Width: | Height: | Size: 151 KiB |
62
img/стили_оформления.css
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
|
||||||
|
.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;
|
||||||
|
}
|
||||||
BIN
img2/1 — копия.jpg
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
img2/1.jpg
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
img2/100.jpg
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
img2/11.jpg
Normal file
|
After Width: | Height: | Size: 183 KiB |
BIN
img2/111.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
img2/11_1.png
Normal file
|
After Width: | Height: | Size: 177 KiB |
BIN
img2/1_2.jpg
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
img2/1_2.png
Normal file
|
After Width: | Height: | Size: 190 KiB |
BIN
img2/22.jpg
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
img2/25.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
img2/2_2.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
img2/2_2.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
img2/3.jpg
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
img2/3_3.png
Normal file
|
After Width: | Height: | Size: 414 KiB |
BIN
img2/4.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
img2/44.jpg
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
img2/444 (1).png
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
img2/444.jpg
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
img2/444.png
Normal file
|
After Width: | Height: | Size: 291 KiB |
BIN
img2/4_1.jpg
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
img2/5.jpg
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
img2/5_5.png
Normal file
|
After Width: | Height: | Size: 198 KiB |
BIN
img2/6.jpg
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
img2/6_6.png
Normal file
|
After Width: | Height: | Size: 372 KiB |
BIN
img2/7.jpg
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
img2/77.jpg
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
img2/777 (1).png
Normal file
|
After Width: | Height: | Size: 265 KiB |
BIN
img2/777.jpg
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
img2/777.png
Normal file
|
After Width: | Height: | Size: 555 KiB |
BIN
img2/7_7.png
Normal file
|
After Width: | Height: | Size: 479 KiB |
BIN
img2/8.jpg
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
img2/88.jpg
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
img2/888 (1).png
Normal file
|
After Width: | Height: | Size: 176 KiB |
BIN
img2/888.jpg
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
img2/888.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
img2/8_8.png
Normal file
|
After Width: | Height: | Size: 430 KiB |
BIN
img2/9.jpg
Normal file
|
After Width: | Height: | Size: 167 KiB |
BIN
img2/99.jpg
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
img2/99.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
img2/99_1.jpg
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
img2/99_2.jpg
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
img2/99_3.png
Normal file
|
After Width: | Height: | Size: 497 KiB |
BIN
img2/9_9.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
img2/9_9.png
Normal file
|
After Width: | Height: | Size: 759 KiB |
BIN
img2/black.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
img2/black1.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
img2/black2.png
Normal file
|
After Width: | Height: | Size: 654 KiB |
BIN
img2/brown.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
img2/brown1.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |