1031 lines
26 KiB
Vue
1031 lines
26 KiB
Vue
<template>
|
||
<div class="register-container">
|
||
<div class="auth-bg">
|
||
<div class="brand-logo">
|
||
<span class="logo-letter">R</span>
|
||
<span class="logo-letter">E</span>
|
||
<span class="logo-letter">F</span>
|
||
<span class="logo-letter">L</span>
|
||
<span class="logo-letter">E</span>
|
||
<span class="logo-letter">X</span>
|
||
</div>
|
||
|
||
<div class="register-card">
|
||
<div class="register-header">
|
||
<h2>Создать аккаунт</h2>
|
||
<p>Начните свой путь к новым знакомствам</p>
|
||
</div>
|
||
|
||
<form @submit.prevent="handleRegister" class="register-form">
|
||
<div class="form-group">
|
||
<label for="name">
|
||
<i class="bi-person"></i>
|
||
Имя
|
||
</label>
|
||
<input
|
||
type="text"
|
||
id="name"
|
||
v-model="name"
|
||
placeholder="Введите ваше имя"
|
||
required
|
||
:disabled="loading"
|
||
/>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="email">
|
||
<i class="bi-envelope"></i>
|
||
Email
|
||
</label>
|
||
<input
|
||
type="email"
|
||
id="email"
|
||
v-model="email"
|
||
placeholder="Введите ваш email"
|
||
required
|
||
:disabled="loading"
|
||
/>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="birthdate">
|
||
<i class="bi-calendar"></i>
|
||
Дата рождения
|
||
</label>
|
||
<div class="date-input-container">
|
||
<input
|
||
type="date"
|
||
id="birthdate"
|
||
v-model="birthdate"
|
||
required
|
||
:disabled="loading"
|
||
:max="maxDate"
|
||
class="date-input"
|
||
ref="birthdateInput"
|
||
@click="openDatePicker"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="city">
|
||
<i class="bi-geo-alt"></i>
|
||
Город
|
||
</label>
|
||
<div class="select-wrapper">
|
||
<input
|
||
type="text"
|
||
class="form-input"
|
||
id="city"
|
||
v-model="citySearchQuery"
|
||
placeholder="Начните вводить название города..."
|
||
@focus="showCityList = true"
|
||
@input="onCitySearch"
|
||
required
|
||
:disabled="loading"
|
||
/>
|
||
<button
|
||
type="button"
|
||
class="clear-btn"
|
||
@click="clearCitySelection"
|
||
v-if="city"
|
||
:disabled="loading"
|
||
>
|
||
<i class="bi-x"></i>
|
||
</button>
|
||
<div class="dropdown" v-if="showCityList && filteredCities.length > 0">
|
||
<div
|
||
v-for="cityItem in filteredCities"
|
||
:key="cityItem"
|
||
class="dropdown-option"
|
||
@click="selectCity(cityItem)"
|
||
>
|
||
{{ cityItem }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="password">
|
||
<i class="bi-shield-lock"></i>
|
||
Пароль
|
||
</label>
|
||
<input
|
||
type="password"
|
||
id="password"
|
||
v-model="password"
|
||
placeholder="Создайте надежный пароль"
|
||
required
|
||
:disabled="loading"
|
||
/>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="confirmPassword">
|
||
<i class="bi-shield-check"></i>
|
||
Подтверждение пароля
|
||
</label>
|
||
<input
|
||
type="password"
|
||
id="confirmPassword"
|
||
v-model="confirmPassword"
|
||
placeholder="Повторите пароль"
|
||
required
|
||
:disabled="loading"
|
||
/>
|
||
</div>
|
||
|
||
<div v-if="errorMessage" class="error-message">
|
||
<i class="bi-exclamation-circle"></i>
|
||
{{ errorMessage }}
|
||
</div>
|
||
|
||
<button type="submit" class="action-button" :disabled="loading">
|
||
<span v-if="loading" class="spinner"></span>
|
||
<span v-else class="btn-text">Зарегистрироваться</span>
|
||
</button>
|
||
|
||
<div class="auth-footer">
|
||
<p>
|
||
Уже есть аккаунт?
|
||
<router-link to="/login" class="auth-link">Войти</router-link>
|
||
</p>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<router-link to="/" class="back-link">
|
||
<i class="bi-arrow-left"></i>
|
||
Вернуться
|
||
</router-link>
|
||
|
||
<div class="wave-container">
|
||
<div class="wave"></div>
|
||
<div class="wave"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
||
import { useAuth } from '@/auth';
|
||
import russianCities from '@/assets/russian-cities.json';
|
||
|
||
// Слова для базовой проверки на клиентской стороне
|
||
// (меньше, чем в полной библиотеке на сервере, но достаточно для основных случаев)
|
||
const badWords = [
|
||
'блядь', 'хуй', 'пизда', 'ебать', 'ебал', 'ебло', 'хуесос', 'пидор', 'пидорас',
|
||
'мудак', 'говно', 'залупа', 'хер', 'шлюха', 'соска', 'шалава', 'дебил', 'дрочить',
|
||
'сука', 'гандон', 'гондон'
|
||
];
|
||
|
||
// Функция для проверки на нецензурную лексику (упрощенная версия, основная проверка на сервере)
|
||
const hasProfanity = (text) => {
|
||
if (!text) return false;
|
||
|
||
const normalizedText = text.toLowerCase()
|
||
.replace(/[\s\._\-]+/g, '') // Удаляем пробелы, точки, подчеркивания, дефисы
|
||
.replace(/[еёo]/g, 'е') // Приводим похожие символы к общему виду
|
||
.replace(/[аa]/g, 'а')
|
||
.replace(/[оo0]/g, 'о');
|
||
|
||
// Проверяем на запрещенные слова
|
||
return badWords.some(word => normalizedText.includes(word.toLowerCase()));
|
||
};
|
||
|
||
const name = ref('');
|
||
const email = ref('');
|
||
const birthdate = ref('');
|
||
const city = ref('');
|
||
const password = ref('');
|
||
const confirmPassword = ref('');
|
||
const errorMessage = ref('');
|
||
const loading = ref(false);
|
||
const birthdateInput = ref(null);
|
||
const cities = ref([]);
|
||
const citySearchQuery = ref('');
|
||
const showCityList = ref(false);
|
||
const filteredCities = ref([]);
|
||
|
||
// Функция для открытия календаря при клике на поле
|
||
const openDatePicker = () => {
|
||
if (birthdateInput.value && typeof birthdateInput.value.showPicker === 'function') {
|
||
birthdateInput.value.showPicker();
|
||
}
|
||
};
|
||
|
||
// Вычисляем максимальную дату (минимальный возраст 14 лет)
|
||
const maxDate = computed(() => {
|
||
const date = new Date();
|
||
date.setFullYear(date.getFullYear() - 14);
|
||
return date.toISOString().split('T')[0];
|
||
});
|
||
|
||
const { register } = useAuth();
|
||
|
||
// Функция для блокировки прокрутки страницы
|
||
const preventScroll = () => {
|
||
document.body.style.overflow = 'hidden';
|
||
document.body.style.position = 'fixed';
|
||
document.body.style.height = '100%';
|
||
document.body.style.width = '100%';
|
||
};
|
||
|
||
// Функция для восстановления прокрутки
|
||
const enableScroll = () => {
|
||
document.body.style.overflow = '';
|
||
document.body.style.position = '';
|
||
document.body.style.height = '';
|
||
document.body.style.width = '';
|
||
};
|
||
|
||
onMounted(() => {
|
||
preventScroll(); // Блокируем прокрутку при монтировании компонента
|
||
|
||
// Сортируем города по алфавиту
|
||
cities.value = russianCities.sort((a, b) => {
|
||
if (a.name < b.name) return -1;
|
||
if (a.name > b.name) return 1;
|
||
return 0;
|
||
});
|
||
});
|
||
|
||
onUnmounted(() => {
|
||
enableScroll(); // Восстанавливаем прокрутку при размонтировании компонента
|
||
});
|
||
|
||
const handleRegister = async () => {
|
||
errorMessage.value = '';
|
||
loading.value = true;
|
||
|
||
// Простая валидация на клиенте
|
||
if (!name.value || !email.value || !birthdate.value || !city.value || !password.value || !confirmPassword.value) {
|
||
errorMessage.value = 'Пожалуйста, заполните все обязательные поля.';
|
||
loading.value = false;
|
||
return;
|
||
}
|
||
if (password.value !== confirmPassword.value) {
|
||
errorMessage.value = 'Пароли не совпадают.';
|
||
loading.value = false;
|
||
return;
|
||
}
|
||
if (password.value.length < 6) {
|
||
errorMessage.value = 'Пароль должен быть не менее 6 символов.';
|
||
loading.value = false;
|
||
return;
|
||
}
|
||
|
||
// Проверяем возраст (минимум 14 лет)
|
||
const birthDate = new Date(birthdate.value);
|
||
const today = new Date();
|
||
let age = today.getFullYear() - birthDate.getFullYear();
|
||
const monthDiff = today.getMonth() - birthDate.getMonth();
|
||
|
||
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
|
||
age--;
|
||
}
|
||
|
||
if (age < 14) {
|
||
errorMessage.value = 'Вам должно быть не менее 14 лет для регистрации.';
|
||
loading.value = false;
|
||
return;
|
||
}
|
||
|
||
// Проверка имени на запрещенные слова
|
||
if (hasProfanity(name.value)) {
|
||
errorMessage.value = 'Имя содержит запрещенные слова или выражения. Пожалуйста, используйте другое имя.';
|
||
loading.value = false;
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const userData = {
|
||
name: name.value,
|
||
email: email.value,
|
||
dateOfBirth: birthdate.value, // Изменено с birthdate на dateOfBirth для соответствия бэкенду
|
||
city: city.value, // Добавлено поле города
|
||
password: password.value
|
||
};
|
||
|
||
// Для отладки
|
||
console.log('Отправка данных регистрации:', { ...userData, password: '****' });
|
||
|
||
await register(userData);
|
||
} catch (error) {
|
||
errorMessage.value = error.message || 'Произошла неизвестная ошибка при регистрации.';
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
const onCitySearch = () => {
|
||
if (!citySearchQuery.value) {
|
||
filteredCities.value = [];
|
||
return;
|
||
}
|
||
|
||
const query = citySearchQuery.value.toLowerCase();
|
||
filteredCities.value = cities.value
|
||
.map(cityItem => cityItem.name) // Получаем только названия городов
|
||
.filter(cityName => cityName.toLowerCase().includes(query)) // Фильтруем по запросу
|
||
.slice(0, 10); // Ограничиваем количество результатов
|
||
};
|
||
|
||
const selectCity = (cityName) => {
|
||
city.value = cityName;
|
||
citySearchQuery.value = cityName; // Устанавливаем значение в поле ввода
|
||
showCityList.value = false; // Скрываем список городов
|
||
};
|
||
|
||
const clearCitySelection = () => {
|
||
city.value = '';
|
||
citySearchQuery.value = '';
|
||
filteredCities.value = [];
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.register-container {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
overflow: hidden;
|
||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||
touch-action: none;
|
||
color: white; /* Явно задаем белый цвет текста для всего контейнера */
|
||
}
|
||
|
||
.auth-bg {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.brand-logo {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 2rem;
|
||
font-weight: 800;
|
||
letter-spacing: 1px;
|
||
margin-bottom: 1rem;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.logo-letter {
|
||
display: inline-block;
|
||
animation: gradientShift 8s infinite;
|
||
background: linear-gradient(45deg, #ffffff, #00bfff, #9932cc, #ff4500);
|
||
background-size: 300% 300%;
|
||
-webkit-background-clip: text;
|
||
background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
text-shadow:
|
||
-1px -1px 0 rgba(255, 255, 255, 0.3),
|
||
1px -1px 0 rgba(255, 255, 255, 0.3),
|
||
-1px 1px 0 rgba(255, 255, 255, 0.3),
|
||
1px 1px 0 rgba(255, 255, 255, 0.3),
|
||
0 0 8px rgba(255, 255, 255, 0.5);
|
||
}
|
||
|
||
.logo-letter:nth-child(1) { animation-delay: 0s; }
|
||
.logo-letter:nth-child(2) { animation-delay: 0.25s; }
|
||
.logo-letter:nth-child(3) { animation-delay: 0.5s; }
|
||
.logo-letter:nth-child(4) { animation-delay: 0.75s; }
|
||
.logo-letter:nth-child(5) { animation-delay: 1s; }
|
||
.logo-letter:nth-child(6) { animation-delay: 1.25s; }
|
||
|
||
@keyframes gradientShift {
|
||
0% { background-position: 0% 50%; }
|
||
50% { background-position: 100% 50%; }
|
||
100% { background-position: 0% 50%; }
|
||
}
|
||
|
||
.register-card {
|
||
width: 90%;
|
||
max-width: 400px;
|
||
background: rgba(255, 255, 255, 0.1);
|
||
backdrop-filter: blur(10px);
|
||
border-radius: 20px;
|
||
padding: 1.5rem;
|
||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
|
||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||
text-align: center;
|
||
position: relative;
|
||
z-index: 10;
|
||
margin: 0 auto;
|
||
display: flex;
|
||
flex-direction: column;
|
||
color: white; /* Явно задаем белый цвет текста */
|
||
max-height: 90vh;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.register-header {
|
||
margin-bottom: 1rem;
|
||
color: white; /* Явно задаем белый цвет текста для заголовка */
|
||
}
|
||
|
||
.register-header h2 {
|
||
font-size: 1.8rem;
|
||
margin-bottom: 0.3rem;
|
||
color: white; /* Явно задаем белый цвет текста для h2 */
|
||
font-weight: 600;
|
||
}
|
||
|
||
.register-header p {
|
||
font-size: 1rem;
|
||
color: rgba(255, 255, 255, 0.9); /* Полупрозрачный белый для подзаголовка */
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
|
||
.register-form {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 0.8rem;
|
||
position: relative;
|
||
text-align: left; /* Выравниваем текст полей формы по левому краю */
|
||
}
|
||
|
||
.form-group label {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
margin-bottom: 0.4rem;
|
||
color: white;
|
||
font-weight: 500;
|
||
font-size: 1rem;
|
||
}
|
||
|
||
.form-group label i {
|
||
font-size: 1.1rem;
|
||
}
|
||
|
||
.form-group input {
|
||
width: 100%;
|
||
padding: 0.9rem 1rem;
|
||
background: rgba(255, 255, 255, 0.15);
|
||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||
border-radius: 12px;
|
||
color: white;
|
||
font-size: 1rem;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
/* Стили для поля даты */
|
||
.date-input {
|
||
color-scheme: dark; /* Темная тема для календаря */
|
||
}
|
||
|
||
.date-input::-webkit-calendar-picker-indicator {
|
||
filter: invert(1); /* Инвертируем цвет иконки календаря для темной темы */
|
||
}
|
||
|
||
.form-group input::placeholder {
|
||
color: rgba(255, 255, 255, 0.6);
|
||
}
|
||
|
||
.form-group input:focus {
|
||
outline: none;
|
||
background: rgba(255, 255, 255, 0.25);
|
||
border-color: rgba(255, 255, 255, 0.5);
|
||
box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.1);
|
||
}
|
||
|
||
.select-wrapper {
|
||
position: relative;
|
||
width: 100%;
|
||
}
|
||
|
||
.select-wrapper input {
|
||
width: 100%;
|
||
padding: 0.9rem 1rem;
|
||
background: rgba(255, 255, 255, 0.15);
|
||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||
border-radius: 12px;
|
||
color: white;
|
||
font-size: 1rem;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.clear-btn {
|
||
position: absolute;
|
||
top: 50%;
|
||
right: 10px;
|
||
transform: translateY(-50%);
|
||
background: transparent;
|
||
border: none;
|
||
color: rgba(255, 255, 255, 0.7);
|
||
cursor: pointer;
|
||
font-size: 1.1rem;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.clear-btn:disabled {
|
||
cursor: not-allowed;
|
||
opacity: 0.5;
|
||
}
|
||
|
||
.dropdown {
|
||
position: absolute;
|
||
top: 100%;
|
||
left: 0;
|
||
width: 100%;
|
||
background: rgba(255, 255, 255, 0.95); /* Изменение с прозрачного фона на почти непрозрачный белый */
|
||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||
border-radius: 12px;
|
||
max-height: 200px;
|
||
overflow-y: auto;
|
||
z-index: 100;
|
||
margin-top: 0.2rem;
|
||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15); /* Добавляем тень для лучшего визуального разделения */
|
||
}
|
||
|
||
.dropdown-option {
|
||
padding: 0.8rem 1rem;
|
||
cursor: pointer;
|
||
transition: background 0.3s ease;
|
||
color: #333; /* Темный цвет текста для контраста с белым фоном */
|
||
}
|
||
|
||
.dropdown-option:hover {
|
||
background: rgba(102, 126, 234, 0.1); /* Оттенок основного цвета при наведении */
|
||
}
|
||
|
||
.action-button {
|
||
width: 100%;
|
||
padding: 1rem;
|
||
margin-top: 1rem;
|
||
background: #00BFFF;
|
||
border: none;
|
||
border-radius: 50px; /* Более закругленная кнопка как на скриншоте */
|
||
color: white;
|
||
font-size: 1.1rem;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.action-button:before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: -100%;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||
transition: all 0.5s ease;
|
||
}
|
||
|
||
.action-button:hover:before {
|
||
left: 100%;
|
||
}
|
||
|
||
.action-button:hover {
|
||
transform: translateY(-3px);
|
||
box-shadow: 0 7px 15px rgba(0, 191, 255, 0.3);
|
||
}
|
||
|
||
.action-button:disabled {
|
||
opacity: 0.7;
|
||
cursor: not-allowed;
|
||
transform: none;
|
||
}
|
||
|
||
.spinner {
|
||
width: 1.4rem;
|
||
height: 1.4rem;
|
||
border: 3px solid rgba(255, 255, 255, 0.3);
|
||
border-top: 3px solid white;
|
||
border-radius: 50%;
|
||
animation: spin 1s linear infinite;
|
||
}
|
||
|
||
@keyframes spin {
|
||
from { transform: rotate(0deg); }
|
||
to { transform: rotate(360deg); }
|
||
}
|
||
|
||
.auth-footer {
|
||
margin-top: 1.5rem;
|
||
color: white;
|
||
font-size: 0.95rem;
|
||
}
|
||
|
||
.auth-link {
|
||
color: #20B2AA;
|
||
text-decoration: none;
|
||
font-weight: 600;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.auth-link:hover {
|
||
color: white;
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.error-message {
|
||
background: rgba(255, 92, 92, 0.2);
|
||
color: white;
|
||
padding: 1rem;
|
||
border-radius: 10px;
|
||
margin-top: 1rem;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
font-size: 0.95rem;
|
||
}
|
||
|
||
.error-message i {
|
||
font-size: 1.1rem;
|
||
color: #ffcccc;
|
||
}
|
||
|
||
.back-link {
|
||
position: absolute;
|
||
top: 10px;
|
||
left: 10px;
|
||
color: white;
|
||
text-decoration: none;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
font-weight: 500;
|
||
transition: all 0.3s ease;
|
||
z-index: 10;
|
||
font-size: 0.9rem;
|
||
padding: 6px 10px;
|
||
background-color: rgba(255, 255, 255, 0.1);
|
||
border-radius: 50px;
|
||
backdrop-filter: blur(5px);
|
||
}
|
||
|
||
.back-link:hover {
|
||
transform: translateX(-5px);
|
||
background-color: rgba(255, 255, 255, 0.2);
|
||
}
|
||
|
||
.wave-container {
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 150px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.wave {
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
width: 300%; /* Увеличиваем ширину для сглаживания краёв */
|
||
height: 150px;
|
||
background: url('data:image/svg+xml;utf8,<svg viewBox="0 0 1200 120" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 0v46.29c47.79 22.2 103.59 32.17 158 28 70.36-5.37 136.33-33.31 206.8-37.5 73.84-4.36 147.54 16.88 218.2 35.26 69.27 18 138.3 24.88 209.4 13.08 36.15-6 69.85-17.84 104.45-29.34C989.49 25 1113-14.29 1200 52.47V0z" opacity=".25" fill="white"/><path d="M0 0v15.81c13 21.11 27.64 41.05 47.69 56.24C99.41 111.27 165 111 224.58 91.58c31.15-10.15 60.09-26.07 89.67-39.8 40.92-19 84.73-46 130.83-49.67 36.26-2.85 70.9 9.42 98.6 31.56 31.77 25.39 62.32 62 103.63 73 40.44 10.79 81.35-6.69 119.13-24.28s75.16-39 116.92-43.05c59.73-5.85 113.28 22.88 168.9 38.84 30.2 8.66 59 6.17 87.09-7.5 22.43-10.89 48-26.93 60.65-49.24V0z" opacity=".5" fill="white"/><path d="M0 0v5.63C149.93 59 314.09 71.32 475.83 42.57c43-7.64 84.23-20.12 127.61-26.46 59-8.63 112.48 12.24 165.56 35.4C827.93 77.22 886 95.24 951.2 90c86.53-7 172.46-45.71 248.8-84.81V0z" fill="white"/></svg>') repeat-x;
|
||
background-size: 1200px 150px;
|
||
transform: translateX(0) rotate(180deg); /* Начинаем с нулевого положения */
|
||
animation: register-wave 30s cubic-bezier(0.36, 0.45, 0.63, 0.53) infinite; /* Плавная бесконечная анимация */
|
||
opacity: 0.6;
|
||
}
|
||
|
||
.wave:nth-child(2) {
|
||
bottom: 10px;
|
||
animation: register-wave 36s cubic-bezier(0.36, 0.45, 0.63, 0.53) reverse infinite;
|
||
opacity: 0.3;
|
||
}
|
||
|
||
@keyframes register-wave {
|
||
0% { transform: translateX(0) rotate(180deg); }
|
||
100% { transform: translateX(-66.66%) rotate(180deg); } /* Анимируем точно на 2/3 ширины для плавного цикла */
|
||
}
|
||
|
||
/* Адаптивность */
|
||
@media (max-width: 768px) {
|
||
.register-card {
|
||
padding: 2rem 1.5rem;
|
||
max-height: 85vh;
|
||
}
|
||
|
||
.register-header h2 {
|
||
font-size: 1.8rem;
|
||
}
|
||
|
||
.brand-logo {
|
||
font-size: 2rem;
|
||
margin-bottom: 2rem;
|
||
}
|
||
|
||
.back-link {
|
||
top: 1.5rem;
|
||
left: 1.5rem;
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.wave-container {
|
||
height: 120px;
|
||
}
|
||
|
||
.wave {
|
||
height: 120px;
|
||
background-size: 1200px 120px;
|
||
transform: rotate(180deg);
|
||
}
|
||
}
|
||
|
||
@media (max-width: 576px) {
|
||
.brand-logo {
|
||
font-size: 1.8rem;
|
||
margin-top: 2rem;
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.register-card {
|
||
width: 94%;
|
||
padding: 1.5rem 1.2rem;
|
||
margin: 0;
|
||
max-height: 80vh;
|
||
}
|
||
|
||
.register-header h2 {
|
||
font-size: 1.6rem;
|
||
}
|
||
|
||
.register-header p {
|
||
font-size: 0.9rem;
|
||
margin-bottom: 1rem;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.brand-logo {
|
||
font-size: 1.6rem;
|
||
margin-bottom: 0.8rem;
|
||
margin-top: 1.8rem;
|
||
}
|
||
|
||
.register-card {
|
||
padding: 1.3rem 1.1rem;
|
||
width: 95%;
|
||
max-height: 75vh;
|
||
}
|
||
|
||
.register-header h2 {
|
||
font-size: 1.4rem;
|
||
}
|
||
|
||
.register-header p {
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 0.7rem;
|
||
}
|
||
|
||
.form-group input {
|
||
padding: 0.7rem 0.9rem;
|
||
font-size: 0.95rem;
|
||
}
|
||
|
||
.action-button {
|
||
padding: 0.8rem;
|
||
font-size: 0.95rem;
|
||
}
|
||
}
|
||
|
||
@media (max-height: 700px) {
|
||
.brand-logo {
|
||
font-size: 1.6rem;
|
||
margin-bottom: 0.7rem;
|
||
margin-top: 0.7rem;
|
||
}
|
||
|
||
.register-header {
|
||
margin-bottom: 0.7rem;
|
||
}
|
||
|
||
.register-header h2 {
|
||
font-size: 1.5rem;
|
||
margin-bottom: 0.2rem;
|
||
}
|
||
|
||
.register-header p {
|
||
margin-bottom: 0.5rem;
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
|
||
.form-group label {
|
||
margin-bottom: 0.2rem;
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.form-group input {
|
||
padding: 0.6rem 0.8rem;
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.action-button {
|
||
padding: 0.7rem;
|
||
margin-top: 0.7rem;
|
||
font-size: 1rem;
|
||
}
|
||
|
||
.auth-footer {
|
||
margin-top: 0.7rem;
|
||
font-size: 0.9rem;
|
||
}
|
||
}
|
||
|
||
@media (max-height: 640px) {
|
||
.brand-logo {
|
||
font-size: 1.4rem;
|
||
margin-bottom: 0.5rem;
|
||
margin-top: 0.5rem;
|
||
}
|
||
|
||
.register-card {
|
||
padding: 1rem;
|
||
max-height: calc(100vh - 60px);
|
||
}
|
||
|
||
.register-header h2 {
|
||
font-size: 1.2rem;
|
||
margin-bottom: 0.1rem;
|
||
}
|
||
|
||
.register-header p {
|
||
font-size: 0.8rem;
|
||
margin-bottom: 0.3rem;
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 0.4rem;
|
||
}
|
||
|
||
.form-group label {
|
||
font-size: 0.8rem;
|
||
margin-bottom: 0.1rem;
|
||
}
|
||
|
||
.form-group input {
|
||
padding: 0.5rem 0.6rem;
|
||
font-size: 0.85rem;
|
||
}
|
||
|
||
.action-button {
|
||
padding: 0.5rem;
|
||
font-size: 0.85rem;
|
||
margin-top: 0.5rem;
|
||
}
|
||
}
|
||
|
||
@media (max-height: 570px) {
|
||
.brand-logo {
|
||
font-size: 1.2rem;
|
||
margin-bottom: 0.3rem;
|
||
margin-top: 0.3rem;
|
||
}
|
||
|
||
.register-card {
|
||
padding: 0.8rem;
|
||
max-height: calc(100vh - 40px);
|
||
}
|
||
|
||
.register-header h2 {
|
||
font-size: 1.1rem;
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.register-header p {
|
||
font-size: 0.75rem;
|
||
margin-bottom: 0.2rem;
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 0.25rem;
|
||
}
|
||
|
||
.form-group label {
|
||
font-size: 0.75rem;
|
||
}
|
||
|
||
.form-group input {
|
||
padding: 0.4rem 0.5rem;
|
||
font-size: 0.8rem;
|
||
}
|
||
|
||
.action-button {
|
||
padding: 0.4rem;
|
||
font-size: 0.8rem;
|
||
margin-top: 0.3rem;
|
||
}
|
||
|
||
.auth-footer {
|
||
font-size: 0.75rem;
|
||
margin-top: 0.3rem;
|
||
}
|
||
|
||
.wave-container {
|
||
height: 80px; /* Уменьшаем высоту волн */
|
||
}
|
||
|
||
.wave {
|
||
height: 80px;
|
||
background-size: 1200px 80px;
|
||
}
|
||
}
|
||
|
||
@media (max-height: 480px) {
|
||
.brand-logo {
|
||
font-size: 1rem;
|
||
margin-bottom: 0.2rem;
|
||
margin-top: 0.2rem;
|
||
}
|
||
|
||
.register-card {
|
||
padding: 0.6rem;
|
||
max-height: calc(100vh - 30px);
|
||
}
|
||
|
||
.register-header h2 {
|
||
font-size: 1rem;
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.register-header p {
|
||
font-size: 0.7rem;
|
||
margin-bottom: 0.2rem;
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 0.2rem;
|
||
}
|
||
|
||
.form-group label {
|
||
font-size: 0.7rem;
|
||
}
|
||
|
||
.form-group input {
|
||
padding: 0.35rem 0.4rem;
|
||
font-size: 0.75rem;
|
||
}
|
||
|
||
.action-button {
|
||
padding: 0.35rem;
|
||
font-size: 0.75rem;
|
||
margin-top: 0.2rem;
|
||
}
|
||
|
||
.auth-footer {
|
||
font-size: 0.7rem;
|
||
margin-top: 0.2rem;
|
||
}
|
||
|
||
.wave-container {
|
||
display: none; /* Скрываем волны на очень маленьких экранах */
|
||
}
|
||
}
|
||
|
||
/* Исправления Safari */
|
||
@supports (-webkit-touch-callout: none) {
|
||
.logo-letter {
|
||
background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
}
|
||
|
||
.date-input::-webkit-calendar-picker-indicator {
|
||
background-color: rgba(255, 255, 255, 0.3);
|
||
border-radius: 4px;
|
||
}
|
||
}
|
||
</style> |