Add .gitignore and project files

This commit is contained in:
kirill.khorkov
2025-12-16 01:28:06 +03:00
parent 0541b0c020
commit 3f257120fa
140 changed files with 13360 additions and 0 deletions

778
профиль.php Normal file
View File

@@ -0,0 +1,778 @@
<?php
if (isset($_GET['quick_login'])) {
session_start();
if ($_GET['quick_login'] == 'admin') {
$_SESSION['user_id'] = 1;
$_SESSION['user_email'] = 'admin@aeterna.ru';
$_SESSION['full_name'] = 'Администратор AETERNA';
$_SESSION['isLoggedIn'] = true;
$_SESSION['isAdmin'] = true;
$_SESSION['login_time'] = time();
header('Location: catalog.php');
exit();
}
if ($_GET['quick_login'] == 'user') {
$_SESSION['user_id'] = 2;
$_SESSION['user_email'] = 'user@example.com';
$_SESSION['full_name'] = 'Тестовый Пользователь';
$_SESSION['isLoggedIn'] = true;
$_SESSION['isAdmin'] = false;
$_SESSION['login_time'] = time();
header('Location: catalog.php');
exit();
}
}
session_start();
require_once 'config/database.php';
// Проверяем, если пользователь уже авторизован - перенаправляем
if (isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true) {
header('Location: catalog.php');
exit();
}
// Получаем сообщения из сессии
$registration_errors = $_SESSION['registration_errors'] ?? [];
$old_data = $_SESSION['old_data'] ?? [];
$registration_success = $_SESSION['registration_success'] ?? '';
// Очищаем сессию от сообщений
unset($_SESSION['registration_errors']);
unset($_SESSION['old_data']);
unset($_SESSION['registration_success']);
// Обработка быстрой регистрации (для тестирования)
if (isset($_GET['quick_register'])) {
$email = $_GET['quick_register'] == 'admin' ? 'admin@aeterna.ru' : 'test@user.com';
$password = $_GET['quick_register'] == 'admin' ? 'admin123' : 'user123';
$full_name = $_GET['quick_register'] == 'admin' ? 'Администратор' : 'Тестовый Пользователь';
$phone = '+79129991223';
$city = 'Москва';
$db = Database::getInstance()->getConnection();
try {
// Проверяем, существует ли пользователь
$checkStmt = $db->prepare("SELECT user_id FROM users WHERE email = ?");
$checkStmt->execute([$email]);
if (!$checkStmt->fetch()) {
// Создаем пользователя
$password_hash = password_hash($password, PASSWORD_DEFAULT);
$is_admin = ($_GET['quick_register'] == 'admin');
$stmt = $db->prepare("
INSERT INTO users (email, password_hash, full_name, phone, city, is_admin)
VALUES (?, ?, ?, ?, ?, ?)
RETURNING user_id
");
$stmt->execute([$email, $password_hash, $full_name, $phone, $city, $is_admin]);
$user_id = $stmt->fetchColumn();
} else {
// Получаем существующего пользователя
$stmt = $db->prepare("SELECT user_id, is_admin FROM users WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch();
$user_id = $user['user_id'];
$is_admin = $user['is_admin'];
}
// Авторизуем
$_SESSION['user_id'] = $user_id;
$_SESSION['user_email'] = $email;
$_SESSION['full_name'] = $full_name;
$_SESSION['user_phone'] = $phone;
$_SESSION['user_city'] = $city;
$_SESSION['isLoggedIn'] = true;
$_SESSION['isAdmin'] = $is_admin;
$_SESSION['login_time'] = time();
header('Location: catalog.php');
exit();
} catch (Exception $e) {
$registration_errors[] = 'Ошибка быстрой регистрации: ' . $e->getMessage();
}
}
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AETERNA - Регистрация</title>
<link rel="stylesheet/less" type="text/css" href="style_for_cite.less">
<script src="https://cdn.jsdelivr.net/npm/less"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Anek+Kannada:wght@400;500;600;700&family=Anonymous+Pro:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
<style>
body {
padding-bottom: 120px;
}
.profile-page-main {
min-height: calc(100vh - 0px);
}
.registration-errors {
background: #f8d7da;
color: #721c24;
padding: 15px;
border-radius: 5px;
margin: 20px auto;
max-width: 800px;
border: 1px solid #f5c6cb;
}
.registration-errors ul {
margin: 0;
padding-left: 20px;
}
.registration-success {
background: #d4edda;
color: #155724;
padding: 15px;
border-radius: 5px;
margin: 20px auto;
max-width: 800px;
border: 1px solid #c3e6cb;
}
.quick-register-buttons {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 1000;
display: flex;
flex-direction: column;
gap: 10px;
}
.quick-btn {
background: #453227;
color: white;
border: none;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
}
.quick-btn.admin {
background: #617365;
}
.quick-btn:hover {
opacity: 0.9;
}
.form-notice {
background: #e8f4fd;
padding: 15px;
border-radius: 5px;
margin: 20px auto;
max-width: 800px;
text-align: center;
font-size: 14px;
color: #0c5460;
}
</style>
</head>
<body>
<header class="header">
<div class="header__top">
<div class="container header__top-content">
<div class="logo">AETERNA</div>
<div class="search-catalog">
<div class="catalog-dropdown">
Все категории <span>&#9660;</span>
<div class="catalog-dropdown__menu">
<ul>
<li><a href="#" onclick="checkAuth('catalog.php')">Диваны</a></li>
<li><a href="#" onclick="checkAuth('catalog.php')">Кровати</a></li>
<li><a href="#" onclick="checkAuth('catalog.php')">Шкафы</a></li>
<li><a href="#" onclick="checkAuth('catalog.php')">Стулья</a></li>
<li><a href="#" onclick="checkAuth('catalog.php')">Столы</a></li>
</ul>
</div>
</div>
<div class="search-box">
<input type="text" placeholder="Поиск товаров" disabled>
<span class="search-icon"><i class="fas fa-search"></i></span>
</div>
</div>
<div class="header__icons--top">
<a href="javascript:void(0)" onclick="checkAuth('оформлениеаказа.php')" class="icon">
<i class="fas fa-shopping-cart"></i>
</a>
<a href="вход.php" class="icon">
<i class="far fa-user"></i>
</a>
<a href="вход.php" style="font-size: 12px; color: #666; margin-left: 5px;">
Войти
</a>
</div>
</div>
</div>
<div class="header__bottom">
<div class="container header__bottom-content">
<div class="catalog-menu">
<a href="javascript:void(0)" onclick="checkAuth('catalog.php')" class="catalog-link">
<div class="catalog-icon">
<span class="line"></span>
<span class="line"></span>
<span class="line"></span>
</div>
<span class="catalog-lines">☰</span>
Каталог
</a>
</div>
<nav class="nav">
<ul class="nav-list">
<li><a href="cite_mebel.php">Главная</a></li>
<li><a href="услуги.php">Услуги</a></li>
<li><a href="Доставка.php">Доставка и оплата</a></li>
<li><a href="Гарантия.php">Гарантия</a></li>
<li><a href="#footer">Контакты</a></li>
</ul>
</nav>
<div class="header-phone">+7(912)999-12-23</div>
</div>
</div>
</header>
<main class="profile-page-main">
<?php if (!empty($registration_errors)): ?>
<div class="registration-errors">
<h4><i class="fas fa-exclamation-circle"></i> Ошибки регистрации:</h4>
<ul>
<?php foreach ($registration_errors as $error): ?>
<li><?= htmlspecialchars($error) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if (!empty($registration_success)): ?>
<div class="registration-success">
<i class="fas fa-check-circle"></i> <?= htmlspecialchars($registration_success) ?>
</div>
<?php endif; ?>
<div class="form-notice">
<i class="fas fa-info-circle"></i> Для доступа к каталогу и оформления заказов необходимо зарегистрироваться
</div>
<div class="profile-container">
<div class="profile-left-col">
<div class="logo" style="color: white;">AETERNA</div>
<div style="margin-top: 30px; color: rgba(255,255,255,0.8);">
<h3 style="margin-bottom: 15px; font-size: 18px;">Присоединяйтесь к нам</h3>
<p style="font-size: 14px; line-height: 1.5;">
Создайте аккаунт чтобы получить доступ ко всем функциям:
</p>
<ul style="margin-top: 15px; padding-left: 20px; font-size: 13px;">
<li>Доступ к каталогу товаров</li>
<li>Добавление товаров в корзину</li>
<li>Оформление заказов</li>
<li>История покупок</li>
<li>Специальные предложения</li>
</ul>
</div>
</div>
<div class="profile-right-col">
<div class="profile-form-block">
<h2>РЕГИСТРАЦИЯ</h2>
<form class="profile-form" action="register_handler.php" method="POST" id="registrationForm">
<div class="input-group">
<label for="fio">ФИО *</label>
<input type="text" id="fio" name="fio" placeholder="Введите ваше ФИО"
value="<?= htmlspecialchars($old_data['fio'] ?? '') ?>"
required
oninput="this.value = this.value.replace(/[0-9]/g, '')">
<div class="error-message" id="fio-error" style="display: none;">ФИО должно содержать минимум 2 слова (без цифр)</div>
</div>
<div class="input-group">
<label for="city">Город *</label>
<input type="text" id="city" name="city" placeholder="Укажите ваш город"
value="<?= htmlspecialchars($old_data['city'] ?? '') ?>" required>
<div class="error-message" id="city-error" style="display: none;">Укажите корректное название города</div>
</div>
<div class="input-group">
<label for="email">E-mail *</label>
<input type="email" id="email" name="email" placeholder="Ваш электронный адрес"
value="<?= htmlspecialchars($old_data['email'] ?? '') ?>" required>
<div class="error-message" id="email-error" style="display: none;">
Введите корректный email адрес (только латинские буквы перед @)
</div>
</div>
<div class="input-group">
<label for="phone">Телефон *</label>
<input type="tel" id="phone" name="phone" placeholder="+7(912)999-12-23"
value="<?= htmlspecialchars($old_data['phone'] ?? '') ?>" required>
<div class="error-message" id="phone-error" style="display: none;">Введите корректный номер телефона</div>
</div>
<div class="input-group">
<label for="password">Пароль *</label>
<input type="password" id="password" name="password" placeholder="Придумайте пароль (минимум 6 символов)" required>
<div class="error-message" id="password-error" style="display: none;">Пароль должен содержать минимум 6 символов</div>
</div>
<div class="input-group">
<label for="confirm-password">Подтвердите пароль *</label>
<input type="password" id="confirm-password" name="confirm-password" placeholder="Повторите пароль" required>
<div class="error-message" id="confirm-password-error" style="display: none;">Пароли не совпадают</div>
</div>
<div class="privacy-checkbox">
<label>
<input type="checkbox" id="privacy" name="privacy" required>
Я соглашаюсь с условиями обработки персональных данных *
</label>
<div class="privacy-error" id="privacy-error" style="display: none; color: #dc3545; font-size: 12px; margin-top: 5px;">
Необходимо согласие с условиями
</div>
</div>
<a href="вход.php" class="password-link" style="display: block; margin: 15px 0; text-align: center; color: #453227;">
Уже есть аккаунт? Войти
</a>
<button type="submit" class="btn primary-btn save-btn" id="submitBtn">
Зарегистрироваться
</button>
<div class="auth-actions">
<span class="auth-text">После регистрации вы будете перенаправлены в каталог</span>
</div>
</form>
</div>
</div>
</div>
</main>
<!-- Блок для системных сообщений -->
<div class="page-messages">
<div class="message error" id="errorMessage" style="display: none;"></div>
<div class="message success" id="successMessage" style="display: none;"></div>
<div class="message warning" id="warningMessage" style="display: none;"></div>
</div>
<footer class="footer" id="footer">
<div class="container footer__content">
<div class="footer__col footer__col--logo">
<div class="logo">AETERNA</div>
</div>
<div class="footer__col">
<h5>ПОКУПАТЕЛЮ</h5>
<ul>
<li><a href="javascript:void(0)" onclick="checkAuth('catalog.php')">Каталог</a></li>
<li><a href="услуги.php">Услуги</a></li>
</ul>
</div>
<div class="footer__col">
<h5>ПОМОЩЬ</h5>
<ul>
<li><a href="Доставка.php">Доставка и оплата</a></li>
<li><a href="Гарантия.php">Гарантия и возврат</a></li>
<li><a href="cite_mebel.php#faq">Ответы на вопросы</a></li>
<li><a href="#footer">Контакты</a></li>
</ul>
</div>
<div class="footer__col">
<h5>КОНТАКТЫ</h5>
<p>aeterna@mail.ru</p>
<p>+7(912)999-12-23</p>
<div class="social-icons">
<span class="icon"><i class="fab fa-telegram"></i></span>
<span class="icon"><i class="fab fa-instagram"></i></span>
<span class="icon"><i class="fab fa-vk"></i></span>
</div>
</div>
<div class="footer__col">
<h5>ПРИНИМАЕМ К ОПЛАТЕ</h5>
<div class="payment-icons">
<span class="pay-icon"><i class="fab fa-cc-visa"></i></span>
<span class="pay-icon"><i class="fab fa-cc-mastercard"></i></span>
</div>
</div>
</div>
<div class="copyright">
<p>© 2025 AETERNA. Все права защищены.</p>
</div>
</footer>
<!-- Кнопки для быстрой регистрации (тестирование) -->
<div class="quick-register-buttons">
<button class="quick-btn admin" onclick="window.location.href='?quick_register=admin'">
<i class="fas fa-user-shield"></i> Quick Admin
</button>
<button class="quick-btn" onclick="window.location.href='?quick_register=user'">
<i class="fas fa-user"></i> Quick User
</button>
</div>
<script>
$(document).ready(function() {
// Функции для отображения сообщений
function showMessage(type, text) {
const messageId = type + 'Message';
const $message = $('#' + messageId);
$message.text(text).fadeIn(300);
setTimeout(() => {
$message.fadeOut(300);
}, 5000);
}
// Проверка, является ли email администратора
function isAdminEmail(email) {
const adminEmails = ['admin@aeterna.ru', 'administrator@aeterna.ru', 'aeterna@mail.ru'];
return adminEmails.includes(email.toLowerCase());
}
// Валидация ФИО (без цифр, минимум 2 слова)
function validateFIO(fio) {
const words = fio.trim().split(/\s+/);
const hasNoDigits = !/\d/.test(fio);
return words.length >= 2 && words.every(word => word.length >= 2) && hasNoDigits;
}
// Валидация города
function validateCity(city) {
return city.trim().length >= 2 && /^[а-яА-ЯёЁ\s-]+$/.test(city);
}
// Валидация email
function validateEmail(email) {
const localPart = email.split('@')[0];
// Проверка на кириллические символы перед @
if (/[а-яА-ЯёЁ]/.test(localPart)) {
showError('email', 'В тексте перед знаком "@" не должно быть кириллических символов');
return false;
}
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
showError('email', 'Введите корректный email адрес');
return false;
}
hideError('email');
return true;
}
// Валидация телефона
function validatePhone(phone) {
// Очищаем от всех символов кроме цифр
const cleanPhone = phone.replace(/\D/g, '');
// Проверяем российский формат
if (cleanPhone.length === 11 && (cleanPhone.startsWith('7') || cleanPhone.startsWith('8'))) {
return true;
}
// Проверяем международный формат
if (cleanPhone.length === 12 && cleanPhone.startsWith('7')) {
return true;
}
return false;
}
// Валидация пароля
function validatePassword(password) {
return password.length >= 6;
}
// Показать/скрыть ошибку
function showError(fieldId, message) {
$('#' + fieldId).addClass('error');
$('#' + fieldId + '-error').text(message).show();
}
function hideError(fieldId) {
$('#' + fieldId).removeClass('error');
$('#' + fieldId + '-error').hide();
}
// Реальная валидация при вводе
$('input').on('blur', function() {
const fieldId = $(this).attr('id');
const value = $(this).val();
switch(fieldId) {
case 'fio':
if (!validateFIO(value)) {
if (/\d/.test(value)) {
showError(fieldId, 'ФИО не должно содержать цифры');
} else {
showError(fieldId, 'ФИО должно содержать минимум 2 слова (каждое от 2 символов)');
}
} else {
hideError(fieldId);
}
break;
case 'city':
if (!validateCity(value)) {
showError(fieldId, 'Укажите корректное название города (только русские буквы, дефисы и пробелы)');
} else {
hideError(fieldId);
}
break;
case 'email':
if (!validateEmail(value)) {
showError(fieldId, 'Введите корректный email адрес');
} else {
hideError(fieldId);
}
break;
case 'phone':
if (!validatePhone(value)) {
showError(fieldId, 'Введите корректный номер телефона (например: +7 912 999-12-23)');
} else {
hideError(fieldId);
}
break;
case 'password':
if (!validatePassword(value)) {
showError(fieldId, 'Пароль должен содержать минимум 6 символов');
} else {
hideError(fieldId);
}
break;
case 'confirm-password':
const password = $('#password').val();
if (value !== password) {
showError(fieldId, 'Пароли не совпадают');
} else {
hideError(fieldId);
}
break;
}
});
// Очистка ошибки при фокусе
$('input').on('focus', function() {
const fieldId = $(this).attr('id');
hideError(fieldId);
});
// Валидация всей формы
function validateForm() {
let isValid = true;
// Валидация ФИО
const fio = $('#fio').val();
if (!validateFIO(fio)) {
if (/\d/.test(fio)) {
showError('fio', 'ФИО не должно содержать цифры');
} else {
showError('fio', 'ФИО должно содержать минимум 2 слова (каждое от 2 символов)');
}
isValid = false;
} else {
hideError('fio');
}
// Валидация города
const city = $('#city').val();
if (!validateCity(city)) {
showError('city', 'Укажите корректное название города (только русские буквы)');
isValid = false;
} else {
hideError('city');
}
// Валидация email
const email = $('#email').val();
if (!validateEmail(email)) {
showError('email', 'Введите корректный email адрес');
isValid = false;
} else {
hideError('email');
}
// Валидация телефона
const phone = $('#phone').val();
if (!validatePhone(phone)) {
showError('phone', 'Введите номер в формате: +7(912)999-12-23');
isValid = false;
} else {
hideError('phone');
}
// Валидация пароля
const password = $('#password').val();
if (!validatePassword(password)) {
showError('password', 'Пароль должен содержать минимум 6 символов');
isValid = false;
} else {
hideError('password');
}
// Проверка совпадения паролей
const confirmPassword = $('#confirm-password').val();
if (password !== confirmPassword) {
showError('confirm-password', 'Пароли не совпадают');
isValid = false;
} else {
hideError('confirm-password');
}
// Проверка согласия с условиями
if (!$('#privacy').is(':checked')) {
$('#privacy-error').show();
isValid = false;
} else {
$('#privacy-error').hide();
}
return isValid;
}
// Обработка отправки формы
$('#registrationForm').on('submit', function(e) {
e.preventDefault();
if (validateForm()) {
// Показываем загрузку
$('#submitBtn').prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Регистрация...');
// Отправляем форму
this.submit();
} else {
showMessage('error', 'Пожалуйста, исправьте ошибки в форме');
// Прокручиваем к первой ошибке
$('html, body').animate({
scrollTop: $('.error').first().offset().top - 100
}, 500);
}
});
// Маска для телефона
$('#phone').on('input', function() {
let value = $(this).val().replace(/\D/g, '');
if (value.length > 0) {
if (!value.startsWith('7') && !value.startsWith('8')) {
value = '7' + value;
}
if (value.startsWith('8')) {
value = '7' + value.substring(1);
}
// Форматируем номер
let formatted = '+7';
if (value.length > 1) formatted += ' (' + value.substring(1, 4);
if (value.length > 4) formatted += ') ' + value.substring(4, 7);
if (value.length > 7) formatted += '-' + value.substring(7, 9);
if (value.length > 9) formatted += '-' + value.substring(9, 11);
$(this).val(formatted);
}
});
// Запрет ввода цифр в поле ФИО
$('#fio').on('input', function() {
let value = $(this).val();
// Удаляем цифры из значения
value = value.replace(/\d/g, '');
$(this).val(value);
});
// Проверка авторизации для ссылок
function checkAuth(redirectUrl) {
<?php if (isset($_SESSION['isLoggedIn']) && $_SESSION['isLoggedIn'] === true): ?>
window.location.href = redirectUrl;
<?php else: ?>
showMessage('warning', 'Требуется авторизация. Зарегистрируйтесь или войдите в систему.');
// Перенаправляем на страницу входа
setTimeout(() => {
window.location.href = 'вход.php?redirect=' + encodeURIComponent(redirectUrl);
}, 1500);
<?php endif; ?>
return false;
}
// Удаление кириллических символов из email
$('#email').on('input', function() {
let value = $(this).val();
// Если есть кириллические символы до @, заменяем их
const atIndex = value.indexOf('@');
if (atIndex > -1) {
const localPart = value.substring(0, atIndex);
const domainPart = value.substring(atIndex);
const cleanLocalPart = localPart.replace(/[а-яА-ЯёЁ]/g, '');
$(this).val(cleanLocalPart + domainPart);
}
});
// Показываем тестовые данные для демонстрации
function fillTestData(isAdmin = false) {
if (isAdmin) {
$('#fio').val('Администратор Системы');
$('#city').val('Москва');
$('#email').val('admin@aeterna.ru');
$('#phone').val('+7 (912) 999-12-23');
$('#password').val('admin123');
$('#confirm-password').val('admin123');
} else {
$('#fio').val('Иванов Иван Иванович');
$('#city').val('Санкт-Петербург');
$('#email').val('user@example.com');
$('#phone').val('+7 (911) 222-33-44');
$('#password').val('user123');
$('#confirm-password').val('user123');
}
$('#privacy').prop('checked', true);
showMessage('success', 'Тестовые данные заполнены. Теперь можно нажать "Зарегистрироваться"');
}
// Добавляем кнопки для заполнения тестовых данных
$(document).on('keydown', function(e) {
// Alt+A - заполнить данные администратора
if (e.altKey && e.key === 'a') {
e.preventDefault();
fillTestData(true);
}
// Alt+U - заполнить данные пользователя
if (e.altKey && e.key === 'u') {
e.preventDefault();
fillTestData(false);
}
});
// Информация о горячих клавишах
console.log('Горячие клавиши для тестирования:');
console.log('Alt+A - заполнить данные администратора');
console.log('Alt+U - заполнить данные пользователя');
});
</script>
</body>
</html>