Delete comment
This commit is contained in:
1399
admin/index.php
1399
admin/index.php
File diff suppressed because it is too large
Load Diff
@@ -1,116 +1,112 @@
|
|||||||
<?php
|
<?php
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
|
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['product_id'])) {
|
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['product_id'])) {
|
||||||
$product_id = intval($_POST['product_id']);
|
$product_id = intval($_POST['product_id']);
|
||||||
$quantity = intval($_POST['quantity'] ?? 1);
|
$quantity = intval($_POST['quantity'] ?? 1);
|
||||||
$user_id = $_SESSION['user_id'] ?? 0;
|
$user_id = $_SESSION['user_id'] ?? 0;
|
||||||
|
|
||||||
if ($user_id == 0) {
|
if ($user_id == 0) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
|
echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Проверяем наличие товара на складе
|
|
||||||
$checkStock = $db->prepare("
|
$checkStock = $db->prepare("
|
||||||
SELECT stock_quantity, name, price
|
SELECT stock_quantity, name, price
|
||||||
FROM products
|
FROM products
|
||||||
WHERE product_id = ? AND is_available = TRUE
|
WHERE product_id = ? AND is_available = TRUE
|
||||||
");
|
");
|
||||||
$checkStock->execute([$product_id]);
|
$checkStock->execute([$product_id]);
|
||||||
$product = $checkStock->fetch();
|
$product = $checkStock->fetch();
|
||||||
|
|
||||||
if (!$product) {
|
if (!$product) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Товар не найден']);
|
echo json_encode(['success' => false, 'message' => 'Товар не найден']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($product['stock_quantity'] < $quantity) {
|
if ($product['stock_quantity'] < $quantity) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Недостаточно товара на складе']);
|
echo json_encode(['success' => false, 'message' => 'Недостаточно товара на складе']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, есть ли товар уже в корзине пользователя
|
$checkCart = $db->prepare("
|
||||||
$checkCart = $db->prepare("
|
SELECT cart_id, quantity
|
||||||
SELECT cart_id, quantity
|
FROM cart
|
||||||
FROM cart
|
WHERE user_id = ? AND product_id = ?
|
||||||
WHERE user_id = ? AND product_id = ?
|
");
|
||||||
");
|
$checkCart->execute([$user_id, $product_id]);
|
||||||
$checkCart->execute([$user_id, $product_id]);
|
$cartItem = $checkCart->fetch();
|
||||||
$cartItem = $checkCart->fetch();
|
|
||||||
|
if ($cartItem) {
|
||||||
if ($cartItem) {
|
|
||||||
// Обновляем количество
|
$newQuantity = $cartItem['quantity'] + $quantity;
|
||||||
$newQuantity = $cartItem['quantity'] + $quantity;
|
|
||||||
|
if ($newQuantity > $product['stock_quantity']) {
|
||||||
// Проверяем общее количество
|
echo json_encode(['success' => false, 'message' => 'Превышено доступное количество']);
|
||||||
if ($newQuantity > $product['stock_quantity']) {
|
exit();
|
||||||
echo json_encode(['success' => false, 'message' => 'Превышено доступное количество']);
|
}
|
||||||
exit();
|
|
||||||
}
|
$updateStmt = $db->prepare("
|
||||||
|
UPDATE cart
|
||||||
$updateStmt = $db->prepare("
|
SET quantity = ?, updated_at = CURRENT_TIMESTAMP
|
||||||
UPDATE cart
|
WHERE cart_id = ?
|
||||||
SET quantity = ?, updated_at = CURRENT_TIMESTAMP
|
");
|
||||||
WHERE cart_id = ?
|
$updateStmt->execute([$newQuantity, $cartItem['cart_id']]);
|
||||||
");
|
} else {
|
||||||
$updateStmt->execute([$newQuantity, $cartItem['cart_id']]);
|
|
||||||
} else {
|
$insertStmt = $db->prepare("
|
||||||
// Добавляем новый товар
|
INSERT INTO cart (user_id, product_id, quantity)
|
||||||
$insertStmt = $db->prepare("
|
VALUES (?, ?, ?)
|
||||||
INSERT INTO cart (user_id, product_id, quantity)
|
");
|
||||||
VALUES (?, ?, ?)
|
$insertStmt->execute([$user_id, $product_id, $quantity]);
|
||||||
");
|
}
|
||||||
$insertStmt->execute([$user_id, $product_id, $quantity]);
|
|
||||||
}
|
if (!isset($_SESSION['cart'])) {
|
||||||
|
$_SESSION['cart'] = [];
|
||||||
// Обновляем сессию
|
}
|
||||||
if (!isset($_SESSION['cart'])) {
|
|
||||||
$_SESSION['cart'] = [];
|
if (isset($_SESSION['cart'][$product_id])) {
|
||||||
}
|
$_SESSION['cart'][$product_id]['quantity'] += $quantity;
|
||||||
|
} else {
|
||||||
if (isset($_SESSION['cart'][$product_id])) {
|
$_SESSION['cart'][$product_id] = [
|
||||||
$_SESSION['cart'][$product_id]['quantity'] += $quantity;
|
'quantity' => $quantity,
|
||||||
} else {
|
'name' => $product['name'],
|
||||||
$_SESSION['cart'][$product_id] = [
|
'price' => $product['price'],
|
||||||
'quantity' => $quantity,
|
'added_at' => time()
|
||||||
'name' => $product['name'],
|
];
|
||||||
'price' => $product['price'],
|
}
|
||||||
'added_at' => time()
|
|
||||||
];
|
$cartCountStmt = $db->prepare("
|
||||||
}
|
SELECT SUM(quantity) as total
|
||||||
|
FROM cart
|
||||||
// Получаем общее количество товаров в корзине
|
WHERE user_id = ?
|
||||||
$cartCountStmt = $db->prepare("
|
");
|
||||||
SELECT SUM(quantity) as total
|
$cartCountStmt->execute([$user_id]);
|
||||||
FROM cart
|
$cart_count = $cartCountStmt->fetchColumn() ?: 0;
|
||||||
WHERE user_id = ?
|
|
||||||
");
|
echo json_encode([
|
||||||
$cartCountStmt->execute([$user_id]);
|
'success' => true,
|
||||||
$cart_count = $cartCountStmt->fetchColumn() ?: 0;
|
'cart_count' => $cart_count,
|
||||||
|
'message' => 'Товар добавлен в корзину'
|
||||||
echo json_encode([
|
]);
|
||||||
'success' => true,
|
|
||||||
'cart_count' => $cart_count,
|
} catch (PDOException $e) {
|
||||||
'message' => 'Товар добавлен в корзину'
|
echo json_encode([
|
||||||
]);
|
'success' => false,
|
||||||
|
'message' => 'Ошибка базы данных: ' . $e->getMessage()
|
||||||
} catch (PDOException $e) {
|
]);
|
||||||
echo json_encode([
|
}
|
||||||
'success' => false,
|
} else {
|
||||||
'message' => 'Ошибка базы данных: ' . $e->getMessage()
|
echo json_encode(['success' => false, 'message' => 'Неверный запрос']);
|
||||||
]);
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Неверный запрос']);
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
127
api/auth.php
127
api/auth.php
@@ -1,66 +1,63 @@
|
|||||||
<?php
|
<?php
|
||||||
// login_handler.php
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$email = $_POST['email'] ?? '';
|
$email = $_POST['email'] ?? '';
|
||||||
$password = $_POST['password'] ?? '';
|
$password = $_POST['password'] ?? '';
|
||||||
|
|
||||||
if (empty($email) || empty($password)) {
|
if (empty($email) || empty($password)) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Заполните все поля']);
|
echo json_encode(['success' => false, 'message' => 'Заполните все поля']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Проверяем пользователя в базе данных
|
|
||||||
$stmt = $db->prepare("
|
$stmt = $db->prepare("
|
||||||
SELECT user_id, email, password_hash, full_name, phone, city, is_admin, is_active
|
SELECT user_id, email, password_hash, full_name, phone, city, is_admin, is_active
|
||||||
FROM users
|
FROM users
|
||||||
WHERE email = ?
|
WHERE email = ?
|
||||||
");
|
");
|
||||||
$stmt->execute([$email]);
|
$stmt->execute([$email]);
|
||||||
$user = $stmt->fetch();
|
$user = $stmt->fetch();
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
|
echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$user['is_active']) {
|
if (!$user['is_active']) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Аккаунт заблокирован']);
|
echo json_encode(['success' => false, 'message' => 'Аккаунт заблокирован']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем пароль
|
if (!password_verify($password, $user['password_hash'])) {
|
||||||
if (!password_verify($password, $user['password_hash'])) {
|
echo json_encode(['success' => false, 'message' => 'Неверный пароль']);
|
||||||
echo json_encode(['success' => false, 'message' => 'Неверный пароль']);
|
exit();
|
||||||
exit();
|
}
|
||||||
}
|
|
||||||
|
$_SESSION['user_id'] = $user['user_id'];
|
||||||
// Сохраняем в сессию
|
$_SESSION['user_email'] = $user['email'];
|
||||||
$_SESSION['user_id'] = $user['user_id'];
|
$_SESSION['full_name'] = $user['full_name'];
|
||||||
$_SESSION['user_email'] = $user['email'];
|
$_SESSION['user_phone'] = $user['phone'] ?? '';
|
||||||
$_SESSION['full_name'] = $user['full_name'];
|
$_SESSION['user_city'] = $user['city'] ?? '';
|
||||||
$_SESSION['user_phone'] = $user['phone'] ?? '';
|
$_SESSION['isLoggedIn'] = true;
|
||||||
$_SESSION['user_city'] = $user['city'] ?? '';
|
$_SESSION['isAdmin'] = (bool)$user['is_admin'];
|
||||||
$_SESSION['isLoggedIn'] = true;
|
$_SESSION['login_time'] = time();
|
||||||
$_SESSION['isAdmin'] = (bool)$user['is_admin'];
|
|
||||||
$_SESSION['login_time'] = time();
|
$updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?");
|
||||||
|
$updateStmt->execute([$user['user_id']]);
|
||||||
// Обновляем время последнего входа
|
|
||||||
$updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?");
|
echo json_encode(['success' => true, 'redirect' => 'catalog.php']);
|
||||||
$updateStmt->execute([$user['user_id']]);
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
echo json_encode(['success' => true, 'redirect' => 'catalog.php']);
|
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных']);
|
||||||
|
}
|
||||||
} catch (PDOException $e) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных']);
|
} else {
|
||||||
}
|
echo json_encode(['success' => false, 'message' => 'Неверный запрос']);
|
||||||
|
}
|
||||||
} else {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Неверный запрос']);
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
57
api/cart.php
57
api/cart.php
@@ -1,14 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* API для работы с корзиной
|
|
||||||
* Эндпоинты: add, update, remove, get, count
|
|
||||||
*/
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
// Проверка авторизации
|
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
|
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
|
||||||
exit();
|
exit();
|
||||||
@@ -24,66 +20,64 @@ try {
|
|||||||
case 'add':
|
case 'add':
|
||||||
$productId = (int)($_POST['product_id'] ?? 0);
|
$productId = (int)($_POST['product_id'] ?? 0);
|
||||||
$quantity = (int)($_POST['quantity'] ?? 1);
|
$quantity = (int)($_POST['quantity'] ?? 1);
|
||||||
|
|
||||||
if ($productId <= 0) {
|
if ($productId <= 0) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Неверный ID товара']);
|
echo json_encode(['success' => false, 'message' => 'Неверный ID товара']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем существование товара
|
|
||||||
$checkProduct = $db->prepare("SELECT product_id, stock_quantity FROM products WHERE product_id = ? AND is_available = TRUE");
|
$checkProduct = $db->prepare("SELECT product_id, stock_quantity FROM products WHERE product_id = ? AND is_available = TRUE");
|
||||||
$checkProduct->execute([$productId]);
|
$checkProduct->execute([$productId]);
|
||||||
$product = $checkProduct->fetch();
|
$product = $checkProduct->fetch();
|
||||||
|
|
||||||
if (!$product) {
|
if (!$product) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Товар не найден']);
|
echo json_encode(['success' => false, 'message' => 'Товар не найден']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, есть ли товар уже в корзине
|
|
||||||
$checkCart = $db->prepare("SELECT cart_id, quantity FROM cart WHERE user_id = ? AND product_id = ?");
|
$checkCart = $db->prepare("SELECT cart_id, quantity FROM cart WHERE user_id = ? AND product_id = ?");
|
||||||
$checkCart->execute([$userId, $productId]);
|
$checkCart->execute([$userId, $productId]);
|
||||||
$cartItem = $checkCart->fetch();
|
$cartItem = $checkCart->fetch();
|
||||||
|
|
||||||
if ($cartItem) {
|
if ($cartItem) {
|
||||||
// Обновляем количество
|
|
||||||
$newQuantity = $cartItem['quantity'] + $quantity;
|
$newQuantity = $cartItem['quantity'] + $quantity;
|
||||||
$stmt = $db->prepare("UPDATE cart SET quantity = ?, updated_at = CURRENT_TIMESTAMP WHERE cart_id = ?");
|
$stmt = $db->prepare("UPDATE cart SET quantity = ?, updated_at = CURRENT_TIMESTAMP WHERE cart_id = ?");
|
||||||
$stmt->execute([$newQuantity, $cartItem['cart_id']]);
|
$stmt->execute([$newQuantity, $cartItem['cart_id']]);
|
||||||
} else {
|
} else {
|
||||||
// Добавляем новый товар
|
|
||||||
$stmt = $db->prepare("INSERT INTO cart (user_id, product_id, quantity) VALUES (?, ?, ?)");
|
$stmt = $db->prepare("INSERT INTO cart (user_id, product_id, quantity) VALUES (?, ?, ?)");
|
||||||
$stmt->execute([$userId, $productId, $quantity]);
|
$stmt->execute([$userId, $productId, $quantity]);
|
||||||
}
|
}
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Товар добавлен в корзину']);
|
echo json_encode(['success' => true, 'message' => 'Товар добавлен в корзину']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'update':
|
case 'update':
|
||||||
$productId = (int)($_POST['product_id'] ?? 0);
|
$productId = (int)($_POST['product_id'] ?? 0);
|
||||||
$quantity = (int)($_POST['quantity'] ?? 1);
|
$quantity = (int)($_POST['quantity'] ?? 1);
|
||||||
|
|
||||||
if ($quantity <= 0) {
|
if ($quantity <= 0) {
|
||||||
// Удаляем товар если количество 0
|
|
||||||
$stmt = $db->prepare("DELETE FROM cart WHERE user_id = ? AND product_id = ?");
|
$stmt = $db->prepare("DELETE FROM cart WHERE user_id = ? AND product_id = ?");
|
||||||
$stmt->execute([$userId, $productId]);
|
$stmt->execute([$userId, $productId]);
|
||||||
} else {
|
} else {
|
||||||
$stmt = $db->prepare("UPDATE cart SET quantity = ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ? AND product_id = ?");
|
$stmt = $db->prepare("UPDATE cart SET quantity = ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ? AND product_id = ?");
|
||||||
$stmt->execute([$quantity, $userId, $productId]);
|
$stmt->execute([$quantity, $userId, $productId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Корзина обновлена']);
|
echo json_encode(['success' => true, 'message' => 'Корзина обновлена']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'remove':
|
case 'remove':
|
||||||
$productId = (int)($_POST['product_id'] ?? 0);
|
$productId = (int)($_POST['product_id'] ?? 0);
|
||||||
|
|
||||||
$stmt = $db->prepare("DELETE FROM cart WHERE user_id = ? AND product_id = ?");
|
$stmt = $db->prepare("DELETE FROM cart WHERE user_id = ? AND product_id = ?");
|
||||||
$stmt->execute([$userId, $productId]);
|
$stmt->execute([$userId, $productId]);
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Товар удален из корзины']);
|
echo json_encode(['success' => true, 'message' => 'Товар удален из корзины']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'get':
|
case 'get':
|
||||||
$stmt = $db->prepare("
|
$stmt = $db->prepare("
|
||||||
SELECT c.cart_id, c.product_id, c.quantity, p.name, p.price, p.image_url, p.stock_quantity
|
SELECT c.cart_id, c.product_id, c.quantity, p.name, p.price, p.image_url, p.stock_quantity
|
||||||
@@ -94,13 +88,13 @@ try {
|
|||||||
");
|
");
|
||||||
$stmt->execute([$userId]);
|
$stmt->execute([$userId]);
|
||||||
$items = $stmt->fetchAll();
|
$items = $stmt->fetchAll();
|
||||||
|
|
||||||
$total = 0;
|
$total = 0;
|
||||||
foreach ($items as &$item) {
|
foreach ($items as &$item) {
|
||||||
$item['subtotal'] = $item['price'] * $item['quantity'];
|
$item['subtotal'] = $item['price'] * $item['quantity'];
|
||||||
$total += $item['subtotal'];
|
$total += $item['subtotal'];
|
||||||
}
|
}
|
||||||
|
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'items' => $items,
|
'items' => $items,
|
||||||
@@ -108,27 +102,26 @@ try {
|
|||||||
'count' => array_sum(array_column($items, 'quantity'))
|
'count' => array_sum(array_column($items, 'quantity'))
|
||||||
]);
|
]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'count':
|
case 'count':
|
||||||
$stmt = $db->prepare("SELECT COALESCE(SUM(quantity), 0) FROM cart WHERE user_id = ?");
|
$stmt = $db->prepare("SELECT COALESCE(SUM(quantity), 0) FROM cart WHERE user_id = ?");
|
||||||
$stmt->execute([$userId]);
|
$stmt->execute([$userId]);
|
||||||
$count = $stmt->fetchColumn();
|
$count = $stmt->fetchColumn();
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'count' => (int)$count]);
|
echo json_encode(['success' => true, 'count' => (int)$count]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'clear':
|
case 'clear':
|
||||||
$stmt = $db->prepare("DELETE FROM cart WHERE user_id = ?");
|
$stmt = $db->prepare("DELETE FROM cart WHERE user_id = ?");
|
||||||
$stmt->execute([$userId]);
|
$stmt->execute([$userId]);
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Корзина очищена']);
|
echo json_encode(['success' => true, 'message' => 'Корзина очищена']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
echo json_encode(['success' => false, 'message' => 'Неизвестное действие']);
|
echo json_encode(['success' => false, 'message' => 'Неизвестное действие']);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]);
|
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
121
api/get_cart.php
121
api/get_cart.php
@@ -1,62 +1,61 @@
|
|||||||
<?php
|
<?php
|
||||||
// get_cart.php
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
|
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_id = $_SESSION['user_id'] ?? 0;
|
$user_id = $_SESSION['user_id'] ?? 0;
|
||||||
|
|
||||||
if ($user_id == 0) {
|
if ($user_id == 0) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
|
echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Получаем корзину из БД
|
|
||||||
$stmt = $db->prepare("
|
$stmt = $db->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
c.cart_id,
|
c.cart_id,
|
||||||
c.product_id,
|
c.product_id,
|
||||||
c.quantity,
|
c.quantity,
|
||||||
p.name,
|
p.name,
|
||||||
p.price,
|
p.price,
|
||||||
p.image_url,
|
p.image_url,
|
||||||
p.stock_quantity
|
p.stock_quantity
|
||||||
FROM cart c
|
FROM cart c
|
||||||
JOIN products p ON c.product_id = p.product_id
|
JOIN products p ON c.product_id = p.product_id
|
||||||
WHERE c.user_id = ? AND p.is_available = TRUE
|
WHERE c.user_id = ? AND p.is_available = TRUE
|
||||||
ORDER BY c.created_at DESC
|
ORDER BY c.created_at DESC
|
||||||
");
|
");
|
||||||
$stmt->execute([$user_id]);
|
$stmt->execute([$user_id]);
|
||||||
$cart_items = $stmt->fetchAll();
|
$cart_items = $stmt->fetchAll();
|
||||||
|
|
||||||
// Обновляем сессию
|
$_SESSION['cart'] = [];
|
||||||
$_SESSION['cart'] = [];
|
foreach ($cart_items as $item) {
|
||||||
foreach ($cart_items as $item) {
|
$_SESSION['cart'][$item['product_id']] = [
|
||||||
$_SESSION['cart'][$item['product_id']] = [
|
'quantity' => $item['quantity'],
|
||||||
'quantity' => $item['quantity'],
|
'name' => $item['name'],
|
||||||
'name' => $item['name'],
|
'price' => $item['price'],
|
||||||
'price' => $item['price'],
|
'added_at' => time()
|
||||||
'added_at' => time()
|
];
|
||||||
];
|
}
|
||||||
}
|
|
||||||
|
echo json_encode([
|
||||||
echo json_encode([
|
'success' => true,
|
||||||
'success' => true,
|
'cart_items' => $cart_items,
|
||||||
'cart_items' => $cart_items,
|
'total_items' => count($cart_items)
|
||||||
'total_items' => count($cart_items)
|
]);
|
||||||
]);
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
} catch (PDOException $e) {
|
echo json_encode([
|
||||||
echo json_encode([
|
'success' => false,
|
||||||
'success' => false,
|
'message' => 'Ошибка базы данных: ' . $e->getMessage()
|
||||||
'message' => 'Ошибка базы данных: ' . $e->getMessage()
|
]);
|
||||||
]);
|
}
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
// get_cart_count.php
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
echo json_encode(['success' => false, 'cart_count' => 0]);
|
echo json_encode(['success' => false, 'cart_count' => 0]);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_id = $_SESSION['user_id'] ?? 0;
|
$user_id = $_SESSION['user_id'] ?? 0;
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$stmt = $db->prepare("SELECT SUM(quantity) as total FROM cart WHERE user_id = ?");
|
$stmt = $db->prepare("SELECT SUM(quantity) as total FROM cart WHERE user_id = ?");
|
||||||
$stmt->execute([$user_id]);
|
$stmt->execute([$user_id]);
|
||||||
$cart_count = $stmt->fetchColumn() ?: 0;
|
$cart_count = $stmt->fetchColumn() ?: 0;
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'cart_count' => $cart_count]);
|
echo json_encode(['success' => true, 'cart_count' => $cart_count]);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
echo json_encode(['success' => false, 'cart_count' => 0]);
|
echo json_encode(['success' => false, 'cart_count' => 0]);
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,32 @@
|
|||||||
<?php
|
<?php
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
// Проверяем авторизацию администратора
|
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
|
||||||
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
|
echo json_encode(['success' => false, 'message' => 'Доступ запрещен']);
|
||||||
echo json_encode(['success' => false, 'message' => 'Доступ запрещен']);
|
exit();
|
||||||
exit();
|
}
|
||||||
}
|
|
||||||
|
if (!isset($_GET['id'])) {
|
||||||
if (!isset($_GET['id'])) {
|
echo json_encode(['success' => false, 'message' => 'ID не указан']);
|
||||||
echo json_encode(['success' => false, 'message' => 'ID не указан']);
|
exit();
|
||||||
exit();
|
}
|
||||||
}
|
|
||||||
|
try {
|
||||||
try {
|
$db = Database::getInstance()->getConnection();
|
||||||
$db = Database::getInstance()->getConnection();
|
$product_id = $_GET['id'];
|
||||||
$product_id = $_GET['id'];
|
|
||||||
|
$stmt = $db->prepare("SELECT * FROM products WHERE product_id = ?");
|
||||||
$stmt = $db->prepare("SELECT * FROM products WHERE product_id = ?");
|
$stmt->execute([$product_id]);
|
||||||
$stmt->execute([$product_id]);
|
$product = $stmt->fetch();
|
||||||
$product = $stmt->fetch();
|
|
||||||
|
if ($product) {
|
||||||
if ($product) {
|
echo json_encode($product);
|
||||||
echo json_encode($product);
|
} else {
|
||||||
} else {
|
echo json_encode(['success' => false, 'message' => 'Товар не найден']);
|
||||||
echo json_encode(['success' => false, 'message' => 'Товар не найден']);
|
}
|
||||||
}
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
} catch (PDOException $e) {
|
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]);
|
||||||
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]);
|
}
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
@@ -1,134 +1,124 @@
|
|||||||
<?php
|
<?php
|
||||||
// process_order.php
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
header('Location: login.php?error=auth_required');
|
header('Location: login.php?error=auth_required');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_id = $_SESSION['user_id'] ?? 0;
|
$user_id = $_SESSION['user_id'] ?? 0;
|
||||||
|
|
||||||
if ($user_id == 0) {
|
if ($user_id == 0) {
|
||||||
header('Location: login.php?error=user_not_found');
|
header('Location: login.php?error=user_not_found');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$db->beginTransaction();
|
$db->beginTransaction();
|
||||||
|
|
||||||
// Получаем данные из формы
|
$customer_name = $_POST['full_name'] ?? '';
|
||||||
$customer_name = $_POST['full_name'] ?? '';
|
$customer_email = $_POST['email'] ?? '';
|
||||||
$customer_email = $_POST['email'] ?? '';
|
$customer_phone = $_POST['phone'] ?? '';
|
||||||
$customer_phone = $_POST['phone'] ?? '';
|
$delivery_address = $_POST['address'] ?? '';
|
||||||
$delivery_address = $_POST['address'] ?? '';
|
$region = $_POST['region'] ?? '';
|
||||||
$region = $_POST['region'] ?? '';
|
$payment_method = $_POST['payment'] ?? 'card';
|
||||||
$payment_method = $_POST['payment'] ?? 'card';
|
$delivery_method = $_POST['delivery'] ?? 'courier';
|
||||||
$delivery_method = $_POST['delivery'] ?? 'courier';
|
$notes = $_POST['notes'] ?? '';
|
||||||
$notes = $_POST['notes'] ?? '';
|
$discount_amount = floatval($_POST['discount'] ?? 0);
|
||||||
$discount_amount = floatval($_POST['discount'] ?? 0);
|
$delivery_cost = floatval($_POST['delivery_price'] ?? 2000);
|
||||||
$delivery_cost = floatval($_POST['delivery_price'] ?? 2000);
|
|
||||||
|
$order_number = 'ORD-' . date('Ymd-His') . '-' . rand(1000, 9999);
|
||||||
// Генерируем номер заказа
|
|
||||||
$order_number = 'ORD-' . date('Ymd-His') . '-' . rand(1000, 9999);
|
$cartStmt = $db->prepare("
|
||||||
|
SELECT
|
||||||
// Получаем корзину пользователя
|
c.product_id,
|
||||||
$cartStmt = $db->prepare("
|
c.quantity,
|
||||||
SELECT
|
p.name,
|
||||||
c.product_id,
|
p.price,
|
||||||
c.quantity,
|
p.stock_quantity
|
||||||
p.name,
|
FROM cart c
|
||||||
p.price,
|
JOIN products p ON c.product_id = p.product_id
|
||||||
p.stock_quantity
|
WHERE c.user_id = ?
|
||||||
FROM cart c
|
");
|
||||||
JOIN products p ON c.product_id = p.product_id
|
$cartStmt->execute([$user_id]);
|
||||||
WHERE c.user_id = ?
|
$cart_items = $cartStmt->fetchAll();
|
||||||
");
|
|
||||||
$cartStmt->execute([$user_id]);
|
if (empty($cart_items)) {
|
||||||
$cart_items = $cartStmt->fetchAll();
|
throw new Exception('Корзина пуста');
|
||||||
|
}
|
||||||
if (empty($cart_items)) {
|
|
||||||
throw new Exception('Корзина пуста');
|
$total_amount = 0;
|
||||||
}
|
foreach ($cart_items as $item) {
|
||||||
|
$total_amount += $item['price'] * $item['quantity'];
|
||||||
// Рассчитываем итоги
|
}
|
||||||
$total_amount = 0;
|
|
||||||
foreach ($cart_items as $item) {
|
$final_amount = $total_amount - $discount_amount + $delivery_cost;
|
||||||
$total_amount += $item['price'] * $item['quantity'];
|
|
||||||
}
|
$orderStmt = $db->prepare("
|
||||||
|
INSERT INTO orders (
|
||||||
$final_amount = $total_amount - $discount_amount + $delivery_cost;
|
user_id, order_number, total_amount, discount_amount,
|
||||||
|
delivery_cost, final_amount, status, payment_method,
|
||||||
// Создаем заказ
|
delivery_method, delivery_address, customer_name,
|
||||||
$orderStmt = $db->prepare("
|
customer_email, customer_phone, notes
|
||||||
INSERT INTO orders (
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
user_id, order_number, total_amount, discount_amount,
|
RETURNING order_id
|
||||||
delivery_cost, final_amount, status, payment_method,
|
");
|
||||||
delivery_method, delivery_address, customer_name,
|
|
||||||
customer_email, customer_phone, notes
|
$orderStmt->execute([
|
||||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
$user_id, $order_number, $total_amount, $discount_amount,
|
||||||
RETURNING order_id
|
$delivery_cost, $final_amount, 'pending', $payment_method,
|
||||||
");
|
$delivery_method, $delivery_address, $customer_name,
|
||||||
|
$customer_email, $customer_phone, $notes
|
||||||
$orderStmt->execute([
|
]);
|
||||||
$user_id, $order_number, $total_amount, $discount_amount,
|
|
||||||
$delivery_cost, $final_amount, 'pending', $payment_method,
|
$order_id = $orderStmt->fetchColumn();
|
||||||
$delivery_method, $delivery_address, $customer_name,
|
|
||||||
$customer_email, $customer_phone, $notes
|
foreach ($cart_items as $item) {
|
||||||
]);
|
|
||||||
|
$itemStmt = $db->prepare("
|
||||||
$order_id = $orderStmt->fetchColumn();
|
INSERT INTO order_items (
|
||||||
|
order_id, product_id, product_name,
|
||||||
// Добавляем товары в заказ и обновляем остатки
|
quantity, unit_price, total_price
|
||||||
foreach ($cart_items as $item) {
|
) VALUES (?, ?, ?, ?, ?, ?)
|
||||||
// Добавляем в order_items
|
");
|
||||||
$itemStmt = $db->prepare("
|
|
||||||
INSERT INTO order_items (
|
$item_total = $item['price'] * $item['quantity'];
|
||||||
order_id, product_id, product_name,
|
$itemStmt->execute([
|
||||||
quantity, unit_price, total_price
|
$order_id, $item['product_id'], $item['name'],
|
||||||
) VALUES (?, ?, ?, ?, ?, ?)
|
$item['quantity'], $item['price'], $item_total
|
||||||
");
|
]);
|
||||||
|
|
||||||
$item_total = $item['price'] * $item['quantity'];
|
$updateStmt = $db->prepare("
|
||||||
$itemStmt->execute([
|
UPDATE products
|
||||||
$order_id, $item['product_id'], $item['name'],
|
SET stock_quantity = stock_quantity - ?,
|
||||||
$item['quantity'], $item['price'], $item_total
|
updated_at = CURRENT_TIMESTAMP
|
||||||
]);
|
WHERE product_id = ?
|
||||||
|
");
|
||||||
// Обновляем остатки на складе
|
$updateStmt->execute([$item['quantity'], $item['product_id']]);
|
||||||
$updateStmt = $db->prepare("
|
}
|
||||||
UPDATE products
|
|
||||||
SET stock_quantity = stock_quantity - ?,
|
$clearCartStmt = $db->prepare("DELETE FROM cart WHERE user_id = ?");
|
||||||
updated_at = CURRENT_TIMESTAMP
|
$clearCartStmt->execute([$user_id]);
|
||||||
WHERE product_id = ?
|
|
||||||
");
|
unset($_SESSION['cart']);
|
||||||
$updateStmt->execute([$item['quantity'], $item['product_id']]);
|
|
||||||
}
|
$db->commit();
|
||||||
|
|
||||||
// Очищаем корзину
|
header('Location: order_success.php?id=' . $order_id);
|
||||||
$clearCartStmt = $db->prepare("DELETE FROM cart WHERE user_id = ?");
|
exit();
|
||||||
$clearCartStmt->execute([$user_id]);
|
|
||||||
|
} catch (Exception $e) {
|
||||||
// Очищаем сессию
|
$db->rollBack();
|
||||||
unset($_SESSION['cart']);
|
header('Location: checkout.php?error=' . urlencode($e->getMessage()));
|
||||||
|
exit();
|
||||||
$db->commit();
|
}
|
||||||
|
} else {
|
||||||
// Перенаправляем на страницу успеха
|
header('Location: checkout.php');
|
||||||
header('Location: order_success.php?id=' . $order_id);
|
exit();
|
||||||
exit();
|
}
|
||||||
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$db->rollBack();
|
|
||||||
header('Location: checkout.php?error=' . urlencode($e->getMessage()));
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
header('Location: checkout.php');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
@@ -1,182 +1,151 @@
|
|||||||
<?php
|
<?php
|
||||||
// register_handler.php
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$errors = [];
|
$errors = [];
|
||||||
|
|
||||||
// Получаем данные из формы
|
$full_name = trim($_POST['fio'] ?? '');
|
||||||
$full_name = trim($_POST['fio'] ?? '');
|
$city = trim($_POST['city'] ?? '');
|
||||||
$city = trim($_POST['city'] ?? '');
|
$email = trim($_POST['email'] ?? '');
|
||||||
$email = trim($_POST['email'] ?? '');
|
$phone = trim($_POST['phone'] ?? '');
|
||||||
$phone = trim($_POST['phone'] ?? '');
|
$password = $_POST['password'] ?? '';
|
||||||
$password = $_POST['password'] ?? '';
|
$confirm_password = $_POST['confirm-password'] ?? '';
|
||||||
$confirm_password = $_POST['confirm-password'] ?? '';
|
|
||||||
|
if (empty($full_name) || strlen($full_name) < 3) {
|
||||||
// Валидация данных
|
$errors[] = 'ФИО должно содержать минимум 3 символа';
|
||||||
if (empty($full_name) || strlen($full_name) < 3) {
|
}
|
||||||
$errors[] = 'ФИО должно содержать минимум 3 символа';
|
|
||||||
}
|
if (empty($city) || strlen($city) < 2) {
|
||||||
|
$errors[] = 'Введите корректное название города';
|
||||||
if (empty($city) || strlen($city) < 2) {
|
}
|
||||||
$errors[] = 'Введите корректное название города';
|
|
||||||
}
|
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$errors[] = 'Введите корректный email адрес';
|
||||||
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
}
|
||||||
$errors[] = 'Введите корректный email адрес';
|
|
||||||
}
|
if (empty($phone) || !preg_match('/^(\+7|8)[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/', $phone)) {
|
||||||
|
$errors[] = 'Введите корректный номер телефона';
|
||||||
if (empty($phone) || !preg_match('/^(\+7|8)[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/', $phone)) {
|
}
|
||||||
$errors[] = 'Введите корректный номер телефона';
|
|
||||||
}
|
if (empty($password) || strlen($password) < 6) {
|
||||||
|
$errors[] = 'Пароль должен содержать минимум 6 символов';
|
||||||
if (empty($password) || strlen($password) < 6) {
|
}
|
||||||
$errors[] = 'Пароль должен содержать минимум 6 символов';
|
|
||||||
}
|
if ($password !== $confirm_password) {
|
||||||
|
$errors[] = 'Пароли не совпадают';
|
||||||
if ($password !== $confirm_password) {
|
}
|
||||||
$errors[] = 'Пароли не совпадают';
|
|
||||||
}
|
if (!isset($_POST['privacy']) || $_POST['privacy'] !== 'on') {
|
||||||
|
$errors[] = 'Необходимо согласие с условиями обработки персональных данных';
|
||||||
// Проверка согласия с условиями
|
}
|
||||||
if (!isset($_POST['privacy']) || $_POST['privacy'] !== 'on') {
|
|
||||||
$errors[] = 'Необходимо согласие с условиями обработки персональных данных';
|
if (!empty($errors)) {
|
||||||
}
|
$_SESSION['registration_errors'] = $errors;
|
||||||
|
$_SESSION['old_data'] = [
|
||||||
// Если есть ошибки, возвращаем на форму
|
'fio' => $full_name,
|
||||||
if (!empty($errors)) {
|
'city' => $city,
|
||||||
$_SESSION['registration_errors'] = $errors;
|
'email' => $email,
|
||||||
$_SESSION['old_data'] = [
|
'phone' => $phone
|
||||||
'fio' => $full_name,
|
];
|
||||||
'city' => $city,
|
header('Location: register.php');
|
||||||
'email' => $email,
|
exit();
|
||||||
'phone' => $phone
|
}
|
||||||
];
|
|
||||||
header('Location: register.php');
|
$db = Database::getInstance()->getConnection();
|
||||||
exit();
|
|
||||||
}
|
try {
|
||||||
|
|
||||||
// Подключаемся к базе данных
|
$checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?");
|
||||||
$db = Database::getInstance()->getConnection();
|
$checkStmt->execute([$email]);
|
||||||
|
|
||||||
try {
|
if ($checkStmt->fetch()) {
|
||||||
// Проверяем, существует ли пользователь с таким email
|
$_SESSION['registration_errors'] = ['Пользователь с таким email уже существует'];
|
||||||
$checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?");
|
$_SESSION['old_data'] = [
|
||||||
$checkStmt->execute([$email]);
|
'fio' => $full_name,
|
||||||
|
'city' => $city,
|
||||||
if ($checkStmt->fetch()) {
|
'email' => $email,
|
||||||
$_SESSION['registration_errors'] = ['Пользователь с таким email уже существует'];
|
'phone' => $phone
|
||||||
$_SESSION['old_data'] = [
|
];
|
||||||
'fio' => $full_name,
|
header('Location: register.php');
|
||||||
'city' => $city,
|
exit();
|
||||||
'email' => $email,
|
}
|
||||||
'phone' => $phone
|
|
||||||
];
|
$password_hash = password_hash($password, PASSWORD_DEFAULT);
|
||||||
header('Location: register.php');
|
|
||||||
exit();
|
$is_admin = false;
|
||||||
}
|
$admin_emails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru'];
|
||||||
|
if (in_array(strtolower($email), $admin_emails)) {
|
||||||
// Хэшируем пароль
|
$is_admin = true;
|
||||||
$password_hash = password_hash($password, PASSWORD_DEFAULT);
|
}
|
||||||
|
|
||||||
// Определяем, является ли пользователь администратором
|
$stmt = $db->prepare("
|
||||||
$is_admin = false;
|
INSERT INTO users (email, password_hash, full_name, phone, city, is_admin)
|
||||||
$admin_emails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru'];
|
VALUES (?, ?, ?, ?, ?, ?)
|
||||||
if (in_array(strtolower($email), $admin_emails)) {
|
RETURNING user_id
|
||||||
$is_admin = true;
|
");
|
||||||
}
|
|
||||||
|
$stmt->execute([
|
||||||
// РАЗНЫЕ ВАРИАНТЫ ДЛЯ ТЕСТИРОВАНИЯ - РАСКОММЕНТИРУЙТЕ НУЖНЫЙ
|
$email,
|
||||||
|
$password_hash,
|
||||||
// Вариант 1: С явным преобразованием boolean (самый надежный)
|
$full_name,
|
||||||
$stmt = $db->prepare("
|
$phone,
|
||||||
INSERT INTO users (email, password_hash, full_name, phone, city, is_admin)
|
$city,
|
||||||
VALUES (?, ?, ?, ?, ?, ?)
|
$is_admin ? 1 : 0
|
||||||
RETURNING user_id
|
]);
|
||||||
");
|
|
||||||
|
$user_id = $stmt->fetchColumn();
|
||||||
// Преобразуем boolean в integer для PostgreSQL
|
|
||||||
$stmt->execute([
|
if ($user_id) {
|
||||||
$email,
|
|
||||||
$password_hash,
|
$_SESSION['user_id'] = $user_id;
|
||||||
$full_name,
|
$_SESSION['user_email'] = $email;
|
||||||
$phone,
|
$_SESSION['full_name'] = $full_name;
|
||||||
$city,
|
$_SESSION['user_phone'] = $phone;
|
||||||
$is_admin ? 1 : 0 // Преобразуем в integer (1 или 0)
|
$_SESSION['user_city'] = $city;
|
||||||
]);
|
$_SESSION['isLoggedIn'] = true;
|
||||||
|
$_SESSION['isAdmin'] = $is_admin;
|
||||||
// Вариант 2: С использованием CAST в SQL (альтернатива)
|
$_SESSION['login_time'] = time();
|
||||||
/*
|
|
||||||
$stmt = $db->prepare("
|
$updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?");
|
||||||
INSERT INTO users (email, password_hash, full_name, phone, city, is_admin)
|
$updateStmt->execute([$user_id]);
|
||||||
VALUES (?, ?, ?, ?, ?, CAST(? AS boolean))
|
|
||||||
RETURNING user_id
|
$_SESSION['registration_success'] = 'Регистрация прошла успешно! ' .
|
||||||
");
|
($is_admin ? 'Вы зарегистрированы как администратор.' : 'Добро пожаловать в AETERNA!');
|
||||||
|
|
||||||
$stmt->execute([
|
header('Location: catalog.php');
|
||||||
$email,
|
exit();
|
||||||
$password_hash,
|
} else {
|
||||||
$full_name,
|
throw new Exception('Ошибка при создании пользователя');
|
||||||
$phone,
|
}
|
||||||
$city,
|
|
||||||
$is_admin ? 'true' : 'false' // Строковые значения true/false
|
} catch (PDOException $e) {
|
||||||
]);
|
|
||||||
*/
|
error_log("Registration DB Error: " . $e->getMessage());
|
||||||
|
error_log("SQL State: " . $e->getCode());
|
||||||
$user_id = $stmt->fetchColumn();
|
error_log("Email: " . $email);
|
||||||
|
|
||||||
if ($user_id) {
|
$_SESSION['registration_errors'] = ['Ошибка базы данных: ' . $e->getMessage()];
|
||||||
// Автоматически авторизуем пользователя
|
$_SESSION['old_data'] = [
|
||||||
$_SESSION['user_id'] = $user_id;
|
'fio' => $full_name,
|
||||||
$_SESSION['user_email'] = $email;
|
'city' => $city,
|
||||||
$_SESSION['full_name'] = $full_name;
|
'email' => $email,
|
||||||
$_SESSION['user_phone'] = $phone;
|
'phone' => $phone
|
||||||
$_SESSION['user_city'] = $city;
|
];
|
||||||
$_SESSION['isLoggedIn'] = true;
|
header('Location: register.php');
|
||||||
$_SESSION['isAdmin'] = $is_admin;
|
exit();
|
||||||
$_SESSION['login_time'] = time();
|
} catch (Exception $e) {
|
||||||
|
error_log("Registration Error: " . $e->getMessage());
|
||||||
// Обновляем время последнего входа
|
|
||||||
$updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?");
|
$_SESSION['registration_errors'] = [$e->getMessage()];
|
||||||
$updateStmt->execute([$user_id]);
|
header('Location: register.php');
|
||||||
|
exit();
|
||||||
// Перенаправляем на главную или каталог
|
}
|
||||||
$_SESSION['registration_success'] = 'Регистрация прошла успешно! ' .
|
|
||||||
($is_admin ? 'Вы зарегистрированы как администратор.' : 'Добро пожаловать в AETERNA!');
|
} else {
|
||||||
|
|
||||||
header('Location: catalog.php');
|
header('Location: register.php');
|
||||||
exit();
|
exit();
|
||||||
} else {
|
}
|
||||||
throw new Exception('Ошибка при создании пользователя');
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
// Логируем полную ошибку для отладки
|
|
||||||
error_log("Registration DB Error: " . $e->getMessage());
|
|
||||||
error_log("SQL State: " . $e->getCode());
|
|
||||||
error_log("Email: " . $email);
|
|
||||||
|
|
||||||
$_SESSION['registration_errors'] = ['Ошибка базы данных: ' . $e->getMessage()];
|
|
||||||
$_SESSION['old_data'] = [
|
|
||||||
'fio' => $full_name,
|
|
||||||
'city' => $city,
|
|
||||||
'email' => $email,
|
|
||||||
'phone' => $phone
|
|
||||||
];
|
|
||||||
header('Location: register.php');
|
|
||||||
exit();
|
|
||||||
} catch (Exception $e) {
|
|
||||||
error_log("Registration Error: " . $e->getMessage());
|
|
||||||
|
|
||||||
$_SESSION['registration_errors'] = [$e->getMessage()];
|
|
||||||
header('Location: register.php');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Если запрос не POST, перенаправляем на форму регистрации
|
|
||||||
header('Location: register.php');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
@@ -1,62 +1,61 @@
|
|||||||
|
|
||||||
.error-message {
|
.error-message {
|
||||||
color: #ff0000;
|
color: #ff0000;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__input.error {
|
.form__input.error {
|
||||||
border-color: #ff0000;
|
border-color: #ff0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__group {
|
.form__group {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Стили для сообщений внизу страницы */
|
.page-messages {
|
||||||
.page-messages {
|
position: fixed;
|
||||||
position: fixed;
|
bottom: 20px;
|
||||||
bottom: 20px;
|
left: 50%;
|
||||||
left: 50%;
|
transform: translateX(-50%);
|
||||||
transform: translateX(-50%);
|
z-index: 1000;
|
||||||
z-index: 1000;
|
width: 90%;
|
||||||
width: 90%;
|
max-width: 500px;
|
||||||
max-width: 500px;
|
}
|
||||||
}
|
|
||||||
|
.message {
|
||||||
.message {
|
padding: 15px;
|
||||||
padding: 15px;
|
margin: 10px 0;
|
||||||
margin: 10px 0;
|
border-radius: 5px;
|
||||||
border-radius: 5px;
|
text-align: center;
|
||||||
text-align: center;
|
font-weight: bold;
|
||||||
font-weight: bold;
|
display: none;
|
||||||
display: none;
|
}
|
||||||
}
|
|
||||||
|
.message.error {
|
||||||
.message.error {
|
background-color: #ffebee;
|
||||||
background-color: #ffebee;
|
color: #c62828;
|
||||||
color: #c62828;
|
border: 1px solid #ffcdd2;
|
||||||
border: 1px solid #ffcdd2;
|
}
|
||||||
}
|
|
||||||
|
.message.success {
|
||||||
.message.success {
|
background-color: #e8f5e9;
|
||||||
background-color: #e8f5e9;
|
color: #453227;
|
||||||
color: #453227;
|
border: 1px solid #c8e6c9;
|
||||||
border: 1px solid #c8e6c9;
|
}
|
||||||
}
|
|
||||||
|
.message.warning {
|
||||||
.message.warning {
|
background-color: #fff3e0;
|
||||||
background-color: #fff3e0;
|
color: #ef6c00;
|
||||||
color: #ef6c00;
|
border: 1px solid #ffe0b2;
|
||||||
border: 1px solid #ffe0b2;
|
}
|
||||||
}
|
|
||||||
|
.privacy-error {
|
||||||
.privacy-error {
|
color: #ff0000;
|
||||||
color: #ff0000;
|
font-size: 12px;
|
||||||
font-size: 12px;
|
margin-top: 5px;
|
||||||
margin-top: 5px;
|
display: none;
|
||||||
display: none;
|
text-align: center;
|
||||||
text-align: center;
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,346 +1,306 @@
|
|||||||
// script.js
|
|
||||||
|
$(document).ready(function() {
|
||||||
$(document).ready(function() {
|
|
||||||
// Инициализация корзины
|
let cart = {
|
||||||
let cart = {
|
items: [
|
||||||
items: [
|
{ id: 1, name: 'Кресло OPPORTUNITY', price: 16999, quantity: 1 },
|
||||||
{ id: 1, name: 'Кресло OPPORTUNITY', price: 16999, quantity: 1 },
|
{ id: 2, name: 'Кресло GOLDEN', price: 19999, quantity: 1 },
|
||||||
{ id: 2, name: 'Кресло GOLDEN', price: 19999, quantity: 1 },
|
{ id: 3, name: 'Светильник POLET', price: 7999, quantity: 1 }
|
||||||
{ id: 3, name: 'Светильник POLET', price: 7999, quantity: 1 }
|
],
|
||||||
],
|
delivery: 2000,
|
||||||
delivery: 2000,
|
discount: 0
|
||||||
discount: 0
|
};
|
||||||
};
|
|
||||||
|
function updateTotal() {
|
||||||
// Функция обновления общей суммы
|
let productsTotal = 0;
|
||||||
function updateTotal() {
|
let totalCount = 0;
|
||||||
let productsTotal = 0;
|
|
||||||
let totalCount = 0;
|
$('.products__item').each(function() {
|
||||||
|
const $item = $(this);
|
||||||
// Пересчитываем товары
|
const price = parseInt($item.data('price'));
|
||||||
$('.products__item').each(function() {
|
const quantity = parseInt($item.find('.products__qty-value').text());
|
||||||
const $item = $(this);
|
|
||||||
const price = parseInt($item.data('price'));
|
productsTotal += price * quantity;
|
||||||
const quantity = parseInt($item.find('.products__qty-value').text());
|
totalCount += quantity;
|
||||||
|
});
|
||||||
productsTotal += price * quantity;
|
|
||||||
totalCount += quantity;
|
$('.products-total').text(productsTotal + ' ₽');
|
||||||
});
|
$('.summary-count').text(totalCount);
|
||||||
|
$('.total-count').text(totalCount + ' шт.');
|
||||||
// Обновляем отображение
|
$('.cart-count').text(totalCount);
|
||||||
$('.products-total').text(productsTotal + ' ₽');
|
|
||||||
$('.summary-count').text(totalCount);
|
const finalTotal = productsTotal + cart.delivery - cart.discount;
|
||||||
$('.total-count').text(totalCount + ' шт.');
|
$('.final-total').text(finalTotal + ' ₽');
|
||||||
$('.cart-count').text(totalCount);
|
}
|
||||||
|
|
||||||
// Обновляем итоговую сумму
|
function validateEmail(email) {
|
||||||
const finalTotal = productsTotal + cart.delivery - cart.discount;
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
$('.final-total').text(finalTotal + ' ₽');
|
return emailRegex.test(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Функция валидации email
|
function validateFullName(name) {
|
||||||
function validateEmail(email) {
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
const nameRegex = /^[a-zA-Zа-яА-ЯёЁ\s\-']+$/;
|
||||||
return emailRegex.test(email);
|
|
||||||
}
|
const words = name.trim().split(/\s+/);
|
||||||
|
|
||||||
// Функция валидации имени (ФИО)
|
return nameRegex.test(name) && words.length >= 2;
|
||||||
function validateFullName(name) {
|
}
|
||||||
// Проверяем, что имя содержит только буквы, пробелы, дефисы и апострофы
|
|
||||||
const nameRegex = /^[a-zA-Zа-яА-ЯёЁ\s\-']+$/;
|
function validatePhone(phone) {
|
||||||
|
const phoneRegex = /^\+7\d{10}$/;
|
||||||
// Проверяем, что имя состоит минимум из 2 слов
|
return phoneRegex.test(phone);
|
||||||
const words = name.trim().split(/\s+/);
|
}
|
||||||
|
|
||||||
return nameRegex.test(name) && words.length >= 2;
|
function showMessage(messageId, duration = 5000) {
|
||||||
}
|
$('.message').hide();
|
||||||
|
|
||||||
// Функция валидации телефона
|
$(messageId).fadeIn(300);
|
||||||
function validatePhone(phone) {
|
|
||||||
// Российский формат телефона: +7XXXXXXXXXX
|
if (duration > 0) {
|
||||||
const phoneRegex = /^\+7\d{10}$/;
|
setTimeout(() => {
|
||||||
return phoneRegex.test(phone);
|
$(messageId).fadeOut(300);
|
||||||
}
|
}, duration);
|
||||||
|
}
|
||||||
// Функция отображения сообщения
|
}
|
||||||
function showMessage(messageId, duration = 5000) {
|
|
||||||
// Скрываем все сообщения
|
function showPrivacyError(show) {
|
||||||
$('.message').hide();
|
if (show) {
|
||||||
|
$('#privacy-error').show();
|
||||||
// Показываем нужное сообщение
|
} else {
|
||||||
$(messageId).fadeIn(300);
|
$('#privacy-error').hide();
|
||||||
|
}
|
||||||
// Автоматически скрываем через указанное время
|
}
|
||||||
if (duration > 0) {
|
|
||||||
setTimeout(() => {
|
function showFieldError(fieldId, message) {
|
||||||
$(messageId).fadeOut(300);
|
$(fieldId).removeClass('error-input');
|
||||||
}, duration);
|
$(fieldId + '-error').remove();
|
||||||
}
|
|
||||||
}
|
if (message) {
|
||||||
|
$(fieldId).addClass('error-input');
|
||||||
// Функция показа ошибки приватности
|
$(fieldId).after('<div class="field-error" id="' + fieldId.replace('#', '') + '-error">' + message + '</div>');
|
||||||
function showPrivacyError(show) {
|
}
|
||||||
if (show) {
|
}
|
||||||
$('#privacy-error').show();
|
|
||||||
} else {
|
$('#fullname').on('blur', function() {
|
||||||
$('#privacy-error').hide();
|
const value = $(this).val().trim();
|
||||||
}
|
if (value) {
|
||||||
}
|
if (!validateFullName(value)) {
|
||||||
|
showFieldError('#fullname', 'ФИО должно содержать только буквы и состоять минимум из 2 слов');
|
||||||
// Функция отображения ошибки конкретного поля
|
} else {
|
||||||
function showFieldError(fieldId, message) {
|
showFieldError('#fullname', '');
|
||||||
// Убираем старые ошибки
|
}
|
||||||
$(fieldId).removeClass('error-input');
|
} else {
|
||||||
$(fieldId + '-error').remove();
|
showFieldError('#fullname', '');
|
||||||
|
}
|
||||||
if (message) {
|
});
|
||||||
$(fieldId).addClass('error-input');
|
|
||||||
$(fieldId).after('<div class="field-error" id="' + fieldId.replace('#', '') + '-error">' + message + '</div>');
|
$('#email').on('blur', function() {
|
||||||
}
|
const value = $(this).val().trim();
|
||||||
}
|
if (value) {
|
||||||
|
if (!validateEmail(value)) {
|
||||||
// Валидация поля при потере фокуса с указанием конкретной ошибки
|
showFieldError('#email', 'Введите корректный email адрес (например: example@mail.ru)');
|
||||||
$('#fullname').on('blur', function() {
|
} else {
|
||||||
const value = $(this).val().trim();
|
showFieldError('#email', '');
|
||||||
if (value) {
|
}
|
||||||
if (!validateFullName(value)) {
|
} else {
|
||||||
showFieldError('#fullname', 'ФИО должно содержать только буквы и состоять минимум из 2 слов');
|
showFieldError('#email', '');
|
||||||
} else {
|
}
|
||||||
showFieldError('#fullname', '');
|
});
|
||||||
}
|
|
||||||
} else {
|
$('#phone').on('blur', function() {
|
||||||
showFieldError('#fullname', '');
|
const value = $(this).val().trim();
|
||||||
}
|
if (value) {
|
||||||
});
|
if (!validatePhone(value)) {
|
||||||
|
showFieldError('#phone', 'Введите номер в формате +7XXXXXXXXXX (10 цифр после +7)');
|
||||||
$('#email').on('blur', function() {
|
} else {
|
||||||
const value = $(this).val().trim();
|
showFieldError('#phone', '');
|
||||||
if (value) {
|
}
|
||||||
if (!validateEmail(value)) {
|
} else {
|
||||||
showFieldError('#email', 'Введите корректный email адрес (например: example@mail.ru)');
|
showFieldError('#phone', '');
|
||||||
} else {
|
}
|
||||||
showFieldError('#email', '');
|
});
|
||||||
}
|
|
||||||
} else {
|
$('#region').on('blur', function() {
|
||||||
showFieldError('#email', '');
|
const value = $(this).val().trim();
|
||||||
}
|
if (!value) {
|
||||||
});
|
showFieldError('#region', 'Укажите регион доставки');
|
||||||
|
} else {
|
||||||
$('#phone').on('blur', function() {
|
showFieldError('#region', '');
|
||||||
const value = $(this).val().trim();
|
}
|
||||||
if (value) {
|
});
|
||||||
if (!validatePhone(value)) {
|
|
||||||
showFieldError('#phone', 'Введите номер в формате +7XXXXXXXXXX (10 цифр после +7)');
|
$('#address').on('blur', function() {
|
||||||
} else {
|
const value = $(this).val().trim();
|
||||||
showFieldError('#phone', '');
|
if (!value) {
|
||||||
}
|
showFieldError('#address', 'Укажите адрес доставки (улица, дом, квартира)');
|
||||||
} else {
|
} else {
|
||||||
showFieldError('#phone', '');
|
showFieldError('#address', '');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Валидация обязательных полей
|
$('.form__input').on('input', function() {
|
||||||
$('#region').on('blur', function() {
|
const fieldId = '#' + $(this).attr('id');
|
||||||
const value = $(this).val().trim();
|
showFieldError(fieldId, '');
|
||||||
if (!value) {
|
});
|
||||||
showFieldError('#region', 'Укажите регион доставки');
|
|
||||||
} else {
|
$('.products__qty-btn.plus').click(function() {
|
||||||
showFieldError('#region', '');
|
const $qtyValue = $(this).siblings('.products__qty-value');
|
||||||
}
|
let quantity = parseInt($qtyValue.text());
|
||||||
});
|
$qtyValue.text(quantity + 1);
|
||||||
|
updateTotal();
|
||||||
$('#address').on('blur', function() {
|
});
|
||||||
const value = $(this).val().trim();
|
|
||||||
if (!value) {
|
$('.products__qty-btn.minus').click(function() {
|
||||||
showFieldError('#address', 'Укажите адрес доставки (улица, дом, квартира)');
|
const $qtyValue = $(this).siblings('.products__qty-value');
|
||||||
} else {
|
let quantity = parseInt($qtyValue.text());
|
||||||
showFieldError('#address', '');
|
if (quantity > 1) {
|
||||||
}
|
$qtyValue.text(quantity - 1);
|
||||||
});
|
updateTotal();
|
||||||
|
}
|
||||||
// Очистка ошибки при начале ввода
|
});
|
||||||
$('.form__input').on('input', function() {
|
|
||||||
const fieldId = '#' + $(this).attr('id');
|
$('.remove-from-cart').click(function() {
|
||||||
showFieldError(fieldId, '');
|
const $productItem = $(this).closest('.products__item');
|
||||||
});
|
$productItem.fadeOut(300, function() {
|
||||||
|
$(this).remove();
|
||||||
// Обработчик увеличения количества
|
updateTotal();
|
||||||
$('.products__qty-btn.plus').click(function() {
|
|
||||||
const $qtyValue = $(this).siblings('.products__qty-value');
|
if ($('.products__item').length === 0) {
|
||||||
let quantity = parseInt($qtyValue.text());
|
$('.products__list').html('<div class="empty-cart">Корзина пуста</div>');
|
||||||
$qtyValue.text(quantity + 1);
|
}
|
||||||
updateTotal();
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Обработчик уменьшения количества
|
$('.promo__btn').click(function() {
|
||||||
$('.products__qty-btn.minus').click(function() {
|
const promoCode = $('.promo__input').val().toUpperCase();
|
||||||
const $qtyValue = $(this).siblings('.products__qty-value');
|
|
||||||
let quantity = parseInt($qtyValue.text());
|
if (promoCode === 'SALE10') {
|
||||||
if (quantity > 1) {
|
cart.discount = Math.round(parseInt($('.products-total').text()) * 0.1);
|
||||||
$qtyValue.text(quantity - 1);
|
$('.discount-total').text(cart.discount + ' ₽');
|
||||||
updateTotal();
|
showMessage('#form-error', 3000);
|
||||||
}
|
$('#form-error').text('Промокод применен! Скидка 10%').removeClass('error').addClass('success');
|
||||||
});
|
} else if (promoCode === 'FREE') {
|
||||||
|
cart.delivery = 0;
|
||||||
// Обработчик удаления товара
|
$('.delivery-price').text('0 ₽');
|
||||||
$('.remove-from-cart').click(function() {
|
showMessage('#form-error', 3000);
|
||||||
const $productItem = $(this).closest('.products__item');
|
$('#form-error').text('Промокод применен! Бесплатная доставка').removeClass('error').addClass('success');
|
||||||
$productItem.fadeOut(300, function() {
|
} else if (promoCode) {
|
||||||
$(this).remove();
|
showMessage('#form-error', 3000);
|
||||||
updateTotal();
|
$('#form-error').text('Промокод недействителен').removeClass('success').addClass('error');
|
||||||
|
}
|
||||||
// Показываем сообщение, если корзина пуста
|
|
||||||
if ($('.products__item').length === 0) {
|
updateTotal();
|
||||||
$('.products__list').html('<div class="empty-cart">Корзина пуста</div>');
|
});
|
||||||
}
|
|
||||||
});
|
$('input[name="delivery"]').change(function() {
|
||||||
});
|
if ($(this).val() === 'pickup') {
|
||||||
|
cart.delivery = 0;
|
||||||
// Обработчик применения промокода
|
$('.delivery-price').text('0 ₽');
|
||||||
$('.promo__btn').click(function() {
|
} else {
|
||||||
const promoCode = $('.promo__input').val().toUpperCase();
|
cart.delivery = 2000;
|
||||||
|
$('.delivery-price').text('2000 ₽');
|
||||||
if (promoCode === 'SALE10') {
|
}
|
||||||
cart.discount = Math.round(parseInt($('.products-total').text()) * 0.1);
|
updateTotal();
|
||||||
$('.discount-total').text(cart.discount + ' ₽');
|
});
|
||||||
showMessage('#form-error', 3000);
|
|
||||||
$('#form-error').text('Промокод применен! Скидка 10%').removeClass('error').addClass('success');
|
function validateForm() {
|
||||||
} else if (promoCode === 'FREE') {
|
let isValid = true;
|
||||||
cart.delivery = 0;
|
let errorMessages = [];
|
||||||
$('.delivery-price').text('0 ₽');
|
|
||||||
showMessage('#form-error', 3000);
|
$('.field-error').remove();
|
||||||
$('#form-error').text('Промокод применен! Бесплатная доставка').removeClass('error').addClass('success');
|
$('.form__input').removeClass('error-input');
|
||||||
} else if (promoCode) {
|
|
||||||
showMessage('#form-error', 3000);
|
const requiredFields = [
|
||||||
$('#form-error').text('Промокод недействителен').removeClass('success').addClass('error');
|
{
|
||||||
}
|
id: '#fullname',
|
||||||
|
value: $('#fullname').val().trim(),
|
||||||
updateTotal();
|
validator: validateFullName,
|
||||||
});
|
required: true,
|
||||||
|
message: 'ФИО должно содержать только буквы и состоять минимум из 2 слов'
|
||||||
// Обработчик выбора доставки
|
},
|
||||||
$('input[name="delivery"]').change(function() {
|
{
|
||||||
if ($(this).val() === 'pickup') {
|
id: '#phone',
|
||||||
cart.delivery = 0;
|
value: $('#phone').val().trim(),
|
||||||
$('.delivery-price').text('0 ₽');
|
validator: validatePhone,
|
||||||
} else {
|
required: true,
|
||||||
cart.delivery = 2000;
|
message: 'Введите корректный номер телефона в формате +7XXXXXXXXXX'
|
||||||
$('.delivery-price').text('2000 ₽');
|
},
|
||||||
}
|
{
|
||||||
updateTotal();
|
id: '#email',
|
||||||
});
|
value: $('#email').val().trim(),
|
||||||
|
validator: validateEmail,
|
||||||
// Функция проверки всех полей формы
|
required: true,
|
||||||
function validateForm() {
|
message: 'Введите корректный email адрес'
|
||||||
let isValid = true;
|
},
|
||||||
let errorMessages = [];
|
{
|
||||||
|
id: '#region',
|
||||||
// Очищаем все старые ошибки
|
value: $('#region').val().trim(),
|
||||||
$('.field-error').remove();
|
validator: (val) => val.length > 0,
|
||||||
$('.form__input').removeClass('error-input');
|
required: true,
|
||||||
|
message: 'Поле "Регион" обязательно для заполнения'
|
||||||
// Проверка обязательных полей
|
},
|
||||||
const requiredFields = [
|
{
|
||||||
{
|
id: '#address',
|
||||||
id: '#fullname',
|
value: $('#address').val().trim(),
|
||||||
value: $('#fullname').val().trim(),
|
validator: (val) => val.length > 0,
|
||||||
validator: validateFullName,
|
required: true,
|
||||||
required: true,
|
message: 'Поле "Адрес" обязательно для заполнения'
|
||||||
message: 'ФИО должно содержать только буквы и состоять минимум из 2 слов'
|
}
|
||||||
},
|
];
|
||||||
{
|
|
||||||
id: '#phone',
|
requiredFields.forEach(field => {
|
||||||
value: $('#phone').val().trim(),
|
if (field.required && (!field.value || !field.validator(field.value))) {
|
||||||
validator: validatePhone,
|
isValid = false;
|
||||||
required: true,
|
errorMessages.push(field.message);
|
||||||
message: 'Введите корректный номер телефона в формате +7XXXXXXXXXX'
|
showFieldError(field.id, field.message);
|
||||||
},
|
}
|
||||||
{
|
});
|
||||||
id: '#email',
|
|
||||||
value: $('#email').val().trim(),
|
if (!$('#privacy-checkbox').is(':checked')) {
|
||||||
validator: validateEmail,
|
isValid = false;
|
||||||
required: true,
|
showPrivacyError(true);
|
||||||
message: 'Введите корректный email адрес'
|
errorMessages.push('Необходимо согласие на обработку персональных данных');
|
||||||
},
|
} else {
|
||||||
{
|
showPrivacyError(false);
|
||||||
id: '#region',
|
}
|
||||||
value: $('#region').val().trim(),
|
|
||||||
validator: (val) => val.length > 0,
|
if (!isValid && errorMessages.length > 0) {
|
||||||
required: true,
|
showMessage('#form-error', 5000);
|
||||||
message: 'Поле "Регион" обязательно для заполнения'
|
$('#form-error').text('Исправьте следующие ошибки: ' + errorMessages.join('; ')).removeClass('success').addClass('error');
|
||||||
},
|
|
||||||
{
|
$('html, body').animate({
|
||||||
id: '#address',
|
scrollTop: $('.error-input').first().offset().top - 100
|
||||||
value: $('#address').val().trim(),
|
}, 500);
|
||||||
validator: (val) => val.length > 0,
|
}
|
||||||
required: true,
|
|
||||||
message: 'Поле "Адрес" обязательно для заполнения'
|
return isValid;
|
||||||
}
|
}
|
||||||
];
|
|
||||||
|
$('#submit-order').click(function() {
|
||||||
// Проверяем каждое поле
|
if (!validateForm()) {
|
||||||
requiredFields.forEach(field => {
|
return;
|
||||||
if (field.required && (!field.value || !field.validator(field.value))) {
|
}
|
||||||
isValid = false;
|
|
||||||
errorMessages.push(field.message);
|
$(this).prop('disabled', true).text('ОБРАБОТКА...');
|
||||||
showFieldError(field.id, field.message);
|
|
||||||
}
|
setTimeout(() => {
|
||||||
});
|
showMessage('#order-success', 5000);
|
||||||
|
$(this).prop('disabled', false).text('ОФОРМИТЬ ЗАКАЗ');
|
||||||
// Проверка согласия на обработку данных
|
|
||||||
if (!$('#privacy-checkbox').is(':checked')) {
|
}, 2000);
|
||||||
isValid = false;
|
});
|
||||||
showPrivacyError(true);
|
|
||||||
errorMessages.push('Необходимо согласие на обработку персональных данных');
|
$('#phone').on('input', function() {
|
||||||
} else {
|
let phone = $(this).val().replace(/\D/g, '');
|
||||||
showPrivacyError(false);
|
if (phone.length > 0) {
|
||||||
}
|
if (phone[0] !== '7' && phone[0] !== '8') {
|
||||||
|
phone = '7' + phone;
|
||||||
// Показываем общее сообщение, если есть ошибки
|
}
|
||||||
if (!isValid && errorMessages.length > 0) {
|
phone = '+7' + phone.substring(1, 11);
|
||||||
showMessage('#form-error', 5000);
|
$(this).val(phone);
|
||||||
$('#form-error').text('Исправьте следующие ошибки: ' + errorMessages.join('; ')).removeClass('success').addClass('error');
|
}
|
||||||
|
});
|
||||||
// Прокручиваем к первой ошибке
|
|
||||||
$('html, body').animate({
|
updateTotal();
|
||||||
scrollTop: $('.error-input').first().offset().top - 100
|
});
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обработчик оформления заказа
|
|
||||||
$('#submit-order').click(function() {
|
|
||||||
// Проверка валидации всех полей
|
|
||||||
if (!validateForm()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Симуляция отправки заказа
|
|
||||||
$(this).prop('disabled', true).text('ОБРАБОТКА...');
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
showMessage('#order-success', 5000);
|
|
||||||
$(this).prop('disabled', false).text('ОФОРМИТЬ ЗАКАЗ');
|
|
||||||
|
|
||||||
// Здесь можно добавить редирект на страницу благодарности
|
|
||||||
// window.location.href = 'спасибо.html';
|
|
||||||
}, 2000);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Маска для телефона
|
|
||||||
$('#phone').on('input', function() {
|
|
||||||
let phone = $(this).val().replace(/\D/g, '');
|
|
||||||
if (phone.length > 0) {
|
|
||||||
if (phone[0] !== '7' && phone[0] !== '8') {
|
|
||||||
phone = '7' + phone;
|
|
||||||
}
|
|
||||||
phone = '+7' + phone.substring(1, 11);
|
|
||||||
$(this).val(phone);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Инициализация при загрузке
|
|
||||||
updateTotal();
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,384 +1,348 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Функции для отображения сообщений
|
|
||||||
function showMessage(type, text) {
|
function showMessage(type, text) {
|
||||||
const messageId = type + 'Message';
|
const messageId = type + 'Message';
|
||||||
const $message = $('#' + messageId);
|
const $message = $('#' + messageId);
|
||||||
$message.text(text).fadeIn(300);
|
$message.text(text).fadeIn(300);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
$message.fadeOut(300);
|
$message.fadeOut(300);
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверка, является ли email администратора
|
function isAdminEmail(email) {
|
||||||
function isAdminEmail(email) {
|
const adminEmails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru'];
|
||||||
const adminEmails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru'];
|
return adminEmails.includes(email.toLowerCase());
|
||||||
return adminEmails.includes(email.toLowerCase());
|
}
|
||||||
}
|
|
||||||
|
function validateFIO(fio) {
|
||||||
// Валидация ФИО (без цифр)
|
const words = fio.trim().split(/\s+/);
|
||||||
function validateFIO(fio) {
|
|
||||||
const words = fio.trim().split(/\s+/);
|
const hasNoDigits = !/\d/.test(fio);
|
||||||
// Проверяем, что минимум 2 слова и нет цифр
|
return words.length >= 2 && words.every(word => word.length >= 2) && hasNoDigits;
|
||||||
const hasNoDigits = !/\d/.test(fio);
|
}
|
||||||
return words.length >= 2 && words.every(word => word.length >= 2) && hasNoDigits;
|
|
||||||
}
|
function validateCity(city) {
|
||||||
|
return city.trim().length >= 2 && /^[а-яА-ЯёЁ\s-]+$/.test(city);
|
||||||
// Валидация города
|
}
|
||||||
function validateCity(city) {
|
|
||||||
return city.trim().length >= 2 && /^[а-яА-ЯёЁ\s-]+$/.test(city);
|
function validateEmail(email) {
|
||||||
}
|
const localPart = email.split('@')[0];
|
||||||
|
|
||||||
// Валидация email
|
if (/[а-яА-ЯёЁ]/.test(localPart)) {
|
||||||
function validateEmail(email) {
|
showError('email', 'В тексте перед знаком "@" не должно быть кириллических символов');
|
||||||
const localPart = email.split('@')[0];
|
return false;
|
||||||
|
}
|
||||||
// Проверка на кириллические символы перед @
|
|
||||||
if (/[а-яА-ЯёЁ]/.test(localPart)) {
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
showError('email', 'В тексте перед знаком "@" не должно быть кириллических символов');
|
if (!emailRegex.test(email)) {
|
||||||
return false;
|
showError('email', 'Введите корректный email адрес');
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(email)) {
|
hideError('email');
|
||||||
showError('email', 'Введите корректный email адрес');
|
return true;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
function validatePhone(phone) {
|
||||||
hideError('email');
|
const phoneRegex = /^(\+7|8)[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/;
|
||||||
return true;
|
return phoneRegex.test(phone.replace(/\s/g, ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Валидация телефона
|
function validatePassword(password) {
|
||||||
function validatePhone(phone) {
|
return password.length >= 6;
|
||||||
const phoneRegex = /^(\+7|8)[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/;
|
}
|
||||||
return phoneRegex.test(phone.replace(/\s/g, ''));
|
|
||||||
}
|
function showError(fieldId, message) {
|
||||||
|
$('#' + fieldId).addClass('error');
|
||||||
// Валидация пароля
|
$('#' + fieldId + '-error').text(message).show();
|
||||||
function validatePassword(password) {
|
}
|
||||||
return password.length >= 6;
|
|
||||||
}
|
function hideError(fieldId) {
|
||||||
|
$('#' + fieldId).removeClass('error');
|
||||||
// Показать/скрыть ошибку
|
$('#' + fieldId + '-error').hide();
|
||||||
function showError(fieldId, message) {
|
}
|
||||||
$('#' + fieldId).addClass('error');
|
|
||||||
$('#' + fieldId + '-error').text(message).show();
|
function validateForm() {
|
||||||
}
|
let isValid = true;
|
||||||
|
|
||||||
function hideError(fieldId) {
|
const fio = $('#fio').val();
|
||||||
$('#' + fieldId).removeClass('error');
|
if (!validateFIO(fio)) {
|
||||||
$('#' + fieldId + '-error').hide();
|
if (/\d/.test(fio)) {
|
||||||
}
|
showError('fio', 'ФИО не должно содержать цифры');
|
||||||
|
} else {
|
||||||
// Валидация формы
|
showError('fio', 'ФИО должно содержать минимум 2 слова (каждое от 2 символов)');
|
||||||
function validateForm() {
|
}
|
||||||
let isValid = true;
|
isValid = false;
|
||||||
|
} else {
|
||||||
// Валидация ФИО
|
hideError('fio');
|
||||||
const fio = $('#fio').val();
|
}
|
||||||
if (!validateFIO(fio)) {
|
|
||||||
if (/\d/.test(fio)) {
|
const city = $('#city').val();
|
||||||
showError('fio', 'ФИО не должно содержать цифры');
|
if (!validateCity(city)) {
|
||||||
} else {
|
showError('city', 'Укажите корректное название города (только русские буквы)');
|
||||||
showError('fio', 'ФИО должно содержать минимум 2 слова (каждое от 2 символов)');
|
isValid = false;
|
||||||
}
|
} else {
|
||||||
isValid = false;
|
hideError('city');
|
||||||
} else {
|
}
|
||||||
hideError('fio');
|
|
||||||
}
|
const email = $('#email').val();
|
||||||
|
if (!validateEmail(email)) {
|
||||||
// Валидация города
|
showError('email', 'Введите корректный email адрес');
|
||||||
const city = $('#city').val();
|
isValid = false;
|
||||||
if (!validateCity(city)) {
|
} else {
|
||||||
showError('city', 'Укажите корректное название города (только русские буквы)');
|
hideError('email');
|
||||||
isValid = false;
|
}
|
||||||
} else {
|
|
||||||
hideError('city');
|
const phone = $('#phone').val();
|
||||||
}
|
if (!validatePhone(phone)) {
|
||||||
|
showError('phone', 'Введите номер в формате: +7(912)999-12-23');
|
||||||
// Валидация email
|
isValid = false;
|
||||||
const email = $('#email').val();
|
} else {
|
||||||
if (!validateEmail(email)) {
|
hideError('phone');
|
||||||
showError('email', 'Введите корректный email адрес');
|
}
|
||||||
isValid = false;
|
|
||||||
} else {
|
const password = $('#password').val();
|
||||||
hideError('email');
|
if (!validatePassword(password)) {
|
||||||
}
|
showError('password', 'Пароль должен содержать минимум 6 символов');
|
||||||
|
isValid = false;
|
||||||
// Валидация телефона
|
} else {
|
||||||
const phone = $('#phone').val();
|
hideError('password');
|
||||||
if (!validatePhone(phone)) {
|
}
|
||||||
showError('phone', 'Введите номер в формате: +7(912)999-12-23');
|
|
||||||
isValid = false;
|
const confirmPassword = $('#confirm-password').val();
|
||||||
} else {
|
if (password !== confirmPassword) {
|
||||||
hideError('phone');
|
showError('confirm-password', 'Пароли не совпадают');
|
||||||
}
|
isValid = false;
|
||||||
|
} else {
|
||||||
// Валидация пароля
|
hideError('confirm-password');
|
||||||
const password = $('#password').val();
|
}
|
||||||
if (!validatePassword(password)) {
|
|
||||||
showError('password', 'Пароль должен содержать минимум 6 символов');
|
if (!$('#privacy').is(':checked')) {
|
||||||
isValid = false;
|
$('#privacy-error').show();
|
||||||
} else {
|
isValid = false;
|
||||||
hideError('password');
|
} else {
|
||||||
}
|
$('#privacy-error').hide();
|
||||||
|
}
|
||||||
// Проверка совпадения паролей
|
|
||||||
const confirmPassword = $('#confirm-password').val();
|
return isValid;
|
||||||
if (password !== confirmPassword) {
|
}
|
||||||
showError('confirm-password', 'Пароли не совпадают');
|
|
||||||
isValid = false;
|
$('input').on('blur', function() {
|
||||||
} else {
|
const fieldId = $(this).attr('id');
|
||||||
hideError('confirm-password');
|
const value = $(this).val();
|
||||||
}
|
|
||||||
|
switch(fieldId) {
|
||||||
// Проверка согласия с условиями
|
case 'fio':
|
||||||
if (!$('#privacy').is(':checked')) {
|
if (!validateFIO(value)) {
|
||||||
$('#privacy-error').show();
|
if (/\d/.test(value)) {
|
||||||
isValid = false;
|
showError(fieldId, 'ФИО не должно содержать цифры');
|
||||||
} else {
|
} else {
|
||||||
$('#privacy-error').hide();
|
showError(fieldId, 'ФИО должно содержать минимум 2 слова');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
return isValid;
|
hideError(fieldId);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
// Реальная валидация при вводе
|
case 'city':
|
||||||
$('input').on('blur', function() {
|
if (!validateCity(value)) {
|
||||||
const fieldId = $(this).attr('id');
|
showError(fieldId, 'Укажите корректное название города');
|
||||||
const value = $(this).val();
|
} else {
|
||||||
|
hideError(fieldId);
|
||||||
switch(fieldId) {
|
}
|
||||||
case 'fio':
|
break;
|
||||||
if (!validateFIO(value)) {
|
case 'email':
|
||||||
if (/\d/.test(value)) {
|
if (!validateEmail(value)) {
|
||||||
showError(fieldId, 'ФИО не должно содержать цифры');
|
showError(fieldId, 'Введите корректный email адрес');
|
||||||
} else {
|
} else {
|
||||||
showError(fieldId, 'ФИО должно содержать минимум 2 слова');
|
hideError(fieldId);
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
hideError(fieldId);
|
case 'phone':
|
||||||
}
|
if (!validatePhone(value)) {
|
||||||
break;
|
showError(fieldId, 'Введите номер в формате: +7(912)999-12-23');
|
||||||
case 'city':
|
} else {
|
||||||
if (!validateCity(value)) {
|
hideError(fieldId);
|
||||||
showError(fieldId, 'Укажите корректное название города');
|
}
|
||||||
} else {
|
break;
|
||||||
hideError(fieldId);
|
case 'password':
|
||||||
}
|
if (!validatePassword(value)) {
|
||||||
break;
|
showError(fieldId, 'Пароль должен содержать минимум 6 символов');
|
||||||
case 'email':
|
} else {
|
||||||
if (!validateEmail(value)) {
|
hideError(fieldId);
|
||||||
showError(fieldId, 'Введите корректный email адрес');
|
}
|
||||||
} else {
|
break;
|
||||||
hideError(fieldId);
|
case 'confirm-password':
|
||||||
}
|
const password = $('#password').val();
|
||||||
break;
|
if (value !== password) {
|
||||||
case 'phone':
|
showError(fieldId, 'Пароли не совпадают');
|
||||||
if (!validatePhone(value)) {
|
} else {
|
||||||
showError(fieldId, 'Введите номер в формате: +7(912)999-12-23');
|
hideError(fieldId);
|
||||||
} else {
|
}
|
||||||
hideError(fieldId);
|
break;
|
||||||
}
|
}
|
||||||
break;
|
});
|
||||||
case 'password':
|
|
||||||
if (!validatePassword(value)) {
|
$('#registrationForm').on('submit', function(e) {
|
||||||
showError(fieldId, 'Пароль должен содержать минимум 6 символов');
|
e.preventDefault();
|
||||||
} else {
|
|
||||||
hideError(fieldId);
|
if (validateForm()) {
|
||||||
}
|
const email = $('#email').val();
|
||||||
break;
|
const isAdmin = isAdminEmail(email);
|
||||||
case 'confirm-password':
|
|
||||||
const password = $('#password').val();
|
const userData = {
|
||||||
if (value !== password) {
|
email: email,
|
||||||
showError(fieldId, 'Пароли не совпадают');
|
fio: $('#fio').val(),
|
||||||
} else {
|
phone: $('#phone').val(),
|
||||||
hideError(fieldId);
|
isAdmin: isAdmin,
|
||||||
}
|
registered: new Date().toISOString()
|
||||||
break;
|
};
|
||||||
}
|
|
||||||
});
|
localStorage.setItem('userData', JSON.stringify(userData));
|
||||||
|
localStorage.setItem('isLoggedIn', 'true');
|
||||||
// Обработка отправки формы
|
localStorage.setItem('isAdmin', isAdmin.toString());
|
||||||
$('#registrationForm').on('submit', function(e) {
|
|
||||||
e.preventDefault();
|
showMessage('success', 'Регистрация прошла успешно! ' +
|
||||||
|
(isAdmin ? 'Вы зарегистрированы как администратор.' : 'Добро пожаловать в AETERNA!'));
|
||||||
if (validateForm()) {
|
|
||||||
const email = $('#email').val();
|
setTimeout(() => {
|
||||||
const isAdmin = isAdminEmail(email);
|
|
||||||
|
window.location.href = 'cite_mebel.php';
|
||||||
// Сохраняем данные пользователя в localStorage
|
}, 2000);
|
||||||
const userData = {
|
} else {
|
||||||
email: email,
|
showMessage('error', 'Пожалуйста, исправьте ошибки в форме');
|
||||||
fio: $('#fio').val(),
|
}
|
||||||
phone: $('#phone').val(),
|
});
|
||||||
isAdmin: isAdmin,
|
|
||||||
registered: new Date().toISOString()
|
$('a[href^="#"]').on('click', function(event) {
|
||||||
};
|
var target = $(this.getAttribute('href'));
|
||||||
|
if (target.length) {
|
||||||
localStorage.setItem('userData', JSON.stringify(userData));
|
event.preventDefault();
|
||||||
localStorage.setItem('isLoggedIn', 'true');
|
$('html, body').stop().animate({
|
||||||
localStorage.setItem('isAdmin', isAdmin.toString());
|
scrollTop: target.offset().top
|
||||||
|
}, 1000);
|
||||||
// Эмуляция успешной регистрации
|
}
|
||||||
showMessage('success', 'Регистрация прошла успешно! ' +
|
});
|
||||||
(isAdmin ? 'Вы зарегистрированы как администратор.' : 'Добро пожаловать в AETERNA!'));
|
|
||||||
|
$('.login-btn').on('click', function() {
|
||||||
setTimeout(() => {
|
showMessage('warning', 'Переход к форме входа...');
|
||||||
// Перенаправление на главную страницу
|
setTimeout(() => {
|
||||||
window.location.href = 'cite_mebel.php';
|
window.location.href = 'вход.php';
|
||||||
}, 2000);
|
}, 1000);
|
||||||
} else {
|
});
|
||||||
showMessage('error', 'Пожалуйста, исправьте ошибки в форме');
|
|
||||||
}
|
$('.password-link').on('click', function(e) {
|
||||||
});
|
e.preventDefault();
|
||||||
|
showMessage('warning', 'Функция смены пароля будет доступна после регистрации');
|
||||||
// Плавная прокрутка к якорям
|
});
|
||||||
$('a[href^="#"]').on('click', function(event) {
|
|
||||||
var target = $(this.getAttribute('href'));
|
$('#phone').on('input', function() {
|
||||||
if (target.length) {
|
let value = $(this).val().replace(/\D/g, '');
|
||||||
event.preventDefault();
|
if (value.startsWith('7') || value.startsWith('8')) {
|
||||||
$('html, body').stop().animate({
|
value = value.substring(1);
|
||||||
scrollTop: target.offset().top
|
}
|
||||||
}, 1000);
|
if (value.length > 0) {
|
||||||
}
|
value = '+7(' + value;
|
||||||
});
|
if (value.length > 6) value = value.substring(0, 6) + ')' + value.substring(6);
|
||||||
|
if (value.length > 10) value = value.substring(0, 10) + '-' + value.substring(10);
|
||||||
// Переключение между регистрацией и входом
|
if (value.length > 13) value = value.substring(0, 13) + '-' + value.substring(13);
|
||||||
$('.login-btn').on('click', function() {
|
if (value.length > 16) value = value.substring(0, 16);
|
||||||
showMessage('warning', 'Переход к форме входа...');
|
}
|
||||||
setTimeout(() => {
|
$(this).val(value);
|
||||||
window.location.href = 'вход.php';
|
});
|
||||||
}, 1000);
|
|
||||||
});
|
$('#fio').on('input', function() {
|
||||||
|
let value = $(this).val();
|
||||||
// Обработка ссылки "Сменить пароль"
|
|
||||||
$('.password-link').on('click', function(e) {
|
value = value.replace(/\d/g, '');
|
||||||
e.preventDefault();
|
$(this).val(value);
|
||||||
showMessage('warning', 'Функция смены пароля будет доступна после регистрации');
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Маска для телефона
|
$(document).ready(function() {
|
||||||
$('#phone').on('input', function() {
|
|
||||||
let value = $(this).val().replace(/\D/g, '');
|
if (localStorage.getItem('isLoggedIn') === 'true') {
|
||||||
if (value.startsWith('7') || value.startsWith('8')) {
|
const userData = JSON.parse(localStorage.getItem('userData') || '{}');
|
||||||
value = value.substring(1);
|
if (userData.email) {
|
||||||
}
|
$('#login-email').val(userData.email);
|
||||||
if (value.length > 0) {
|
}
|
||||||
value = '+7(' + value;
|
}
|
||||||
if (value.length > 6) value = value.substring(0, 6) + ')' + value.substring(6);
|
|
||||||
if (value.length > 10) value = value.substring(0, 10) + '-' + value.substring(10);
|
function checkAdminPassword(email, password) {
|
||||||
if (value.length > 13) value = value.substring(0, 13) + '-' + value.substring(13);
|
|
||||||
if (value.length > 16) value = value.substring(0, 16);
|
const adminAccounts = {
|
||||||
}
|
'admin@aeterna.ru': 'admin123',
|
||||||
$(this).val(value);
|
'administrator@aeterna.ru': 'admin123',
|
||||||
});
|
'aeterna@mail.ru': 'admin123'
|
||||||
|
};
|
||||||
// Запрет ввода цифр в поле ФИО
|
|
||||||
$('#fio').on('input', function() {
|
return adminAccounts[email.toLowerCase()] === password;
|
||||||
let value = $(this).val();
|
}
|
||||||
// Удаляем цифры из значения
|
|
||||||
value = value.replace(/\d/g, '');
|
$('#loginForm').on('submit', function(e) {
|
||||||
$(this).val(value);
|
e.preventDefault();
|
||||||
});
|
|
||||||
});
|
let isValid = true;
|
||||||
|
const email = $('#login-email').val();
|
||||||
// Для входа (файл вход.html)
|
const password = $('#login-password').val();
|
||||||
$(document).ready(function() {
|
|
||||||
// Проверяем, если пользователь уже вошел
|
if (!isValidEmail(email)) {
|
||||||
if (localStorage.getItem('isLoggedIn') === 'true') {
|
$('#email-error').show();
|
||||||
const userData = JSON.parse(localStorage.getItem('userData') || '{}');
|
isValid = false;
|
||||||
if (userData.email) {
|
} else {
|
||||||
$('#login-email').val(userData.email);
|
$('#email-error').hide();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (password.length < 6) {
|
||||||
// Функция проверки пароля администратора
|
$('#password-error').show();
|
||||||
function checkAdminPassword(email, password) {
|
isValid = false;
|
||||||
// Административные аккаунты
|
} else {
|
||||||
const adminAccounts = {
|
$('#password-error').hide();
|
||||||
'admin@aeterna.ru': 'admin123',
|
}
|
||||||
'administrator@aeterna.ru': 'admin123',
|
|
||||||
'aeterna@mail.ru': 'admin123'
|
if (isValid) {
|
||||||
};
|
|
||||||
|
showMessage('success', 'Вы успешно вошли в систему!');
|
||||||
return adminAccounts[email.toLowerCase()] === password;
|
|
||||||
}
|
setTimeout(function() {
|
||||||
|
window.location.href = 'cite_mebel.php';
|
||||||
// Валидация формы входа
|
}, 1500);
|
||||||
$('#loginForm').on('submit', function(e) {
|
}
|
||||||
e.preventDefault();
|
});
|
||||||
|
|
||||||
let isValid = true;
|
function showMessage(type, text) {
|
||||||
const email = $('#login-email').val();
|
const messageId = type + 'Message';
|
||||||
const password = $('#login-password').val();
|
const $message = $('#' + messageId);
|
||||||
|
|
||||||
// Валидация email
|
$message.text(text).show();
|
||||||
if (!isValidEmail(email)) {
|
|
||||||
$('#email-error').show();
|
setTimeout(function() {
|
||||||
isValid = false;
|
$message.fadeOut();
|
||||||
} else {
|
}, 3000);
|
||||||
$('#email-error').hide();
|
}
|
||||||
}
|
|
||||||
|
$('input').on('focus', function() {
|
||||||
// Валидация пароля
|
$(this).next('.error-message').hide();
|
||||||
if (password.length < 6) {
|
});
|
||||||
$('#password-error').show();
|
|
||||||
isValid = false;
|
$('#remember').on('change', function() {
|
||||||
} else {
|
if ($(this).is(':checked')) {
|
||||||
$('#password-error').hide();
|
const email = $('#login-email').val();
|
||||||
}
|
if (email) {
|
||||||
|
localStorage.setItem('rememberedEmail', email);
|
||||||
if (isValid) {
|
}
|
||||||
// Здесь обычно отправка данных на сервер
|
} else {
|
||||||
showMessage('success', 'Вы успешно вошли в систему!');
|
localStorage.removeItem('rememberedEmail');
|
||||||
|
}
|
||||||
// Перенаправление на главную страницу через 1.5 секунды
|
});
|
||||||
setTimeout(function() {
|
|
||||||
window.location.href = 'cite_mebel.php';
|
const rememberedEmail = localStorage.getItem('rememberedEmail');
|
||||||
}, 1500);
|
if (rememberedEmail) {
|
||||||
}
|
$('#login-email').val(rememberedEmail);
|
||||||
});
|
$('#remember').prop('checked', true);
|
||||||
|
}
|
||||||
// Функция показа сообщений
|
|
||||||
function showMessage(type, text) {
|
$('.forgot-password').on('click', function(e) {
|
||||||
const messageId = type + 'Message';
|
e.preventDefault();
|
||||||
const $message = $('#' + messageId);
|
showMessage('info', 'Для восстановления пароля обратитесь к администратору');
|
||||||
|
});
|
||||||
$message.text(text).show();
|
});
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
$message.fadeOut();
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Скрываем сообщения об ошибках при фокусе на полях
|
|
||||||
$('input').on('focus', function() {
|
|
||||||
$(this).next('.error-message').hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Обработка чекбокса "Запомнить меня"
|
|
||||||
$('#remember').on('change', function() {
|
|
||||||
if ($(this).is(':checked')) {
|
|
||||||
const email = $('#login-email').val();
|
|
||||||
if (email) {
|
|
||||||
localStorage.setItem('rememberedEmail', email);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
localStorage.removeItem('rememberedEmail');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Автозаполнение email, если пользователь выбрал "Запомнить меня"
|
|
||||||
const rememberedEmail = localStorage.getItem('rememberedEmail');
|
|
||||||
if (rememberedEmail) {
|
|
||||||
$('#login-email').val(rememberedEmail);
|
|
||||||
$('#remember').prop('checked', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обработка ссылки "Забыли пароль?"
|
|
||||||
$('.forgot-password').on('click', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
showMessage('info', 'Для восстановления пароля обратитесь к администратору');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,142 +1,137 @@
|
|||||||
.error-message {
|
.error-message {
|
||||||
color: #ff0000;
|
color: #ff0000;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__input.error {
|
.form__input.error {
|
||||||
border-color: #ff0000;
|
border-color: #ff0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__group {
|
.form__group {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Стили для сообщений внизу страницы */
|
.page-messages {
|
||||||
.page-messages {
|
position: fixed;
|
||||||
position: fixed;
|
bottom: 20px;
|
||||||
bottom: 20px;
|
left: 50%;
|
||||||
left: 50%;
|
transform: translateX(-50%);
|
||||||
transform: translateX(-50%);
|
z-index: 1000;
|
||||||
z-index: 1000;
|
width: 90%;
|
||||||
width: 90%;
|
max-width: 500px;
|
||||||
max-width: 500px;
|
}
|
||||||
}
|
|
||||||
|
.message {
|
||||||
.message {
|
padding: 15px;
|
||||||
padding: 15px;
|
margin: 10px 0;
|
||||||
margin: 10px 0;
|
border-radius: 5px;
|
||||||
border-radius: 5px;
|
text-align: center;
|
||||||
text-align: center;
|
font-weight: bold;
|
||||||
font-weight: bold;
|
display: none;
|
||||||
display: none;
|
}
|
||||||
}
|
|
||||||
|
.message.error {
|
||||||
.message.error {
|
background-color: #ffebee;
|
||||||
background-color: #ffebee;
|
color: #c62828;
|
||||||
color: #c62828;
|
border: 1px solid #ffcdd2;
|
||||||
border: 1px solid #ffcdd2;
|
}
|
||||||
}
|
|
||||||
|
.message.success {
|
||||||
.message.success {
|
background-color: #e8f5e9;
|
||||||
background-color: #e8f5e9;
|
color: #453227;
|
||||||
color: #453227;
|
border: 1px solid #c8e6c9;
|
||||||
border: 1px solid #c8e6c9;
|
}
|
||||||
}
|
|
||||||
|
.message.warning {
|
||||||
.message.warning {
|
background-color: #fff3e0;
|
||||||
background-color: #fff3e0;
|
color: #ef6c00;
|
||||||
color: #ef6c00;
|
border: 1px solid #ffe0b2;
|
||||||
border: 1px solid #ffe0b2;
|
}
|
||||||
}
|
|
||||||
|
.privacy-error {
|
||||||
.privacy-error {
|
color: #ff0000;
|
||||||
color: #ff0000;
|
font-size: 12px;
|
||||||
font-size: 12px;
|
margin-top: 5px;
|
||||||
margin-top: 5px;
|
display: none;
|
||||||
display: none;
|
text-align: center;
|
||||||
text-align: center;
|
}
|
||||||
}
|
|
||||||
|
.input-group {
|
||||||
/* Дополнительные стили для формы регистрации */
|
position: relative;
|
||||||
.input-group {
|
margin-bottom: 20px;
|
||||||
position: relative;
|
}
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
.profile-form input.error {
|
||||||
|
border-color: #ff0000;
|
||||||
.profile-form input.error {
|
background-color: #fff5f5;
|
||||||
border-color: #ff0000;
|
}
|
||||||
background-color: #fff5f5;
|
|
||||||
}
|
.privacy-checkbox {
|
||||||
|
margin: 20px 0;
|
||||||
.privacy-checkbox {
|
text-align: center;
|
||||||
margin: 20px 0;
|
}
|
||||||
text-align: center;
|
|
||||||
}
|
.privacy-checkbox label {
|
||||||
|
display: flex;
|
||||||
.privacy-checkbox label {
|
align-items: center;
|
||||||
display: flex;
|
justify-content: center;
|
||||||
align-items: center;
|
gap: 8px;
|
||||||
justify-content: center;
|
cursor: pointer;
|
||||||
gap: 8px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
}
|
||||||
font-size: 14px;
|
|
||||||
}
|
.privacy-checkbox input[type="checkbox"] {
|
||||||
|
margin: 0;
|
||||||
.privacy-checkbox input[type="checkbox"] {
|
}
|
||||||
margin: 0;
|
|
||||||
}
|
.profile-page-main {
|
||||||
|
padding: 40px 0;
|
||||||
/* Исправление отступов для страницы регистрации */
|
min-height: calc(100vh - 200px);
|
||||||
.profile-page-main {
|
}
|
||||||
padding: 40px 0;
|
|
||||||
min-height: calc(100vh - 200px);
|
.profile-container {
|
||||||
}
|
margin: 0 auto;
|
||||||
|
position: relative;
|
||||||
/* Убедимся, что контейнер не перекрывает шапку и футер */
|
z-index: 1;
|
||||||
.profile-container {
|
}
|
||||||
margin: 0 auto;
|
|
||||||
position: relative;
|
.input-hint {
|
||||||
z-index: 1;
|
font-size: 12px;
|
||||||
}
|
color: #666;
|
||||||
|
margin-top: 5px;
|
||||||
.input-hint {
|
}
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
.form-options {
|
||||||
margin-top: 5px;
|
display: flex;
|
||||||
}
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
/* Стили для страницы входа */
|
margin: 20px 0;
|
||||||
.form-options {
|
}
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
.remember-me {
|
||||||
align-items: center;
|
display: flex;
|
||||||
margin: 20px 0;
|
align-items: center;
|
||||||
}
|
gap: 8px;
|
||||||
|
font-size: 14px;
|
||||||
.remember-me {
|
color: #453227;
|
||||||
display: flex;
|
}
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
.remember-me input[type="checkbox"] {
|
||||||
font-size: 14px;
|
width: 16px;
|
||||||
color: #453227;
|
height: 16px;
|
||||||
}
|
cursor: pointer;
|
||||||
|
}
|
||||||
.remember-me input[type="checkbox"] {
|
|
||||||
width: 16px;
|
.forgot-password {
|
||||||
height: 16px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
color: #453227;
|
||||||
}
|
text-decoration: underline;
|
||||||
|
}
|
||||||
.forgot-password {
|
|
||||||
font-size: 14px;
|
.forgot-password:hover {
|
||||||
color: #453227;
|
color: #617365;
|
||||||
text-decoration: underline;
|
text-decoration: none;
|
||||||
}
|
|
||||||
|
|
||||||
.forgot-password:hover {
|
|
||||||
color: #617365;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
@@ -83,4 +83,3 @@
|
|||||||
border-color: @color-primary;
|
border-color: @color-primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,114 +1,107 @@
|
|||||||
// check_auth.js
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Проверка авторизации при загрузке страницы
|
|
||||||
checkAuthStatus();
|
checkAuthStatus();
|
||||||
|
|
||||||
// Обработка формы входа
|
$('#loginForm').on('submit', function(e) {
|
||||||
$('#loginForm').on('submit', function(e) {
|
e.preventDefault();
|
||||||
e.preventDefault();
|
|
||||||
|
const email = $('#login-email').val();
|
||||||
const email = $('#login-email').val();
|
const password = $('#login-password').val();
|
||||||
const password = $('#login-password').val();
|
const remember = $('#remember').is(':checked');
|
||||||
const remember = $('#remember').is(':checked');
|
|
||||||
|
$.ajax({
|
||||||
$.ajax({
|
url: 'login_handler.php',
|
||||||
url: 'login_handler.php',
|
method: 'POST',
|
||||||
method: 'POST',
|
data: {
|
||||||
data: {
|
email: email,
|
||||||
email: email,
|
password: password
|
||||||
password: password
|
},
|
||||||
},
|
success: function(response) {
|
||||||
success: function(response) {
|
try {
|
||||||
try {
|
const result = JSON.parse(response);
|
||||||
const result = JSON.parse(response);
|
if (result.success) {
|
||||||
if (result.success) {
|
|
||||||
// Сохраняем в localStorage если выбрано "Запомнить меня"
|
if (remember) {
|
||||||
if (remember) {
|
localStorage.setItem('rememberedEmail', email);
|
||||||
localStorage.setItem('rememberedEmail', email);
|
} else {
|
||||||
} else {
|
localStorage.removeItem('rememberedEmail');
|
||||||
localStorage.removeItem('rememberedEmail');
|
}
|
||||||
}
|
|
||||||
|
window.location.href = result.redirect || 'catalog.php';
|
||||||
// Перенаправляем
|
} else {
|
||||||
window.location.href = result.redirect || 'catalog.php';
|
showMessage('error', result.message || 'Ошибка авторизации');
|
||||||
} else {
|
}
|
||||||
showMessage('error', result.message || 'Ошибка авторизации');
|
} catch(e) {
|
||||||
}
|
showMessage('error', 'Ошибка обработки ответа');
|
||||||
} catch(e) {
|
}
|
||||||
showMessage('error', 'Ошибка обработки ответа');
|
},
|
||||||
}
|
error: function() {
|
||||||
},
|
showMessage('error', 'Ошибка сервера');
|
||||||
error: function() {
|
}
|
||||||
showMessage('error', 'Ошибка сервера');
|
});
|
||||||
}
|
});
|
||||||
});
|
|
||||||
});
|
function checkAuthStatus() {
|
||||||
|
$.ajax({
|
||||||
// Проверка статуса авторизации
|
url: 'check_auth_status.php',
|
||||||
function checkAuthStatus() {
|
method: 'GET',
|
||||||
$.ajax({
|
success: function(response) {
|
||||||
url: 'check_auth_status.php',
|
try {
|
||||||
method: 'GET',
|
const result = JSON.parse(response);
|
||||||
success: function(response) {
|
if (result.loggedIn) {
|
||||||
try {
|
updateUserProfile(result.user);
|
||||||
const result = JSON.parse(response);
|
}
|
||||||
if (result.loggedIn) {
|
} catch(e) {
|
||||||
updateUserProfile(result.user);
|
console.error('Ошибка проверки авторизации', e);
|
||||||
}
|
}
|
||||||
} catch(e) {
|
}
|
||||||
console.error('Ошибка проверки авторизации', e);
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
function updateUserProfile(user) {
|
||||||
}
|
|
||||||
|
if ($('#userEmail').length) {
|
||||||
// Обновление профиля пользователя
|
$('#userEmail').text(user.email);
|
||||||
function updateUserProfile(user) {
|
}
|
||||||
// Обновляем шапку, если есть элементы для профиля
|
if ($('#userName').length) {
|
||||||
if ($('#userEmail').length) {
|
$('#userName').text(user.full_name);
|
||||||
$('#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);
|
||||||
function showMessage(type, text) {
|
} else {
|
||||||
const $message = $('#' + type + 'Message');
|
alert(text);
|
||||||
if ($message.length) {
|
}
|
||||||
$message.text(text).fadeIn();
|
}
|
||||||
setTimeout(() => $message.fadeOut(), 5000);
|
|
||||||
} else {
|
function checkAuth(redirectUrl) {
|
||||||
alert(text);
|
$.ajax({
|
||||||
}
|
url: 'check_auth_status.php',
|
||||||
}
|
method: 'GET',
|
||||||
|
success: function(response) {
|
||||||
// Проверка авторизации для ссылок
|
try {
|
||||||
function checkAuth(redirectUrl) {
|
const result = JSON.parse(response);
|
||||||
$.ajax({
|
if (result.loggedIn) {
|
||||||
url: 'check_auth_status.php',
|
window.location.href = redirectUrl;
|
||||||
method: 'GET',
|
} else {
|
||||||
success: function(response) {
|
|
||||||
try {
|
showLoginModal(redirectUrl);
|
||||||
const result = JSON.parse(response);
|
}
|
||||||
if (result.loggedIn) {
|
} catch(e) {
|
||||||
window.location.href = redirectUrl;
|
showLoginModal(redirectUrl);
|
||||||
} else {
|
}
|
||||||
// Показываем модальное окно или перенаправляем на вход
|
}
|
||||||
showLoginModal(redirectUrl);
|
});
|
||||||
}
|
return false;
|
||||||
} catch(e) {
|
}
|
||||||
showLoginModal(redirectUrl);
|
|
||||||
}
|
function showLoginModal(redirectUrl) {
|
||||||
}
|
|
||||||
});
|
window.location.href = 'вход.php?redirect=' + encodeURIComponent(redirectUrl);
|
||||||
return false;
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
// Показать модальное окно входа
|
|
||||||
function showLoginModal(redirectUrl) {
|
|
||||||
// Можно реализовать модальное окно или перенаправить на страницу входа
|
|
||||||
window.location.href = 'вход.php?redirect=' + encodeURIComponent(redirectUrl);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
<?php
|
<?php
|
||||||
// config/database.php
|
|
||||||
class Database {
|
class Database {
|
||||||
private static $instance = null;
|
private static $instance = null;
|
||||||
private $connection;
|
private $connection;
|
||||||
|
|
||||||
private function __construct() {
|
private function __construct() {
|
||||||
try {
|
try {
|
||||||
$this->connection = new PDO(
|
$this->connection = new PDO(
|
||||||
"pgsql:host=185.130.224.177;port=5481;dbname=postgres",
|
"pgsql:host=185.130.224.177;port=5481;dbname=postgres",
|
||||||
"admin",
|
"admin",
|
||||||
"38feaad2840ccfda0e71243a6faaecfd"
|
"38feaad2840ccfda0e71243a6faaecfd"
|
||||||
);
|
);
|
||||||
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
$this->connection->exec("SET NAMES 'utf8'");
|
$this->connection->exec("SET NAMES 'utf8'");
|
||||||
} catch(PDOException $e) {
|
} catch(PDOException $e) {
|
||||||
die("Ошибка подключения: " . $e->getMessage());
|
die("Ошибка подключения: " . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getInstance() {
|
public static function getInstance() {
|
||||||
if (self::$instance == null) {
|
if (self::$instance == null) {
|
||||||
self::$instance = new Database();
|
self::$instance = new Database();
|
||||||
}
|
}
|
||||||
return self::$instance;
|
return self::$instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getConnection() {
|
public function getConnection() {
|
||||||
return $this->connection;
|
return $this->connection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
@@ -1,16 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* Функции авторизации для AETERNA
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
/**
|
|
||||||
* Авторизация пользователя
|
|
||||||
*/
|
|
||||||
function loginUser(string $email, string $password): array {
|
function loginUser(string $email, string $password): array {
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$stmt = $db->prepare("
|
$stmt = $db->prepare("
|
||||||
SELECT user_id, email, password_hash, full_name, phone, city, is_admin, is_active
|
SELECT user_id, email, password_hash, full_name, phone, city, is_admin, is_active
|
||||||
@@ -31,7 +25,6 @@ function loginUser(string $email, string $password): array {
|
|||||||
return ['success' => false, 'message' => 'Неверный пароль'];
|
return ['success' => false, 'message' => 'Неверный пароль'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Сохраняем в сессию
|
|
||||||
$_SESSION['user_id'] = $user['user_id'];
|
$_SESSION['user_id'] = $user['user_id'];
|
||||||
$_SESSION['user_email'] = $user['email'];
|
$_SESSION['user_email'] = $user['email'];
|
||||||
$_SESSION['full_name'] = $user['full_name'];
|
$_SESSION['full_name'] = $user['full_name'];
|
||||||
@@ -41,7 +34,6 @@ function loginUser(string $email, string $password): array {
|
|||||||
$_SESSION['isAdmin'] = (bool)$user['is_admin'];
|
$_SESSION['isAdmin'] = (bool)$user['is_admin'];
|
||||||
$_SESSION['login_time'] = time();
|
$_SESSION['login_time'] = time();
|
||||||
|
|
||||||
// Обновляем время последнего входа
|
|
||||||
$updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?");
|
$updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?");
|
||||||
$updateStmt->execute([$user['user_id']]);
|
$updateStmt->execute([$user['user_id']]);
|
||||||
|
|
||||||
@@ -52,43 +44,38 @@ function loginUser(string $email, string $password): array {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Регистрация нового пользователя
|
|
||||||
*/
|
|
||||||
function registerUser(array $data): array {
|
function registerUser(array $data): array {
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
$email = trim($data['email'] ?? '');
|
$email = trim($data['email'] ?? '');
|
||||||
$password = $data['password'] ?? '';
|
$password = $data['password'] ?? '';
|
||||||
$fullName = trim($data['full_name'] ?? '');
|
$fullName = trim($data['full_name'] ?? '');
|
||||||
$phone = trim($data['phone'] ?? '');
|
$phone = trim($data['phone'] ?? '');
|
||||||
$city = trim($data['city'] ?? '');
|
$city = trim($data['city'] ?? '');
|
||||||
|
|
||||||
// Валидация
|
|
||||||
if (empty($email) || empty($password) || empty($fullName)) {
|
if (empty($email) || empty($password) || empty($fullName)) {
|
||||||
return ['success' => false, 'message' => 'Заполните все обязательные поля'];
|
return ['success' => false, 'message' => 'Заполните все обязательные поля'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
return ['success' => false, 'message' => 'Некорректный email'];
|
return ['success' => false, 'message' => 'Некорректный email'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen($password) < 6) {
|
if (strlen($password) < 6) {
|
||||||
return ['success' => false, 'message' => 'Пароль должен содержать минимум 6 символов'];
|
return ['success' => false, 'message' => 'Пароль должен содержать минимум 6 символов'];
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Проверяем существование пользователя
|
|
||||||
$checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?");
|
$checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?");
|
||||||
$checkStmt->execute([$email]);
|
$checkStmt->execute([$email]);
|
||||||
|
|
||||||
if ($checkStmt->fetch()) {
|
if ($checkStmt->fetch()) {
|
||||||
return ['success' => false, 'message' => 'Пользователь с таким email уже существует'];
|
return ['success' => false, 'message' => 'Пользователь с таким email уже существует'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Создаем пользователя
|
|
||||||
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
|
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
|
||||||
|
|
||||||
$stmt = $db->prepare("
|
$stmt = $db->prepare("
|
||||||
INSERT INTO users (email, password_hash, full_name, phone, city, is_active)
|
INSERT INTO users (email, password_hash, full_name, phone, city, is_active)
|
||||||
VALUES (?, ?, ?, ?, ?, TRUE)
|
VALUES (?, ?, ?, ?, ?, TRUE)
|
||||||
@@ -96,8 +83,7 @@ function registerUser(array $data): array {
|
|||||||
");
|
");
|
||||||
$stmt->execute([$email, $passwordHash, $fullName, $phone, $city]);
|
$stmt->execute([$email, $passwordHash, $fullName, $phone, $city]);
|
||||||
$userId = $stmt->fetchColumn();
|
$userId = $stmt->fetchColumn();
|
||||||
|
|
||||||
// Автоматически авторизуем
|
|
||||||
$_SESSION['user_id'] = $userId;
|
$_SESSION['user_id'] = $userId;
|
||||||
$_SESSION['user_email'] = $email;
|
$_SESSION['user_email'] = $email;
|
||||||
$_SESSION['full_name'] = $fullName;
|
$_SESSION['full_name'] = $fullName;
|
||||||
@@ -106,20 +92,17 @@ function registerUser(array $data): array {
|
|||||||
$_SESSION['isLoggedIn'] = true;
|
$_SESSION['isLoggedIn'] = true;
|
||||||
$_SESSION['isAdmin'] = false;
|
$_SESSION['isAdmin'] = false;
|
||||||
$_SESSION['login_time'] = time();
|
$_SESSION['login_time'] = time();
|
||||||
|
|
||||||
return ['success' => true, 'user_id' => $userId];
|
return ['success' => true, 'user_id' => $userId];
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
return ['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()];
|
return ['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Выход пользователя
|
|
||||||
*/
|
|
||||||
function logoutUser(): void {
|
function logoutUser(): void {
|
||||||
$_SESSION = [];
|
$_SESSION = [];
|
||||||
|
|
||||||
if (ini_get("session.use_cookies")) {
|
if (ini_get("session.use_cookies")) {
|
||||||
$params = session_get_cookie_params();
|
$params = session_get_cookie_params();
|
||||||
setcookie(session_name(), '', time() - 42000,
|
setcookie(session_name(), '', time() - 42000,
|
||||||
@@ -127,22 +110,18 @@ function logoutUser(): void {
|
|||||||
$params["secure"], $params["httponly"]
|
$params["secure"], $params["httponly"]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
session_destroy();
|
session_destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Проверка является ли пользователь администратором
|
|
||||||
*/
|
|
||||||
function checkAdminAccess(): bool {
|
function checkAdminAccess(): bool {
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
|
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,4 +47,3 @@
|
|||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* Общие функции для AETERNA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Проверка авторизации пользователя
|
|
||||||
*/
|
|
||||||
function isLoggedIn(): bool {
|
function isLoggedIn(): bool {
|
||||||
return isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true;
|
return isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Проверка прав администратора
|
|
||||||
*/
|
|
||||||
function isAdmin(): bool {
|
function isAdmin(): bool {
|
||||||
return isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
return isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Требовать авторизацию - редирект на login если не авторизован
|
|
||||||
*/
|
|
||||||
function requireAuth(string $redirectUrl = 'login.php'): void {
|
function requireAuth(string $redirectUrl = 'login.php'): void {
|
||||||
if (!isLoggedIn()) {
|
if (!isLoggedIn()) {
|
||||||
header('Location: ' . $redirectUrl . '?error=auth_required&redirect=' . urlencode($_SERVER['REQUEST_URI']));
|
header('Location: ' . $redirectUrl . '?error=auth_required&redirect=' . urlencode($_SERVER['REQUEST_URI']));
|
||||||
@@ -27,9 +15,6 @@ function requireAuth(string $redirectUrl = 'login.php'): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Требовать права администратора
|
|
||||||
*/
|
|
||||||
function requireAdmin(string $redirectUrl = 'login.php'): void {
|
function requireAdmin(string $redirectUrl = 'login.php'): void {
|
||||||
if (!isAdmin()) {
|
if (!isAdmin()) {
|
||||||
header('Location: ' . $redirectUrl . '?error=admin_required');
|
header('Location: ' . $redirectUrl . '?error=admin_required');
|
||||||
@@ -37,14 +22,11 @@ function requireAdmin(string $redirectUrl = 'login.php'): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Получить текущего пользователя
|
|
||||||
*/
|
|
||||||
function getCurrentUser(): ?array {
|
function getCurrentUser(): ?array {
|
||||||
if (!isLoggedIn()) {
|
if (!isLoggedIn()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'user_id' => $_SESSION['user_id'] ?? 0,
|
'user_id' => $_SESSION['user_id'] ?? 0,
|
||||||
'email' => $_SESSION['user_email'] ?? '',
|
'email' => $_SESSION['user_email'] ?? '',
|
||||||
@@ -53,38 +35,23 @@ function getCurrentUser(): ?array {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Форматирование цены
|
|
||||||
*/
|
|
||||||
function formatPrice(float $price): string {
|
function formatPrice(float $price): string {
|
||||||
return number_format($price, 0, '', ' ') . ' ₽';
|
return number_format($price, 0, '', ' ') . ' ₽';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Безопасный вывод HTML
|
|
||||||
*/
|
|
||||||
function e(string $str): string {
|
function e(string $str): string {
|
||||||
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
|
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Генерация номера заказа
|
|
||||||
*/
|
|
||||||
function generateOrderNumber(): string {
|
function generateOrderNumber(): string {
|
||||||
return 'AET-' . date('Ymd') . '-' . strtoupper(substr(uniqid(), -6));
|
return 'AET-' . date('Ymd') . '-' . strtoupper(substr(uniqid(), -6));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Генерация SKU для товара
|
|
||||||
*/
|
|
||||||
function generateSKU(string $productName): string {
|
function generateSKU(string $productName): string {
|
||||||
$prefix = strtoupper(substr(preg_replace('/[^a-zA-Z0-9]/', '', transliterate($productName)), 0, 6));
|
$prefix = strtoupper(substr(preg_replace('/[^a-zA-Z0-9]/', '', transliterate($productName)), 0, 6));
|
||||||
return $prefix . '-' . rand(100, 999);
|
return $prefix . '-' . rand(100, 999);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Транслитерация кириллицы в латиницу
|
|
||||||
*/
|
|
||||||
function transliterate(string $str): string {
|
function transliterate(string $str): string {
|
||||||
$converter = [
|
$converter = [
|
||||||
'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd',
|
'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd',
|
||||||
@@ -105,9 +72,6 @@ function transliterate(string $str): string {
|
|||||||
return strtr($str, $converter);
|
return strtr($str, $converter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Создание slug из строки
|
|
||||||
*/
|
|
||||||
function createSlug(string $str): string {
|
function createSlug(string $str): string {
|
||||||
$slug = transliterate($str);
|
$slug = transliterate($str);
|
||||||
$slug = strtolower($slug);
|
$slug = strtolower($slug);
|
||||||
@@ -116,9 +80,6 @@ function createSlug(string $str): string {
|
|||||||
return $slug;
|
return $slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Показать flash-сообщение
|
|
||||||
*/
|
|
||||||
function setFlashMessage(string $type, string $message): void {
|
function setFlashMessage(string $type, string $message): void {
|
||||||
$_SESSION['flash_message'] = [
|
$_SESSION['flash_message'] = [
|
||||||
'type' => $type,
|
'type' => $type,
|
||||||
@@ -126,9 +87,6 @@ function setFlashMessage(string $type, string $message): void {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Получить и удалить flash-сообщение
|
|
||||||
*/
|
|
||||||
function getFlashMessage(): ?array {
|
function getFlashMessage(): ?array {
|
||||||
if (isset($_SESSION['flash_message'])) {
|
if (isset($_SESSION['flash_message'])) {
|
||||||
$message = $_SESSION['flash_message'];
|
$message = $_SESSION['flash_message'];
|
||||||
@@ -137,4 +95,3 @@ function getFlashMessage(): ?array {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* Единый header для всех страниц AETERNA
|
|
||||||
* Подключение: require_once 'includes/header.php';
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Запускаем сессию если еще не запущена
|
|
||||||
if (session_status() === PHP_SESSION_NONE) {
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
session_start();
|
session_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Определяем текущую страницу
|
|
||||||
$currentPage = basename($_SERVER['PHP_SELF'], '.php');
|
$currentPage = basename($_SERVER['PHP_SELF'], '.php');
|
||||||
|
|
||||||
// Проверяем авторизацию
|
|
||||||
$isLoggedIn = isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true;
|
$isLoggedIn = isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true;
|
||||||
$isAdmin = isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
$isAdmin = isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
||||||
$userEmail = $_SESSION['user_email'] ?? '';
|
$userEmail = $_SESSION['user_email'] ?? '';
|
||||||
@@ -29,7 +22,7 @@ $fullName = $_SESSION['full_name'] ?? $userEmail;
|
|||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></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">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||||
<style>
|
<style>
|
||||||
/* Стили для профиля пользователя */
|
|
||||||
.user-profile-dropdown { position: relative; display: inline-block; }
|
.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 { 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-profile-toggle:hover { background-color: rgba(0, 0, 0, 0.05); }
|
||||||
@@ -86,13 +79,12 @@ $fullName = $_SESSION['full_name'] ?? $userEmail;
|
|||||||
|
|
||||||
<div class="header__icons--top">
|
<div class="header__icons--top">
|
||||||
<?php if ($isLoggedIn): ?>
|
<?php if ($isLoggedIn): ?>
|
||||||
<!-- Иконка корзины -->
|
|
||||||
<a href="checkout.php" class="icon cart-icon">
|
<a href="checkout.php" class="icon cart-icon">
|
||||||
<i class="fas fa-shopping-cart"></i>
|
<i class="fas fa-shopping-cart"></i>
|
||||||
<span class="cart-count" id="cartCount">0</span>
|
<span class="cart-count" id="cartCount">0</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<!-- Блок профиля -->
|
|
||||||
<div class="user-profile-dropdown">
|
<div class="user-profile-dropdown">
|
||||||
<div class="user-profile-toggle" id="profileToggle">
|
<div class="user-profile-toggle" id="profileToggle">
|
||||||
<div class="user-avatar"><?= !empty($userEmail) ? strtoupper(substr($userEmail, 0, 1)) : 'U' ?></div>
|
<div class="user-avatar"><?= !empty($userEmail) ? strtoupper(substr($userEmail, 0, 1)) : 'U' ?></div>
|
||||||
@@ -149,19 +141,18 @@ $fullName = $_SESSION['full_name'] ?? $userEmail;
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Профиль пользователя - открытие/закрытие
|
|
||||||
$('#profileToggle').click(function(e) {
|
$('#profileToggle').click(function(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
$('#profileMenu').toggle();
|
$('#profileMenu').toggle();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).click(function(e) {
|
$(document).click(function(e) {
|
||||||
if (!$(e.target).closest('.user-profile-dropdown').length) {
|
if (!$(e.target).closest('.user-profile-dropdown').length) {
|
||||||
$('#profileMenu').hide();
|
$('#profileMenu').hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Обновление счетчика корзины
|
|
||||||
<?php if ($isLoggedIn): ?>
|
<?php if ($isLoggedIn): ?>
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'api/cart.php?action=count',
|
url: 'api/cart.php?action=count',
|
||||||
@@ -178,4 +169,3 @@ $(document).ready(function() {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* Быстрый скрипт для назначения прав администратора пользователю admin@mail.ru
|
|
||||||
* Запуск: php migrations/grant_admin.php
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
@@ -16,7 +12,6 @@ try {
|
|||||||
|
|
||||||
$email = 'admin@mail.ru';
|
$email = 'admin@mail.ru';
|
||||||
|
|
||||||
// Проверяем, существует ли пользователь
|
|
||||||
$checkStmt = $db->prepare("SELECT user_id, email, full_name, is_admin, is_active FROM users WHERE email = ?");
|
$checkStmt = $db->prepare("SELECT user_id, email, full_name, is_admin, is_active FROM users WHERE email = ?");
|
||||||
$checkStmt->execute([$email]);
|
$checkStmt->execute([$email]);
|
||||||
$user = $checkStmt->fetch(PDO::FETCH_ASSOC);
|
$user = $checkStmt->fetch(PDO::FETCH_ASSOC);
|
||||||
@@ -31,9 +26,9 @@ try {
|
|||||||
if ($user['is_admin']) {
|
if ($user['is_admin']) {
|
||||||
echo "[INFO] Пользователь уже имеет права администратора\n";
|
echo "[INFO] Пользователь уже имеет права администратора\n";
|
||||||
} else {
|
} else {
|
||||||
// Обновляем права
|
|
||||||
$updateStmt = $db->prepare("
|
$updateStmt = $db->prepare("
|
||||||
UPDATE users
|
UPDATE users
|
||||||
SET is_admin = TRUE,
|
SET is_admin = TRUE,
|
||||||
is_active = TRUE,
|
is_active = TRUE,
|
||||||
updated_at = CURRENT_TIMESTAMP
|
updated_at = CURRENT_TIMESTAMP
|
||||||
@@ -47,8 +42,6 @@ try {
|
|||||||
echo "[WARN] Пользователь с email $email не найден\n";
|
echo "[WARN] Пользователь с email $email не найден\n";
|
||||||
echo "[INFO] Создаю нового пользователя с правами администратора...\n";
|
echo "[INFO] Создаю нового пользователя с правами администратора...\n";
|
||||||
|
|
||||||
// Создаем пользователя с правами админа
|
|
||||||
// Пароль по умолчанию: admin123
|
|
||||||
$password_hash = password_hash('admin123', PASSWORD_DEFAULT);
|
$password_hash = password_hash('admin123', PASSWORD_DEFAULT);
|
||||||
|
|
||||||
$insertStmt = $db->prepare("
|
$insertStmt = $db->prepare("
|
||||||
@@ -73,7 +66,6 @@ try {
|
|||||||
echo "[WARN] Рекомендуется сменить пароль после первого входа!\n";
|
echo "[WARN] Рекомендуется сменить пароль после первого входа!\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем результат
|
|
||||||
$verifyStmt = $db->prepare("SELECT user_id, email, full_name, is_admin, is_active FROM users WHERE email = ?");
|
$verifyStmt = $db->prepare("SELECT user_id, email, full_name, is_admin, is_active FROM users WHERE email = ?");
|
||||||
$verifyStmt->execute([$email]);
|
$verifyStmt->execute([$email]);
|
||||||
$finalUser = $verifyStmt->fetch(PDO::FETCH_ASSOC);
|
$finalUser = $verifyStmt->fetch(PDO::FETCH_ASSOC);
|
||||||
@@ -91,4 +83,3 @@ try {
|
|||||||
echo "[ERROR] Ошибка: " . $e->getMessage() . "\n";
|
echo "[ERROR] Ошибка: " . $e->getMessage() . "\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* Простой раннер миграций для PostgreSQL
|
|
||||||
* Запуск: php migrations/migrate.php
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Подключаем конфиг базы данных
|
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
echo "===========================================\n";
|
echo "===========================================\n";
|
||||||
@@ -15,7 +10,6 @@ try {
|
|||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
echo "[OK] Подключение к базе данных успешно\n\n";
|
echo "[OK] Подключение к базе данных успешно\n\n";
|
||||||
|
|
||||||
// 1. Создаем таблицу для отслеживания миграций
|
|
||||||
$db->exec("
|
$db->exec("
|
||||||
CREATE TABLE IF NOT EXISTS migrations (
|
CREATE TABLE IF NOT EXISTS migrations (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
@@ -25,12 +19,10 @@ try {
|
|||||||
");
|
");
|
||||||
echo "[OK] Таблица migrations готова\n";
|
echo "[OK] Таблица migrations готова\n";
|
||||||
|
|
||||||
// 2. Получаем список уже примененных миграций
|
|
||||||
$stmt = $db->query("SELECT filename FROM migrations ORDER BY filename");
|
$stmt = $db->query("SELECT filename FROM migrations ORDER BY filename");
|
||||||
$applied = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
$applied = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||||
echo "[INFO] Уже применено миграций: " . count($applied) . "\n\n";
|
echo "[INFO] Уже применено миграций: " . count($applied) . "\n\n";
|
||||||
|
|
||||||
// 3. Сканируем папку на SQL-файлы
|
|
||||||
$migrationFiles = glob(__DIR__ . '/*.sql');
|
$migrationFiles = glob(__DIR__ . '/*.sql');
|
||||||
sort($migrationFiles);
|
sort($migrationFiles);
|
||||||
|
|
||||||
@@ -38,30 +30,26 @@ try {
|
|||||||
|
|
||||||
foreach ($migrationFiles as $file) {
|
foreach ($migrationFiles as $file) {
|
||||||
$filename = basename($file);
|
$filename = basename($file);
|
||||||
|
|
||||||
// Пропускаем seed_data.sql - он запускается отдельно
|
|
||||||
if ($filename === 'seed_data.sql') {
|
if ($filename === 'seed_data.sql') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, была ли миграция уже применена
|
|
||||||
if (in_array($filename, $applied)) {
|
if (in_array($filename, $applied)) {
|
||||||
echo "[SKIP] $filename (уже применена)\n";
|
echo "[SKIP] $filename (уже применена)\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Применяем миграцию
|
|
||||||
echo "[RUN] Применяю $filename... ";
|
echo "[RUN] Применяю $filename... ";
|
||||||
|
|
||||||
$sql = file_get_contents($file);
|
$sql = file_get_contents($file);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$db->exec($sql);
|
$db->exec($sql);
|
||||||
|
|
||||||
// Записываем в таблицу миграций
|
|
||||||
$stmt = $db->prepare("INSERT INTO migrations (filename) VALUES (?)");
|
$stmt = $db->prepare("INSERT INTO migrations (filename) VALUES (?)");
|
||||||
$stmt->execute([$filename]);
|
$stmt->execute([$filename]);
|
||||||
|
|
||||||
echo "OK\n";
|
echo "OK\n";
|
||||||
$newMigrations++;
|
$newMigrations++;
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
@@ -73,19 +61,18 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
echo "\n-------------------------------------------\n";
|
echo "\n-------------------------------------------\n";
|
||||||
|
|
||||||
if ($newMigrations > 0) {
|
if ($newMigrations > 0) {
|
||||||
echo "[SUCCESS] Применено новых миграций: $newMigrations\n";
|
echo "[SUCCESS] Применено новых миграций: $newMigrations\n";
|
||||||
} else {
|
} else {
|
||||||
echo "[INFO] Все миграции уже применены\n";
|
echo "[INFO] Все миграции уже применены\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Спрашиваем про seed_data
|
|
||||||
$seedFile = __DIR__ . '/seed_data.sql';
|
$seedFile = __DIR__ . '/seed_data.sql';
|
||||||
if (file_exists($seedFile)) {
|
if (file_exists($seedFile)) {
|
||||||
echo "\n[?] Хотите загрузить начальные данные (seed_data.sql)?\n";
|
echo "\n[?] Хотите загрузить начальные данные (seed_data.sql)?\n";
|
||||||
echo " Запустите: php migrations/migrate.php --seed\n";
|
echo " Запустите: php migrations/migrate.php --seed\n";
|
||||||
|
|
||||||
if (isset($argv[1]) && $argv[1] === '--seed') {
|
if (isset($argv[1]) && $argv[1] === '--seed') {
|
||||||
echo "\n[RUN] Загружаю seed_data.sql... ";
|
echo "\n[RUN] Загружаю seed_data.sql... ";
|
||||||
try {
|
try {
|
||||||
@@ -106,4 +93,3 @@ try {
|
|||||||
echo "[ERROR] Ошибка подключения к БД: " . $e->getMessage() . "\n";
|
echo "[ERROR] Ошибка подключения к БД: " . $e->getMessage() . "\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,116 +1,112 @@
|
|||||||
<?php
|
<?php
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
|
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['product_id'])) {
|
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['product_id'])) {
|
||||||
$product_id = intval($_POST['product_id']);
|
$product_id = intval($_POST['product_id']);
|
||||||
$quantity = intval($_POST['quantity'] ?? 1);
|
$quantity = intval($_POST['quantity'] ?? 1);
|
||||||
$user_id = $_SESSION['user_id'] ?? 0;
|
$user_id = $_SESSION['user_id'] ?? 0;
|
||||||
|
|
||||||
if ($user_id == 0) {
|
if ($user_id == 0) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
|
echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Проверяем наличие товара на складе
|
|
||||||
$checkStock = $db->prepare("
|
$checkStock = $db->prepare("
|
||||||
SELECT stock_quantity, name, price
|
SELECT stock_quantity, name, price
|
||||||
FROM products
|
FROM products
|
||||||
WHERE product_id = ? AND is_available = TRUE
|
WHERE product_id = ? AND is_available = TRUE
|
||||||
");
|
");
|
||||||
$checkStock->execute([$product_id]);
|
$checkStock->execute([$product_id]);
|
||||||
$product = $checkStock->fetch();
|
$product = $checkStock->fetch();
|
||||||
|
|
||||||
if (!$product) {
|
if (!$product) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Товар не найден']);
|
echo json_encode(['success' => false, 'message' => 'Товар не найден']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($product['stock_quantity'] < $quantity) {
|
if ($product['stock_quantity'] < $quantity) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Недостаточно товара на складе']);
|
echo json_encode(['success' => false, 'message' => 'Недостаточно товара на складе']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, есть ли товар уже в корзине пользователя
|
$checkCart = $db->prepare("
|
||||||
$checkCart = $db->prepare("
|
SELECT cart_id, quantity
|
||||||
SELECT cart_id, quantity
|
FROM cart
|
||||||
FROM cart
|
WHERE user_id = ? AND product_id = ?
|
||||||
WHERE user_id = ? AND product_id = ?
|
");
|
||||||
");
|
$checkCart->execute([$user_id, $product_id]);
|
||||||
$checkCart->execute([$user_id, $product_id]);
|
$cartItem = $checkCart->fetch();
|
||||||
$cartItem = $checkCart->fetch();
|
|
||||||
|
if ($cartItem) {
|
||||||
if ($cartItem) {
|
|
||||||
// Обновляем количество
|
$newQuantity = $cartItem['quantity'] + $quantity;
|
||||||
$newQuantity = $cartItem['quantity'] + $quantity;
|
|
||||||
|
if ($newQuantity > $product['stock_quantity']) {
|
||||||
// Проверяем общее количество
|
echo json_encode(['success' => false, 'message' => 'Превышено доступное количество']);
|
||||||
if ($newQuantity > $product['stock_quantity']) {
|
exit();
|
||||||
echo json_encode(['success' => false, 'message' => 'Превышено доступное количество']);
|
}
|
||||||
exit();
|
|
||||||
}
|
$updateStmt = $db->prepare("
|
||||||
|
UPDATE cart
|
||||||
$updateStmt = $db->prepare("
|
SET quantity = ?, updated_at = CURRENT_TIMESTAMP
|
||||||
UPDATE cart
|
WHERE cart_id = ?
|
||||||
SET quantity = ?, updated_at = CURRENT_TIMESTAMP
|
");
|
||||||
WHERE cart_id = ?
|
$updateStmt->execute([$newQuantity, $cartItem['cart_id']]);
|
||||||
");
|
} else {
|
||||||
$updateStmt->execute([$newQuantity, $cartItem['cart_id']]);
|
|
||||||
} else {
|
$insertStmt = $db->prepare("
|
||||||
// Добавляем новый товар
|
INSERT INTO cart (user_id, product_id, quantity)
|
||||||
$insertStmt = $db->prepare("
|
VALUES (?, ?, ?)
|
||||||
INSERT INTO cart (user_id, product_id, quantity)
|
");
|
||||||
VALUES (?, ?, ?)
|
$insertStmt->execute([$user_id, $product_id, $quantity]);
|
||||||
");
|
}
|
||||||
$insertStmt->execute([$user_id, $product_id, $quantity]);
|
|
||||||
}
|
if (!isset($_SESSION['cart'])) {
|
||||||
|
$_SESSION['cart'] = [];
|
||||||
// Обновляем сессию
|
}
|
||||||
if (!isset($_SESSION['cart'])) {
|
|
||||||
$_SESSION['cart'] = [];
|
if (isset($_SESSION['cart'][$product_id])) {
|
||||||
}
|
$_SESSION['cart'][$product_id]['quantity'] += $quantity;
|
||||||
|
} else {
|
||||||
if (isset($_SESSION['cart'][$product_id])) {
|
$_SESSION['cart'][$product_id] = [
|
||||||
$_SESSION['cart'][$product_id]['quantity'] += $quantity;
|
'quantity' => $quantity,
|
||||||
} else {
|
'name' => $product['name'],
|
||||||
$_SESSION['cart'][$product_id] = [
|
'price' => $product['price'],
|
||||||
'quantity' => $quantity,
|
'added_at' => time()
|
||||||
'name' => $product['name'],
|
];
|
||||||
'price' => $product['price'],
|
}
|
||||||
'added_at' => time()
|
|
||||||
];
|
$cartCountStmt = $db->prepare("
|
||||||
}
|
SELECT SUM(quantity) as total
|
||||||
|
FROM cart
|
||||||
// Получаем общее количество товаров в корзине
|
WHERE user_id = ?
|
||||||
$cartCountStmt = $db->prepare("
|
");
|
||||||
SELECT SUM(quantity) as total
|
$cartCountStmt->execute([$user_id]);
|
||||||
FROM cart
|
$cart_count = $cartCountStmt->fetchColumn() ?: 0;
|
||||||
WHERE user_id = ?
|
|
||||||
");
|
echo json_encode([
|
||||||
$cartCountStmt->execute([$user_id]);
|
'success' => true,
|
||||||
$cart_count = $cartCountStmt->fetchColumn() ?: 0;
|
'cart_count' => $cart_count,
|
||||||
|
'message' => 'Товар добавлен в корзину'
|
||||||
echo json_encode([
|
]);
|
||||||
'success' => true,
|
|
||||||
'cart_count' => $cart_count,
|
} catch (PDOException $e) {
|
||||||
'message' => 'Товар добавлен в корзину'
|
echo json_encode([
|
||||||
]);
|
'success' => false,
|
||||||
|
'message' => 'Ошибка базы данных: ' . $e->getMessage()
|
||||||
} catch (PDOException $e) {
|
]);
|
||||||
echo json_encode([
|
}
|
||||||
'success' => false,
|
} else {
|
||||||
'message' => 'Ошибка базы данных: ' . $e->getMessage()
|
echo json_encode(['success' => false, 'message' => 'Неверный запрос']);
|
||||||
]);
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Неверный запрос']);
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
@@ -1,71 +1,68 @@
|
|||||||
<?php
|
<?php
|
||||||
// login_handler.php
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$email = $_POST['email'] ?? '';
|
$email = $_POST['email'] ?? '';
|
||||||
$password = $_POST['password'] ?? '';
|
$password = $_POST['password'] ?? '';
|
||||||
|
|
||||||
if (empty($email) || empty($password)) {
|
if (empty($email) || empty($password)) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Заполните все поля']);
|
echo json_encode(['success' => false, 'message' => 'Заполните все поля']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Проверяем пользователя в базе данных
|
|
||||||
$stmt = $db->prepare("
|
$stmt = $db->prepare("
|
||||||
SELECT user_id, email, password_hash, full_name, phone, city, is_admin, is_active
|
SELECT user_id, email, password_hash, full_name, phone, city, is_admin, is_active
|
||||||
FROM users
|
FROM users
|
||||||
WHERE email = ?
|
WHERE email = ?
|
||||||
");
|
");
|
||||||
$stmt->execute([$email]);
|
$stmt->execute([$email]);
|
||||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
|
echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$user['is_active']) {
|
if (!$user['is_active']) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Аккаунт заблокирован']);
|
echo json_encode(['success' => false, 'message' => 'Аккаунт заблокирован']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем пароль
|
if (empty($user['password_hash'])) {
|
||||||
if (empty($user['password_hash'])) {
|
echo json_encode(['success' => false, 'message' => 'Ошибка: пароль не найден в базе данных']);
|
||||||
echo json_encode(['success' => false, 'message' => 'Ошибка: пароль не найден в базе данных']);
|
exit();
|
||||||
exit();
|
}
|
||||||
}
|
|
||||||
|
if (!password_verify($password, $user['password_hash'])) {
|
||||||
if (!password_verify($password, $user['password_hash'])) {
|
echo json_encode(['success' => false, 'message' => 'Неверный пароль']);
|
||||||
echo json_encode(['success' => false, 'message' => 'Неверный пароль']);
|
exit();
|
||||||
exit();
|
}
|
||||||
}
|
|
||||||
|
$_SESSION['user_id'] = $user['user_id'];
|
||||||
// Сохраняем в сессию
|
$_SESSION['user_email'] = $user['email'];
|
||||||
$_SESSION['user_id'] = $user['user_id'];
|
$_SESSION['full_name'] = $user['full_name'];
|
||||||
$_SESSION['user_email'] = $user['email'];
|
$_SESSION['user_phone'] = $user['phone'] ?? '';
|
||||||
$_SESSION['full_name'] = $user['full_name'];
|
$_SESSION['user_city'] = $user['city'] ?? '';
|
||||||
$_SESSION['user_phone'] = $user['phone'] ?? '';
|
$_SESSION['isLoggedIn'] = true;
|
||||||
$_SESSION['user_city'] = $user['city'] ?? '';
|
$_SESSION['isAdmin'] = (bool)$user['is_admin'];
|
||||||
$_SESSION['isLoggedIn'] = true;
|
$_SESSION['login_time'] = time();
|
||||||
$_SESSION['isAdmin'] = (bool)$user['is_admin'];
|
|
||||||
$_SESSION['login_time'] = time();
|
$updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?");
|
||||||
|
$updateStmt->execute([$user['user_id']]);
|
||||||
// Обновляем время последнего входа
|
|
||||||
$updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?");
|
echo json_encode(['success' => true, 'redirect' => 'catalog.php']);
|
||||||
$updateStmt->execute([$user['user_id']]);
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
echo json_encode(['success' => true, 'redirect' => 'catalog.php']);
|
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных']);
|
||||||
|
}
|
||||||
} catch (PDOException $e) {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных']);
|
} else {
|
||||||
}
|
echo json_encode(['success' => false, 'message' => 'Неверный запрос']);
|
||||||
|
}
|
||||||
} else {
|
|
||||||
echo json_encode(['success' => false, 'message' => 'Неверный запрос']);
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
@@ -1,14 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* API для работы с корзиной
|
|
||||||
* Эндпоинты: add, update, remove, get, count
|
|
||||||
*/
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
// Проверка авторизации
|
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
|
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
|
||||||
exit();
|
exit();
|
||||||
@@ -24,66 +20,64 @@ try {
|
|||||||
case 'add':
|
case 'add':
|
||||||
$productId = (int)($_POST['product_id'] ?? 0);
|
$productId = (int)($_POST['product_id'] ?? 0);
|
||||||
$quantity = (int)($_POST['quantity'] ?? 1);
|
$quantity = (int)($_POST['quantity'] ?? 1);
|
||||||
|
|
||||||
if ($productId <= 0) {
|
if ($productId <= 0) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Неверный ID товара']);
|
echo json_encode(['success' => false, 'message' => 'Неверный ID товара']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем существование товара
|
|
||||||
$checkProduct = $db->prepare("SELECT product_id, stock_quantity FROM products WHERE product_id = ? AND is_available = TRUE");
|
$checkProduct = $db->prepare("SELECT product_id, stock_quantity FROM products WHERE product_id = ? AND is_available = TRUE");
|
||||||
$checkProduct->execute([$productId]);
|
$checkProduct->execute([$productId]);
|
||||||
$product = $checkProduct->fetch();
|
$product = $checkProduct->fetch();
|
||||||
|
|
||||||
if (!$product) {
|
if (!$product) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Товар не найден']);
|
echo json_encode(['success' => false, 'message' => 'Товар не найден']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, есть ли товар уже в корзине
|
|
||||||
$checkCart = $db->prepare("SELECT cart_id, quantity FROM cart WHERE user_id = ? AND product_id = ?");
|
$checkCart = $db->prepare("SELECT cart_id, quantity FROM cart WHERE user_id = ? AND product_id = ?");
|
||||||
$checkCart->execute([$userId, $productId]);
|
$checkCart->execute([$userId, $productId]);
|
||||||
$cartItem = $checkCart->fetch();
|
$cartItem = $checkCart->fetch();
|
||||||
|
|
||||||
if ($cartItem) {
|
if ($cartItem) {
|
||||||
// Обновляем количество
|
|
||||||
$newQuantity = $cartItem['quantity'] + $quantity;
|
$newQuantity = $cartItem['quantity'] + $quantity;
|
||||||
$stmt = $db->prepare("UPDATE cart SET quantity = ?, updated_at = CURRENT_TIMESTAMP WHERE cart_id = ?");
|
$stmt = $db->prepare("UPDATE cart SET quantity = ?, updated_at = CURRENT_TIMESTAMP WHERE cart_id = ?");
|
||||||
$stmt->execute([$newQuantity, $cartItem['cart_id']]);
|
$stmt->execute([$newQuantity, $cartItem['cart_id']]);
|
||||||
} else {
|
} else {
|
||||||
// Добавляем новый товар
|
|
||||||
$stmt = $db->prepare("INSERT INTO cart (user_id, product_id, quantity) VALUES (?, ?, ?)");
|
$stmt = $db->prepare("INSERT INTO cart (user_id, product_id, quantity) VALUES (?, ?, ?)");
|
||||||
$stmt->execute([$userId, $productId, $quantity]);
|
$stmt->execute([$userId, $productId, $quantity]);
|
||||||
}
|
}
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Товар добавлен в корзину']);
|
echo json_encode(['success' => true, 'message' => 'Товар добавлен в корзину']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'update':
|
case 'update':
|
||||||
$productId = (int)($_POST['product_id'] ?? 0);
|
$productId = (int)($_POST['product_id'] ?? 0);
|
||||||
$quantity = (int)($_POST['quantity'] ?? 1);
|
$quantity = (int)($_POST['quantity'] ?? 1);
|
||||||
|
|
||||||
if ($quantity <= 0) {
|
if ($quantity <= 0) {
|
||||||
// Удаляем товар если количество 0
|
|
||||||
$stmt = $db->prepare("DELETE FROM cart WHERE user_id = ? AND product_id = ?");
|
$stmt = $db->prepare("DELETE FROM cart WHERE user_id = ? AND product_id = ?");
|
||||||
$stmt->execute([$userId, $productId]);
|
$stmt->execute([$userId, $productId]);
|
||||||
} else {
|
} else {
|
||||||
$stmt = $db->prepare("UPDATE cart SET quantity = ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ? AND product_id = ?");
|
$stmt = $db->prepare("UPDATE cart SET quantity = ?, updated_at = CURRENT_TIMESTAMP WHERE user_id = ? AND product_id = ?");
|
||||||
$stmt->execute([$quantity, $userId, $productId]);
|
$stmt->execute([$quantity, $userId, $productId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Корзина обновлена']);
|
echo json_encode(['success' => true, 'message' => 'Корзина обновлена']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'remove':
|
case 'remove':
|
||||||
$productId = (int)($_POST['product_id'] ?? 0);
|
$productId = (int)($_POST['product_id'] ?? 0);
|
||||||
|
|
||||||
$stmt = $db->prepare("DELETE FROM cart WHERE user_id = ? AND product_id = ?");
|
$stmt = $db->prepare("DELETE FROM cart WHERE user_id = ? AND product_id = ?");
|
||||||
$stmt->execute([$userId, $productId]);
|
$stmt->execute([$userId, $productId]);
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Товар удален из корзины']);
|
echo json_encode(['success' => true, 'message' => 'Товар удален из корзины']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'get':
|
case 'get':
|
||||||
$stmt = $db->prepare("
|
$stmt = $db->prepare("
|
||||||
SELECT c.cart_id, c.product_id, c.quantity, p.name, p.price, p.image_url, p.stock_quantity
|
SELECT c.cart_id, c.product_id, c.quantity, p.name, p.price, p.image_url, p.stock_quantity
|
||||||
@@ -94,13 +88,13 @@ try {
|
|||||||
");
|
");
|
||||||
$stmt->execute([$userId]);
|
$stmt->execute([$userId]);
|
||||||
$items = $stmt->fetchAll();
|
$items = $stmt->fetchAll();
|
||||||
|
|
||||||
$total = 0;
|
$total = 0;
|
||||||
foreach ($items as &$item) {
|
foreach ($items as &$item) {
|
||||||
$item['subtotal'] = $item['price'] * $item['quantity'];
|
$item['subtotal'] = $item['price'] * $item['quantity'];
|
||||||
$total += $item['subtotal'];
|
$total += $item['subtotal'];
|
||||||
}
|
}
|
||||||
|
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'items' => $items,
|
'items' => $items,
|
||||||
@@ -108,27 +102,26 @@ try {
|
|||||||
'count' => array_sum(array_column($items, 'quantity'))
|
'count' => array_sum(array_column($items, 'quantity'))
|
||||||
]);
|
]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'count':
|
case 'count':
|
||||||
$stmt = $db->prepare("SELECT COALESCE(SUM(quantity), 0) FROM cart WHERE user_id = ?");
|
$stmt = $db->prepare("SELECT COALESCE(SUM(quantity), 0) FROM cart WHERE user_id = ?");
|
||||||
$stmt->execute([$userId]);
|
$stmt->execute([$userId]);
|
||||||
$count = $stmt->fetchColumn();
|
$count = $stmt->fetchColumn();
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'count' => (int)$count]);
|
echo json_encode(['success' => true, 'count' => (int)$count]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'clear':
|
case 'clear':
|
||||||
$stmt = $db->prepare("DELETE FROM cart WHERE user_id = ?");
|
$stmt = $db->prepare("DELETE FROM cart WHERE user_id = ?");
|
||||||
$stmt->execute([$userId]);
|
$stmt->execute([$userId]);
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'message' => 'Корзина очищена']);
|
echo json_encode(['success' => true, 'message' => 'Корзина очищена']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
echo json_encode(['success' => false, 'message' => 'Неизвестное действие']);
|
echo json_encode(['success' => false, 'message' => 'Неизвестное действие']);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]);
|
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,62 +1,61 @@
|
|||||||
<?php
|
<?php
|
||||||
// get_cart.php
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
|
echo json_encode(['success' => false, 'message' => 'Требуется авторизация']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_id = $_SESSION['user_id'] ?? 0;
|
$user_id = $_SESSION['user_id'] ?? 0;
|
||||||
|
|
||||||
if ($user_id == 0) {
|
if ($user_id == 0) {
|
||||||
echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
|
echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Получаем корзину из БД
|
|
||||||
$stmt = $db->prepare("
|
$stmt = $db->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
c.cart_id,
|
c.cart_id,
|
||||||
c.product_id,
|
c.product_id,
|
||||||
c.quantity,
|
c.quantity,
|
||||||
p.name,
|
p.name,
|
||||||
p.price,
|
p.price,
|
||||||
p.image_url,
|
p.image_url,
|
||||||
p.stock_quantity
|
p.stock_quantity
|
||||||
FROM cart c
|
FROM cart c
|
||||||
JOIN products p ON c.product_id = p.product_id
|
JOIN products p ON c.product_id = p.product_id
|
||||||
WHERE c.user_id = ? AND p.is_available = TRUE
|
WHERE c.user_id = ? AND p.is_available = TRUE
|
||||||
ORDER BY c.created_at DESC
|
ORDER BY c.created_at DESC
|
||||||
");
|
");
|
||||||
$stmt->execute([$user_id]);
|
$stmt->execute([$user_id]);
|
||||||
$cart_items = $stmt->fetchAll();
|
$cart_items = $stmt->fetchAll();
|
||||||
|
|
||||||
// Обновляем сессию
|
$_SESSION['cart'] = [];
|
||||||
$_SESSION['cart'] = [];
|
foreach ($cart_items as $item) {
|
||||||
foreach ($cart_items as $item) {
|
$_SESSION['cart'][$item['product_id']] = [
|
||||||
$_SESSION['cart'][$item['product_id']] = [
|
'quantity' => $item['quantity'],
|
||||||
'quantity' => $item['quantity'],
|
'name' => $item['name'],
|
||||||
'name' => $item['name'],
|
'price' => $item['price'],
|
||||||
'price' => $item['price'],
|
'added_at' => time()
|
||||||
'added_at' => time()
|
];
|
||||||
];
|
}
|
||||||
}
|
|
||||||
|
echo json_encode([
|
||||||
echo json_encode([
|
'success' => true,
|
||||||
'success' => true,
|
'cart_items' => $cart_items,
|
||||||
'cart_items' => $cart_items,
|
'total_items' => count($cart_items)
|
||||||
'total_items' => count($cart_items)
|
]);
|
||||||
]);
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
} catch (PDOException $e) {
|
echo json_encode([
|
||||||
echo json_encode([
|
'success' => false,
|
||||||
'success' => false,
|
'message' => 'Ошибка базы данных: ' . $e->getMessage()
|
||||||
'message' => 'Ошибка базы данных: ' . $e->getMessage()
|
]);
|
||||||
]);
|
}
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
// get_cart_count.php
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
echo json_encode(['success' => false, 'cart_count' => 0]);
|
echo json_encode(['success' => false, 'cart_count' => 0]);
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_id = $_SESSION['user_id'] ?? 0;
|
$user_id = $_SESSION['user_id'] ?? 0;
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$stmt = $db->prepare("SELECT SUM(quantity) as total FROM cart WHERE user_id = ?");
|
$stmt = $db->prepare("SELECT SUM(quantity) as total FROM cart WHERE user_id = ?");
|
||||||
$stmt->execute([$user_id]);
|
$stmt->execute([$user_id]);
|
||||||
$cart_count = $stmt->fetchColumn() ?: 0;
|
$cart_count = $stmt->fetchColumn() ?: 0;
|
||||||
|
|
||||||
echo json_encode(['success' => true, 'cart_count' => $cart_count]);
|
echo json_encode(['success' => true, 'cart_count' => $cart_count]);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
echo json_encode(['success' => false, 'cart_count' => 0]);
|
echo json_encode(['success' => false, 'cart_count' => 0]);
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,32 @@
|
|||||||
<?php
|
<?php
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
// Проверяем авторизацию администратора
|
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
|
||||||
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
|
echo json_encode(['success' => false, 'message' => 'Доступ запрещен']);
|
||||||
echo json_encode(['success' => false, 'message' => 'Доступ запрещен']);
|
exit();
|
||||||
exit();
|
}
|
||||||
}
|
|
||||||
|
if (!isset($_GET['id'])) {
|
||||||
if (!isset($_GET['id'])) {
|
echo json_encode(['success' => false, 'message' => 'ID не указан']);
|
||||||
echo json_encode(['success' => false, 'message' => 'ID не указан']);
|
exit();
|
||||||
exit();
|
}
|
||||||
}
|
|
||||||
|
try {
|
||||||
try {
|
$db = Database::getInstance()->getConnection();
|
||||||
$db = Database::getInstance()->getConnection();
|
$product_id = $_GET['id'];
|
||||||
$product_id = $_GET['id'];
|
|
||||||
|
$stmt = $db->prepare("SELECT * FROM products WHERE product_id = ?");
|
||||||
$stmt = $db->prepare("SELECT * FROM products WHERE product_id = ?");
|
$stmt->execute([$product_id]);
|
||||||
$stmt->execute([$product_id]);
|
$product = $stmt->fetch();
|
||||||
$product = $stmt->fetch();
|
|
||||||
|
if ($product) {
|
||||||
if ($product) {
|
echo json_encode($product);
|
||||||
echo json_encode($product);
|
} else {
|
||||||
} else {
|
echo json_encode(['success' => false, 'message' => 'Товар не найден']);
|
||||||
echo json_encode(['success' => false, 'message' => 'Товар не найден']);
|
}
|
||||||
}
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
} catch (PDOException $e) {
|
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]);
|
||||||
echo json_encode(['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()]);
|
}
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
@@ -1,134 +1,124 @@
|
|||||||
<?php
|
<?php
|
||||||
// process_order.php
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
header('Location: login.php?error=auth_required');
|
header('Location: login.php?error=auth_required');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_id = $_SESSION['user_id'] ?? 0;
|
$user_id = $_SESSION['user_id'] ?? 0;
|
||||||
|
|
||||||
if ($user_id == 0) {
|
if ($user_id == 0) {
|
||||||
header('Location: login.php?error=user_not_found');
|
header('Location: login.php?error=user_not_found');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$db->beginTransaction();
|
$db->beginTransaction();
|
||||||
|
|
||||||
// Получаем данные из формы
|
$customer_name = $_POST['full_name'] ?? '';
|
||||||
$customer_name = $_POST['full_name'] ?? '';
|
$customer_email = $_POST['email'] ?? '';
|
||||||
$customer_email = $_POST['email'] ?? '';
|
$customer_phone = $_POST['phone'] ?? '';
|
||||||
$customer_phone = $_POST['phone'] ?? '';
|
$delivery_address = $_POST['address'] ?? '';
|
||||||
$delivery_address = $_POST['address'] ?? '';
|
$region = $_POST['region'] ?? '';
|
||||||
$region = $_POST['region'] ?? '';
|
$payment_method = $_POST['payment'] ?? 'card';
|
||||||
$payment_method = $_POST['payment'] ?? 'card';
|
$delivery_method = $_POST['delivery'] ?? 'courier';
|
||||||
$delivery_method = $_POST['delivery'] ?? 'courier';
|
$notes = $_POST['notes'] ?? '';
|
||||||
$notes = $_POST['notes'] ?? '';
|
$discount_amount = floatval($_POST['discount'] ?? 0);
|
||||||
$discount_amount = floatval($_POST['discount'] ?? 0);
|
$delivery_cost = floatval($_POST['delivery_price'] ?? 2000);
|
||||||
$delivery_cost = floatval($_POST['delivery_price'] ?? 2000);
|
|
||||||
|
$order_number = 'ORD-' . date('Ymd-His') . '-' . rand(1000, 9999);
|
||||||
// Генерируем номер заказа
|
|
||||||
$order_number = 'ORD-' . date('Ymd-His') . '-' . rand(1000, 9999);
|
$cartStmt = $db->prepare("
|
||||||
|
SELECT
|
||||||
// Получаем корзину пользователя
|
c.product_id,
|
||||||
$cartStmt = $db->prepare("
|
c.quantity,
|
||||||
SELECT
|
p.name,
|
||||||
c.product_id,
|
p.price,
|
||||||
c.quantity,
|
p.stock_quantity
|
||||||
p.name,
|
FROM cart c
|
||||||
p.price,
|
JOIN products p ON c.product_id = p.product_id
|
||||||
p.stock_quantity
|
WHERE c.user_id = ?
|
||||||
FROM cart c
|
");
|
||||||
JOIN products p ON c.product_id = p.product_id
|
$cartStmt->execute([$user_id]);
|
||||||
WHERE c.user_id = ?
|
$cart_items = $cartStmt->fetchAll();
|
||||||
");
|
|
||||||
$cartStmt->execute([$user_id]);
|
if (empty($cart_items)) {
|
||||||
$cart_items = $cartStmt->fetchAll();
|
throw new Exception('Корзина пуста');
|
||||||
|
}
|
||||||
if (empty($cart_items)) {
|
|
||||||
throw new Exception('Корзина пуста');
|
$total_amount = 0;
|
||||||
}
|
foreach ($cart_items as $item) {
|
||||||
|
$total_amount += $item['price'] * $item['quantity'];
|
||||||
// Рассчитываем итоги
|
}
|
||||||
$total_amount = 0;
|
|
||||||
foreach ($cart_items as $item) {
|
$final_amount = $total_amount - $discount_amount + $delivery_cost;
|
||||||
$total_amount += $item['price'] * $item['quantity'];
|
|
||||||
}
|
$orderStmt = $db->prepare("
|
||||||
|
INSERT INTO orders (
|
||||||
$final_amount = $total_amount - $discount_amount + $delivery_cost;
|
user_id, order_number, total_amount, discount_amount,
|
||||||
|
delivery_cost, final_amount, status, payment_method,
|
||||||
// Создаем заказ
|
delivery_method, delivery_address, customer_name,
|
||||||
$orderStmt = $db->prepare("
|
customer_email, customer_phone, notes
|
||||||
INSERT INTO orders (
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
user_id, order_number, total_amount, discount_amount,
|
RETURNING order_id
|
||||||
delivery_cost, final_amount, status, payment_method,
|
");
|
||||||
delivery_method, delivery_address, customer_name,
|
|
||||||
customer_email, customer_phone, notes
|
$orderStmt->execute([
|
||||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
$user_id, $order_number, $total_amount, $discount_amount,
|
||||||
RETURNING order_id
|
$delivery_cost, $final_amount, 'pending', $payment_method,
|
||||||
");
|
$delivery_method, $delivery_address, $customer_name,
|
||||||
|
$customer_email, $customer_phone, $notes
|
||||||
$orderStmt->execute([
|
]);
|
||||||
$user_id, $order_number, $total_amount, $discount_amount,
|
|
||||||
$delivery_cost, $final_amount, 'pending', $payment_method,
|
$order_id = $orderStmt->fetchColumn();
|
||||||
$delivery_method, $delivery_address, $customer_name,
|
|
||||||
$customer_email, $customer_phone, $notes
|
foreach ($cart_items as $item) {
|
||||||
]);
|
|
||||||
|
$itemStmt = $db->prepare("
|
||||||
$order_id = $orderStmt->fetchColumn();
|
INSERT INTO order_items (
|
||||||
|
order_id, product_id, product_name,
|
||||||
// Добавляем товары в заказ и обновляем остатки
|
quantity, unit_price, total_price
|
||||||
foreach ($cart_items as $item) {
|
) VALUES (?, ?, ?, ?, ?, ?)
|
||||||
// Добавляем в order_items
|
");
|
||||||
$itemStmt = $db->prepare("
|
|
||||||
INSERT INTO order_items (
|
$item_total = $item['price'] * $item['quantity'];
|
||||||
order_id, product_id, product_name,
|
$itemStmt->execute([
|
||||||
quantity, unit_price, total_price
|
$order_id, $item['product_id'], $item['name'],
|
||||||
) VALUES (?, ?, ?, ?, ?, ?)
|
$item['quantity'], $item['price'], $item_total
|
||||||
");
|
]);
|
||||||
|
|
||||||
$item_total = $item['price'] * $item['quantity'];
|
$updateStmt = $db->prepare("
|
||||||
$itemStmt->execute([
|
UPDATE products
|
||||||
$order_id, $item['product_id'], $item['name'],
|
SET stock_quantity = stock_quantity - ?,
|
||||||
$item['quantity'], $item['price'], $item_total
|
updated_at = CURRENT_TIMESTAMP
|
||||||
]);
|
WHERE product_id = ?
|
||||||
|
");
|
||||||
// Обновляем остатки на складе
|
$updateStmt->execute([$item['quantity'], $item['product_id']]);
|
||||||
$updateStmt = $db->prepare("
|
}
|
||||||
UPDATE products
|
|
||||||
SET stock_quantity = stock_quantity - ?,
|
$clearCartStmt = $db->prepare("DELETE FROM cart WHERE user_id = ?");
|
||||||
updated_at = CURRENT_TIMESTAMP
|
$clearCartStmt->execute([$user_id]);
|
||||||
WHERE product_id = ?
|
|
||||||
");
|
unset($_SESSION['cart']);
|
||||||
$updateStmt->execute([$item['quantity'], $item['product_id']]);
|
|
||||||
}
|
$db->commit();
|
||||||
|
|
||||||
// Очищаем корзину
|
header('Location: order_success.php?id=' . $order_id);
|
||||||
$clearCartStmt = $db->prepare("DELETE FROM cart WHERE user_id = ?");
|
exit();
|
||||||
$clearCartStmt->execute([$user_id]);
|
|
||||||
|
} catch (Exception $e) {
|
||||||
// Очищаем сессию
|
$db->rollBack();
|
||||||
unset($_SESSION['cart']);
|
header('Location: checkout.php?error=' . urlencode($e->getMessage()));
|
||||||
|
exit();
|
||||||
$db->commit();
|
}
|
||||||
|
} else {
|
||||||
// Перенаправляем на страницу успеха
|
header('Location: checkout.php');
|
||||||
header('Location: order_success.php?id=' . $order_id);
|
exit();
|
||||||
exit();
|
}
|
||||||
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$db->rollBack();
|
|
||||||
header('Location: checkout.php?error=' . urlencode($e->getMessage()));
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
header('Location: checkout.php');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
@@ -1,175 +1,162 @@
|
|||||||
<?php
|
<?php
|
||||||
// register_handler.php
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$errors = [];
|
$errors = [];
|
||||||
|
|
||||||
// Получаем данные из формы
|
$full_name = trim($_POST['fio'] ?? '');
|
||||||
$full_name = trim($_POST['fio'] ?? '');
|
$city = trim($_POST['city'] ?? '');
|
||||||
$city = trim($_POST['city'] ?? '');
|
$email = trim($_POST['email'] ?? '');
|
||||||
$email = trim($_POST['email'] ?? '');
|
$phone = trim($_POST['phone'] ?? '');
|
||||||
$phone = trim($_POST['phone'] ?? '');
|
$password = $_POST['password'] ?? '';
|
||||||
$password = $_POST['password'] ?? '';
|
$confirm_password = $_POST['confirm-password'] ?? '';
|
||||||
$confirm_password = $_POST['confirm-password'] ?? '';
|
|
||||||
|
if (empty($full_name) || strlen($full_name) < 3) {
|
||||||
// Валидация данных
|
$errors[] = 'ФИО должно содержать минимум 3 символа';
|
||||||
if (empty($full_name) || strlen($full_name) < 3) {
|
}
|
||||||
$errors[] = 'ФИО должно содержать минимум 3 символа';
|
|
||||||
}
|
if (empty($city) || strlen($city) < 2) {
|
||||||
|
$errors[] = 'Введите корректное название города';
|
||||||
if (empty($city) || strlen($city) < 2) {
|
}
|
||||||
$errors[] = 'Введите корректное название города';
|
|
||||||
}
|
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$errors[] = 'Введите корректный email адрес';
|
||||||
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
}
|
||||||
$errors[] = 'Введите корректный email адрес';
|
|
||||||
}
|
if (empty($phone) || !preg_match('/^(\+7|8)[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/', $phone)) {
|
||||||
|
$errors[] = 'Введите корректный номер телефона';
|
||||||
if (empty($phone) || !preg_match('/^(\+7|8)[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/', $phone)) {
|
}
|
||||||
$errors[] = 'Введите корректный номер телефона';
|
|
||||||
}
|
if (empty($password) || strlen($password) < 6) {
|
||||||
|
$errors[] = 'Пароль должен содержать минимум 6 символов';
|
||||||
if (empty($password) || strlen($password) < 6) {
|
}
|
||||||
$errors[] = 'Пароль должен содержать минимум 6 символов';
|
|
||||||
}
|
if ($password !== $confirm_password) {
|
||||||
|
$errors[] = 'Пароли не совпадают';
|
||||||
if ($password !== $confirm_password) {
|
}
|
||||||
$errors[] = 'Пароли не совпадают';
|
|
||||||
}
|
if (!isset($_POST['privacy']) || $_POST['privacy'] !== 'on') {
|
||||||
|
$errors[] = 'Необходимо согласие с условиями обработки персональных данных';
|
||||||
// Проверка согласия с условиями
|
}
|
||||||
if (!isset($_POST['privacy']) || $_POST['privacy'] !== 'on') {
|
|
||||||
$errors[] = 'Необходимо согласие с условиями обработки персональных данных';
|
if (!empty($errors)) {
|
||||||
}
|
$_SESSION['registration_errors'] = $errors;
|
||||||
|
$_SESSION['old_data'] = [
|
||||||
// Если есть ошибки, возвращаем на форму
|
'fio' => $full_name,
|
||||||
if (!empty($errors)) {
|
'city' => $city,
|
||||||
$_SESSION['registration_errors'] = $errors;
|
'email' => $email,
|
||||||
$_SESSION['old_data'] = [
|
'phone' => $phone
|
||||||
'fio' => $full_name,
|
];
|
||||||
'city' => $city,
|
header('Location: ../register.php');
|
||||||
'email' => $email,
|
exit();
|
||||||
'phone' => $phone
|
}
|
||||||
];
|
|
||||||
header('Location: ../register.php');
|
$db = Database::getInstance()->getConnection();
|
||||||
exit();
|
|
||||||
}
|
try {
|
||||||
|
|
||||||
// Подключаемся к базе данных
|
$checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?");
|
||||||
$db = Database::getInstance()->getConnection();
|
$checkStmt->execute([$email]);
|
||||||
|
|
||||||
try {
|
if ($checkStmt->fetch()) {
|
||||||
// Проверяем, существует ли пользователь с таким email
|
$_SESSION['registration_errors'] = ['Пользователь с таким email уже существует'];
|
||||||
$checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?");
|
$_SESSION['old_data'] = [
|
||||||
$checkStmt->execute([$email]);
|
'fio' => $full_name,
|
||||||
|
'city' => $city,
|
||||||
if ($checkStmt->fetch()) {
|
'email' => $email,
|
||||||
$_SESSION['registration_errors'] = ['Пользователь с таким email уже существует'];
|
'phone' => $phone
|
||||||
$_SESSION['old_data'] = [
|
];
|
||||||
'fio' => $full_name,
|
header('Location: ../register.php');
|
||||||
'city' => $city,
|
exit();
|
||||||
'email' => $email,
|
}
|
||||||
'phone' => $phone
|
|
||||||
];
|
$password_hash = password_hash($password, PASSWORD_DEFAULT);
|
||||||
header('Location: ../register.php');
|
|
||||||
exit();
|
$is_admin = false;
|
||||||
}
|
$admin_emails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru'];
|
||||||
|
if (in_array(strtolower($email), $admin_emails)) {
|
||||||
// Хэшируем пароль
|
$is_admin = true;
|
||||||
$password_hash = password_hash($password, PASSWORD_DEFAULT);
|
}
|
||||||
|
|
||||||
// Определяем, является ли пользователь администратором
|
$stmt = $db->prepare("
|
||||||
$is_admin = false;
|
INSERT INTO users (email, password_hash, full_name, phone, city, is_admin, is_active)
|
||||||
$admin_emails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru'];
|
VALUES (?, ?, ?, ?, ?, CAST(? AS boolean), TRUE)
|
||||||
if (in_array(strtolower($email), $admin_emails)) {
|
RETURNING user_id
|
||||||
$is_admin = true;
|
");
|
||||||
}
|
|
||||||
|
$stmt->execute([
|
||||||
// Используем CAST для правильной передачи boolean в PostgreSQL
|
$email,
|
||||||
$stmt = $db->prepare("
|
$password_hash,
|
||||||
INSERT INTO users (email, password_hash, full_name, phone, city, is_admin, is_active)
|
$full_name,
|
||||||
VALUES (?, ?, ?, ?, ?, CAST(? AS boolean), TRUE)
|
$phone,
|
||||||
RETURNING user_id
|
$city,
|
||||||
");
|
$is_admin ? 'true' : 'false'
|
||||||
|
]);
|
||||||
$stmt->execute([
|
|
||||||
$email,
|
$user_id = $stmt->fetchColumn();
|
||||||
$password_hash,
|
|
||||||
$full_name,
|
if (!$user_id) {
|
||||||
$phone,
|
throw new Exception('Ошибка при создании пользователя: user_id не получен');
|
||||||
$city,
|
}
|
||||||
$is_admin ? 'true' : 'false' // Строковые значения true/false для CAST
|
|
||||||
]);
|
$verifyStmt = $db->prepare("SELECT user_id, email, password_hash FROM users WHERE user_id = ?");
|
||||||
|
$verifyStmt->execute([$user_id]);
|
||||||
$user_id = $stmt->fetchColumn();
|
$verifyUser = $verifyStmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
if (!$user_id) {
|
if (!$verifyUser) {
|
||||||
throw new Exception('Ошибка при создании пользователя: user_id не получен');
|
throw new Exception('Ошибка: пользователь не найден после создания');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверяем, что пользователь действительно создался
|
if (empty($verifyUser['password_hash'])) {
|
||||||
$verifyStmt = $db->prepare("SELECT user_id, email, password_hash FROM users WHERE user_id = ?");
|
throw new Exception('Ошибка: пароль не сохранен');
|
||||||
$verifyStmt->execute([$user_id]);
|
}
|
||||||
$verifyUser = $verifyStmt->fetch(PDO::FETCH_ASSOC);
|
|
||||||
|
$_SESSION['user_id'] = $user_id;
|
||||||
if (!$verifyUser) {
|
$_SESSION['user_email'] = $email;
|
||||||
throw new Exception('Ошибка: пользователь не найден после создания');
|
$_SESSION['full_name'] = $full_name;
|
||||||
}
|
$_SESSION['user_phone'] = $phone;
|
||||||
|
$_SESSION['user_city'] = $city;
|
||||||
// Проверяем, что пароль сохранился правильно
|
$_SESSION['isLoggedIn'] = true;
|
||||||
if (empty($verifyUser['password_hash'])) {
|
$_SESSION['isAdmin'] = (bool)$is_admin;
|
||||||
throw new Exception('Ошибка: пароль не сохранен');
|
$_SESSION['login_time'] = time();
|
||||||
}
|
|
||||||
|
$updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?");
|
||||||
// Автоматически авторизуем пользователя
|
$updateStmt->execute([$user_id]);
|
||||||
$_SESSION['user_id'] = $user_id;
|
|
||||||
$_SESSION['user_email'] = $email;
|
$_SESSION['registration_success'] = 'Регистрация прошла успешно! ' .
|
||||||
$_SESSION['full_name'] = $full_name;
|
($is_admin ? 'Вы зарегистрированы как администратор.' : 'Добро пожаловать в AETERNA!');
|
||||||
$_SESSION['user_phone'] = $phone;
|
|
||||||
$_SESSION['user_city'] = $city;
|
header('Location: ../catalog.php');
|
||||||
$_SESSION['isLoggedIn'] = true;
|
exit();
|
||||||
$_SESSION['isAdmin'] = (bool)$is_admin;
|
|
||||||
$_SESSION['login_time'] = time();
|
} catch (PDOException $e) {
|
||||||
|
|
||||||
// Обновляем время последнего входа
|
error_log("Registration DB Error: " . $e->getMessage());
|
||||||
$updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?");
|
error_log("SQL State: " . $e->getCode());
|
||||||
$updateStmt->execute([$user_id]);
|
error_log("Email: " . $email);
|
||||||
|
|
||||||
// Перенаправляем на главную или каталог
|
$_SESSION['registration_errors'] = ['Ошибка базы данных: ' . $e->getMessage()];
|
||||||
$_SESSION['registration_success'] = 'Регистрация прошла успешно! ' .
|
$_SESSION['old_data'] = [
|
||||||
($is_admin ? 'Вы зарегистрированы как администратор.' : 'Добро пожаловать в AETERNA!');
|
'fio' => $full_name,
|
||||||
|
'city' => $city,
|
||||||
header('Location: ../catalog.php');
|
'email' => $email,
|
||||||
exit();
|
'phone' => $phone
|
||||||
|
];
|
||||||
} catch (PDOException $e) {
|
header('Location: ../register.php');
|
||||||
// Логируем полную ошибку для отладки
|
exit();
|
||||||
error_log("Registration DB Error: " . $e->getMessage());
|
} catch (Exception $e) {
|
||||||
error_log("SQL State: " . $e->getCode());
|
error_log("Registration Error: " . $e->getMessage());
|
||||||
error_log("Email: " . $email);
|
|
||||||
|
$_SESSION['registration_errors'] = [$e->getMessage()];
|
||||||
$_SESSION['registration_errors'] = ['Ошибка базы данных: ' . $e->getMessage()];
|
header('Location: ../register.php');
|
||||||
$_SESSION['old_data'] = [
|
exit();
|
||||||
'fio' => $full_name,
|
}
|
||||||
'city' => $city,
|
|
||||||
'email' => $email,
|
} else {
|
||||||
'phone' => $phone
|
|
||||||
];
|
header('Location: register.php');
|
||||||
header('Location: ../register.php');
|
exit();
|
||||||
exit();
|
}
|
||||||
} catch (Exception $e) {
|
|
||||||
error_log("Registration Error: " . $e->getMessage());
|
|
||||||
|
|
||||||
$_SESSION['registration_errors'] = [$e->getMessage()];
|
|
||||||
header('Location: ../register.php');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Если запрос не POST, перенаправляем на форму регистрации
|
|
||||||
header('Location: register.php');
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
@@ -1,62 +1,61 @@
|
|||||||
|
|
||||||
.error-message {
|
.error-message {
|
||||||
color: #ff0000;
|
color: #ff0000;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__input.error {
|
.form__input.error {
|
||||||
border-color: #ff0000;
|
border-color: #ff0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__group {
|
.form__group {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Стили для сообщений внизу страницы */
|
.page-messages {
|
||||||
.page-messages {
|
position: fixed;
|
||||||
position: fixed;
|
bottom: 20px;
|
||||||
bottom: 20px;
|
left: 50%;
|
||||||
left: 50%;
|
transform: translateX(-50%);
|
||||||
transform: translateX(-50%);
|
z-index: 1000;
|
||||||
z-index: 1000;
|
width: 90%;
|
||||||
width: 90%;
|
max-width: 500px;
|
||||||
max-width: 500px;
|
}
|
||||||
}
|
|
||||||
|
.message {
|
||||||
.message {
|
padding: 15px;
|
||||||
padding: 15px;
|
margin: 10px 0;
|
||||||
margin: 10px 0;
|
border-radius: 5px;
|
||||||
border-radius: 5px;
|
text-align: center;
|
||||||
text-align: center;
|
font-weight: bold;
|
||||||
font-weight: bold;
|
display: none;
|
||||||
display: none;
|
}
|
||||||
}
|
|
||||||
|
.message.error {
|
||||||
.message.error {
|
background-color: #ffebee;
|
||||||
background-color: #ffebee;
|
color: #c62828;
|
||||||
color: #c62828;
|
border: 1px solid #ffcdd2;
|
||||||
border: 1px solid #ffcdd2;
|
}
|
||||||
}
|
|
||||||
|
.message.success {
|
||||||
.message.success {
|
background-color: #e8f5e9;
|
||||||
background-color: #e8f5e9;
|
color: #453227;
|
||||||
color: #453227;
|
border: 1px solid #c8e6c9;
|
||||||
border: 1px solid #c8e6c9;
|
}
|
||||||
}
|
|
||||||
|
.message.warning {
|
||||||
.message.warning {
|
background-color: #fff3e0;
|
||||||
background-color: #fff3e0;
|
color: #ef6c00;
|
||||||
color: #ef6c00;
|
border: 1px solid #ffe0b2;
|
||||||
border: 1px solid #ffe0b2;
|
}
|
||||||
}
|
|
||||||
|
.privacy-error {
|
||||||
.privacy-error {
|
color: #ff0000;
|
||||||
color: #ff0000;
|
font-size: 12px;
|
||||||
font-size: 12px;
|
margin-top: 5px;
|
||||||
margin-top: 5px;
|
display: none;
|
||||||
display: none;
|
text-align: center;
|
||||||
text-align: center;
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,346 +1,306 @@
|
|||||||
// script.js
|
|
||||||
|
$(document).ready(function() {
|
||||||
$(document).ready(function() {
|
|
||||||
// Инициализация корзины
|
let cart = {
|
||||||
let cart = {
|
items: [
|
||||||
items: [
|
{ id: 1, name: 'Кресло OPPORTUNITY', price: 16999, quantity: 1 },
|
||||||
{ id: 1, name: 'Кресло OPPORTUNITY', price: 16999, quantity: 1 },
|
{ id: 2, name: 'Кресло GOLDEN', price: 19999, quantity: 1 },
|
||||||
{ id: 2, name: 'Кресло GOLDEN', price: 19999, quantity: 1 },
|
{ id: 3, name: 'Светильник POLET', price: 7999, quantity: 1 }
|
||||||
{ id: 3, name: 'Светильник POLET', price: 7999, quantity: 1 }
|
],
|
||||||
],
|
delivery: 2000,
|
||||||
delivery: 2000,
|
discount: 0
|
||||||
discount: 0
|
};
|
||||||
};
|
|
||||||
|
function updateTotal() {
|
||||||
// Функция обновления общей суммы
|
let productsTotal = 0;
|
||||||
function updateTotal() {
|
let totalCount = 0;
|
||||||
let productsTotal = 0;
|
|
||||||
let totalCount = 0;
|
$('.products__item').each(function() {
|
||||||
|
const $item = $(this);
|
||||||
// Пересчитываем товары
|
const price = parseInt($item.data('price'));
|
||||||
$('.products__item').each(function() {
|
const quantity = parseInt($item.find('.products__qty-value').text());
|
||||||
const $item = $(this);
|
|
||||||
const price = parseInt($item.data('price'));
|
productsTotal += price * quantity;
|
||||||
const quantity = parseInt($item.find('.products__qty-value').text());
|
totalCount += quantity;
|
||||||
|
});
|
||||||
productsTotal += price * quantity;
|
|
||||||
totalCount += quantity;
|
$('.products-total').text(productsTotal + ' ₽');
|
||||||
});
|
$('.summary-count').text(totalCount);
|
||||||
|
$('.total-count').text(totalCount + ' шт.');
|
||||||
// Обновляем отображение
|
$('.cart-count').text(totalCount);
|
||||||
$('.products-total').text(productsTotal + ' ₽');
|
|
||||||
$('.summary-count').text(totalCount);
|
const finalTotal = productsTotal + cart.delivery - cart.discount;
|
||||||
$('.total-count').text(totalCount + ' шт.');
|
$('.final-total').text(finalTotal + ' ₽');
|
||||||
$('.cart-count').text(totalCount);
|
}
|
||||||
|
|
||||||
// Обновляем итоговую сумму
|
function validateEmail(email) {
|
||||||
const finalTotal = productsTotal + cart.delivery - cart.discount;
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
$('.final-total').text(finalTotal + ' ₽');
|
return emailRegex.test(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Функция валидации email
|
function validateFullName(name) {
|
||||||
function validateEmail(email) {
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
const nameRegex = /^[a-zA-Zа-яА-ЯёЁ\s\-']+$/;
|
||||||
return emailRegex.test(email);
|
|
||||||
}
|
const words = name.trim().split(/\s+/);
|
||||||
|
|
||||||
// Функция валидации имени (ФИО)
|
return nameRegex.test(name) && words.length >= 2;
|
||||||
function validateFullName(name) {
|
}
|
||||||
// Проверяем, что имя содержит только буквы, пробелы, дефисы и апострофы
|
|
||||||
const nameRegex = /^[a-zA-Zа-яА-ЯёЁ\s\-']+$/;
|
function validatePhone(phone) {
|
||||||
|
const phoneRegex = /^\+7\d{10}$/;
|
||||||
// Проверяем, что имя состоит минимум из 2 слов
|
return phoneRegex.test(phone);
|
||||||
const words = name.trim().split(/\s+/);
|
}
|
||||||
|
|
||||||
return nameRegex.test(name) && words.length >= 2;
|
function showMessage(messageId, duration = 5000) {
|
||||||
}
|
$('.message').hide();
|
||||||
|
|
||||||
// Функция валидации телефона
|
$(messageId).fadeIn(300);
|
||||||
function validatePhone(phone) {
|
|
||||||
// Российский формат телефона: +7XXXXXXXXXX
|
if (duration > 0) {
|
||||||
const phoneRegex = /^\+7\d{10}$/;
|
setTimeout(() => {
|
||||||
return phoneRegex.test(phone);
|
$(messageId).fadeOut(300);
|
||||||
}
|
}, duration);
|
||||||
|
}
|
||||||
// Функция отображения сообщения
|
}
|
||||||
function showMessage(messageId, duration = 5000) {
|
|
||||||
// Скрываем все сообщения
|
function showPrivacyError(show) {
|
||||||
$('.message').hide();
|
if (show) {
|
||||||
|
$('#privacy-error').show();
|
||||||
// Показываем нужное сообщение
|
} else {
|
||||||
$(messageId).fadeIn(300);
|
$('#privacy-error').hide();
|
||||||
|
}
|
||||||
// Автоматически скрываем через указанное время
|
}
|
||||||
if (duration > 0) {
|
|
||||||
setTimeout(() => {
|
function showFieldError(fieldId, message) {
|
||||||
$(messageId).fadeOut(300);
|
$(fieldId).removeClass('error-input');
|
||||||
}, duration);
|
$(fieldId + '-error').remove();
|
||||||
}
|
|
||||||
}
|
if (message) {
|
||||||
|
$(fieldId).addClass('error-input');
|
||||||
// Функция показа ошибки приватности
|
$(fieldId).after('<div class="field-error" id="' + fieldId.replace('#', '') + '-error">' + message + '</div>');
|
||||||
function showPrivacyError(show) {
|
}
|
||||||
if (show) {
|
}
|
||||||
$('#privacy-error').show();
|
|
||||||
} else {
|
$('#fullname').on('blur', function() {
|
||||||
$('#privacy-error').hide();
|
const value = $(this).val().trim();
|
||||||
}
|
if (value) {
|
||||||
}
|
if (!validateFullName(value)) {
|
||||||
|
showFieldError('#fullname', 'ФИО должно содержать только буквы и состоять минимум из 2 слов');
|
||||||
// Функция отображения ошибки конкретного поля
|
} else {
|
||||||
function showFieldError(fieldId, message) {
|
showFieldError('#fullname', '');
|
||||||
// Убираем старые ошибки
|
}
|
||||||
$(fieldId).removeClass('error-input');
|
} else {
|
||||||
$(fieldId + '-error').remove();
|
showFieldError('#fullname', '');
|
||||||
|
}
|
||||||
if (message) {
|
});
|
||||||
$(fieldId).addClass('error-input');
|
|
||||||
$(fieldId).after('<div class="field-error" id="' + fieldId.replace('#', '') + '-error">' + message + '</div>');
|
$('#email').on('blur', function() {
|
||||||
}
|
const value = $(this).val().trim();
|
||||||
}
|
if (value) {
|
||||||
|
if (!validateEmail(value)) {
|
||||||
// Валидация поля при потере фокуса с указанием конкретной ошибки
|
showFieldError('#email', 'Введите корректный email адрес (например: example@mail.ru)');
|
||||||
$('#fullname').on('blur', function() {
|
} else {
|
||||||
const value = $(this).val().trim();
|
showFieldError('#email', '');
|
||||||
if (value) {
|
}
|
||||||
if (!validateFullName(value)) {
|
} else {
|
||||||
showFieldError('#fullname', 'ФИО должно содержать только буквы и состоять минимум из 2 слов');
|
showFieldError('#email', '');
|
||||||
} else {
|
}
|
||||||
showFieldError('#fullname', '');
|
});
|
||||||
}
|
|
||||||
} else {
|
$('#phone').on('blur', function() {
|
||||||
showFieldError('#fullname', '');
|
const value = $(this).val().trim();
|
||||||
}
|
if (value) {
|
||||||
});
|
if (!validatePhone(value)) {
|
||||||
|
showFieldError('#phone', 'Введите номер в формате +7XXXXXXXXXX (10 цифр после +7)');
|
||||||
$('#email').on('blur', function() {
|
} else {
|
||||||
const value = $(this).val().trim();
|
showFieldError('#phone', '');
|
||||||
if (value) {
|
}
|
||||||
if (!validateEmail(value)) {
|
} else {
|
||||||
showFieldError('#email', 'Введите корректный email адрес (например: example@mail.ru)');
|
showFieldError('#phone', '');
|
||||||
} else {
|
}
|
||||||
showFieldError('#email', '');
|
});
|
||||||
}
|
|
||||||
} else {
|
$('#region').on('blur', function() {
|
||||||
showFieldError('#email', '');
|
const value = $(this).val().trim();
|
||||||
}
|
if (!value) {
|
||||||
});
|
showFieldError('#region', 'Укажите регион доставки');
|
||||||
|
} else {
|
||||||
$('#phone').on('blur', function() {
|
showFieldError('#region', '');
|
||||||
const value = $(this).val().trim();
|
}
|
||||||
if (value) {
|
});
|
||||||
if (!validatePhone(value)) {
|
|
||||||
showFieldError('#phone', 'Введите номер в формате +7XXXXXXXXXX (10 цифр после +7)');
|
$('#address').on('blur', function() {
|
||||||
} else {
|
const value = $(this).val().trim();
|
||||||
showFieldError('#phone', '');
|
if (!value) {
|
||||||
}
|
showFieldError('#address', 'Укажите адрес доставки (улица, дом, квартира)');
|
||||||
} else {
|
} else {
|
||||||
showFieldError('#phone', '');
|
showFieldError('#address', '');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Валидация обязательных полей
|
$('.form__input').on('input', function() {
|
||||||
$('#region').on('blur', function() {
|
const fieldId = '#' + $(this).attr('id');
|
||||||
const value = $(this).val().trim();
|
showFieldError(fieldId, '');
|
||||||
if (!value) {
|
});
|
||||||
showFieldError('#region', 'Укажите регион доставки');
|
|
||||||
} else {
|
$('.products__qty-btn.plus').click(function() {
|
||||||
showFieldError('#region', '');
|
const $qtyValue = $(this).siblings('.products__qty-value');
|
||||||
}
|
let quantity = parseInt($qtyValue.text());
|
||||||
});
|
$qtyValue.text(quantity + 1);
|
||||||
|
updateTotal();
|
||||||
$('#address').on('blur', function() {
|
});
|
||||||
const value = $(this).val().trim();
|
|
||||||
if (!value) {
|
$('.products__qty-btn.minus').click(function() {
|
||||||
showFieldError('#address', 'Укажите адрес доставки (улица, дом, квартира)');
|
const $qtyValue = $(this).siblings('.products__qty-value');
|
||||||
} else {
|
let quantity = parseInt($qtyValue.text());
|
||||||
showFieldError('#address', '');
|
if (quantity > 1) {
|
||||||
}
|
$qtyValue.text(quantity - 1);
|
||||||
});
|
updateTotal();
|
||||||
|
}
|
||||||
// Очистка ошибки при начале ввода
|
});
|
||||||
$('.form__input').on('input', function() {
|
|
||||||
const fieldId = '#' + $(this).attr('id');
|
$('.remove-from-cart').click(function() {
|
||||||
showFieldError(fieldId, '');
|
const $productItem = $(this).closest('.products__item');
|
||||||
});
|
$productItem.fadeOut(300, function() {
|
||||||
|
$(this).remove();
|
||||||
// Обработчик увеличения количества
|
updateTotal();
|
||||||
$('.products__qty-btn.plus').click(function() {
|
|
||||||
const $qtyValue = $(this).siblings('.products__qty-value');
|
if ($('.products__item').length === 0) {
|
||||||
let quantity = parseInt($qtyValue.text());
|
$('.products__list').html('<div class="empty-cart">Корзина пуста</div>');
|
||||||
$qtyValue.text(quantity + 1);
|
}
|
||||||
updateTotal();
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Обработчик уменьшения количества
|
$('.promo__btn').click(function() {
|
||||||
$('.products__qty-btn.minus').click(function() {
|
const promoCode = $('.promo__input').val().toUpperCase();
|
||||||
const $qtyValue = $(this).siblings('.products__qty-value');
|
|
||||||
let quantity = parseInt($qtyValue.text());
|
if (promoCode === 'SALE10') {
|
||||||
if (quantity > 1) {
|
cart.discount = Math.round(parseInt($('.products-total').text()) * 0.1);
|
||||||
$qtyValue.text(quantity - 1);
|
$('.discount-total').text(cart.discount + ' ₽');
|
||||||
updateTotal();
|
showMessage('#form-error', 3000);
|
||||||
}
|
$('#form-error').text('Промокод применен! Скидка 10%').removeClass('error').addClass('success');
|
||||||
});
|
} else if (promoCode === 'FREE') {
|
||||||
|
cart.delivery = 0;
|
||||||
// Обработчик удаления товара
|
$('.delivery-price').text('0 ₽');
|
||||||
$('.remove-from-cart').click(function() {
|
showMessage('#form-error', 3000);
|
||||||
const $productItem = $(this).closest('.products__item');
|
$('#form-error').text('Промокод применен! Бесплатная доставка').removeClass('error').addClass('success');
|
||||||
$productItem.fadeOut(300, function() {
|
} else if (promoCode) {
|
||||||
$(this).remove();
|
showMessage('#form-error', 3000);
|
||||||
updateTotal();
|
$('#form-error').text('Промокод недействителен').removeClass('success').addClass('error');
|
||||||
|
}
|
||||||
// Показываем сообщение, если корзина пуста
|
|
||||||
if ($('.products__item').length === 0) {
|
updateTotal();
|
||||||
$('.products__list').html('<div class="empty-cart">Корзина пуста</div>');
|
});
|
||||||
}
|
|
||||||
});
|
$('input[name="delivery"]').change(function() {
|
||||||
});
|
if ($(this).val() === 'pickup') {
|
||||||
|
cart.delivery = 0;
|
||||||
// Обработчик применения промокода
|
$('.delivery-price').text('0 ₽');
|
||||||
$('.promo__btn').click(function() {
|
} else {
|
||||||
const promoCode = $('.promo__input').val().toUpperCase();
|
cart.delivery = 2000;
|
||||||
|
$('.delivery-price').text('2000 ₽');
|
||||||
if (promoCode === 'SALE10') {
|
}
|
||||||
cart.discount = Math.round(parseInt($('.products-total').text()) * 0.1);
|
updateTotal();
|
||||||
$('.discount-total').text(cart.discount + ' ₽');
|
});
|
||||||
showMessage('#form-error', 3000);
|
|
||||||
$('#form-error').text('Промокод применен! Скидка 10%').removeClass('error').addClass('success');
|
function validateForm() {
|
||||||
} else if (promoCode === 'FREE') {
|
let isValid = true;
|
||||||
cart.delivery = 0;
|
let errorMessages = [];
|
||||||
$('.delivery-price').text('0 ₽');
|
|
||||||
showMessage('#form-error', 3000);
|
$('.field-error').remove();
|
||||||
$('#form-error').text('Промокод применен! Бесплатная доставка').removeClass('error').addClass('success');
|
$('.form__input').removeClass('error-input');
|
||||||
} else if (promoCode) {
|
|
||||||
showMessage('#form-error', 3000);
|
const requiredFields = [
|
||||||
$('#form-error').text('Промокод недействителен').removeClass('success').addClass('error');
|
{
|
||||||
}
|
id: '#fullname',
|
||||||
|
value: $('#fullname').val().trim(),
|
||||||
updateTotal();
|
validator: validateFullName,
|
||||||
});
|
required: true,
|
||||||
|
message: 'ФИО должно содержать только буквы и состоять минимум из 2 слов'
|
||||||
// Обработчик выбора доставки
|
},
|
||||||
$('input[name="delivery"]').change(function() {
|
{
|
||||||
if ($(this).val() === 'pickup') {
|
id: '#phone',
|
||||||
cart.delivery = 0;
|
value: $('#phone').val().trim(),
|
||||||
$('.delivery-price').text('0 ₽');
|
validator: validatePhone,
|
||||||
} else {
|
required: true,
|
||||||
cart.delivery = 2000;
|
message: 'Введите корректный номер телефона в формате +7XXXXXXXXXX'
|
||||||
$('.delivery-price').text('2000 ₽');
|
},
|
||||||
}
|
{
|
||||||
updateTotal();
|
id: '#email',
|
||||||
});
|
value: $('#email').val().trim(),
|
||||||
|
validator: validateEmail,
|
||||||
// Функция проверки всех полей формы
|
required: true,
|
||||||
function validateForm() {
|
message: 'Введите корректный email адрес'
|
||||||
let isValid = true;
|
},
|
||||||
let errorMessages = [];
|
{
|
||||||
|
id: '#region',
|
||||||
// Очищаем все старые ошибки
|
value: $('#region').val().trim(),
|
||||||
$('.field-error').remove();
|
validator: (val) => val.length > 0,
|
||||||
$('.form__input').removeClass('error-input');
|
required: true,
|
||||||
|
message: 'Поле "Регион" обязательно для заполнения'
|
||||||
// Проверка обязательных полей
|
},
|
||||||
const requiredFields = [
|
{
|
||||||
{
|
id: '#address',
|
||||||
id: '#fullname',
|
value: $('#address').val().trim(),
|
||||||
value: $('#fullname').val().trim(),
|
validator: (val) => val.length > 0,
|
||||||
validator: validateFullName,
|
required: true,
|
||||||
required: true,
|
message: 'Поле "Адрес" обязательно для заполнения'
|
||||||
message: 'ФИО должно содержать только буквы и состоять минимум из 2 слов'
|
}
|
||||||
},
|
];
|
||||||
{
|
|
||||||
id: '#phone',
|
requiredFields.forEach(field => {
|
||||||
value: $('#phone').val().trim(),
|
if (field.required && (!field.value || !field.validator(field.value))) {
|
||||||
validator: validatePhone,
|
isValid = false;
|
||||||
required: true,
|
errorMessages.push(field.message);
|
||||||
message: 'Введите корректный номер телефона в формате +7XXXXXXXXXX'
|
showFieldError(field.id, field.message);
|
||||||
},
|
}
|
||||||
{
|
});
|
||||||
id: '#email',
|
|
||||||
value: $('#email').val().trim(),
|
if (!$('#privacy-checkbox').is(':checked')) {
|
||||||
validator: validateEmail,
|
isValid = false;
|
||||||
required: true,
|
showPrivacyError(true);
|
||||||
message: 'Введите корректный email адрес'
|
errorMessages.push('Необходимо согласие на обработку персональных данных');
|
||||||
},
|
} else {
|
||||||
{
|
showPrivacyError(false);
|
||||||
id: '#region',
|
}
|
||||||
value: $('#region').val().trim(),
|
|
||||||
validator: (val) => val.length > 0,
|
if (!isValid && errorMessages.length > 0) {
|
||||||
required: true,
|
showMessage('#form-error', 5000);
|
||||||
message: 'Поле "Регион" обязательно для заполнения'
|
$('#form-error').text('Исправьте следующие ошибки: ' + errorMessages.join('; ')).removeClass('success').addClass('error');
|
||||||
},
|
|
||||||
{
|
$('html, body').animate({
|
||||||
id: '#address',
|
scrollTop: $('.error-input').first().offset().top - 100
|
||||||
value: $('#address').val().trim(),
|
}, 500);
|
||||||
validator: (val) => val.length > 0,
|
}
|
||||||
required: true,
|
|
||||||
message: 'Поле "Адрес" обязательно для заполнения'
|
return isValid;
|
||||||
}
|
}
|
||||||
];
|
|
||||||
|
$('#submit-order').click(function() {
|
||||||
// Проверяем каждое поле
|
if (!validateForm()) {
|
||||||
requiredFields.forEach(field => {
|
return;
|
||||||
if (field.required && (!field.value || !field.validator(field.value))) {
|
}
|
||||||
isValid = false;
|
|
||||||
errorMessages.push(field.message);
|
$(this).prop('disabled', true).text('ОБРАБОТКА...');
|
||||||
showFieldError(field.id, field.message);
|
|
||||||
}
|
setTimeout(() => {
|
||||||
});
|
showMessage('#order-success', 5000);
|
||||||
|
$(this).prop('disabled', false).text('ОФОРМИТЬ ЗАКАЗ');
|
||||||
// Проверка согласия на обработку данных
|
|
||||||
if (!$('#privacy-checkbox').is(':checked')) {
|
}, 2000);
|
||||||
isValid = false;
|
});
|
||||||
showPrivacyError(true);
|
|
||||||
errorMessages.push('Необходимо согласие на обработку персональных данных');
|
$('#phone').on('input', function() {
|
||||||
} else {
|
let phone = $(this).val().replace(/\D/g, '');
|
||||||
showPrivacyError(false);
|
if (phone.length > 0) {
|
||||||
}
|
if (phone[0] !== '7' && phone[0] !== '8') {
|
||||||
|
phone = '7' + phone;
|
||||||
// Показываем общее сообщение, если есть ошибки
|
}
|
||||||
if (!isValid && errorMessages.length > 0) {
|
phone = '+7' + phone.substring(1, 11);
|
||||||
showMessage('#form-error', 5000);
|
$(this).val(phone);
|
||||||
$('#form-error').text('Исправьте следующие ошибки: ' + errorMessages.join('; ')).removeClass('success').addClass('error');
|
}
|
||||||
|
});
|
||||||
// Прокручиваем к первой ошибке
|
|
||||||
$('html, body').animate({
|
updateTotal();
|
||||||
scrollTop: $('.error-input').first().offset().top - 100
|
});
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обработчик оформления заказа
|
|
||||||
$('#submit-order').click(function() {
|
|
||||||
// Проверка валидации всех полей
|
|
||||||
if (!validateForm()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Симуляция отправки заказа
|
|
||||||
$(this).prop('disabled', true).text('ОБРАБОТКА...');
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
showMessage('#order-success', 5000);
|
|
||||||
$(this).prop('disabled', false).text('ОФОРМИТЬ ЗАКАЗ');
|
|
||||||
|
|
||||||
// Здесь можно добавить редирект на страницу благодарности
|
|
||||||
// window.location.href = 'спасибо.html';
|
|
||||||
}, 2000);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Маска для телефона
|
|
||||||
$('#phone').on('input', function() {
|
|
||||||
let phone = $(this).val().replace(/\D/g, '');
|
|
||||||
if (phone.length > 0) {
|
|
||||||
if (phone[0] !== '7' && phone[0] !== '8') {
|
|
||||||
phone = '7' + phone;
|
|
||||||
}
|
|
||||||
phone = '+7' + phone.substring(1, 11);
|
|
||||||
$(this).val(phone);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Инициализация при загрузке
|
|
||||||
updateTotal();
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,384 +1,348 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Функции для отображения сообщений
|
|
||||||
function showMessage(type, text) {
|
function showMessage(type, text) {
|
||||||
const messageId = type + 'Message';
|
const messageId = type + 'Message';
|
||||||
const $message = $('#' + messageId);
|
const $message = $('#' + messageId);
|
||||||
$message.text(text).fadeIn(300);
|
$message.text(text).fadeIn(300);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
$message.fadeOut(300);
|
$message.fadeOut(300);
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверка, является ли email администратора
|
function isAdminEmail(email) {
|
||||||
function isAdminEmail(email) {
|
const adminEmails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru'];
|
||||||
const adminEmails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru'];
|
return adminEmails.includes(email.toLowerCase());
|
||||||
return adminEmails.includes(email.toLowerCase());
|
}
|
||||||
}
|
|
||||||
|
function validateFIO(fio) {
|
||||||
// Валидация ФИО (без цифр)
|
const words = fio.trim().split(/\s+/);
|
||||||
function validateFIO(fio) {
|
|
||||||
const words = fio.trim().split(/\s+/);
|
const hasNoDigits = !/\d/.test(fio);
|
||||||
// Проверяем, что минимум 2 слова и нет цифр
|
return words.length >= 2 && words.every(word => word.length >= 2) && hasNoDigits;
|
||||||
const hasNoDigits = !/\d/.test(fio);
|
}
|
||||||
return words.length >= 2 && words.every(word => word.length >= 2) && hasNoDigits;
|
|
||||||
}
|
function validateCity(city) {
|
||||||
|
return city.trim().length >= 2 && /^[а-яА-ЯёЁ\s-]+$/.test(city);
|
||||||
// Валидация города
|
}
|
||||||
function validateCity(city) {
|
|
||||||
return city.trim().length >= 2 && /^[а-яА-ЯёЁ\s-]+$/.test(city);
|
function validateEmail(email) {
|
||||||
}
|
const localPart = email.split('@')[0];
|
||||||
|
|
||||||
// Валидация email
|
if (/[а-яА-ЯёЁ]/.test(localPart)) {
|
||||||
function validateEmail(email) {
|
showError('email', 'В тексте перед знаком "@" не должно быть кириллических символов');
|
||||||
const localPart = email.split('@')[0];
|
return false;
|
||||||
|
}
|
||||||
// Проверка на кириллические символы перед @
|
|
||||||
if (/[а-яА-ЯёЁ]/.test(localPart)) {
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
showError('email', 'В тексте перед знаком "@" не должно быть кириллических символов');
|
if (!emailRegex.test(email)) {
|
||||||
return false;
|
showError('email', 'Введите корректный email адрес');
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
if (!emailRegex.test(email)) {
|
hideError('email');
|
||||||
showError('email', 'Введите корректный email адрес');
|
return true;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
function validatePhone(phone) {
|
||||||
hideError('email');
|
const phoneRegex = /^(\+7|8)[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/;
|
||||||
return true;
|
return phoneRegex.test(phone.replace(/\s/g, ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Валидация телефона
|
function validatePassword(password) {
|
||||||
function validatePhone(phone) {
|
return password.length >= 6;
|
||||||
const phoneRegex = /^(\+7|8)[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}$/;
|
}
|
||||||
return phoneRegex.test(phone.replace(/\s/g, ''));
|
|
||||||
}
|
function showError(fieldId, message) {
|
||||||
|
$('#' + fieldId).addClass('error');
|
||||||
// Валидация пароля
|
$('#' + fieldId + '-error').text(message).show();
|
||||||
function validatePassword(password) {
|
}
|
||||||
return password.length >= 6;
|
|
||||||
}
|
function hideError(fieldId) {
|
||||||
|
$('#' + fieldId).removeClass('error');
|
||||||
// Показать/скрыть ошибку
|
$('#' + fieldId + '-error').hide();
|
||||||
function showError(fieldId, message) {
|
}
|
||||||
$('#' + fieldId).addClass('error');
|
|
||||||
$('#' + fieldId + '-error').text(message).show();
|
function validateForm() {
|
||||||
}
|
let isValid = true;
|
||||||
|
|
||||||
function hideError(fieldId) {
|
const fio = $('#fio').val();
|
||||||
$('#' + fieldId).removeClass('error');
|
if (!validateFIO(fio)) {
|
||||||
$('#' + fieldId + '-error').hide();
|
if (/\d/.test(fio)) {
|
||||||
}
|
showError('fio', 'ФИО не должно содержать цифры');
|
||||||
|
} else {
|
||||||
// Валидация формы
|
showError('fio', 'ФИО должно содержать минимум 2 слова (каждое от 2 символов)');
|
||||||
function validateForm() {
|
}
|
||||||
let isValid = true;
|
isValid = false;
|
||||||
|
} else {
|
||||||
// Валидация ФИО
|
hideError('fio');
|
||||||
const fio = $('#fio').val();
|
}
|
||||||
if (!validateFIO(fio)) {
|
|
||||||
if (/\d/.test(fio)) {
|
const city = $('#city').val();
|
||||||
showError('fio', 'ФИО не должно содержать цифры');
|
if (!validateCity(city)) {
|
||||||
} else {
|
showError('city', 'Укажите корректное название города (только русские буквы)');
|
||||||
showError('fio', 'ФИО должно содержать минимум 2 слова (каждое от 2 символов)');
|
isValid = false;
|
||||||
}
|
} else {
|
||||||
isValid = false;
|
hideError('city');
|
||||||
} else {
|
}
|
||||||
hideError('fio');
|
|
||||||
}
|
const email = $('#email').val();
|
||||||
|
if (!validateEmail(email)) {
|
||||||
// Валидация города
|
showError('email', 'Введите корректный email адрес');
|
||||||
const city = $('#city').val();
|
isValid = false;
|
||||||
if (!validateCity(city)) {
|
} else {
|
||||||
showError('city', 'Укажите корректное название города (только русские буквы)');
|
hideError('email');
|
||||||
isValid = false;
|
}
|
||||||
} else {
|
|
||||||
hideError('city');
|
const phone = $('#phone').val();
|
||||||
}
|
if (!validatePhone(phone)) {
|
||||||
|
showError('phone', 'Введите номер в формате: +7(912)999-12-23');
|
||||||
// Валидация email
|
isValid = false;
|
||||||
const email = $('#email').val();
|
} else {
|
||||||
if (!validateEmail(email)) {
|
hideError('phone');
|
||||||
showError('email', 'Введите корректный email адрес');
|
}
|
||||||
isValid = false;
|
|
||||||
} else {
|
const password = $('#password').val();
|
||||||
hideError('email');
|
if (!validatePassword(password)) {
|
||||||
}
|
showError('password', 'Пароль должен содержать минимум 6 символов');
|
||||||
|
isValid = false;
|
||||||
// Валидация телефона
|
} else {
|
||||||
const phone = $('#phone').val();
|
hideError('password');
|
||||||
if (!validatePhone(phone)) {
|
}
|
||||||
showError('phone', 'Введите номер в формате: +7(912)999-12-23');
|
|
||||||
isValid = false;
|
const confirmPassword = $('#confirm-password').val();
|
||||||
} else {
|
if (password !== confirmPassword) {
|
||||||
hideError('phone');
|
showError('confirm-password', 'Пароли не совпадают');
|
||||||
}
|
isValid = false;
|
||||||
|
} else {
|
||||||
// Валидация пароля
|
hideError('confirm-password');
|
||||||
const password = $('#password').val();
|
}
|
||||||
if (!validatePassword(password)) {
|
|
||||||
showError('password', 'Пароль должен содержать минимум 6 символов');
|
if (!$('#privacy').is(':checked')) {
|
||||||
isValid = false;
|
$('#privacy-error').show();
|
||||||
} else {
|
isValid = false;
|
||||||
hideError('password');
|
} else {
|
||||||
}
|
$('#privacy-error').hide();
|
||||||
|
}
|
||||||
// Проверка совпадения паролей
|
|
||||||
const confirmPassword = $('#confirm-password').val();
|
return isValid;
|
||||||
if (password !== confirmPassword) {
|
}
|
||||||
showError('confirm-password', 'Пароли не совпадают');
|
|
||||||
isValid = false;
|
$('input').on('blur', function() {
|
||||||
} else {
|
const fieldId = $(this).attr('id');
|
||||||
hideError('confirm-password');
|
const value = $(this).val();
|
||||||
}
|
|
||||||
|
switch(fieldId) {
|
||||||
// Проверка согласия с условиями
|
case 'fio':
|
||||||
if (!$('#privacy').is(':checked')) {
|
if (!validateFIO(value)) {
|
||||||
$('#privacy-error').show();
|
if (/\d/.test(value)) {
|
||||||
isValid = false;
|
showError(fieldId, 'ФИО не должно содержать цифры');
|
||||||
} else {
|
} else {
|
||||||
$('#privacy-error').hide();
|
showError(fieldId, 'ФИО должно содержать минимум 2 слова');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
return isValid;
|
hideError(fieldId);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
// Реальная валидация при вводе
|
case 'city':
|
||||||
$('input').on('blur', function() {
|
if (!validateCity(value)) {
|
||||||
const fieldId = $(this).attr('id');
|
showError(fieldId, 'Укажите корректное название города');
|
||||||
const value = $(this).val();
|
} else {
|
||||||
|
hideError(fieldId);
|
||||||
switch(fieldId) {
|
}
|
||||||
case 'fio':
|
break;
|
||||||
if (!validateFIO(value)) {
|
case 'email':
|
||||||
if (/\d/.test(value)) {
|
if (!validateEmail(value)) {
|
||||||
showError(fieldId, 'ФИО не должно содержать цифры');
|
showError(fieldId, 'Введите корректный email адрес');
|
||||||
} else {
|
} else {
|
||||||
showError(fieldId, 'ФИО должно содержать минимум 2 слова');
|
hideError(fieldId);
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
hideError(fieldId);
|
case 'phone':
|
||||||
}
|
if (!validatePhone(value)) {
|
||||||
break;
|
showError(fieldId, 'Введите номер в формате: +7(912)999-12-23');
|
||||||
case 'city':
|
} else {
|
||||||
if (!validateCity(value)) {
|
hideError(fieldId);
|
||||||
showError(fieldId, 'Укажите корректное название города');
|
}
|
||||||
} else {
|
break;
|
||||||
hideError(fieldId);
|
case 'password':
|
||||||
}
|
if (!validatePassword(value)) {
|
||||||
break;
|
showError(fieldId, 'Пароль должен содержать минимум 6 символов');
|
||||||
case 'email':
|
} else {
|
||||||
if (!validateEmail(value)) {
|
hideError(fieldId);
|
||||||
showError(fieldId, 'Введите корректный email адрес');
|
}
|
||||||
} else {
|
break;
|
||||||
hideError(fieldId);
|
case 'confirm-password':
|
||||||
}
|
const password = $('#password').val();
|
||||||
break;
|
if (value !== password) {
|
||||||
case 'phone':
|
showError(fieldId, 'Пароли не совпадают');
|
||||||
if (!validatePhone(value)) {
|
} else {
|
||||||
showError(fieldId, 'Введите номер в формате: +7(912)999-12-23');
|
hideError(fieldId);
|
||||||
} else {
|
}
|
||||||
hideError(fieldId);
|
break;
|
||||||
}
|
}
|
||||||
break;
|
});
|
||||||
case 'password':
|
|
||||||
if (!validatePassword(value)) {
|
$('#registrationForm').on('submit', function(e) {
|
||||||
showError(fieldId, 'Пароль должен содержать минимум 6 символов');
|
e.preventDefault();
|
||||||
} else {
|
|
||||||
hideError(fieldId);
|
if (validateForm()) {
|
||||||
}
|
const email = $('#email').val();
|
||||||
break;
|
const isAdmin = isAdminEmail(email);
|
||||||
case 'confirm-password':
|
|
||||||
const password = $('#password').val();
|
const userData = {
|
||||||
if (value !== password) {
|
email: email,
|
||||||
showError(fieldId, 'Пароли не совпадают');
|
fio: $('#fio').val(),
|
||||||
} else {
|
phone: $('#phone').val(),
|
||||||
hideError(fieldId);
|
isAdmin: isAdmin,
|
||||||
}
|
registered: new Date().toISOString()
|
||||||
break;
|
};
|
||||||
}
|
|
||||||
});
|
localStorage.setItem('userData', JSON.stringify(userData));
|
||||||
|
localStorage.setItem('isLoggedIn', 'true');
|
||||||
// Обработка отправки формы
|
localStorage.setItem('isAdmin', isAdmin.toString());
|
||||||
$('#registrationForm').on('submit', function(e) {
|
|
||||||
e.preventDefault();
|
showMessage('success', 'Регистрация прошла успешно! ' +
|
||||||
|
(isAdmin ? 'Вы зарегистрированы как администратор.' : 'Добро пожаловать в AETERNA!'));
|
||||||
if (validateForm()) {
|
|
||||||
const email = $('#email').val();
|
setTimeout(() => {
|
||||||
const isAdmin = isAdminEmail(email);
|
|
||||||
|
window.location.href = 'cite_mebel.php';
|
||||||
// Сохраняем данные пользователя в localStorage
|
}, 2000);
|
||||||
const userData = {
|
} else {
|
||||||
email: email,
|
showMessage('error', 'Пожалуйста, исправьте ошибки в форме');
|
||||||
fio: $('#fio').val(),
|
}
|
||||||
phone: $('#phone').val(),
|
});
|
||||||
isAdmin: isAdmin,
|
|
||||||
registered: new Date().toISOString()
|
$('a[href^="#"]').on('click', function(event) {
|
||||||
};
|
var target = $(this.getAttribute('href'));
|
||||||
|
if (target.length) {
|
||||||
localStorage.setItem('userData', JSON.stringify(userData));
|
event.preventDefault();
|
||||||
localStorage.setItem('isLoggedIn', 'true');
|
$('html, body').stop().animate({
|
||||||
localStorage.setItem('isAdmin', isAdmin.toString());
|
scrollTop: target.offset().top
|
||||||
|
}, 1000);
|
||||||
// Эмуляция успешной регистрации
|
}
|
||||||
showMessage('success', 'Регистрация прошла успешно! ' +
|
});
|
||||||
(isAdmin ? 'Вы зарегистрированы как администратор.' : 'Добро пожаловать в AETERNA!'));
|
|
||||||
|
$('.login-btn').on('click', function() {
|
||||||
setTimeout(() => {
|
showMessage('warning', 'Переход к форме входа...');
|
||||||
// Перенаправление на главную страницу
|
setTimeout(() => {
|
||||||
window.location.href = 'cite_mebel.php';
|
window.location.href = 'вход.php';
|
||||||
}, 2000);
|
}, 1000);
|
||||||
} else {
|
});
|
||||||
showMessage('error', 'Пожалуйста, исправьте ошибки в форме');
|
|
||||||
}
|
$('.password-link').on('click', function(e) {
|
||||||
});
|
e.preventDefault();
|
||||||
|
showMessage('warning', 'Функция смены пароля будет доступна после регистрации');
|
||||||
// Плавная прокрутка к якорям
|
});
|
||||||
$('a[href^="#"]').on('click', function(event) {
|
|
||||||
var target = $(this.getAttribute('href'));
|
$('#phone').on('input', function() {
|
||||||
if (target.length) {
|
let value = $(this).val().replace(/\D/g, '');
|
||||||
event.preventDefault();
|
if (value.startsWith('7') || value.startsWith('8')) {
|
||||||
$('html, body').stop().animate({
|
value = value.substring(1);
|
||||||
scrollTop: target.offset().top
|
}
|
||||||
}, 1000);
|
if (value.length > 0) {
|
||||||
}
|
value = '+7(' + value;
|
||||||
});
|
if (value.length > 6) value = value.substring(0, 6) + ')' + value.substring(6);
|
||||||
|
if (value.length > 10) value = value.substring(0, 10) + '-' + value.substring(10);
|
||||||
// Переключение между регистрацией и входом
|
if (value.length > 13) value = value.substring(0, 13) + '-' + value.substring(13);
|
||||||
$('.login-btn').on('click', function() {
|
if (value.length > 16) value = value.substring(0, 16);
|
||||||
showMessage('warning', 'Переход к форме входа...');
|
}
|
||||||
setTimeout(() => {
|
$(this).val(value);
|
||||||
window.location.href = 'вход.php';
|
});
|
||||||
}, 1000);
|
|
||||||
});
|
$('#fio').on('input', function() {
|
||||||
|
let value = $(this).val();
|
||||||
// Обработка ссылки "Сменить пароль"
|
|
||||||
$('.password-link').on('click', function(e) {
|
value = value.replace(/\d/g, '');
|
||||||
e.preventDefault();
|
$(this).val(value);
|
||||||
showMessage('warning', 'Функция смены пароля будет доступна после регистрации');
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Маска для телефона
|
$(document).ready(function() {
|
||||||
$('#phone').on('input', function() {
|
|
||||||
let value = $(this).val().replace(/\D/g, '');
|
if (localStorage.getItem('isLoggedIn') === 'true') {
|
||||||
if (value.startsWith('7') || value.startsWith('8')) {
|
const userData = JSON.parse(localStorage.getItem('userData') || '{}');
|
||||||
value = value.substring(1);
|
if (userData.email) {
|
||||||
}
|
$('#login-email').val(userData.email);
|
||||||
if (value.length > 0) {
|
}
|
||||||
value = '+7(' + value;
|
}
|
||||||
if (value.length > 6) value = value.substring(0, 6) + ')' + value.substring(6);
|
|
||||||
if (value.length > 10) value = value.substring(0, 10) + '-' + value.substring(10);
|
function checkAdminPassword(email, password) {
|
||||||
if (value.length > 13) value = value.substring(0, 13) + '-' + value.substring(13);
|
|
||||||
if (value.length > 16) value = value.substring(0, 16);
|
const adminAccounts = {
|
||||||
}
|
'admin@aeterna.ru': 'admin123',
|
||||||
$(this).val(value);
|
'administrator@aeterna.ru': 'admin123',
|
||||||
});
|
'aeterna@mail.ru': 'admin123'
|
||||||
|
};
|
||||||
// Запрет ввода цифр в поле ФИО
|
|
||||||
$('#fio').on('input', function() {
|
return adminAccounts[email.toLowerCase()] === password;
|
||||||
let value = $(this).val();
|
}
|
||||||
// Удаляем цифры из значения
|
|
||||||
value = value.replace(/\d/g, '');
|
$('#loginForm').on('submit', function(e) {
|
||||||
$(this).val(value);
|
e.preventDefault();
|
||||||
});
|
|
||||||
});
|
let isValid = true;
|
||||||
|
const email = $('#login-email').val();
|
||||||
// Для входа (файл вход.html)
|
const password = $('#login-password').val();
|
||||||
$(document).ready(function() {
|
|
||||||
// Проверяем, если пользователь уже вошел
|
if (!isValidEmail(email)) {
|
||||||
if (localStorage.getItem('isLoggedIn') === 'true') {
|
$('#email-error').show();
|
||||||
const userData = JSON.parse(localStorage.getItem('userData') || '{}');
|
isValid = false;
|
||||||
if (userData.email) {
|
} else {
|
||||||
$('#login-email').val(userData.email);
|
$('#email-error').hide();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (password.length < 6) {
|
||||||
// Функция проверки пароля администратора
|
$('#password-error').show();
|
||||||
function checkAdminPassword(email, password) {
|
isValid = false;
|
||||||
// Административные аккаунты
|
} else {
|
||||||
const adminAccounts = {
|
$('#password-error').hide();
|
||||||
'admin@aeterna.ru': 'admin123',
|
}
|
||||||
'administrator@aeterna.ru': 'admin123',
|
|
||||||
'aeterna@mail.ru': 'admin123'
|
if (isValid) {
|
||||||
};
|
|
||||||
|
showMessage('success', 'Вы успешно вошли в систему!');
|
||||||
return adminAccounts[email.toLowerCase()] === password;
|
|
||||||
}
|
setTimeout(function() {
|
||||||
|
window.location.href = 'cite_mebel.php';
|
||||||
// Валидация формы входа
|
}, 1500);
|
||||||
$('#loginForm').on('submit', function(e) {
|
}
|
||||||
e.preventDefault();
|
});
|
||||||
|
|
||||||
let isValid = true;
|
function showMessage(type, text) {
|
||||||
const email = $('#login-email').val();
|
const messageId = type + 'Message';
|
||||||
const password = $('#login-password').val();
|
const $message = $('#' + messageId);
|
||||||
|
|
||||||
// Валидация email
|
$message.text(text).show();
|
||||||
if (!isValidEmail(email)) {
|
|
||||||
$('#email-error').show();
|
setTimeout(function() {
|
||||||
isValid = false;
|
$message.fadeOut();
|
||||||
} else {
|
}, 3000);
|
||||||
$('#email-error').hide();
|
}
|
||||||
}
|
|
||||||
|
$('input').on('focus', function() {
|
||||||
// Валидация пароля
|
$(this).next('.error-message').hide();
|
||||||
if (password.length < 6) {
|
});
|
||||||
$('#password-error').show();
|
|
||||||
isValid = false;
|
$('#remember').on('change', function() {
|
||||||
} else {
|
if ($(this).is(':checked')) {
|
||||||
$('#password-error').hide();
|
const email = $('#login-email').val();
|
||||||
}
|
if (email) {
|
||||||
|
localStorage.setItem('rememberedEmail', email);
|
||||||
if (isValid) {
|
}
|
||||||
// Здесь обычно отправка данных на сервер
|
} else {
|
||||||
showMessage('success', 'Вы успешно вошли в систему!');
|
localStorage.removeItem('rememberedEmail');
|
||||||
|
}
|
||||||
// Перенаправление на главную страницу через 1.5 секунды
|
});
|
||||||
setTimeout(function() {
|
|
||||||
window.location.href = 'cite_mebel.php';
|
const rememberedEmail = localStorage.getItem('rememberedEmail');
|
||||||
}, 1500);
|
if (rememberedEmail) {
|
||||||
}
|
$('#login-email').val(rememberedEmail);
|
||||||
});
|
$('#remember').prop('checked', true);
|
||||||
|
}
|
||||||
// Функция показа сообщений
|
|
||||||
function showMessage(type, text) {
|
$('.forgot-password').on('click', function(e) {
|
||||||
const messageId = type + 'Message';
|
e.preventDefault();
|
||||||
const $message = $('#' + messageId);
|
showMessage('info', 'Для восстановления пароля обратитесь к администратору');
|
||||||
|
});
|
||||||
$message.text(text).show();
|
});
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
$message.fadeOut();
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Скрываем сообщения об ошибках при фокусе на полях
|
|
||||||
$('input').on('focus', function() {
|
|
||||||
$(this).next('.error-message').hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Обработка чекбокса "Запомнить меня"
|
|
||||||
$('#remember').on('change', function() {
|
|
||||||
if ($(this).is(':checked')) {
|
|
||||||
const email = $('#login-email').val();
|
|
||||||
if (email) {
|
|
||||||
localStorage.setItem('rememberedEmail', email);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
localStorage.removeItem('rememberedEmail');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Автозаполнение email, если пользователь выбрал "Запомнить меня"
|
|
||||||
const rememberedEmail = localStorage.getItem('rememberedEmail');
|
|
||||||
if (rememberedEmail) {
|
|
||||||
$('#login-email').val(rememberedEmail);
|
|
||||||
$('#remember').prop('checked', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обработка ссылки "Забыли пароль?"
|
|
||||||
$('.forgot-password').on('click', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
showMessage('info', 'Для восстановления пароля обратитесь к администратору');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,142 +1,137 @@
|
|||||||
.error-message {
|
.error-message {
|
||||||
color: #ff0000;
|
color: #ff0000;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__input.error {
|
.form__input.error {
|
||||||
border-color: #ff0000;
|
border-color: #ff0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__group {
|
.form__group {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Стили для сообщений внизу страницы */
|
.page-messages {
|
||||||
.page-messages {
|
position: fixed;
|
||||||
position: fixed;
|
bottom: 20px;
|
||||||
bottom: 20px;
|
left: 50%;
|
||||||
left: 50%;
|
transform: translateX(-50%);
|
||||||
transform: translateX(-50%);
|
z-index: 1000;
|
||||||
z-index: 1000;
|
width: 90%;
|
||||||
width: 90%;
|
max-width: 500px;
|
||||||
max-width: 500px;
|
}
|
||||||
}
|
|
||||||
|
.message {
|
||||||
.message {
|
padding: 15px;
|
||||||
padding: 15px;
|
margin: 10px 0;
|
||||||
margin: 10px 0;
|
border-radius: 5px;
|
||||||
border-radius: 5px;
|
text-align: center;
|
||||||
text-align: center;
|
font-weight: bold;
|
||||||
font-weight: bold;
|
display: none;
|
||||||
display: none;
|
}
|
||||||
}
|
|
||||||
|
.message.error {
|
||||||
.message.error {
|
background-color: #ffebee;
|
||||||
background-color: #ffebee;
|
color: #c62828;
|
||||||
color: #c62828;
|
border: 1px solid #ffcdd2;
|
||||||
border: 1px solid #ffcdd2;
|
}
|
||||||
}
|
|
||||||
|
.message.success {
|
||||||
.message.success {
|
background-color: #e8f5e9;
|
||||||
background-color: #e8f5e9;
|
color: #453227;
|
||||||
color: #453227;
|
border: 1px solid #c8e6c9;
|
||||||
border: 1px solid #c8e6c9;
|
}
|
||||||
}
|
|
||||||
|
.message.warning {
|
||||||
.message.warning {
|
background-color: #fff3e0;
|
||||||
background-color: #fff3e0;
|
color: #ef6c00;
|
||||||
color: #ef6c00;
|
border: 1px solid #ffe0b2;
|
||||||
border: 1px solid #ffe0b2;
|
}
|
||||||
}
|
|
||||||
|
.privacy-error {
|
||||||
.privacy-error {
|
color: #ff0000;
|
||||||
color: #ff0000;
|
font-size: 12px;
|
||||||
font-size: 12px;
|
margin-top: 5px;
|
||||||
margin-top: 5px;
|
display: none;
|
||||||
display: none;
|
text-align: center;
|
||||||
text-align: center;
|
}
|
||||||
}
|
|
||||||
|
.input-group {
|
||||||
/* Дополнительные стили для формы регистрации */
|
position: relative;
|
||||||
.input-group {
|
margin-bottom: 20px;
|
||||||
position: relative;
|
}
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
.profile-form input.error {
|
||||||
|
border-color: #ff0000;
|
||||||
.profile-form input.error {
|
background-color: #fff5f5;
|
||||||
border-color: #ff0000;
|
}
|
||||||
background-color: #fff5f5;
|
|
||||||
}
|
.privacy-checkbox {
|
||||||
|
margin: 20px 0;
|
||||||
.privacy-checkbox {
|
text-align: center;
|
||||||
margin: 20px 0;
|
}
|
||||||
text-align: center;
|
|
||||||
}
|
.privacy-checkbox label {
|
||||||
|
display: flex;
|
||||||
.privacy-checkbox label {
|
align-items: center;
|
||||||
display: flex;
|
justify-content: center;
|
||||||
align-items: center;
|
gap: 8px;
|
||||||
justify-content: center;
|
cursor: pointer;
|
||||||
gap: 8px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
}
|
||||||
font-size: 14px;
|
|
||||||
}
|
.privacy-checkbox input[type="checkbox"] {
|
||||||
|
margin: 0;
|
||||||
.privacy-checkbox input[type="checkbox"] {
|
}
|
||||||
margin: 0;
|
|
||||||
}
|
.profile-page-main {
|
||||||
|
padding: 40px 0;
|
||||||
/* Исправление отступов для страницы регистрации */
|
min-height: calc(100vh - 200px);
|
||||||
.profile-page-main {
|
}
|
||||||
padding: 40px 0;
|
|
||||||
min-height: calc(100vh - 200px);
|
.profile-container {
|
||||||
}
|
margin: 0 auto;
|
||||||
|
position: relative;
|
||||||
/* Убедимся, что контейнер не перекрывает шапку и футер */
|
z-index: 1;
|
||||||
.profile-container {
|
}
|
||||||
margin: 0 auto;
|
|
||||||
position: relative;
|
.input-hint {
|
||||||
z-index: 1;
|
font-size: 12px;
|
||||||
}
|
color: #666;
|
||||||
|
margin-top: 5px;
|
||||||
.input-hint {
|
}
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
.form-options {
|
||||||
margin-top: 5px;
|
display: flex;
|
||||||
}
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
/* Стили для страницы входа */
|
margin: 20px 0;
|
||||||
.form-options {
|
}
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
.remember-me {
|
||||||
align-items: center;
|
display: flex;
|
||||||
margin: 20px 0;
|
align-items: center;
|
||||||
}
|
gap: 8px;
|
||||||
|
font-size: 14px;
|
||||||
.remember-me {
|
color: #453227;
|
||||||
display: flex;
|
}
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
.remember-me input[type="checkbox"] {
|
||||||
font-size: 14px;
|
width: 16px;
|
||||||
color: #453227;
|
height: 16px;
|
||||||
}
|
cursor: pointer;
|
||||||
|
}
|
||||||
.remember-me input[type="checkbox"] {
|
|
||||||
width: 16px;
|
.forgot-password {
|
||||||
height: 16px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
color: #453227;
|
||||||
}
|
text-decoration: underline;
|
||||||
|
}
|
||||||
.forgot-password {
|
|
||||||
font-size: 14px;
|
.forgot-password:hover {
|
||||||
color: #453227;
|
color: #617365;
|
||||||
text-decoration: underline;
|
text-decoration: none;
|
||||||
}
|
|
||||||
|
|
||||||
.forgot-password:hover {
|
|
||||||
color: #617365;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
@@ -83,4 +83,3 @@
|
|||||||
border-color: @color-primary;
|
border-color: @color-primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2647
public/catalog.php
2647
public/catalog.php
File diff suppressed because it is too large
Load Diff
@@ -1,114 +1,107 @@
|
|||||||
// check_auth.js
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Проверка авторизации при загрузке страницы
|
|
||||||
checkAuthStatus();
|
checkAuthStatus();
|
||||||
|
|
||||||
// Обработка формы входа
|
$('#loginForm').on('submit', function(e) {
|
||||||
$('#loginForm').on('submit', function(e) {
|
e.preventDefault();
|
||||||
e.preventDefault();
|
|
||||||
|
const email = $('#login-email').val();
|
||||||
const email = $('#login-email').val();
|
const password = $('#login-password').val();
|
||||||
const password = $('#login-password').val();
|
const remember = $('#remember').is(':checked');
|
||||||
const remember = $('#remember').is(':checked');
|
|
||||||
|
$.ajax({
|
||||||
$.ajax({
|
url: 'login_handler.php',
|
||||||
url: 'login_handler.php',
|
method: 'POST',
|
||||||
method: 'POST',
|
data: {
|
||||||
data: {
|
email: email,
|
||||||
email: email,
|
password: password
|
||||||
password: password
|
},
|
||||||
},
|
success: function(response) {
|
||||||
success: function(response) {
|
try {
|
||||||
try {
|
const result = JSON.parse(response);
|
||||||
const result = JSON.parse(response);
|
if (result.success) {
|
||||||
if (result.success) {
|
|
||||||
// Сохраняем в localStorage если выбрано "Запомнить меня"
|
if (remember) {
|
||||||
if (remember) {
|
localStorage.setItem('rememberedEmail', email);
|
||||||
localStorage.setItem('rememberedEmail', email);
|
} else {
|
||||||
} else {
|
localStorage.removeItem('rememberedEmail');
|
||||||
localStorage.removeItem('rememberedEmail');
|
}
|
||||||
}
|
|
||||||
|
window.location.href = result.redirect || 'catalog.php';
|
||||||
// Перенаправляем
|
} else {
|
||||||
window.location.href = result.redirect || 'catalog.php';
|
showMessage('error', result.message || 'Ошибка авторизации');
|
||||||
} else {
|
}
|
||||||
showMessage('error', result.message || 'Ошибка авторизации');
|
} catch(e) {
|
||||||
}
|
showMessage('error', 'Ошибка обработки ответа');
|
||||||
} catch(e) {
|
}
|
||||||
showMessage('error', 'Ошибка обработки ответа');
|
},
|
||||||
}
|
error: function() {
|
||||||
},
|
showMessage('error', 'Ошибка сервера');
|
||||||
error: function() {
|
}
|
||||||
showMessage('error', 'Ошибка сервера');
|
});
|
||||||
}
|
});
|
||||||
});
|
|
||||||
});
|
function checkAuthStatus() {
|
||||||
|
$.ajax({
|
||||||
// Проверка статуса авторизации
|
url: 'check_auth_status.php',
|
||||||
function checkAuthStatus() {
|
method: 'GET',
|
||||||
$.ajax({
|
success: function(response) {
|
||||||
url: 'check_auth_status.php',
|
try {
|
||||||
method: 'GET',
|
const result = JSON.parse(response);
|
||||||
success: function(response) {
|
if (result.loggedIn) {
|
||||||
try {
|
updateUserProfile(result.user);
|
||||||
const result = JSON.parse(response);
|
}
|
||||||
if (result.loggedIn) {
|
} catch(e) {
|
||||||
updateUserProfile(result.user);
|
console.error('Ошибка проверки авторизации', e);
|
||||||
}
|
}
|
||||||
} catch(e) {
|
}
|
||||||
console.error('Ошибка проверки авторизации', e);
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
function updateUserProfile(user) {
|
||||||
}
|
|
||||||
|
if ($('#userEmail').length) {
|
||||||
// Обновление профиля пользователя
|
$('#userEmail').text(user.email);
|
||||||
function updateUserProfile(user) {
|
}
|
||||||
// Обновляем шапку, если есть элементы для профиля
|
if ($('#userName').length) {
|
||||||
if ($('#userEmail').length) {
|
$('#userName').text(user.full_name);
|
||||||
$('#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);
|
||||||
function showMessage(type, text) {
|
} else {
|
||||||
const $message = $('#' + type + 'Message');
|
alert(text);
|
||||||
if ($message.length) {
|
}
|
||||||
$message.text(text).fadeIn();
|
}
|
||||||
setTimeout(() => $message.fadeOut(), 5000);
|
|
||||||
} else {
|
function checkAuth(redirectUrl) {
|
||||||
alert(text);
|
$.ajax({
|
||||||
}
|
url: 'check_auth_status.php',
|
||||||
}
|
method: 'GET',
|
||||||
|
success: function(response) {
|
||||||
// Проверка авторизации для ссылок
|
try {
|
||||||
function checkAuth(redirectUrl) {
|
const result = JSON.parse(response);
|
||||||
$.ajax({
|
if (result.loggedIn) {
|
||||||
url: 'check_auth_status.php',
|
window.location.href = redirectUrl;
|
||||||
method: 'GET',
|
} else {
|
||||||
success: function(response) {
|
|
||||||
try {
|
showLoginModal(redirectUrl);
|
||||||
const result = JSON.parse(response);
|
}
|
||||||
if (result.loggedIn) {
|
} catch(e) {
|
||||||
window.location.href = redirectUrl;
|
showLoginModal(redirectUrl);
|
||||||
} else {
|
}
|
||||||
// Показываем модальное окно или перенаправляем на вход
|
}
|
||||||
showLoginModal(redirectUrl);
|
});
|
||||||
}
|
return false;
|
||||||
} catch(e) {
|
}
|
||||||
showLoginModal(redirectUrl);
|
|
||||||
}
|
function showLoginModal(redirectUrl) {
|
||||||
}
|
|
||||||
});
|
window.location.href = 'вход.php?redirect=' + encodeURIComponent(redirectUrl);
|
||||||
return false;
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
// Показать модальное окно входа
|
|
||||||
function showLoginModal(redirectUrl) {
|
|
||||||
// Можно реализовать модальное окно или перенаправить на страницу входа
|
|
||||||
window.location.href = 'вход.php?redirect=' + encodeURIComponent(redirectUrl);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,114 +1,107 @@
|
|||||||
// check_auth.js
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Проверка авторизации при загрузке страницы
|
|
||||||
checkAuthStatus();
|
checkAuthStatus();
|
||||||
|
|
||||||
// Обработка формы входа
|
$('#loginForm').on('submit', function(e) {
|
||||||
$('#loginForm').on('submit', function(e) {
|
e.preventDefault();
|
||||||
e.preventDefault();
|
|
||||||
|
const email = $('#login-email').val();
|
||||||
const email = $('#login-email').val();
|
const password = $('#login-password').val();
|
||||||
const password = $('#login-password').val();
|
const remember = $('#remember').is(':checked');
|
||||||
const remember = $('#remember').is(':checked');
|
|
||||||
|
$.ajax({
|
||||||
$.ajax({
|
url: 'login_handler.php',
|
||||||
url: 'login_handler.php',
|
method: 'POST',
|
||||||
method: 'POST',
|
data: {
|
||||||
data: {
|
email: email,
|
||||||
email: email,
|
password: password
|
||||||
password: password
|
},
|
||||||
},
|
success: function(response) {
|
||||||
success: function(response) {
|
try {
|
||||||
try {
|
const result = JSON.parse(response);
|
||||||
const result = JSON.parse(response);
|
if (result.success) {
|
||||||
if (result.success) {
|
|
||||||
// Сохраняем в localStorage если выбрано "Запомнить меня"
|
if (remember) {
|
||||||
if (remember) {
|
localStorage.setItem('rememberedEmail', email);
|
||||||
localStorage.setItem('rememberedEmail', email);
|
} else {
|
||||||
} else {
|
localStorage.removeItem('rememberedEmail');
|
||||||
localStorage.removeItem('rememberedEmail');
|
}
|
||||||
}
|
|
||||||
|
window.location.href = result.redirect || 'catalog.php';
|
||||||
// Перенаправляем
|
} else {
|
||||||
window.location.href = result.redirect || 'catalog.php';
|
showMessage('error', result.message || 'Ошибка авторизации');
|
||||||
} else {
|
}
|
||||||
showMessage('error', result.message || 'Ошибка авторизации');
|
} catch(e) {
|
||||||
}
|
showMessage('error', 'Ошибка обработки ответа');
|
||||||
} catch(e) {
|
}
|
||||||
showMessage('error', 'Ошибка обработки ответа');
|
},
|
||||||
}
|
error: function() {
|
||||||
},
|
showMessage('error', 'Ошибка сервера');
|
||||||
error: function() {
|
}
|
||||||
showMessage('error', 'Ошибка сервера');
|
});
|
||||||
}
|
});
|
||||||
});
|
|
||||||
});
|
function checkAuthStatus() {
|
||||||
|
$.ajax({
|
||||||
// Проверка статуса авторизации
|
url: 'check_auth_status.php',
|
||||||
function checkAuthStatus() {
|
method: 'GET',
|
||||||
$.ajax({
|
success: function(response) {
|
||||||
url: 'check_auth_status.php',
|
try {
|
||||||
method: 'GET',
|
const result = JSON.parse(response);
|
||||||
success: function(response) {
|
if (result.loggedIn) {
|
||||||
try {
|
updateUserProfile(result.user);
|
||||||
const result = JSON.parse(response);
|
}
|
||||||
if (result.loggedIn) {
|
} catch(e) {
|
||||||
updateUserProfile(result.user);
|
console.error('Ошибка проверки авторизации', e);
|
||||||
}
|
}
|
||||||
} catch(e) {
|
}
|
||||||
console.error('Ошибка проверки авторизации', e);
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
function updateUserProfile(user) {
|
||||||
}
|
|
||||||
|
if ($('#userEmail').length) {
|
||||||
// Обновление профиля пользователя
|
$('#userEmail').text(user.email);
|
||||||
function updateUserProfile(user) {
|
}
|
||||||
// Обновляем шапку, если есть элементы для профиля
|
if ($('#userName').length) {
|
||||||
if ($('#userEmail').length) {
|
$('#userName').text(user.full_name);
|
||||||
$('#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);
|
||||||
function showMessage(type, text) {
|
} else {
|
||||||
const $message = $('#' + type + 'Message');
|
alert(text);
|
||||||
if ($message.length) {
|
}
|
||||||
$message.text(text).fadeIn();
|
}
|
||||||
setTimeout(() => $message.fadeOut(), 5000);
|
|
||||||
} else {
|
function checkAuth(redirectUrl) {
|
||||||
alert(text);
|
$.ajax({
|
||||||
}
|
url: 'check_auth_status.php',
|
||||||
}
|
method: 'GET',
|
||||||
|
success: function(response) {
|
||||||
// Проверка авторизации для ссылок
|
try {
|
||||||
function checkAuth(redirectUrl) {
|
const result = JSON.parse(response);
|
||||||
$.ajax({
|
if (result.loggedIn) {
|
||||||
url: 'check_auth_status.php',
|
window.location.href = redirectUrl;
|
||||||
method: 'GET',
|
} else {
|
||||||
success: function(response) {
|
|
||||||
try {
|
showLoginModal(redirectUrl);
|
||||||
const result = JSON.parse(response);
|
}
|
||||||
if (result.loggedIn) {
|
} catch(e) {
|
||||||
window.location.href = redirectUrl;
|
showLoginModal(redirectUrl);
|
||||||
} else {
|
}
|
||||||
// Показываем модальное окно или перенаправляем на вход
|
}
|
||||||
showLoginModal(redirectUrl);
|
});
|
||||||
}
|
return false;
|
||||||
} catch(e) {
|
}
|
||||||
showLoginModal(redirectUrl);
|
|
||||||
}
|
function showLoginModal(redirectUrl) {
|
||||||
}
|
|
||||||
});
|
window.location.href = 'вход.php?redirect=' + encodeURIComponent(redirectUrl);
|
||||||
return false;
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
// Показать модальное окно входа
|
|
||||||
function showLoginModal(redirectUrl) {
|
|
||||||
// Можно реализовать модальное окно или перенаправить на страницу входа
|
|
||||||
window.location.href = 'вход.php?redirect=' + encodeURIComponent(redirectUrl);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
<?php
|
<?php
|
||||||
// config/database.php
|
|
||||||
class Database {
|
class Database {
|
||||||
private static $instance = null;
|
private static $instance = null;
|
||||||
private $connection;
|
private $connection;
|
||||||
|
|
||||||
private function __construct() {
|
private function __construct() {
|
||||||
try {
|
try {
|
||||||
$this->connection = new PDO(
|
$this->connection = new PDO(
|
||||||
"pgsql:host=185.130.224.177;port=5481;dbname=postgres",
|
"pgsql:host=185.130.224.177;port=5481;dbname=postgres",
|
||||||
"admin",
|
"admin",
|
||||||
"38feaad2840ccfda0e71243a6faaecfd"
|
"38feaad2840ccfda0e71243a6faaecfd"
|
||||||
);
|
);
|
||||||
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
$this->connection->exec("SET NAMES 'utf8'");
|
$this->connection->exec("SET NAMES 'utf8'");
|
||||||
} catch(PDOException $e) {
|
} catch(PDOException $e) {
|
||||||
die("Ошибка подключения: " . $e->getMessage());
|
die("Ошибка подключения: " . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getInstance() {
|
public static function getInstance() {
|
||||||
if (self::$instance == null) {
|
if (self::$instance == null) {
|
||||||
self::$instance = new Database();
|
self::$instance = new Database();
|
||||||
}
|
}
|
||||||
return self::$instance;
|
return self::$instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getConnection() {
|
public function getConnection() {
|
||||||
return $this->connection;
|
return $this->connection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
@@ -1,174 +1,174 @@
|
|||||||
<?php
|
<?php
|
||||||
// В начале файла
|
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>AETERNA - Доставка и оплата</title>
|
<title>AETERNA - Доставка и оплата</title>
|
||||||
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
|
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/less"></script>
|
<script src="https://cdn.jsdelivr.net/npm/less"></script>
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||||
<script src="check_auth.js"></script>
|
<script src="check_auth.js"></script>
|
||||||
<style>
|
<style>
|
||||||
/* Стили для блокировки доступа */
|
|
||||||
.link-disabled {
|
.link-disabled {
|
||||||
cursor: not-allowed !important;
|
cursor: not-allowed !important;
|
||||||
opacity: 0.7 !important;
|
opacity: 0.7 !important;
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-required {
|
.auth-required {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-required::after {
|
.auth-required::after {
|
||||||
content: "🔒";
|
content: "🔒";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -5px;
|
top: -5px;
|
||||||
right: -10px;
|
right: -10px;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<?php include 'header_common.php'; ?>
|
<?php include 'header_common.php'; ?>
|
||||||
|
|
||||||
<main class="catalog-main">
|
<main class="catalog-main">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="breadcrumbs">
|
<div class="breadcrumbs">
|
||||||
<a href="cite_mebel.php">Главная</a> • <span class="current-page">Доставка и оплата</span>
|
<a href="cite_mebel.php">Главная</a> • <span class="current-page">Доставка и оплата</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="delivery-content">
|
<div class="delivery-content">
|
||||||
<h1>ДОСТАВКА И ОПЛАТА</h1>
|
<h1>ДОСТАВКА И ОПЛАТА</h1>
|
||||||
|
|
||||||
<div class="delivery-section">
|
<div class="delivery-section">
|
||||||
<div class="delivery-card">
|
<div class="delivery-card">
|
||||||
<div class="delivery-icon">
|
<div class="delivery-icon">
|
||||||
<i class="fas fa-truck"></i>
|
<i class="fas fa-truck"></i>
|
||||||
</div>
|
</div>
|
||||||
<h3>Курьерская доставка</h3>
|
<h3>Курьерская доставка</h3>
|
||||||
<div class="delivery-details">
|
<div class="delivery-details">
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">Бесплатная доставка:</span>
|
<span class="detail-label">Бесплатная доставка:</span>
|
||||||
<span class="detail-value">при заказе от 30 000 ₽</span>
|
<span class="detail-value">при заказе от 30 000 ₽</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">В пределах МКАД:</span>
|
<span class="detail-label">В пределах МКАД:</span>
|
||||||
<span class="detail-value">1 500 ₽</span>
|
<span class="detail-value">1 500 ₽</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">За МКАД:</span>
|
<span class="detail-label">За МКАД:</span>
|
||||||
<span class="detail-value">1 500 ₽ + 50 ₽/км</span>
|
<span class="detail-value">1 500 ₽ + 50 ₽/км</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">Время доставки:</span>
|
<span class="detail-label">Время доставки:</span>
|
||||||
<span class="detail-value">с 9:00 до 21:00</span>
|
<span class="detail-value">с 9:00 до 21:00</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="delivery-card">
|
<div class="delivery-card">
|
||||||
<div class="delivery-icon">
|
<div class="delivery-icon">
|
||||||
<i class="fas fa-store"></i>
|
<i class="fas fa-store"></i>
|
||||||
</div>
|
</div>
|
||||||
<h3>Самовывоз из шоурума</h3>
|
<h3>Самовывоз из шоурума</h3>
|
||||||
<div class="delivery-details">
|
<div class="delivery-details">
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">Адрес:</span>
|
<span class="detail-label">Адрес:</span>
|
||||||
<span class="detail-value">г. Москва, ул. Дизайнерская, 15</span>
|
<span class="detail-value">г. Москва, ул. Дизайнерская, 15</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">Стоимость:</span>
|
<span class="detail-label">Стоимость:</span>
|
||||||
<span class="detail-value">Бесплатно</span>
|
<span class="detail-value">Бесплатно</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">Время получения:</span>
|
<span class="detail-label">Время получения:</span>
|
||||||
<span class="detail-value">в течение 2 часов после подтверждения</span>
|
<span class="detail-value">в течение 2 часов после подтверждения</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">Парковка:</span>
|
<span class="detail-label">Парковка:</span>
|
||||||
<span class="detail-value">Бесплатная для клиентов</span>
|
<span class="detail-value">Бесплатная для клиентов</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="delivery-card">
|
<div class="delivery-card">
|
||||||
<div class="delivery-icon">
|
<div class="delivery-icon">
|
||||||
<i class="fas fa-map-marked-alt"></i>
|
<i class="fas fa-map-marked-alt"></i>
|
||||||
</div>
|
</div>
|
||||||
<h3>Доставка по России</h3>
|
<h3>Доставка по России</h3>
|
||||||
<div class="delivery-details">
|
<div class="delivery-details">
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">Стоимость:</span>
|
<span class="detail-label">Стоимость:</span>
|
||||||
<span class="detail-value">рассчитывается индивидуально</span>
|
<span class="detail-value">рассчитывается индивидуально</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">Сроки:</span>
|
<span class="detail-label">Сроки:</span>
|
||||||
<span class="detail-value">от 3 до 14 дней</span>
|
<span class="detail-value">от 3 до 14 дней</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-item">
|
<div class="detail-item">
|
||||||
<span class="detail-label">Транспортные компании:</span>
|
<span class="detail-label">Транспортные компании:</span>
|
||||||
<span class="detail-value">СДЭК, Boxberry, Деловые Линии</span>
|
<span class="detail-value">СДЭК, Boxberry, Деловые Линии</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer class="footer" id="footer">
|
<footer class="footer" id="footer">
|
||||||
<div class="container footer__content">
|
<div class="container footer__content">
|
||||||
<div class="footer__col footer__col--logo">
|
<div class="footer__col footer__col--logo">
|
||||||
<div class="logo">AETERNA</div>
|
<div class="logo">AETERNA</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer__col">
|
<div class="footer__col">
|
||||||
<h5>ПОКУПАТЕЛЮ</h5>
|
<h5>ПОКУПАТЕЛЮ</h5>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="/catalog.php">Каталог</a></li>
|
<li><a href="/catalog.php">Каталог</a></li>
|
||||||
<li><a href="services.php">Услуги</a></li>
|
<li><a href="services.php">Услуги</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer__col">
|
<div class="footer__col">
|
||||||
<h5>ПОМОЩЬ</h5>
|
<h5>ПОМОЩЬ</h5>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="доставка.php">Доставка и оплата</a></li>
|
<li><a href="доставка.php">Доставка и оплата</a></li>
|
||||||
<li><a href="гарантия.php">Гарантия и возврат</a></li>
|
<li><a href="гарантия.php">Гарантия и возврат</a></li>
|
||||||
<li><a href="cite_mebel.php#faq">Ответы на вопросы</a></li>
|
<li><a href="cite_mebel.php#faq">Ответы на вопросы</a></li>
|
||||||
<li><a href="#footer">Контакты</a></li>
|
<li><a href="#footer">Контакты</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer__col">
|
<div class="footer__col">
|
||||||
<h5>КОНТАКТЫ</h5>
|
<h5>КОНТАКТЫ</h5>
|
||||||
<p>aeterna@mail.ru</p>
|
<p>aeterna@mail.ru</p>
|
||||||
<p>+7(912)999-12-23</p>
|
<p>+7(912)999-12-23</p>
|
||||||
<div class="social-icons">
|
<div class="social-icons">
|
||||||
<span class="icon"><i class="fab fa-telegram"></i></span>
|
<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-instagram"></i></span>
|
||||||
<span class="icon"><i class="fab fa-vk"></i></span>
|
<span class="icon"><i class="fab fa-vk"></i></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer__col">
|
<div class="footer__col">
|
||||||
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
|
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
|
||||||
<div class="payment-icons">
|
<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-visa"></i></span>
|
||||||
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
|
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="copyright">
|
<div class="copyright">
|
||||||
<p>© 2025 AETERNA. Все права защищены.</p>
|
<p>© 2025 AETERNA. Все права защищены.</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -47,4 +47,3 @@
|
|||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* Единый header для страниц AETERNA (версия для public/)
|
|
||||||
* Подключение: include 'header_common.php';
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Запускаем сессию если еще не запущена
|
|
||||||
if (session_status() === PHP_SESSION_NONE) {
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
session_start();
|
session_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Определяем текущую страницу
|
|
||||||
$currentPage = basename($_SERVER['PHP_SELF'], '.php');
|
$currentPage = basename($_SERVER['PHP_SELF'], '.php');
|
||||||
|
|
||||||
// Проверяем авторизацию
|
|
||||||
$isLoggedIn = isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true;
|
$isLoggedIn = isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true;
|
||||||
$isAdmin = isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
$isAdmin = isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
||||||
$userEmail = $_SESSION['user_email'] ?? '';
|
$userEmail = $_SESSION['user_email'] ?? '';
|
||||||
@@ -49,13 +42,12 @@ $fullName = $_SESSION['full_name'] ?? $userEmail;
|
|||||||
|
|
||||||
<div class="header__icons--top">
|
<div class="header__icons--top">
|
||||||
<?php if ($isLoggedIn): ?>
|
<?php if ($isLoggedIn): ?>
|
||||||
<!-- Иконка корзины -->
|
|
||||||
<a href="checkout.php" class="icon cart-icon">
|
<a href="checkout.php" class="icon cart-icon">
|
||||||
<i class="fas fa-shopping-cart"></i>
|
<i class="fas fa-shopping-cart"></i>
|
||||||
<span class="cart-count" id="cartCount">0</span>
|
<span class="cart-count" id="cartCount">0</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<!-- Блок профиля -->
|
|
||||||
<div class="user-profile-dropdown">
|
<div class="user-profile-dropdown">
|
||||||
<div class="user-profile-toggle" id="profileToggle">
|
<div class="user-profile-toggle" id="profileToggle">
|
||||||
<div class="user-avatar"><?= !empty($userEmail) ? strtoupper(substr($userEmail, 0, 1)) : 'U' ?></div>
|
<div class="user-avatar"><?= !empty($userEmail) ? strtoupper(substr($userEmail, 0, 1)) : 'U' ?></div>
|
||||||
@@ -111,7 +103,7 @@ $fullName = $_SESSION['full_name'] ?? $userEmail;
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* Стили для профиля пользователя */
|
|
||||||
.user-profile-dropdown { position: relative; display: inline-block; }
|
.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 { 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-profile-toggle:hover { background-color: rgba(0, 0, 0, 0.05); }
|
||||||
@@ -137,19 +129,18 @@ $fullName = $_SESSION['full_name'] ?? $userEmail;
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Профиль пользователя - открытие/закрытие
|
|
||||||
$('#profileToggle').click(function(e) {
|
$('#profileToggle').click(function(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
$('#profileMenu').toggle();
|
$('#profileMenu').toggle();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).click(function(e) {
|
$(document).click(function(e) {
|
||||||
if (!$(e.target).closest('.user-profile-dropdown').length) {
|
if (!$(e.target).closest('.user-profile-dropdown').length) {
|
||||||
$('#profileMenu').hide();
|
$('#profileMenu').hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Обновление счетчика корзины
|
|
||||||
<?php if ($isLoggedIn): ?>
|
<?php if ($isLoggedIn): ?>
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'api/cart.php?action=count',
|
url: 'api/cart.php?action=count',
|
||||||
@@ -166,4 +157,3 @@ $(document).ready(function() {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,62 +1,61 @@
|
|||||||
|
|
||||||
.error-message {
|
.error-message {
|
||||||
color: #ff0000;
|
color: #ff0000;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__input.error {
|
.form__input.error {
|
||||||
border-color: #ff0000;
|
border-color: #ff0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__group {
|
.form__group {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Стили для сообщений внизу страницы */
|
.page-messages {
|
||||||
.page-messages {
|
position: fixed;
|
||||||
position: fixed;
|
bottom: 20px;
|
||||||
bottom: 20px;
|
left: 50%;
|
||||||
left: 50%;
|
transform: translateX(-50%);
|
||||||
transform: translateX(-50%);
|
z-index: 1000;
|
||||||
z-index: 1000;
|
width: 90%;
|
||||||
width: 90%;
|
max-width: 500px;
|
||||||
max-width: 500px;
|
}
|
||||||
}
|
|
||||||
|
.message {
|
||||||
.message {
|
padding: 15px;
|
||||||
padding: 15px;
|
margin: 10px 0;
|
||||||
margin: 10px 0;
|
border-radius: 5px;
|
||||||
border-radius: 5px;
|
text-align: center;
|
||||||
text-align: center;
|
font-weight: bold;
|
||||||
font-weight: bold;
|
display: none;
|
||||||
display: none;
|
}
|
||||||
}
|
|
||||||
|
.message.error {
|
||||||
.message.error {
|
background-color: #ffebee;
|
||||||
background-color: #ffebee;
|
color: #c62828;
|
||||||
color: #c62828;
|
border: 1px solid #ffcdd2;
|
||||||
border: 1px solid #ffcdd2;
|
}
|
||||||
}
|
|
||||||
|
.message.success {
|
||||||
.message.success {
|
background-color: #e8f5e9;
|
||||||
background-color: #e8f5e9;
|
color: #453227;
|
||||||
color: #453227;
|
border: 1px solid #c8e6c9;
|
||||||
border: 1px solid #c8e6c9;
|
}
|
||||||
}
|
|
||||||
|
.message.warning {
|
||||||
.message.warning {
|
background-color: #fff3e0;
|
||||||
background-color: #fff3e0;
|
color: #ef6c00;
|
||||||
color: #ef6c00;
|
border: 1px solid #ffe0b2;
|
||||||
border: 1px solid #ffe0b2;
|
}
|
||||||
}
|
|
||||||
|
.privacy-error {
|
||||||
.privacy-error {
|
color: #ff0000;
|
||||||
color: #ff0000;
|
font-size: 12px;
|
||||||
font-size: 12px;
|
margin-top: 5px;
|
||||||
margin-top: 5px;
|
display: none;
|
||||||
display: none;
|
text-align: center;
|
||||||
text-align: center;
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,62 +1,61 @@
|
|||||||
|
|
||||||
.error-message {
|
.error-message {
|
||||||
color: #ff0000;
|
color: #ff0000;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__input.error {
|
.form__input.error {
|
||||||
border-color: #ff0000;
|
border-color: #ff0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__group {
|
.form__group {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Стили для сообщений внизу страницы */
|
.page-messages {
|
||||||
.page-messages {
|
position: fixed;
|
||||||
position: fixed;
|
bottom: 20px;
|
||||||
bottom: 20px;
|
left: 50%;
|
||||||
left: 50%;
|
transform: translateX(-50%);
|
||||||
transform: translateX(-50%);
|
z-index: 1000;
|
||||||
z-index: 1000;
|
width: 90%;
|
||||||
width: 90%;
|
max-width: 500px;
|
||||||
max-width: 500px;
|
}
|
||||||
}
|
|
||||||
|
.message {
|
||||||
.message {
|
padding: 15px;
|
||||||
padding: 15px;
|
margin: 10px 0;
|
||||||
margin: 10px 0;
|
border-radius: 5px;
|
||||||
border-radius: 5px;
|
text-align: center;
|
||||||
text-align: center;
|
font-weight: bold;
|
||||||
font-weight: bold;
|
display: none;
|
||||||
display: none;
|
}
|
||||||
}
|
|
||||||
|
.message.error {
|
||||||
.message.error {
|
background-color: #ffebee;
|
||||||
background-color: #ffebee;
|
color: #c62828;
|
||||||
color: #c62828;
|
border: 1px solid #ffcdd2;
|
||||||
border: 1px solid #ffcdd2;
|
}
|
||||||
}
|
|
||||||
|
.message.success {
|
||||||
.message.success {
|
background-color: #e8f5e9;
|
||||||
background-color: #e8f5e9;
|
color: #453227;
|
||||||
color: #453227;
|
border: 1px solid #c8e6c9;
|
||||||
border: 1px solid #c8e6c9;
|
}
|
||||||
}
|
|
||||||
|
.message.warning {
|
||||||
.message.warning {
|
background-color: #fff3e0;
|
||||||
background-color: #fff3e0;
|
color: #ef6c00;
|
||||||
color: #ef6c00;
|
border: 1px solid #ffe0b2;
|
||||||
border: 1px solid #ffe0b2;
|
}
|
||||||
}
|
|
||||||
|
.privacy-error {
|
||||||
.privacy-error {
|
color: #ff0000;
|
||||||
color: #ff0000;
|
font-size: 12px;
|
||||||
font-size: 12px;
|
margin-top: 5px;
|
||||||
margin-top: 5px;
|
display: none;
|
||||||
display: none;
|
text-align: center;
|
||||||
text-align: center;
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* Функции авторизации для AETERNA
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
/**
|
|
||||||
* Авторизация пользователя
|
|
||||||
*/
|
|
||||||
function loginUser(string $email, string $password): array {
|
function loginUser(string $email, string $password): array {
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$stmt = $db->prepare("
|
$stmt = $db->prepare("
|
||||||
SELECT user_id, email, password_hash, full_name, phone, city, is_admin, is_active
|
SELECT user_id, email, password_hash, full_name, phone, city, is_admin, is_active
|
||||||
@@ -31,7 +25,6 @@ function loginUser(string $email, string $password): array {
|
|||||||
return ['success' => false, 'message' => 'Неверный пароль'];
|
return ['success' => false, 'message' => 'Неверный пароль'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Сохраняем в сессию
|
|
||||||
$_SESSION['user_id'] = $user['user_id'];
|
$_SESSION['user_id'] = $user['user_id'];
|
||||||
$_SESSION['user_email'] = $user['email'];
|
$_SESSION['user_email'] = $user['email'];
|
||||||
$_SESSION['full_name'] = $user['full_name'];
|
$_SESSION['full_name'] = $user['full_name'];
|
||||||
@@ -41,7 +34,6 @@ function loginUser(string $email, string $password): array {
|
|||||||
$_SESSION['isAdmin'] = (bool)$user['is_admin'];
|
$_SESSION['isAdmin'] = (bool)$user['is_admin'];
|
||||||
$_SESSION['login_time'] = time();
|
$_SESSION['login_time'] = time();
|
||||||
|
|
||||||
// Обновляем время последнего входа
|
|
||||||
$updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?");
|
$updateStmt = $db->prepare("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE user_id = ?");
|
||||||
$updateStmt->execute([$user['user_id']]);
|
$updateStmt->execute([$user['user_id']]);
|
||||||
|
|
||||||
@@ -52,43 +44,38 @@ function loginUser(string $email, string $password): array {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Регистрация нового пользователя
|
|
||||||
*/
|
|
||||||
function registerUser(array $data): array {
|
function registerUser(array $data): array {
|
||||||
$db = Database::getInstance()->getConnection();
|
$db = Database::getInstance()->getConnection();
|
||||||
|
|
||||||
$email = trim($data['email'] ?? '');
|
$email = trim($data['email'] ?? '');
|
||||||
$password = $data['password'] ?? '';
|
$password = $data['password'] ?? '';
|
||||||
$fullName = trim($data['full_name'] ?? '');
|
$fullName = trim($data['full_name'] ?? '');
|
||||||
$phone = trim($data['phone'] ?? '');
|
$phone = trim($data['phone'] ?? '');
|
||||||
$city = trim($data['city'] ?? '');
|
$city = trim($data['city'] ?? '');
|
||||||
|
|
||||||
// Валидация
|
|
||||||
if (empty($email) || empty($password) || empty($fullName)) {
|
if (empty($email) || empty($password) || empty($fullName)) {
|
||||||
return ['success' => false, 'message' => 'Заполните все обязательные поля'];
|
return ['success' => false, 'message' => 'Заполните все обязательные поля'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
return ['success' => false, 'message' => 'Некорректный email'];
|
return ['success' => false, 'message' => 'Некорректный email'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen($password) < 6) {
|
if (strlen($password) < 6) {
|
||||||
return ['success' => false, 'message' => 'Пароль должен содержать минимум 6 символов'];
|
return ['success' => false, 'message' => 'Пароль должен содержать минимум 6 символов'];
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Проверяем существование пользователя
|
|
||||||
$checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?");
|
$checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?");
|
||||||
$checkStmt->execute([$email]);
|
$checkStmt->execute([$email]);
|
||||||
|
|
||||||
if ($checkStmt->fetch()) {
|
if ($checkStmt->fetch()) {
|
||||||
return ['success' => false, 'message' => 'Пользователь с таким email уже существует'];
|
return ['success' => false, 'message' => 'Пользователь с таким email уже существует'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Создаем пользователя
|
|
||||||
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
|
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
|
||||||
|
|
||||||
$stmt = $db->prepare("
|
$stmt = $db->prepare("
|
||||||
INSERT INTO users (email, password_hash, full_name, phone, city, is_active)
|
INSERT INTO users (email, password_hash, full_name, phone, city, is_active)
|
||||||
VALUES (?, ?, ?, ?, ?, TRUE)
|
VALUES (?, ?, ?, ?, ?, TRUE)
|
||||||
@@ -96,8 +83,7 @@ function registerUser(array $data): array {
|
|||||||
");
|
");
|
||||||
$stmt->execute([$email, $passwordHash, $fullName, $phone, $city]);
|
$stmt->execute([$email, $passwordHash, $fullName, $phone, $city]);
|
||||||
$userId = $stmt->fetchColumn();
|
$userId = $stmt->fetchColumn();
|
||||||
|
|
||||||
// Автоматически авторизуем
|
|
||||||
$_SESSION['user_id'] = $userId;
|
$_SESSION['user_id'] = $userId;
|
||||||
$_SESSION['user_email'] = $email;
|
$_SESSION['user_email'] = $email;
|
||||||
$_SESSION['full_name'] = $fullName;
|
$_SESSION['full_name'] = $fullName;
|
||||||
@@ -106,20 +92,17 @@ function registerUser(array $data): array {
|
|||||||
$_SESSION['isLoggedIn'] = true;
|
$_SESSION['isLoggedIn'] = true;
|
||||||
$_SESSION['isAdmin'] = false;
|
$_SESSION['isAdmin'] = false;
|
||||||
$_SESSION['login_time'] = time();
|
$_SESSION['login_time'] = time();
|
||||||
|
|
||||||
return ['success' => true, 'user_id' => $userId];
|
return ['success' => true, 'user_id' => $userId];
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
return ['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()];
|
return ['success' => false, 'message' => 'Ошибка базы данных: ' . $e->getMessage()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Выход пользователя
|
|
||||||
*/
|
|
||||||
function logoutUser(): void {
|
function logoutUser(): void {
|
||||||
$_SESSION = [];
|
$_SESSION = [];
|
||||||
|
|
||||||
if (ini_get("session.use_cookies")) {
|
if (ini_get("session.use_cookies")) {
|
||||||
$params = session_get_cookie_params();
|
$params = session_get_cookie_params();
|
||||||
setcookie(session_name(), '', time() - 42000,
|
setcookie(session_name(), '', time() - 42000,
|
||||||
@@ -127,22 +110,18 @@ function logoutUser(): void {
|
|||||||
$params["secure"], $params["httponly"]
|
$params["secure"], $params["httponly"]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
session_destroy();
|
session_destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Проверка является ли пользователь администратором
|
|
||||||
*/
|
|
||||||
function checkAdminAccess(): bool {
|
function checkAdminAccess(): bool {
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
|
if (!isset($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,4 +47,3 @@
|
|||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* Общие функции для AETERNA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Проверка авторизации пользователя
|
|
||||||
*/
|
|
||||||
function isLoggedIn(): bool {
|
function isLoggedIn(): bool {
|
||||||
return isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true;
|
return isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Проверка прав администратора
|
|
||||||
*/
|
|
||||||
function isAdmin(): bool {
|
function isAdmin(): bool {
|
||||||
return isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
return isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Требовать авторизацию - редирект на login если не авторизован
|
|
||||||
*/
|
|
||||||
function requireAuth(string $redirectUrl = 'login.php'): void {
|
function requireAuth(string $redirectUrl = 'login.php'): void {
|
||||||
if (!isLoggedIn()) {
|
if (!isLoggedIn()) {
|
||||||
header('Location: ' . $redirectUrl . '?error=auth_required&redirect=' . urlencode($_SERVER['REQUEST_URI']));
|
header('Location: ' . $redirectUrl . '?error=auth_required&redirect=' . urlencode($_SERVER['REQUEST_URI']));
|
||||||
@@ -27,9 +15,6 @@ function requireAuth(string $redirectUrl = 'login.php'): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Требовать права администратора
|
|
||||||
*/
|
|
||||||
function requireAdmin(string $redirectUrl = 'login.php'): void {
|
function requireAdmin(string $redirectUrl = 'login.php'): void {
|
||||||
if (!isAdmin()) {
|
if (!isAdmin()) {
|
||||||
header('Location: ' . $redirectUrl . '?error=admin_required');
|
header('Location: ' . $redirectUrl . '?error=admin_required');
|
||||||
@@ -37,14 +22,11 @@ function requireAdmin(string $redirectUrl = 'login.php'): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Получить текущего пользователя
|
|
||||||
*/
|
|
||||||
function getCurrentUser(): ?array {
|
function getCurrentUser(): ?array {
|
||||||
if (!isLoggedIn()) {
|
if (!isLoggedIn()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'user_id' => $_SESSION['user_id'] ?? 0,
|
'user_id' => $_SESSION['user_id'] ?? 0,
|
||||||
'email' => $_SESSION['user_email'] ?? '',
|
'email' => $_SESSION['user_email'] ?? '',
|
||||||
@@ -53,38 +35,23 @@ function getCurrentUser(): ?array {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Форматирование цены
|
|
||||||
*/
|
|
||||||
function formatPrice(float $price): string {
|
function formatPrice(float $price): string {
|
||||||
return number_format($price, 0, '', ' ') . ' ₽';
|
return number_format($price, 0, '', ' ') . ' ₽';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Безопасный вывод HTML
|
|
||||||
*/
|
|
||||||
function e(string $str): string {
|
function e(string $str): string {
|
||||||
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
|
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Генерация номера заказа
|
|
||||||
*/
|
|
||||||
function generateOrderNumber(): string {
|
function generateOrderNumber(): string {
|
||||||
return 'AET-' . date('Ymd') . '-' . strtoupper(substr(uniqid(), -6));
|
return 'AET-' . date('Ymd') . '-' . strtoupper(substr(uniqid(), -6));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Генерация SKU для товара
|
|
||||||
*/
|
|
||||||
function generateSKU(string $productName): string {
|
function generateSKU(string $productName): string {
|
||||||
$prefix = strtoupper(substr(preg_replace('/[^a-zA-Z0-9]/', '', transliterate($productName)), 0, 6));
|
$prefix = strtoupper(substr(preg_replace('/[^a-zA-Z0-9]/', '', transliterate($productName)), 0, 6));
|
||||||
return $prefix . '-' . rand(100, 999);
|
return $prefix . '-' . rand(100, 999);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Транслитерация кириллицы в латиницу
|
|
||||||
*/
|
|
||||||
function transliterate(string $str): string {
|
function transliterate(string $str): string {
|
||||||
$converter = [
|
$converter = [
|
||||||
'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd',
|
'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd',
|
||||||
@@ -105,9 +72,6 @@ function transliterate(string $str): string {
|
|||||||
return strtr($str, $converter);
|
return strtr($str, $converter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Создание slug из строки
|
|
||||||
*/
|
|
||||||
function createSlug(string $str): string {
|
function createSlug(string $str): string {
|
||||||
$slug = transliterate($str);
|
$slug = transliterate($str);
|
||||||
$slug = strtolower($slug);
|
$slug = strtolower($slug);
|
||||||
@@ -116,9 +80,6 @@ function createSlug(string $str): string {
|
|||||||
return $slug;
|
return $slug;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Показать flash-сообщение
|
|
||||||
*/
|
|
||||||
function setFlashMessage(string $type, string $message): void {
|
function setFlashMessage(string $type, string $message): void {
|
||||||
$_SESSION['flash_message'] = [
|
$_SESSION['flash_message'] = [
|
||||||
'type' => $type,
|
'type' => $type,
|
||||||
@@ -126,9 +87,6 @@ function setFlashMessage(string $type, string $message): void {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Получить и удалить flash-сообщение
|
|
||||||
*/
|
|
||||||
function getFlashMessage(): ?array {
|
function getFlashMessage(): ?array {
|
||||||
if (isset($_SESSION['flash_message'])) {
|
if (isset($_SESSION['flash_message'])) {
|
||||||
$message = $_SESSION['flash_message'];
|
$message = $_SESSION['flash_message'];
|
||||||
@@ -137,4 +95,3 @@ function getFlashMessage(): ?array {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* Единый header для всех страниц AETERNA
|
|
||||||
* Подключение: require_once 'includes/header.php';
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Запускаем сессию если еще не запущена
|
|
||||||
if (session_status() === PHP_SESSION_NONE) {
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
session_start();
|
session_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Определяем текущую страницу
|
|
||||||
$currentPage = basename($_SERVER['PHP_SELF'], '.php');
|
$currentPage = basename($_SERVER['PHP_SELF'], '.php');
|
||||||
|
|
||||||
// Проверяем авторизацию
|
|
||||||
$isLoggedIn = isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true;
|
$isLoggedIn = isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true;
|
||||||
$isAdmin = isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
$isAdmin = isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true;
|
||||||
$userEmail = $_SESSION['user_email'] ?? '';
|
$userEmail = $_SESSION['user_email'] ?? '';
|
||||||
@@ -29,7 +22,7 @@ $fullName = $_SESSION['full_name'] ?? $userEmail;
|
|||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></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">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||||
<style>
|
<style>
|
||||||
/* Стили для профиля пользователя */
|
|
||||||
.user-profile-dropdown { position: relative; display: inline-block; }
|
.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 { 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-profile-toggle:hover { background-color: rgba(0, 0, 0, 0.05); }
|
||||||
@@ -88,13 +81,12 @@ $fullName = $_SESSION['full_name'] ?? $userEmail;
|
|||||||
|
|
||||||
<div class="header__icons--top">
|
<div class="header__icons--top">
|
||||||
<?php if ($isLoggedIn): ?>
|
<?php if ($isLoggedIn): ?>
|
||||||
<!-- Иконка корзины -->
|
|
||||||
<a href="checkout.php" class="icon cart-icon">
|
<a href="checkout.php" class="icon cart-icon">
|
||||||
<i class="fas fa-shopping-cart"></i>
|
<i class="fas fa-shopping-cart"></i>
|
||||||
<span class="cart-count" id="cartCount">0</span>
|
<span class="cart-count" id="cartCount">0</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<!-- Блок профиля -->
|
|
||||||
<div class="user-profile-dropdown">
|
<div class="user-profile-dropdown">
|
||||||
<div class="user-profile-toggle" id="profileToggle">
|
<div class="user-profile-toggle" id="profileToggle">
|
||||||
<div class="user-avatar"><?= !empty($userEmail) ? strtoupper(substr($userEmail, 0, 1)) : 'U' ?></div>
|
<div class="user-avatar"><?= !empty($userEmail) ? strtoupper(substr($userEmail, 0, 1)) : 'U' ?></div>
|
||||||
@@ -151,19 +143,18 @@ $fullName = $_SESSION['full_name'] ?? $userEmail;
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// Профиль пользователя - открытие/закрытие
|
|
||||||
$('#profileToggle').click(function(e) {
|
$('#profileToggle').click(function(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
$('#profileMenu').toggle();
|
$('#profileMenu').toggle();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).click(function(e) {
|
$(document).click(function(e) {
|
||||||
if (!$(e.target).closest('.user-profile-dropdown').length) {
|
if (!$(e.target).closest('.user-profile-dropdown').length) {
|
||||||
$('#profileMenu').hide();
|
$('#profileMenu').hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Обновление счетчика корзины
|
|
||||||
<?php if ($isLoggedIn): ?>
|
<?php if ($isLoggedIn): ?>
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'api/cart.php?action=count',
|
url: 'api/cart.php?action=count',
|
||||||
@@ -180,4 +171,3 @@ $(document).ready(function() {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
1532
public/index.php
1532
public/index.php
File diff suppressed because it is too large
Load Diff
593
public/login.php
593
public/login.php
@@ -1,299 +1,294 @@
|
|||||||
<?php
|
<?php
|
||||||
session_start();
|
session_start();
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>AETERNA - Вход</title>
|
<title>AETERNA - Вход</title>
|
||||||
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
|
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/less"></script>
|
<script src="https://cdn.jsdelivr.net/npm/less"></script>
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></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">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||||
<style>
|
<style>
|
||||||
/* Добавляем стили для статуса пользователя */
|
|
||||||
.user-status {
|
.user-status {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 20px;
|
top: 20px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
background: white;
|
background: white;
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-status.admin {
|
.user-status.admin {
|
||||||
border-left: 4px solid #617365;
|
border-left: 4px solid #617365;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-status.user {
|
.user-status.user {
|
||||||
border-left: 4px solid #28a745;
|
border-left: 4px solid #28a745;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-icon {
|
.status-icon {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-icon {
|
.admin-icon {
|
||||||
color: #617365;
|
color: #617365;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-icon {
|
.user-icon {
|
||||||
color: #28a745;
|
color: #28a745;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="check_auth.js"></script>
|
<script src="check_auth.js"></script>
|
||||||
<style>
|
<style>
|
||||||
/* Стили для блокировки доступа */
|
|
||||||
.link-disabled {
|
.link-disabled {
|
||||||
cursor: not-allowed !important;
|
cursor: not-allowed !important;
|
||||||
opacity: 0.7 !important;
|
opacity: 0.7 !important;
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-required {
|
.auth-required {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-required::after {
|
.auth-required::after {
|
||||||
content: "🔒";
|
content: "🔒";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -5px;
|
top: -5px;
|
||||||
right: -10px;
|
right: -10px;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- Статус пользователя -->
|
|
||||||
<div class="user-status" id="userStatus" style="display: none;">
|
<div class="user-status" id="userStatus" style="display: none;">
|
||||||
<i class="fas fa-user status-icon" id="statusIcon"></i>
|
<i class="fas fa-user status-icon" id="statusIcon"></i>
|
||||||
<div>
|
<div>
|
||||||
<div id="statusText"></div>
|
<div id="statusText"></div>
|
||||||
<div id="userEmail" style="font-size: 12px; color: #666;"></div>
|
<div id="userEmail" style="font-size: 12px; color: #666;"></div>
|
||||||
</div>
|
</div>
|
||||||
<button onclick="logout()" style="background: none; border: none; color: #666; cursor: pointer;">
|
<button onclick="logout()" style="background: none; border: none; color: #666; cursor: pointer;">
|
||||||
<i class="fas fa-sign-out-alt"></i>
|
<i class="fas fa-sign-out-alt"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<div class="header__top">
|
<div class="header__top">
|
||||||
<div class="container header__top-content">
|
<div class="container header__top-content">
|
||||||
<div class="logo">AETERNA</div>
|
<div class="logo">AETERNA</div>
|
||||||
|
|
||||||
<div class="search-catalog">
|
<div class="search-catalog">
|
||||||
<div class="catalog-dropdown">
|
<div class="catalog-dropdown">
|
||||||
Все категории <span>▼</span>
|
Все категории <span>▼</span>
|
||||||
<div class="catalog-dropdown__menu">
|
<div class="catalog-dropdown__menu">
|
||||||
<ul>
|
<ul>
|
||||||
<li>Диваны</li>
|
<li>Диваны</li>
|
||||||
<li>Кровати</li>
|
<li>Кровати</li>
|
||||||
<li>Шкафы</li>
|
<li>Шкафы</li>
|
||||||
<li>Стулья</li>
|
<li>Стулья</li>
|
||||||
<li>Столы</li>
|
<li>Столы</li>
|
||||||
<li>Комоды</li>
|
<li>Комоды</li>
|
||||||
<li>Тумбы</li>
|
<li>Тумбы</li>
|
||||||
<li>Полки</li>
|
<li>Полки</li>
|
||||||
<li>Стенки</li>
|
<li>Стенки</li>
|
||||||
<li>Аксессуары</li>
|
<li>Аксессуары</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="search-box">
|
<div class="search-box">
|
||||||
<input type="text" placeholder="Поиск товаров">
|
<input type="text" placeholder="Поиск товаров">
|
||||||
<span class="search-icon"><i class="fas fa-search"></i></span>
|
<span class="search-icon"><i class="fas fa-search"></i></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="header__icons header__icons--top">
|
<div class="header__icons header__icons--top">
|
||||||
<a href="checkout.php" class="icon"><i class="fas fa-shopping-cart"></i></a>
|
<a href="checkout.php" class="icon"><i class="fas fa-shopping-cart"></i></a>
|
||||||
<a href="register.php" class="icon"><i class="far fa-user"></i></a>
|
<a href="register.php" class="icon"><i class="far fa-user"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="header__bottom">
|
<div class="header__bottom">
|
||||||
<div class="container header__bottom-content">
|
<div class="container header__bottom-content">
|
||||||
<div class="catalog-menu">
|
<div class="catalog-menu">
|
||||||
<a href="/catalog.php" class="catalog-link">
|
<a href="/catalog.php" class="catalog-link">
|
||||||
<div class="catalog-icon">
|
<div class="catalog-icon">
|
||||||
<span class="line"></span>
|
<span class="line"></span>
|
||||||
<span class="line"></span>
|
<span class="line"></span>
|
||||||
<span class="line"></span>
|
<span class="line"></span>
|
||||||
</div>
|
</div>
|
||||||
<span class="catalog-lines">☰</span>
|
<span class="catalog-lines">☰</span>
|
||||||
Каталог
|
Каталог
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav class="nav">
|
<nav class="nav">
|
||||||
<ul class="nav-list">
|
<ul class="nav-list">
|
||||||
<li><a href="cite_mebel.php">Главная</a></li>
|
<li><a href="cite_mebel.php">Главная</a></li>
|
||||||
<li><a href="services.php">Услуги</a></li>
|
<li><a href="services.php">Услуги</a></li>
|
||||||
<li><a href="delivery.php">Доставка и оплата</a></li>
|
<li><a href="delivery.php">Доставка и оплата</a></li>
|
||||||
<li><a href="warranty.php">Гарантия</a></li>
|
<li><a href="warranty.php">Гарантия</a></li>
|
||||||
<li><a href="#footer">Контакты</a></li>
|
<li><a href="#footer">Контакты</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="header-phone">+7(912)999-12-23</div>
|
<div class="header-phone">+7(912)999-12-23</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="profile-page-main">
|
<main class="profile-page-main">
|
||||||
<div class="profile-container">
|
<div class="profile-container">
|
||||||
<div class="profile-left-col">
|
<div class="profile-left-col">
|
||||||
<div class="logo">AETERNA</div>
|
<div class="logo">AETERNA</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="profile-right-col">
|
<div class="profile-right-col">
|
||||||
<div class="profile-form-block">
|
<div class="profile-form-block">
|
||||||
<h2>ВХОД В АККАУНТ</h2>
|
<h2>ВХОД В АККАУНТ</h2>
|
||||||
<form class="profile-form" action="#" method="POST" id="loginForm">
|
<form class="profile-form" action="#" method="POST" id="loginForm">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<label for="login-email">E-mail</label>
|
<label for="login-email">E-mail</label>
|
||||||
<input type="email" id="login-email" name="email" placeholder="Ваш электронный адрес" required>
|
<input type="email" id="login-email" name="email" placeholder="Ваш электронный адрес" required>
|
||||||
<div class="error-message" id="email-error">
|
<div class="error-message" id="email-error">
|
||||||
Введите корректный email адрес
|
Введите корректный email адрес
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<label for="login-password">Пароль</label>
|
<label for="login-password">Пароль</label>
|
||||||
<input type="password" id="login-password" name="password" placeholder="Введите пароль" required>
|
<input type="password" id="login-password" name="password" placeholder="Введите пароль" required>
|
||||||
<div class="error-message" id="password-error">Неверный пароль</div>
|
<div class="error-message" id="password-error">Неверный пароль</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-options">
|
<div class="form-options">
|
||||||
<label class="remember-me">
|
<label class="remember-me">
|
||||||
<input type="checkbox" id="remember" name="remember">
|
<input type="checkbox" id="remember" name="remember">
|
||||||
Запомнить меня
|
Запомнить меня
|
||||||
</label>
|
</label>
|
||||||
<a href="#" class="forgot-password">Забыли пароль?</a>
|
<a href="#" class="forgot-password">Забыли пароль?</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn primary-btn save-btn">Войти</button>
|
<button type="submit" class="btn primary-btn save-btn">Войти</button>
|
||||||
|
|
||||||
<div class="auth-actions">
|
<div class="auth-actions">
|
||||||
<span class="auth-text">Нет аккаунта?</span>
|
<span class="auth-text">Нет аккаунта?</span>
|
||||||
<a href="register.php" class="login-btn">Зарегистрироваться</a>
|
<a href="register.php" class="login-btn">Зарегистрироваться</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- Блок для системных сообщений -->
|
<div class="page-messages">
|
||||||
<div class="page-messages">
|
<div class="message error" id="errorMessage"></div>
|
||||||
<div class="message error" id="errorMessage"></div>
|
<div class="message success" id="successMessage"></div>
|
||||||
<div class="message success" id="successMessage"></div>
|
<div class="message warning" id="warningMessage"></div>
|
||||||
<div class="message warning" id="warningMessage"></div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<footer class="footer" id="footer">
|
||||||
<footer class="footer" id="footer">
|
<div class="container footer__content">
|
||||||
<div class="container footer__content">
|
<div class="footer__col footer__col--logo">
|
||||||
<div class="footer__col footer__col--logo">
|
<div class="logo">AETERNA</div>
|
||||||
<div class="logo">AETERNA</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="footer__col">
|
||||||
<div class="footer__col">
|
<h5>ПОКУПАТЕЛЮ</h5>
|
||||||
<h5>ПОКУПАТЕЛЮ</h5>
|
<ul>
|
||||||
<ul>
|
<li><a href="/catalog.php">Каталог</a></li>
|
||||||
<li><a href="/catalog.php">Каталог</a></li>
|
<li><a href="услуги.html">Услуги</a></li>
|
||||||
<li><a href="услуги.html">Услуги</a></li>
|
</ul>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="footer__col">
|
||||||
<div class="footer__col">
|
<h5>ПОМОЩЬ</h5>
|
||||||
<h5>ПОМОЩЬ</h5>
|
<ul>
|
||||||
<ul>
|
<li><a href="Доставка.html">Доставка и оплата</a></li>
|
||||||
<li><a href="Доставка.html">Доставка и оплата</a></li>
|
<li><a href="Гарантия.html">Гарантия и возврат</a></li>
|
||||||
<li><a href="Гарантия.html">Гарантия и возврат</a></li>
|
<li><a href="cite_mebel.html#faq">Ответы на вопросы</a></li>
|
||||||
<li><a href="cite_mebel.html#faq">Ответы на вопросы</a></li>
|
<li><a href="#footer">Контакты</a></li>
|
||||||
<li><a href="#footer">Контакты</a></li>
|
</ul>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="footer__col">
|
||||||
<div class="footer__col">
|
<h5>КОНТАКТЫ</h5>
|
||||||
<h5>КОНТАКТЫ</h5>
|
<p>aeterna@mail.ru</p>
|
||||||
<p>aeterna@mail.ru</p>
|
<p>+7(912)999-12-23</p>
|
||||||
<p>+7(912)999-12-23</p>
|
<div class="social-icons">
|
||||||
<div class="social-icons">
|
<span class="icon"><i class="fab fa-telegram"></i></span>
|
||||||
<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-instagram"></i></span>
|
<span class="icon"><i class="fab fa-vk"></i></span>
|
||||||
<span class="icon"><i class="fab fa-vk"></i></span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="footer__col">
|
||||||
<div class="footer__col">
|
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
|
||||||
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
|
<div class="payment-icons">
|
||||||
<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-visa"></i></span>
|
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
|
||||||
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="copyright">
|
||||||
<div class="copyright">
|
<p>© 2025 AETERNA. Все права защищены.</p>
|
||||||
<p>© 2025 AETERNA. Все права защищены.</p>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
|
||||||
|
<script>
|
||||||
<script>
|
$(document).ready(function() {
|
||||||
$(document).ready(function() {
|
|
||||||
// Проверяем редирект после входа
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const redirectUrl = urlParams.get('redirect');
|
||||||
const redirectUrl = urlParams.get('redirect');
|
|
||||||
|
if (redirectUrl) {
|
||||||
// Если есть редирект - сохраняем его
|
sessionStorage.setItem('redirectAfterLogin', redirectUrl);
|
||||||
if (redirectUrl) {
|
}
|
||||||
sessionStorage.setItem('redirectAfterLogin', redirectUrl);
|
|
||||||
}
|
$('#loginForm').on('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
// Обработка формы входа
|
|
||||||
$('#loginForm').on('submit', function(e) {
|
const email = $('#login-email').val();
|
||||||
e.preventDefault();
|
const password = $('#login-password').val();
|
||||||
|
|
||||||
const email = $('#login-email').val();
|
if (!email || !password) {
|
||||||
const password = $('#login-password').val();
|
alert('Заполните все поля');
|
||||||
|
return;
|
||||||
// Валидация на клиенте
|
}
|
||||||
if (!email || !password) {
|
|
||||||
alert('Заполните все поля');
|
$.ajax({
|
||||||
return;
|
url: 'api/auth.php',
|
||||||
}
|
method: 'POST',
|
||||||
|
data: {
|
||||||
// Отправляем данные на сервер для PHP сессии
|
email: email,
|
||||||
$.ajax({
|
password: password
|
||||||
url: 'api/auth.php',
|
},
|
||||||
method: 'POST',
|
dataType: 'json',
|
||||||
data: {
|
success: function(result) {
|
||||||
email: email,
|
if (result.success) {
|
||||||
password: password
|
|
||||||
},
|
const savedRedirect = sessionStorage.getItem('redirectAfterLogin') || 'catalog.php';
|
||||||
dataType: 'json',
|
sessionStorage.removeItem('redirectAfterLogin');
|
||||||
success: function(result) {
|
window.location.href = savedRedirect;
|
||||||
if (result.success) {
|
} else {
|
||||||
// Редирект на сохраненный URL или каталог
|
alert(result.message || 'Ошибка авторизации');
|
||||||
const savedRedirect = sessionStorage.getItem('redirectAfterLogin') || 'catalog.php';
|
}
|
||||||
sessionStorage.removeItem('redirectAfterLogin');
|
},
|
||||||
window.location.href = savedRedirect;
|
error: function() {
|
||||||
} else {
|
alert('Ошибка сервера. Попробуйте позже.');
|
||||||
alert(result.message || 'Ошибка авторизации');
|
}
|
||||||
}
|
});
|
||||||
},
|
});
|
||||||
error: function() {
|
});
|
||||||
alert('Ошибка сервера. Попробуйте позже.');
|
</script>
|
||||||
}
|
|
||||||
});
|
</body>
|
||||||
});
|
</html>
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
session_start();
|
session_start();
|
||||||
|
|
||||||
// Очищаем все данные сессии
|
|
||||||
$_SESSION = [];
|
$_SESSION = [];
|
||||||
|
|
||||||
// Удаляем cookie сессии
|
|
||||||
if (ini_get("session.use_cookies")) {
|
if (ini_get("session.use_cookies")) {
|
||||||
$params = session_get_cookie_params();
|
$params = session_get_cookie_params();
|
||||||
setcookie(session_name(), '', time() - 42000,
|
setcookie(session_name(), '', time() - 42000,
|
||||||
@@ -13,10 +11,7 @@ if (ini_get("session.use_cookies")) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Уничтожаем сессию
|
|
||||||
session_destroy();
|
session_destroy();
|
||||||
|
|
||||||
// Очищаем localStorage через JS
|
|
||||||
header('Location: index.php');
|
header('Location: index.php');
|
||||||
exit();
|
exit();
|
||||||
|
|
||||||
|
|||||||
@@ -1,492 +1,484 @@
|
|||||||
<?php
|
<?php
|
||||||
// product_page.php
|
|
||||||
session_start();
|
session_start();
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
|
|
||||||
// Проверка авторизации
|
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
||||||
if (!isset($_SESSION['isLoggedIn']) || $_SESSION['isLoggedIn'] !== true) {
|
header('Location: login.php?error=auth_required&redirect=' . urlencode($_SERVER['REQUEST_URI']));
|
||||||
header('Location: login.php?error=auth_required&redirect=' . urlencode($_SERVER['REQUEST_URI']));
|
exit();
|
||||||
exit();
|
}
|
||||||
}
|
|
||||||
|
if (!isset($_GET['id'])) {
|
||||||
if (!isset($_GET['id'])) {
|
header('Location: catalog.php');
|
||||||
header('Location: catalog.php');
|
exit();
|
||||||
exit();
|
}
|
||||||
}
|
|
||||||
|
$product_id = intval($_GET['id']);
|
||||||
$product_id = intval($_GET['id']);
|
|
||||||
|
$db = Database::getInstance()->getConnection();
|
||||||
$db = Database::getInstance()->getConnection();
|
|
||||||
|
try {
|
||||||
try {
|
|
||||||
// Получаем информацию о товаре
|
$productStmt = $db->prepare("
|
||||||
$productStmt = $db->prepare("
|
SELECT
|
||||||
SELECT
|
p.*,
|
||||||
p.*,
|
c.name as category_name,
|
||||||
c.name as category_name,
|
c.slug as category_slug
|
||||||
c.slug as category_slug
|
FROM products p
|
||||||
FROM products p
|
LEFT JOIN categories c ON p.category_id = c.category_id
|
||||||
LEFT JOIN categories c ON p.category_id = c.category_id
|
WHERE p.product_id = ? AND p.is_available = TRUE
|
||||||
WHERE p.product_id = ? AND p.is_available = TRUE
|
");
|
||||||
");
|
$productStmt->execute([$product_id]);
|
||||||
$productStmt->execute([$product_id]);
|
$product = $productStmt->fetch();
|
||||||
$product = $productStmt->fetch();
|
|
||||||
|
if (!$product) {
|
||||||
if (!$product) {
|
header('Location: catalog.php?error=product_not_found');
|
||||||
header('Location: catalog.php?error=product_not_found');
|
exit();
|
||||||
exit();
|
}
|
||||||
}
|
|
||||||
|
$similarStmt = $db->prepare("
|
||||||
// Получаем похожие товары
|
SELECT * FROM products
|
||||||
$similarStmt = $db->prepare("
|
WHERE category_id = ?
|
||||||
SELECT * FROM products
|
AND product_id != ?
|
||||||
WHERE category_id = ?
|
AND is_available = TRUE
|
||||||
AND product_id != ?
|
ORDER BY RANDOM()
|
||||||
AND is_available = TRUE
|
LIMIT 3
|
||||||
ORDER BY RANDOM()
|
");
|
||||||
LIMIT 3
|
$similarStmt->execute([$product['category_id'], $product_id]);
|
||||||
");
|
$similarProducts = $similarStmt->fetchAll();
|
||||||
$similarStmt->execute([$product['category_id'], $product_id]);
|
|
||||||
$similarProducts = $similarStmt->fetchAll();
|
$reviewsStmt = $db->prepare("
|
||||||
|
SELECT rating, comment, created_at
|
||||||
// Получаем отзывы (если есть отдельная таблица reviews)
|
FROM reviews
|
||||||
$reviewsStmt = $db->prepare("
|
WHERE product_id = ?
|
||||||
SELECT rating, comment, created_at
|
ORDER BY created_at DESC
|
||||||
FROM reviews
|
LIMIT 5
|
||||||
WHERE product_id = ?
|
");
|
||||||
ORDER BY created_at DESC
|
$reviewsStmt->execute([$product_id]);
|
||||||
LIMIT 5
|
$reviews = $reviewsStmt->fetchAll();
|
||||||
");
|
|
||||||
$reviewsStmt->execute([$product_id]);
|
} catch (PDOException $e) {
|
||||||
$reviews = $reviewsStmt->fetchAll();
|
die("Ошибка базы данных: " . $e->getMessage());
|
||||||
|
}
|
||||||
} catch (PDOException $e) {
|
|
||||||
die("Ошибка базы данных: " . $e->getMessage());
|
?>
|
||||||
}
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
// HTML код страницы товара
|
<head>
|
||||||
?>
|
<meta charset="UTF-8">
|
||||||
<!DOCTYPE html>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<html lang="ru">
|
<title>AETERNA - <?= htmlspecialchars($product['name']) ?></title>
|
||||||
<head>
|
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
|
||||||
<meta charset="UTF-8">
|
<script src="https://cdn.jsdelivr.net/npm/less"></script>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
<title>AETERNA - <?= htmlspecialchars($product['name']) ?></title>
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||||
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
|
<style>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/less"></script>
|
.product-attributes {
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
background: #f8f9fa;
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
padding: 20px;
|
||||||
<style>
|
border-radius: 8px;
|
||||||
.product-attributes {
|
margin: 20px 0;
|
||||||
background: #f8f9fa;
|
}
|
||||||
padding: 20px;
|
.attribute-row {
|
||||||
border-radius: 8px;
|
display: flex;
|
||||||
margin: 20px 0;
|
justify-content: space-between;
|
||||||
}
|
padding: 10px 0;
|
||||||
.attribute-row {
|
border-bottom: 1px solid #ddd;
|
||||||
display: flex;
|
}
|
||||||
justify-content: space-between;
|
.attribute-label {
|
||||||
padding: 10px 0;
|
font-weight: bold;
|
||||||
border-bottom: 1px solid #ddd;
|
color: #453227;
|
||||||
}
|
}
|
||||||
.attribute-label {
|
.attribute-value {
|
||||||
font-weight: bold;
|
color: #617365;
|
||||||
color: #453227;
|
}
|
||||||
}
|
.stock-status {
|
||||||
.attribute-value {
|
font-weight: bold;
|
||||||
color: #617365;
|
padding: 5px 10px;
|
||||||
}
|
border-radius: 4px;
|
||||||
.stock-status {
|
display: inline-block;
|
||||||
font-weight: bold;
|
}
|
||||||
padding: 5px 10px;
|
.in-stock {
|
||||||
border-radius: 4px;
|
background: #d4edda;
|
||||||
display: inline-block;
|
color: #155724;
|
||||||
}
|
}
|
||||||
.in-stock {
|
.low-stock {
|
||||||
background: #d4edda;
|
background: #fff3cd;
|
||||||
color: #155724;
|
color: #856404;
|
||||||
}
|
}
|
||||||
.low-stock {
|
.out-of-stock {
|
||||||
background: #fff3cd;
|
background: #f8d7da;
|
||||||
color: #856404;
|
color: #721c24;
|
||||||
}
|
}
|
||||||
.out-of-stock {
|
</style>
|
||||||
background: #f8d7da;
|
</head>
|
||||||
color: #721c24;
|
<body>
|
||||||
}
|
<header class="header">
|
||||||
</style>
|
<div class="header__top">
|
||||||
</head>
|
<div class="container header__top-content">
|
||||||
<body>
|
<div class="logo">AETERNA</div>
|
||||||
<header class="header">
|
|
||||||
<div class="header__top">
|
<div class="search-catalog">
|
||||||
<div class="container header__top-content">
|
<div class="catalog-dropdown">
|
||||||
<div class="logo">AETERNA</div>
|
Все категории <span>▼</span>
|
||||||
|
<div class="catalog-dropdown__menu">
|
||||||
<div class="search-catalog">
|
<ul>
|
||||||
<div class="catalog-dropdown">
|
<li><a href="#">Диваны</a></li>
|
||||||
Все категории <span>▼</span>
|
<li><a href="#">Кровати</a></li>
|
||||||
<div class="catalog-dropdown__menu">
|
<li><a href="#">Шкафы</a></li>
|
||||||
<ul>
|
<li><a href="#">Стулья</a></li>
|
||||||
<li><a href="#">Диваны</a></li>
|
<li><a href="#">Столы</a></li>
|
||||||
<li><a href="#">Кровати</a></li>
|
</ul>
|
||||||
<li><a href="#">Шкафы</a></li>
|
</div>
|
||||||
<li><a href="#">Стулья</a></li>
|
</div>
|
||||||
<li><a href="#">Столы</a></li>
|
<div class="search-box">
|
||||||
</ul>
|
<input type="text" placeholder="Поиск товаров">
|
||||||
</div>
|
<span class="search-icon"><i class="fas fa-search"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="search-box">
|
</div>
|
||||||
<input type="text" placeholder="Поиск товаров">
|
|
||||||
<span class="search-icon"><i class="fas fa-search"></i></span>
|
<div class="header__icons--top">
|
||||||
</div>
|
|
||||||
</div>
|
<a href="checkout.php" class="icon"><i class="fas fa-shopping-cart"></i></a>
|
||||||
|
<a href="register.php" class="icon"><i class="far fa-user"></i></a>
|
||||||
<div class="header__icons--top">
|
</div>
|
||||||
|
</div>
|
||||||
<a href="checkout.php" class="icon"><i class="fas fa-shopping-cart"></i></a>
|
</div>
|
||||||
<a href="register.php" class="icon"><i class="far fa-user"></i></a>
|
|
||||||
</div>
|
<div class="header__bottom">
|
||||||
</div>
|
<div class="container header__bottom-content">
|
||||||
</div>
|
<div class="catalog-menu">
|
||||||
|
<a href="/catalog.php" class="catalog-link active-catalog">
|
||||||
<div class="header__bottom">
|
<div class="catalog-icon">
|
||||||
<div class="container header__bottom-content">
|
<span class="line"></span>
|
||||||
<div class="catalog-menu">
|
<span class="line"></span>
|
||||||
<a href="/catalog.php" class="catalog-link active-catalog">
|
<span class="line"></span>
|
||||||
<div class="catalog-icon">
|
</div>
|
||||||
<span class="line"></span>
|
<span class="catalog-lines">☰</span>
|
||||||
<span class="line"></span>
|
Каталог
|
||||||
<span class="line"></span>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<span class="catalog-lines">☰</span>
|
|
||||||
Каталог
|
<nav class="nav">
|
||||||
</a>
|
<ul class="nav-list">
|
||||||
</div>
|
<li><a href="cite_mebel.php">Главная</a></li>
|
||||||
|
<li><a href="services.php">Услуги</a></li>
|
||||||
<nav class="nav">
|
<li><a href="delivery.php">Доставка и оплата</a></li>
|
||||||
<ul class="nav-list">
|
<li><a href="warranty.php">Гарантия</a></li>
|
||||||
<li><a href="cite_mebel.php">Главная</a></li>
|
<li><a href="#footer">Контакты</a></li>
|
||||||
<li><a href="services.php">Услуги</a></li>
|
</ul>
|
||||||
<li><a href="delivery.php">Доставка и оплата</a></li>
|
</nav>
|
||||||
<li><a href="warranty.php">Гарантия</a></li>
|
<div class="header-phone">+7(912)999-12-23</div>
|
||||||
<li><a href="#footer">Контакты</a></li>
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
</nav>
|
</header>
|
||||||
<div class="header-phone">+7(912)999-12-23</div>
|
|
||||||
</div>
|
<main class="container">
|
||||||
</div>
|
<div class="breadcrumbs">
|
||||||
</header>
|
<a href="cite_mebel.php">Главная</a> •
|
||||||
|
<a href="/catalog.php">Каталог</a> •
|
||||||
<main class="container">
|
<?php if ($product['category_name']): ?>
|
||||||
<div class="breadcrumbs">
|
<a href="/catalog.php?category=<?= $product['category_id'] ?>">
|
||||||
<a href="cite_mebel.php">Главная</a> •
|
<?= htmlspecialchars($product['category_name']) ?>
|
||||||
<a href="/catalog.php">Каталог</a> •
|
</a> •
|
||||||
<?php if ($product['category_name']): ?>
|
<?php endif; ?>
|
||||||
<a href="/catalog.php?category=<?= $product['category_id'] ?>">
|
<span><?= htmlspecialchars($product['name']) ?></span>
|
||||||
<?= htmlspecialchars($product['category_name']) ?>
|
</div>
|
||||||
</a> •
|
|
||||||
<?php endif; ?>
|
<div class="product__section">
|
||||||
<span><?= htmlspecialchars($product['name']) ?></span>
|
<div class="product__gallery">
|
||||||
</div>
|
<div class="product__main-image">
|
||||||
|
<img src="<?= htmlspecialchars($product['image_url'] ?? 'img1/default.jpg') ?>"
|
||||||
<div class="product__section">
|
alt="<?= htmlspecialchars($product['name']) ?>"
|
||||||
<div class="product__gallery">
|
id="mainImage">
|
||||||
<div class="product__main-image">
|
</div>
|
||||||
<img src="<?= htmlspecialchars($product['image_url'] ?? 'img1/default.jpg') ?>"
|
</div>
|
||||||
alt="<?= htmlspecialchars($product['name']) ?>"
|
|
||||||
id="mainImage">
|
<div class="product__info">
|
||||||
</div>
|
<h1><?= htmlspecialchars($product['name']) ?></h1>
|
||||||
</div>
|
|
||||||
|
<div class="product__rating">
|
||||||
<div class="product__info">
|
<div class="stars">
|
||||||
<h1><?= htmlspecialchars($product['name']) ?></h1>
|
<?php
|
||||||
|
$rating = $product['rating'] ?? 0;
|
||||||
<div class="product__rating">
|
$fullStars = floor($rating);
|
||||||
<div class="stars">
|
$hasHalfStar = $rating - $fullStars >= 0.5;
|
||||||
<?php
|
|
||||||
$rating = $product['rating'] ?? 0;
|
for ($i = 1; $i <= 5; $i++) {
|
||||||
$fullStars = floor($rating);
|
if ($i <= $fullStars) {
|
||||||
$hasHalfStar = $rating - $fullStars >= 0.5;
|
echo '<span class="star filled">★</span>';
|
||||||
|
} elseif ($i == $fullStars + 1 && $hasHalfStar) {
|
||||||
for ($i = 1; $i <= 5; $i++) {
|
echo '<span class="star half">★</span>';
|
||||||
if ($i <= $fullStars) {
|
} else {
|
||||||
echo '<span class="star filled">★</span>';
|
echo '<span class="star">☆</span>';
|
||||||
} elseif ($i == $fullStars + 1 && $hasHalfStar) {
|
}
|
||||||
echo '<span class="star half">★</span>';
|
}
|
||||||
} else {
|
?>
|
||||||
echo '<span class="star">☆</span>';
|
</div>
|
||||||
}
|
<span class="rating-value"><?= number_format($rating, 1) ?></span>
|
||||||
}
|
<span class="reviews-count">(<?= $product['review_count'] ?> отзывов)</span>
|
||||||
?>
|
</div>
|
||||||
</div>
|
|
||||||
<span class="rating-value"><?= number_format($rating, 1) ?></span>
|
<div class="product__price">
|
||||||
<span class="reviews-count">(<?= $product['review_count'] ?> отзывов)</span>
|
<span class="current-price">
|
||||||
</div>
|
<?= number_format($product['price'], 0, '', ' ') ?> ₽
|
||||||
|
</span>
|
||||||
<div class="product__price">
|
<?php if ($product['old_price'] && $product['old_price'] > $product['price']): ?>
|
||||||
<span class="current-price">
|
<span class="old-price">
|
||||||
<?= number_format($product['price'], 0, '', ' ') ?> ₽
|
<?= number_format($product['old_price'], 0, '', ' ') ?> ₽
|
||||||
</span>
|
</span>
|
||||||
<?php if ($product['old_price'] && $product['old_price'] > $product['price']): ?>
|
<span class="discount-badge">
|
||||||
<span class="old-price">
|
-<?= round(($product['old_price'] - $product['price']) / $product['old_price'] * 100) ?>%
|
||||||
<?= number_format($product['old_price'], 0, '', ' ') ?> ₽
|
</span>
|
||||||
</span>
|
<?php endif; ?>
|
||||||
<span class="discount-badge">
|
</div>
|
||||||
-<?= round(($product['old_price'] - $product['price']) / $product['old_price'] * 100) ?>%
|
|
||||||
</span>
|
<div class="stock-status <?php
|
||||||
<?php endif; ?>
|
if ($product['stock_quantity'] > 10) echo 'in-stock';
|
||||||
</div>
|
elseif ($product['stock_quantity'] > 0) echo 'low-stock';
|
||||||
|
else echo 'out-of-stock';
|
||||||
<div class="stock-status <?php
|
?>">
|
||||||
if ($product['stock_quantity'] > 10) echo 'in-stock';
|
<?php
|
||||||
elseif ($product['stock_quantity'] > 0) echo 'low-stock';
|
if ($product['stock_quantity'] > 10) {
|
||||||
else echo 'out-of-stock';
|
echo '<i class="fas fa-check-circle"></i> В наличии';
|
||||||
?>">
|
} elseif ($product['stock_quantity'] > 0) {
|
||||||
<?php
|
echo '<i class="fas fa-exclamation-circle"></i> Осталось мало: ' . $product['stock_quantity'] . ' шт.';
|
||||||
if ($product['stock_quantity'] > 10) {
|
} else {
|
||||||
echo '<i class="fas fa-check-circle"></i> В наличии';
|
echo '<i class="fas fa-times-circle"></i> Нет в наличии';
|
||||||
} elseif ($product['stock_quantity'] > 0) {
|
}
|
||||||
echo '<i class="fas fa-exclamation-circle"></i> Осталось мало: ' . $product['stock_quantity'] . ' шт.';
|
?>
|
||||||
} else {
|
</div>
|
||||||
echo '<i class="fas fa-times-circle"></i> Нет в наличии';
|
|
||||||
}
|
<div class="product-attributes">
|
||||||
?>
|
<div class="attribute-row">
|
||||||
</div>
|
<span class="attribute-label">Артикул:</span>
|
||||||
|
<span class="attribute-value"><?= $product['sku'] ?? 'N/A' ?></span>
|
||||||
<div class="product-attributes">
|
</div>
|
||||||
<div class="attribute-row">
|
<div class="attribute-row">
|
||||||
<span class="attribute-label">Артикул:</span>
|
<span class="attribute-label">Категория:</span>
|
||||||
<span class="attribute-value"><?= $product['sku'] ?? 'N/A' ?></span>
|
<span class="attribute-value"><?= htmlspecialchars($product['category_name'] ?? 'Без категории') ?></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="attribute-row">
|
<div class="attribute-row">
|
||||||
<span class="attribute-label">Категория:</span>
|
<span class="attribute-label">На складе:</span>
|
||||||
<span class="attribute-value"><?= htmlspecialchars($product['category_name'] ?? 'Без категории') ?></span>
|
<span class="attribute-value"><?= $product['stock_quantity'] ?> шт.</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="attribute-row">
|
</div>
|
||||||
<span class="attribute-label">На складе:</span>
|
|
||||||
<span class="attribute-value"><?= $product['stock_quantity'] ?> шт.</span>
|
<p class="product__description">
|
||||||
</div>
|
<?= nl2br(htmlspecialchars($product['description'] ?? 'Описание отсутствует')) ?>
|
||||||
</div>
|
</p>
|
||||||
|
|
||||||
<p class="product__description">
|
<?php if ($product['stock_quantity'] > 0): ?>
|
||||||
<?= nl2br(htmlspecialchars($product['description'] ?? 'Описание отсутствует')) ?>
|
<div class="product__purchase">
|
||||||
</p>
|
<div class="product__quantity">
|
||||||
|
<button class="product__qty-btn minus">-</button>
|
||||||
<?php if ($product['stock_quantity'] > 0): ?>
|
<input type="number" class="product__qty-value" value="1" min="1" max="<?= $product['stock_quantity'] ?>">
|
||||||
<div class="product__purchase">
|
<button class="product__qty-btn plus">+</button>
|
||||||
<div class="product__quantity">
|
</div>
|
||||||
<button class="product__qty-btn minus">-</button>
|
|
||||||
<input type="number" class="product__qty-value" value="1" min="1" max="<?= $product['stock_quantity'] ?>">
|
<div class="product__actions">
|
||||||
<button class="product__qty-btn plus">+</button>
|
<button class="btn primary-btn" onclick="addToCart(<?= $product['product_id'] ?>)">
|
||||||
</div>
|
<i class="fas fa-shopping-cart"></i> В корзину
|
||||||
|
</button>
|
||||||
<div class="product__actions">
|
<button class="btn secondary-btn" onclick="buyNow(<?= $product['product_id'] ?>)">
|
||||||
<button class="btn primary-btn" onclick="addToCart(<?= $product['product_id'] ?>)">
|
<i class="fas fa-bolt"></i> Купить сейчас
|
||||||
<i class="fas fa-shopping-cart"></i> В корзину
|
</button>
|
||||||
</button>
|
</div>
|
||||||
<button class="btn secondary-btn" onclick="buyNow(<?= $product['product_id'] ?>)">
|
</div>
|
||||||
<i class="fas fa-bolt"></i> Купить сейчас
|
<?php else: ?>
|
||||||
</button>
|
<div class="product__actions">
|
||||||
</div>
|
<button class="btn secondary-btn" onclick="notifyWhenAvailable(<?= $product['product_id'] ?>)">
|
||||||
</div>
|
<i class="fas fa-bell"></i> Уведомить о поступлении
|
||||||
<?php else: ?>
|
</button>
|
||||||
<div class="product__actions">
|
</div>
|
||||||
<button class="btn secondary-btn" onclick="notifyWhenAvailable(<?= $product['product_id'] ?>)">
|
<?php endif; ?>
|
||||||
<i class="fas fa-bell"></i> Уведомить о поступлении
|
|
||||||
</button>
|
<?php if (isset($_SESSION['isAdmin']) && $_SESSION['isAdmin']): ?>
|
||||||
</div>
|
<div class="admin-actions" style="margin-top: 20px;">
|
||||||
<?php endif; ?>
|
<a href="admin_panel.php?action=edit&id=<?= $product['product_id'] ?>"
|
||||||
|
class="btn btn-warning">
|
||||||
<?php if (isset($_SESSION['isAdmin']) && $_SESSION['isAdmin']): ?>
|
<i class="fas fa-edit"></i> Редактировать
|
||||||
<div class="admin-actions" style="margin-top: 20px;">
|
</a>
|
||||||
<a href="admin_panel.php?action=edit&id=<?= $product['product_id'] ?>"
|
<button onclick="deleteProduct(<?= $product['product_id'] ?>)"
|
||||||
class="btn btn-warning">
|
class="btn btn-danger">
|
||||||
<i class="fas fa-edit"></i> Редактировать
|
<i class="fas fa-trash"></i> Удалить
|
||||||
</a>
|
</button>
|
||||||
<button onclick="deleteProduct(<?= $product['product_id'] ?>)"
|
</div>
|
||||||
class="btn btn-danger">
|
<?php endif; ?>
|
||||||
<i class="fas fa-trash"></i> Удалить
|
</div>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
<?php if (!empty($similarProducts)): ?>
|
||||||
</div>
|
<section class="similar-products">
|
||||||
</div>
|
<h2>Похожие товары</h2>
|
||||||
|
<div class="products-grid">
|
||||||
<?php if (!empty($similarProducts)): ?>
|
<?php foreach ($similarProducts as $similar): ?>
|
||||||
<section class="similar-products">
|
<div class="product-card">
|
||||||
<h2>Похожие товары</h2>
|
<div class="product-image">
|
||||||
<div class="products-grid">
|
<img src="<?= htmlspecialchars($similar['image_url'] ?? 'img2/default.jpg') ?>"
|
||||||
<?php foreach ($similarProducts as $similar): ?>
|
alt="<?= htmlspecialchars($similar['name']) ?>">
|
||||||
<div class="product-card">
|
</div>
|
||||||
<div class="product-image">
|
<div class="product-info">
|
||||||
<img src="<?= htmlspecialchars($similar['image_url'] ?? 'img2/default.jpg') ?>"
|
<h3><?= htmlspecialchars($similar['name']) ?></h3>
|
||||||
alt="<?= htmlspecialchars($similar['name']) ?>">
|
<p class="product-price">
|
||||||
</div>
|
<?= number_format($similar['price'], 0, '', ' ') ?> ₽
|
||||||
<div class="product-info">
|
</p>
|
||||||
<h3><?= htmlspecialchars($similar['name']) ?></h3>
|
<a href="product_page.php?id=<?= $similar['product_id'] ?>"
|
||||||
<p class="product-price">
|
class="btn btn-primary">
|
||||||
<?= number_format($similar['price'], 0, '', ' ') ?> ₽
|
Подробнее
|
||||||
</p>
|
</a>
|
||||||
<a href="product_page.php?id=<?= $similar['product_id'] ?>"
|
</div>
|
||||||
class="btn btn-primary">
|
</div>
|
||||||
Подробнее
|
<?php endforeach; ?>
|
||||||
</a>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</div>
|
<?php endif; ?>
|
||||||
<?php endforeach; ?>
|
</main>
|
||||||
</div>
|
|
||||||
</section>
|
<footer class="footer" id="footer">
|
||||||
<?php endif; ?>
|
<div class="container footer__content">
|
||||||
</main>
|
<div class="footer__col footer--logo">
|
||||||
|
<div class="logo">AETERNA</div>
|
||||||
<footer class="footer" id="footer">
|
</div>
|
||||||
<div class="container footer__content">
|
|
||||||
<div class="footer__col footer--logo">
|
<div class="footer__col">
|
||||||
<div class="logo">AETERNA</div>
|
<h5>ПОКУПАТЕЛЮ</h5>
|
||||||
</div>
|
<ul>
|
||||||
|
<li><a href="/catalog.php">Каталог</a></li>
|
||||||
<div class="footer__col">
|
<li><a href="services.php">Услуги</a></li>
|
||||||
<h5>ПОКУПАТЕЛЮ</h5>
|
</ul>
|
||||||
<ul>
|
</div>
|
||||||
<li><a href="/catalog.php">Каталог</a></li>
|
|
||||||
<li><a href="services.php">Услуги</a></li>
|
<div class="footer__col">
|
||||||
</ul>
|
<h5>ПОМОЩЬ</h5>
|
||||||
</div>
|
<ul>
|
||||||
|
<li><a href="delivery.php">Доставка и оплата</a></li>
|
||||||
<div class="footer__col">
|
<li><a href="warranty.php">Гарантия и возврат</a></li>
|
||||||
<h5>ПОМОЩЬ</h5>
|
<li><a href="cite_mebel.php#faq">Ответы на вопросы</a></li>
|
||||||
<ul>
|
<li><a href="#footer">Контакты</a></li>
|
||||||
<li><a href="delivery.php">Доставка и оплата</a></li>
|
</ul>
|
||||||
<li><a href="warranty.php">Гарантия и возврат</a></li>
|
</div>
|
||||||
<li><a href="cite_mebel.php#faq">Ответы на вопросы</a></li>
|
|
||||||
<li><a href="#footer">Контакты</a></li>
|
<div class="footer__col">
|
||||||
</ul>
|
<h5>КОНТАКТЫ</h5>
|
||||||
</div>
|
<p>aeterna@mail.ru</p>
|
||||||
|
<p>+7(912)999-12-23</p>
|
||||||
<div class="footer__col">
|
<div class="social-icons">
|
||||||
<h5>КОНТАКТЫ</h5>
|
<span class="icon"><i class="fab fa-telegram"></i></span>
|
||||||
<p>aeterna@mail.ru</p>
|
<span class="icon"><i class="fab fa-instagram"></i></span>
|
||||||
<p>+7(912)999-12-23</p>
|
<span class="icon"><i class="fab fa-vk"></i></span>
|
||||||
<div class="social-icons">
|
</div>
|
||||||
<span class="icon"><i class="fab fa-telegram"></i></span>
|
</div>
|
||||||
<span class="icon"><i class="fab fa-instagram"></i></span>
|
|
||||||
<span class="icon"><i class="fab fa-vk"></i></span>
|
<div class="footer__col">
|
||||||
</div>
|
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
|
||||||
</div>
|
<div class="payment-icons">
|
||||||
|
<span class="pay-icon"><i class="fab fa-cc-visa"></i></span>
|
||||||
<div class="footer__col">
|
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
|
||||||
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
|
</div>
|
||||||
<div class="payment-icons">
|
</div>
|
||||||
<span class="pay-icon"><i class="fab fa-cc-visa"></i></span>
|
</div>
|
||||||
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
|
<div class="copyright">
|
||||||
</div>
|
<p>© 2025 AETERNA. Все права защищены.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
<div class="copyright">
|
|
||||||
<p>© 2025 AETERNA. Все права защищены.</p>
|
<script>
|
||||||
</div>
|
$(document).ready(function() {
|
||||||
</footer>
|
|
||||||
|
$('.product__qty-btn.plus').click(function() {
|
||||||
<script>
|
const $input = $('.product__qty-value');
|
||||||
$(document).ready(function() {
|
let value = parseInt($input.val());
|
||||||
// Управление количеством
|
let max = parseInt($input.attr('max'));
|
||||||
$('.product__qty-btn.plus').click(function() {
|
if (value < max) {
|
||||||
const $input = $('.product__qty-value');
|
$input.val(value + 1);
|
||||||
let value = parseInt($input.val());
|
}
|
||||||
let max = parseInt($input.attr('max'));
|
});
|
||||||
if (value < max) {
|
|
||||||
$input.val(value + 1);
|
$('.product__qty-btn.minus').click(function() {
|
||||||
}
|
const $input = $('.product__qty-value');
|
||||||
});
|
let value = parseInt($input.val());
|
||||||
|
if (value > 1) {
|
||||||
$('.product__qty-btn.minus').click(function() {
|
$input.val(value - 1);
|
||||||
const $input = $('.product__qty-value');
|
}
|
||||||
let value = parseInt($input.val());
|
});
|
||||||
if (value > 1) {
|
|
||||||
$input.val(value - 1);
|
window.addToCart = function(productId) {
|
||||||
}
|
const quantity = $('.product__qty-value').val();
|
||||||
});
|
|
||||||
|
$.ajax({
|
||||||
// Добавление в корзину
|
url: 'add_to_cart.php',
|
||||||
window.addToCart = function(productId) {
|
method: 'POST',
|
||||||
const quantity = $('.product__qty-value').val();
|
data: {
|
||||||
|
product_id: productId,
|
||||||
$.ajax({
|
quantity: quantity
|
||||||
url: 'add_to_cart.php',
|
},
|
||||||
method: 'POST',
|
success: function(response) {
|
||||||
data: {
|
try {
|
||||||
product_id: productId,
|
const result = JSON.parse(response);
|
||||||
quantity: quantity
|
if (result.success) {
|
||||||
},
|
alert('Товар добавлен в корзину!');
|
||||||
success: function(response) {
|
|
||||||
try {
|
$('.cart-count').text(result.cart_count);
|
||||||
const result = JSON.parse(response);
|
} else {
|
||||||
if (result.success) {
|
alert('Ошибка: ' + result.message);
|
||||||
alert('Товар добавлен в корзину!');
|
}
|
||||||
// Обновляем счетчик в шапке
|
} catch(e) {
|
||||||
$('.cart-count').text(result.cart_count);
|
alert('Товар добавлен в корзину!');
|
||||||
} else {
|
}
|
||||||
alert('Ошибка: ' + result.message);
|
}
|
||||||
}
|
});
|
||||||
} catch(e) {
|
};
|
||||||
alert('Товар добавлен в корзину!');
|
|
||||||
}
|
window.buyNow = function(productId) {
|
||||||
}
|
const quantity = $('.product__qty-value').val();
|
||||||
});
|
|
||||||
};
|
$.ajax({
|
||||||
|
url: 'add_to_cart.php',
|
||||||
// Покупка сейчас
|
method: 'POST',
|
||||||
window.buyNow = function(productId) {
|
data: {
|
||||||
const quantity = $('.product__qty-value').val();
|
product_id: productId,
|
||||||
|
quantity: quantity
|
||||||
$.ajax({
|
},
|
||||||
url: 'add_to_cart.php',
|
success: function() {
|
||||||
method: 'POST',
|
window.location.href = 'checkout.php';
|
||||||
data: {
|
}
|
||||||
product_id: productId,
|
});
|
||||||
quantity: quantity
|
};
|
||||||
},
|
|
||||||
success: function() {
|
window.notifyWhenAvailable = function(productId) {
|
||||||
window.location.href = 'checkout.php';
|
const email = prompt('Введите ваш email для уведомления:');
|
||||||
}
|
if (email) {
|
||||||
});
|
$.ajax({
|
||||||
};
|
url: 'notify_available.php',
|
||||||
|
method: 'POST',
|
||||||
// Уведомление о поступлении
|
data: {
|
||||||
window.notifyWhenAvailable = function(productId) {
|
product_id: productId,
|
||||||
const email = prompt('Введите ваш email для уведомления:');
|
email: email
|
||||||
if (email) {
|
},
|
||||||
$.ajax({
|
success: function(response) {
|
||||||
url: 'notify_available.php',
|
alert('Вы будете уведомлены о поступлении товара!');
|
||||||
method: 'POST',
|
}
|
||||||
data: {
|
});
|
||||||
product_id: productId,
|
}
|
||||||
email: email
|
};
|
||||||
},
|
|
||||||
success: function(response) {
|
window.deleteProduct = function(productId) {
|
||||||
alert('Вы будете уведомлены о поступлении товара!');
|
if (confirm('Вы уверены, что хотите удалить этот товар?')) {
|
||||||
}
|
$.ajax({
|
||||||
});
|
url: 'catalog_admin_action.php',
|
||||||
}
|
method: 'POST',
|
||||||
};
|
data: {
|
||||||
|
action: 'delete',
|
||||||
// Удаление товара (админ)
|
product_id: productId
|
||||||
window.deleteProduct = function(productId) {
|
},
|
||||||
if (confirm('Вы уверены, что хотите удалить этот товар?')) {
|
success: function() {
|
||||||
$.ajax({
|
window.location.href = 'catalog.php';
|
||||||
url: 'catalog_admin_action.php',
|
}
|
||||||
method: 'POST',
|
});
|
||||||
data: {
|
}
|
||||||
action: 'delete',
|
};
|
||||||
product_id: productId
|
});
|
||||||
},
|
</script>
|
||||||
success: function() {
|
</body>
|
||||||
window.location.href = 'catalog.php';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
1517
public/register.php
1517
public/register.php
File diff suppressed because it is too large
Load Diff
@@ -1,113 +1,112 @@
|
|||||||
<?php
|
<?php
|
||||||
// В начале файла
|
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>AETERNA - Услуги</title>
|
<title>AETERNA - Услуги</title>
|
||||||
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
|
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/less"></script>
|
<script src="https://cdn.jsdelivr.net/npm/less"></script>
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||||
<script src="check_auth.js"></script>
|
<script src="check_auth.js"></script>
|
||||||
<style>
|
<style>
|
||||||
/* Стили для блокировки доступа */
|
|
||||||
.link-disabled {
|
.link-disabled {
|
||||||
cursor: not-allowed !important;
|
cursor: not-allowed !important;
|
||||||
opacity: 0.7 !important;
|
opacity: 0.7 !important;
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-required {
|
.auth-required {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-required::after {
|
.auth-required::after {
|
||||||
content: "🔒";
|
content: "🔒";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -5px;
|
top: -5px;
|
||||||
right: -10px;
|
right: -10px;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<?php include 'header_common.php'; ?>
|
<?php include 'header_common.php'; ?>
|
||||||
|
|
||||||
|
<main>
|
||||||
<main>
|
<section class="services-section">
|
||||||
<section class="services-section">
|
<div class="container services__wrapper">
|
||||||
<div class="container services__wrapper">
|
<div class="services__top-row">
|
||||||
<div class="services__top-row">
|
<div class="service-card service-card--green">
|
||||||
<div class="service-card service-card--green">
|
<h3 class="service-card__title">ДОСТАВКА</h3>
|
||||||
<h3 class="service-card__title">ДОСТАВКА</h3>
|
<p class="service-card__text">Стоимость доставки зависит от таких факторов, как: вес, адрес, удаленность от города, дата</p>
|
||||||
<p class="service-card__text">Стоимость доставки зависит от таких факторов, как: вес, адрес, удаленность от города, дата</p>
|
</div>
|
||||||
</div>
|
<div class="service-card service-card--green">
|
||||||
<div class="service-card service-card--green">
|
<h3 class="service-card__title">СБОРКА</h3>
|
||||||
<h3 class="service-card__title">СБОРКА</h3>
|
<p class="service-card__text">Стоимость сборки рассчитывается индивидуально, так как на цену влияет несколько факторов</p>
|
||||||
<p class="service-card__text">Стоимость сборки рассчитывается индивидуально, так как на цену влияет несколько факторов</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="service-card service-card--beige">
|
||||||
<div class="service-card service-card--beige">
|
<h3 class="service-card__title">ДИЗАЙН‑ПРОЕКТ</h3>
|
||||||
<h3 class="service-card__title">ДИЗАЙН‑ПРОЕКТ</h3>
|
<p class="service-card__text">Предоставляем услугу по составлению дизайн‑проекта. Учитываем индивидуальные пожелания каждого клиента. Работаем с интерьерами различной сложности.</p>
|
||||||
<p class="service-card__text">Предоставляем услугу по составлению дизайн‑проекта. Учитываем индивидуальные пожелания каждого клиента. Работаем с интерьерами различной сложности.</p>
|
<div class="image-placeholder"></div>
|
||||||
<div class="image-placeholder"></div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</section>
|
</main>
|
||||||
</main>
|
|
||||||
|
<footer class="footer" id="footer">
|
||||||
<footer class="footer" id="footer">
|
<div class="container footer__content">
|
||||||
<div class="container footer__content">
|
<div class="footer__col footer--logo">
|
||||||
<div class="footer__col footer--logo">
|
<div class="logo">AETERNA</div>
|
||||||
<div class="logo">AETERNA</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="footer__col">
|
||||||
<div class="footer__col">
|
<h5>ПОКУПАТЕЛЮ</h5>
|
||||||
<h5>ПОКУПАТЕЛЮ</h5>
|
<ul>
|
||||||
<ul>
|
<li><a href="/catalog.php">Каталог</a></li>
|
||||||
<li><a href="/catalog.php">Каталог</a></li>
|
<li><a href="услуги.html">Услуги</a></li>
|
||||||
<li><a href="услуги.html">Услуги</a></li>
|
</ul>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="footer__col">
|
||||||
<div class="footer__col">
|
<h5>ПОМОЩЬ</h5>
|
||||||
<h5>ПОМОЩЬ</h5>
|
<ul>
|
||||||
<ul>
|
<li><a href="Доставка.html">Доставка и оплата</a></li>
|
||||||
<li><a href="Доставка.html">Доставка и оплата</a></li>
|
<li><a href="Гарантия.html">Гарантия и возврат</a></li>
|
||||||
<li><a href="Гарантия.html">Гарантия и возврат</a></li>
|
<li><a href="cite_mebel.html#faq">Ответы на вопросы</a></li>
|
||||||
<li><a href="cite_mebel.html#faq">Ответы на вопросы</a></li>
|
<li><a href="#footer">Контакты</a></li>
|
||||||
<li><a href="#footer">Контакты</a></li>
|
</ul>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="footer__col">
|
||||||
<div class="footer__col">
|
<h5>КОНТАКТЫ</h5>
|
||||||
<h5>КОНТАКТЫ</h5>
|
<p>aeterna@mail.ru</p>
|
||||||
<p>aeterna@mail.ru</p>
|
<p>+7(912)999-12-23</p>
|
||||||
<p>+7(912)999-12-23</p>
|
<div class="social-icons">
|
||||||
<div class="social-icons">
|
<span class="icon"><i class="fab fa-telegram"></i></span>
|
||||||
<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-instagram"></i></span>
|
<span class="icon"><i class="fab fa-vk"></i></span>
|
||||||
<span class="icon"><i class="fab fa-vk"></i></span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="footer__col">
|
||||||
<div class="footer__col">
|
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
|
||||||
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
|
<div class="payment-icons">
|
||||||
<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-visa"></i></span>
|
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
|
||||||
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="copyright">
|
||||||
<div class="copyright">
|
<p>© 2025 AETERNA. Все права защищены.</p>
|
||||||
<p>© 2025 AETERNA. Все права защищены.</p>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
|
||||||
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
@@ -1,206 +1,205 @@
|
|||||||
<?php
|
<?php
|
||||||
// В начале файла
|
|
||||||
require_once __DIR__ . '/../config/database.php';
|
require_once __DIR__ . '/../config/database.php';
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>AETERNA - Гарантия</title>
|
<title>AETERNA - Гарантия</title>
|
||||||
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
|
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/less"></script>
|
<script src="https://cdn.jsdelivr.net/npm/less"></script>
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||||||
<script src="check_auth.js"></script>
|
<script src="check_auth.js"></script>
|
||||||
<style>
|
<style>
|
||||||
/* Стили для блокировки доступа */
|
|
||||||
.link-disabled {
|
.link-disabled {
|
||||||
cursor: not-allowed !important;
|
cursor: not-allowed !important;
|
||||||
opacity: 0.7 !important;
|
opacity: 0.7 !important;
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-required {
|
.auth-required {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-required::after {
|
.auth-required::after {
|
||||||
content: "🔒";
|
content: "🔒";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -5px;
|
top: -5px;
|
||||||
right: -10px;
|
right: -10px;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<?php include 'header_common.php'; ?>
|
<?php include 'header_common.php'; ?>
|
||||||
|
|
||||||
|
<main class="catalog-main">
|
||||||
<main class="catalog-main">
|
<div class="container">
|
||||||
<div class="container">
|
<div class="breadcrumbs">
|
||||||
<div class="breadcrumbs">
|
<a href="cite_mebel.php">Главная</a> • <span class="current-page">Гарантия</span>
|
||||||
<a href="cite_mebel.php">Главная</a> • <span class="current-page">Гарантия</span>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="warranty-content">
|
||||||
<div class="warranty-content">
|
<h1>ГАРАНТИЙНЫЕ ОБЯЗАТЕЛЬСТВА</h1>
|
||||||
<h1>ГАРАНТИЙНЫЕ ОБЯЗАТЕЛЬСТВА</h1>
|
|
||||||
|
<div class="warranty-overview">
|
||||||
<div class="warranty-overview">
|
<div class="warranty-card">
|
||||||
<div class="warranty-card">
|
<div class="warranty-icon">
|
||||||
<div class="warranty-icon">
|
<i class="fas fa-couch"></i>
|
||||||
<i class="fas fa-couch"></i>
|
</div>
|
||||||
</div>
|
<h3>Мягкая мебель</h3>
|
||||||
<h3>Мягкая мебель</h3>
|
<div class="warranty-period">18 месяцев</div>
|
||||||
<div class="warranty-period">18 месяцев</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="warranty-card">
|
||||||
<div class="warranty-card">
|
<div class="warranty-icon">
|
||||||
<div class="warranty-icon">
|
<i class="fas fa-archive"></i>
|
||||||
<i class="fas fa-archive"></i>
|
</div>
|
||||||
</div>
|
<h3>Корпусная мебель</h3>
|
||||||
<h3>Корпусная мебель</h3>
|
<div class="warranty-period">24 месяца</div>
|
||||||
<div class="warranty-period">24 месяца</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="warranty-card">
|
||||||
<div class="warranty-card">
|
<div class="warranty-icon">
|
||||||
<div class="warranty-icon">
|
<i class="fas fa-lightbulb"></i>
|
||||||
<i class="fas fa-lightbulb"></i>
|
</div>
|
||||||
</div>
|
<h3>Элементы освещения</h3>
|
||||||
<h3>Элементы освещения</h3>
|
<div class="warranty-period">12 месяцев</div>
|
||||||
<div class="warranty-period">12 месяцев</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="warranty-card">
|
||||||
<div class="warranty-card">
|
<div class="warranty-icon">
|
||||||
<div class="warranty-icon">
|
<i class="fas fa-cogs"></i>
|
||||||
<i class="fas fa-cogs"></i>
|
</div>
|
||||||
</div>
|
<h3>Фурнитура и механизмы</h3>
|
||||||
<h3>Фурнитура и механизмы</h3>
|
<div class="warranty-period">36 месяцев</div>
|
||||||
<div class="warranty-period">36 месяцев</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="coverage-section">
|
||||||
<div class="coverage-section">
|
<div class="coverage-covered">
|
||||||
<div class="coverage-covered">
|
<h2>Что покрывается гарантией</h2>
|
||||||
<h2>Что покрывается гарантией</h2>
|
<div class="coverage-list">
|
||||||
<div class="coverage-list">
|
<div class="coverage-item covered">
|
||||||
<div class="coverage-item covered">
|
<i class="fas fa-check-circle"></i>
|
||||||
<i class="fas fa-check-circle"></i>
|
<div class="coverage-text">
|
||||||
<div class="coverage-text">
|
<h4>Производственные дефекты</h4>
|
||||||
<h4>Производственные дефекты</h4>
|
<p>Трещины, сколы, брак материалов</p>
|
||||||
<p>Трещины, сколы, брак материалов</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="coverage-item covered">
|
||||||
<div class="coverage-item covered">
|
<i class="fas fa-check-circle"></i>
|
||||||
<i class="fas fa-check-circle"></i>
|
<div class="coverage-text">
|
||||||
<div class="coverage-text">
|
<h4>Неисправности механизмов</h4>
|
||||||
<h4>Неисправности механизмов</h4>
|
<p>Трансформации, выдвижные системы</p>
|
||||||
<p>Трансформации, выдвижные системы</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="coverage-item covered">
|
||||||
<div class="coverage-item covered">
|
<i class="fas fa-check-circle"></i>
|
||||||
<i class="fas fa-check-circle"></i>
|
<div class="coverage-text">
|
||||||
<div class="coverage-text">
|
<h4>Проблемы с фурнитурой</h4>
|
||||||
<h4>Проблемы с фурнитурой</h4>
|
<p>Ручки, петли, направляющие</p>
|
||||||
<p>Ручки, петли, направляющие</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="coverage-item covered">
|
||||||
<div class="coverage-item covered">
|
<i class="fas fa-check-circle"></i>
|
||||||
<i class="fas fa-check-circle"></i>
|
<div class="coverage-text">
|
||||||
<div class="coverage-text">
|
<h4>Дефекты покрытия</h4>
|
||||||
<h4>Дефекты покрытия</h4>
|
<p>Отслоение шпона, краски, ламинации</p>
|
||||||
<p>Отслоение шпона, краски, ламинации</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="coverage-not-covered">
|
||||||
<div class="coverage-not-covered">
|
<h2>Что не покрывается гарантией</h2>
|
||||||
<h2>Что не покрывается гарантией</h2>
|
<div class="coverage-list">
|
||||||
<div class="coverage-list">
|
<div class="coverage-item not-covered">
|
||||||
<div class="coverage-item not-covered">
|
<i class="fas fa-times-circle"></i>
|
||||||
<i class="fas fa-times-circle"></i>
|
<div class="coverage-text">
|
||||||
<div class="coverage-text">
|
<h4>Механические повреждения</h4>
|
||||||
<h4>Механические повреждения</h4>
|
<p>Царапины, вмятины от неправильной эксплуатации</p>
|
||||||
<p>Царапины, вмятины от неправильной эксплуатации</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="coverage-item not-covered">
|
||||||
<div class="coverage-item not-covered">
|
<i class="fas fa-times-circle"></i>
|
||||||
<i class="fas fa-times-circle"></i>
|
<div class="coverage-text">
|
||||||
<div class="coverage-text">
|
<h4>Следы износа</h4>
|
||||||
<h4>Следы износа</h4>
|
<p>Естественное старение материалов</p>
|
||||||
<p>Естественное старение материалов</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="coverage-item not-covered">
|
||||||
<div class="coverage-item not-covered">
|
<i class="fas fa-times-circle"></i>
|
||||||
<i class="fas fa-times-circle"></i>
|
<div class="coverage-text">
|
||||||
<div class="coverage-text">
|
<h4>Неправильная сборка</h4>
|
||||||
<h4>Неправильная сборка</h4>
|
<p>Последствия самостоятельного ремонта</p>
|
||||||
<p>Последствия самостоятельного ремонта</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="coverage-item not-covered">
|
||||||
<div class="coverage-item not-covered">
|
<i class="fas fa-times-circle"></i>
|
||||||
<i class="fas fa-times-circle"></i>
|
<div class="coverage-text">
|
||||||
<div class="coverage-text">
|
<h4>Внешние воздействия</h4>
|
||||||
<h4>Внешние воздействия</h4>
|
<p>Повреждения от жидкостей, солнечных лучей</p>
|
||||||
<p>Повреждения от жидкостей, солнечных лучей</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
|
||||||
|
<footer class="footer" id="footer">
|
||||||
<footer class="footer" id="footer">
|
<div class="container footer__content">
|
||||||
<div class="container footer__content">
|
<div class="footer__col footer--logo">
|
||||||
<div class="footer__col footer--logo">
|
<div class="logo">AETERNA</div>
|
||||||
<div class="logo">AETERNA</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="footer__col">
|
||||||
<div class="footer__col">
|
<h5>ПОКУПАТЕЛЮ</h5>
|
||||||
<h5>ПОКУПАТЕЛЮ</h5>
|
<ul>
|
||||||
<ul>
|
<li><a href="/catalog.php">Каталог</a></li>
|
||||||
<li><a href="/catalog.php">Каталог</a></li>
|
<li><a href="services.php">Услуги</a></li>
|
||||||
<li><a href="services.php">Услуги</a></li>
|
</ul>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="footer__col">
|
||||||
<div class="footer__col">
|
<h5>ПОМОЩЬ</h5>
|
||||||
<h5>ПОМОЩЬ</h5>
|
<ul>
|
||||||
<ul>
|
<li><a href="delivery.php">Доставка и оплата</a></li>
|
||||||
<li><a href="delivery.php">Доставка и оплата</a></li>
|
<li><a href="warranty.php">Гарантия и возврат</a></li>
|
||||||
<li><a href="warranty.php">Гарантия и возврат</a></li>
|
<li><a href="cite_mebel.php#faq">Ответы на вопросы</a></li>
|
||||||
<li><a href="cite_mebel.php#faq">Ответы на вопросы</a></li>
|
<li><a href="#footer">Контакты</a></li>
|
||||||
<li><a href="#footer">Контакты</a></li>
|
</ul>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="footer__col">
|
||||||
<div class="footer__col">
|
<h5>КОНТАКТЫ</h5>
|
||||||
<h5>КОНТАКТЫ</h5>
|
<p>aeterna@mail.ru</p>
|
||||||
<p>aeterna@mail.ru</p>
|
<p>+7(912)999-12-23</p>
|
||||||
<p>+7(912)999-12-23</p>
|
<div class="social-icons">
|
||||||
<div class="social-icons">
|
<span class="icon"><i class="fab fa-telegram"></i></span>
|
||||||
<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-instagram"></i></span>
|
<span class="icon"><i class="fab fa-vk"></i></span>
|
||||||
<span class="icon"><i class="fab fa-vk"></i></span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="footer__col">
|
||||||
<div class="footer__col">
|
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
|
||||||
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
|
<div class="payment-icons">
|
||||||
<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-visa"></i></span>
|
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
|
||||||
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="copyright">
|
||||||
<div class="copyright">
|
<p>© 2025 AETERNA. Все права защищены.</p>
|
||||||
<p>© 2025 AETERNA. Все права защищены.</p>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
|
||||||
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
@@ -1,142 +1,137 @@
|
|||||||
.error-message {
|
.error-message {
|
||||||
color: #ff0000;
|
color: #ff0000;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__input.error {
|
.form__input.error {
|
||||||
border-color: #ff0000;
|
border-color: #ff0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__group {
|
.form__group {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Стили для сообщений внизу страницы */
|
.page-messages {
|
||||||
.page-messages {
|
position: fixed;
|
||||||
position: fixed;
|
bottom: 20px;
|
||||||
bottom: 20px;
|
left: 50%;
|
||||||
left: 50%;
|
transform: translateX(-50%);
|
||||||
transform: translateX(-50%);
|
z-index: 1000;
|
||||||
z-index: 1000;
|
width: 90%;
|
||||||
width: 90%;
|
max-width: 500px;
|
||||||
max-width: 500px;
|
}
|
||||||
}
|
|
||||||
|
.message {
|
||||||
.message {
|
padding: 15px;
|
||||||
padding: 15px;
|
margin: 10px 0;
|
||||||
margin: 10px 0;
|
border-radius: 5px;
|
||||||
border-radius: 5px;
|
text-align: center;
|
||||||
text-align: center;
|
font-weight: bold;
|
||||||
font-weight: bold;
|
display: none;
|
||||||
display: none;
|
}
|
||||||
}
|
|
||||||
|
.message.error {
|
||||||
.message.error {
|
background-color: #ffebee;
|
||||||
background-color: #ffebee;
|
color: #c62828;
|
||||||
color: #c62828;
|
border: 1px solid #ffcdd2;
|
||||||
border: 1px solid #ffcdd2;
|
}
|
||||||
}
|
|
||||||
|
.message.success {
|
||||||
.message.success {
|
background-color: #e8f5e9;
|
||||||
background-color: #e8f5e9;
|
color: #453227;
|
||||||
color: #453227;
|
border: 1px solid #c8e6c9;
|
||||||
border: 1px solid #c8e6c9;
|
}
|
||||||
}
|
|
||||||
|
.message.warning {
|
||||||
.message.warning {
|
background-color: #fff3e0;
|
||||||
background-color: #fff3e0;
|
color: #ef6c00;
|
||||||
color: #ef6c00;
|
border: 1px solid #ffe0b2;
|
||||||
border: 1px solid #ffe0b2;
|
}
|
||||||
}
|
|
||||||
|
.privacy-error {
|
||||||
.privacy-error {
|
color: #ff0000;
|
||||||
color: #ff0000;
|
font-size: 12px;
|
||||||
font-size: 12px;
|
margin-top: 5px;
|
||||||
margin-top: 5px;
|
display: none;
|
||||||
display: none;
|
text-align: center;
|
||||||
text-align: center;
|
}
|
||||||
}
|
|
||||||
|
.input-group {
|
||||||
/* Дополнительные стили для формы регистрации */
|
position: relative;
|
||||||
.input-group {
|
margin-bottom: 20px;
|
||||||
position: relative;
|
}
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
.profile-form input.error {
|
||||||
|
border-color: #ff0000;
|
||||||
.profile-form input.error {
|
background-color: #fff5f5;
|
||||||
border-color: #ff0000;
|
}
|
||||||
background-color: #fff5f5;
|
|
||||||
}
|
.privacy-checkbox {
|
||||||
|
margin: 20px 0;
|
||||||
.privacy-checkbox {
|
text-align: center;
|
||||||
margin: 20px 0;
|
}
|
||||||
text-align: center;
|
|
||||||
}
|
.privacy-checkbox label {
|
||||||
|
display: flex;
|
||||||
.privacy-checkbox label {
|
align-items: center;
|
||||||
display: flex;
|
justify-content: center;
|
||||||
align-items: center;
|
gap: 8px;
|
||||||
justify-content: center;
|
cursor: pointer;
|
||||||
gap: 8px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
}
|
||||||
font-size: 14px;
|
|
||||||
}
|
.privacy-checkbox input[type="checkbox"] {
|
||||||
|
margin: 0;
|
||||||
.privacy-checkbox input[type="checkbox"] {
|
}
|
||||||
margin: 0;
|
|
||||||
}
|
.profile-page-main {
|
||||||
|
padding: 40px 0;
|
||||||
/* Исправление отступов для страницы регистрации */
|
min-height: calc(100vh - 200px);
|
||||||
.profile-page-main {
|
}
|
||||||
padding: 40px 0;
|
|
||||||
min-height: calc(100vh - 200px);
|
.profile-container {
|
||||||
}
|
margin: 0 auto;
|
||||||
|
position: relative;
|
||||||
/* Убедимся, что контейнер не перекрывает шапку и футер */
|
z-index: 1;
|
||||||
.profile-container {
|
}
|
||||||
margin: 0 auto;
|
|
||||||
position: relative;
|
.input-hint {
|
||||||
z-index: 1;
|
font-size: 12px;
|
||||||
}
|
color: #666;
|
||||||
|
margin-top: 5px;
|
||||||
.input-hint {
|
}
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
.form-options {
|
||||||
margin-top: 5px;
|
display: flex;
|
||||||
}
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
/* Стили для страницы входа */
|
margin: 20px 0;
|
||||||
.form-options {
|
}
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
.remember-me {
|
||||||
align-items: center;
|
display: flex;
|
||||||
margin: 20px 0;
|
align-items: center;
|
||||||
}
|
gap: 8px;
|
||||||
|
font-size: 14px;
|
||||||
.remember-me {
|
color: #453227;
|
||||||
display: flex;
|
}
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
.remember-me input[type="checkbox"] {
|
||||||
font-size: 14px;
|
width: 16px;
|
||||||
color: #453227;
|
height: 16px;
|
||||||
}
|
cursor: pointer;
|
||||||
|
}
|
||||||
.remember-me input[type="checkbox"] {
|
|
||||||
width: 16px;
|
.forgot-password {
|
||||||
height: 16px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
color: #453227;
|
||||||
}
|
text-decoration: underline;
|
||||||
|
}
|
||||||
.forgot-password {
|
|
||||||
font-size: 14px;
|
.forgot-password:hover {
|
||||||
color: #453227;
|
color: #617365;
|
||||||
text-decoration: underline;
|
text-decoration: none;
|
||||||
}
|
|
||||||
|
|
||||||
.forgot-password:hover {
|
|
||||||
color: #617365;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
@@ -1,142 +1,137 @@
|
|||||||
.error-message {
|
.error-message {
|
||||||
color: #ff0000;
|
color: #ff0000;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__input.error {
|
.form__input.error {
|
||||||
border-color: #ff0000;
|
border-color: #ff0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form__group {
|
.form__group {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Стили для сообщений внизу страницы */
|
.page-messages {
|
||||||
.page-messages {
|
position: fixed;
|
||||||
position: fixed;
|
bottom: 20px;
|
||||||
bottom: 20px;
|
left: 50%;
|
||||||
left: 50%;
|
transform: translateX(-50%);
|
||||||
transform: translateX(-50%);
|
z-index: 1000;
|
||||||
z-index: 1000;
|
width: 90%;
|
||||||
width: 90%;
|
max-width: 500px;
|
||||||
max-width: 500px;
|
}
|
||||||
}
|
|
||||||
|
.message {
|
||||||
.message {
|
padding: 15px;
|
||||||
padding: 15px;
|
margin: 10px 0;
|
||||||
margin: 10px 0;
|
border-radius: 5px;
|
||||||
border-radius: 5px;
|
text-align: center;
|
||||||
text-align: center;
|
font-weight: bold;
|
||||||
font-weight: bold;
|
display: none;
|
||||||
display: none;
|
}
|
||||||
}
|
|
||||||
|
.message.error {
|
||||||
.message.error {
|
background-color: #ffebee;
|
||||||
background-color: #ffebee;
|
color: #c62828;
|
||||||
color: #c62828;
|
border: 1px solid #ffcdd2;
|
||||||
border: 1px solid #ffcdd2;
|
}
|
||||||
}
|
|
||||||
|
.message.success {
|
||||||
.message.success {
|
background-color: #e8f5e9;
|
||||||
background-color: #e8f5e9;
|
color: #453227;
|
||||||
color: #453227;
|
border: 1px solid #c8e6c9;
|
||||||
border: 1px solid #c8e6c9;
|
}
|
||||||
}
|
|
||||||
|
.message.warning {
|
||||||
.message.warning {
|
background-color: #fff3e0;
|
||||||
background-color: #fff3e0;
|
color: #ef6c00;
|
||||||
color: #ef6c00;
|
border: 1px solid #ffe0b2;
|
||||||
border: 1px solid #ffe0b2;
|
}
|
||||||
}
|
|
||||||
|
.privacy-error {
|
||||||
.privacy-error {
|
color: #ff0000;
|
||||||
color: #ff0000;
|
font-size: 12px;
|
||||||
font-size: 12px;
|
margin-top: 5px;
|
||||||
margin-top: 5px;
|
display: none;
|
||||||
display: none;
|
text-align: center;
|
||||||
text-align: center;
|
}
|
||||||
}
|
|
||||||
|
.input-group {
|
||||||
/* Дополнительные стили для формы регистрации */
|
position: relative;
|
||||||
.input-group {
|
margin-bottom: 20px;
|
||||||
position: relative;
|
}
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
.profile-form input.error {
|
||||||
|
border-color: #ff0000;
|
||||||
.profile-form input.error {
|
background-color: #fff5f5;
|
||||||
border-color: #ff0000;
|
}
|
||||||
background-color: #fff5f5;
|
|
||||||
}
|
.privacy-checkbox {
|
||||||
|
margin: 20px 0;
|
||||||
.privacy-checkbox {
|
text-align: center;
|
||||||
margin: 20px 0;
|
}
|
||||||
text-align: center;
|
|
||||||
}
|
.privacy-checkbox label {
|
||||||
|
display: flex;
|
||||||
.privacy-checkbox label {
|
align-items: center;
|
||||||
display: flex;
|
justify-content: center;
|
||||||
align-items: center;
|
gap: 8px;
|
||||||
justify-content: center;
|
cursor: pointer;
|
||||||
gap: 8px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
}
|
||||||
font-size: 14px;
|
|
||||||
}
|
.privacy-checkbox input[type="checkbox"] {
|
||||||
|
margin: 0;
|
||||||
.privacy-checkbox input[type="checkbox"] {
|
}
|
||||||
margin: 0;
|
|
||||||
}
|
.profile-page-main {
|
||||||
|
padding: 40px 0;
|
||||||
/* Исправление отступов для страницы регистрации */
|
min-height: calc(100vh - 200px);
|
||||||
.profile-page-main {
|
}
|
||||||
padding: 40px 0;
|
|
||||||
min-height: calc(100vh - 200px);
|
.profile-container {
|
||||||
}
|
margin: 0 auto;
|
||||||
|
position: relative;
|
||||||
/* Убедимся, что контейнер не перекрывает шапку и футер */
|
z-index: 1;
|
||||||
.profile-container {
|
}
|
||||||
margin: 0 auto;
|
|
||||||
position: relative;
|
.input-hint {
|
||||||
z-index: 1;
|
font-size: 12px;
|
||||||
}
|
color: #666;
|
||||||
|
margin-top: 5px;
|
||||||
.input-hint {
|
}
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
.form-options {
|
||||||
margin-top: 5px;
|
display: flex;
|
||||||
}
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
/* Стили для страницы входа */
|
margin: 20px 0;
|
||||||
.form-options {
|
}
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
.remember-me {
|
||||||
align-items: center;
|
display: flex;
|
||||||
margin: 20px 0;
|
align-items: center;
|
||||||
}
|
gap: 8px;
|
||||||
|
font-size: 14px;
|
||||||
.remember-me {
|
color: #453227;
|
||||||
display: flex;
|
}
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
.remember-me input[type="checkbox"] {
|
||||||
font-size: 14px;
|
width: 16px;
|
||||||
color: #453227;
|
height: 16px;
|
||||||
}
|
cursor: pointer;
|
||||||
|
}
|
||||||
.remember-me input[type="checkbox"] {
|
|
||||||
width: 16px;
|
.forgot-password {
|
||||||
height: 16px;
|
font-size: 14px;
|
||||||
cursor: pointer;
|
color: #453227;
|
||||||
}
|
text-decoration: underline;
|
||||||
|
}
|
||||||
.forgot-password {
|
|
||||||
font-size: 14px;
|
.forgot-password:hover {
|
||||||
color: #453227;
|
color: #617365;
|
||||||
text-decoration: underline;
|
text-decoration: none;
|
||||||
}
|
|
||||||
|
|
||||||
.forgot-password:hover {
|
|
||||||
color: #617365;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user