407 lines
13 KiB
HTML
407 lines
13 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Вход | Rabota.Today</title>
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
}
|
||
|
||
body {
|
||
background: linear-gradient(145deg, #eef5fa 0%, #e0eaf5 100%);
|
||
min-height: 100vh;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 20px;
|
||
}
|
||
|
||
.auth-card {
|
||
max-width: 500px;
|
||
width: 100%;
|
||
background: white;
|
||
border-radius: 48px;
|
||
box-shadow: 0 40px 80px -20px rgba(0, 40, 80, 0.4);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.auth-header {
|
||
background: #0b1c34;
|
||
color: white;
|
||
padding: 40px;
|
||
text-align: center;
|
||
}
|
||
|
||
.auth-header h1 {
|
||
font-size: 32px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 15px;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.auth-header h1 i {
|
||
color: #3b82f6;
|
||
background: rgba(255,255,255,0.1);
|
||
padding: 12px;
|
||
border-radius: 20px;
|
||
}
|
||
|
||
.auth-header p {
|
||
color: #9bb8da;
|
||
}
|
||
|
||
.auth-form {
|
||
padding: 40px;
|
||
}
|
||
|
||
.tabs {
|
||
display: flex;
|
||
gap: 10px;
|
||
margin-bottom: 30px;
|
||
background: #f0f7ff;
|
||
padding: 8px;
|
||
border-radius: 60px;
|
||
}
|
||
|
||
.tab {
|
||
flex: 1;
|
||
padding: 15px;
|
||
text-align: center;
|
||
border-radius: 50px;
|
||
cursor: pointer;
|
||
font-weight: 600;
|
||
transition: 0.2s;
|
||
}
|
||
|
||
.tab.active {
|
||
background: white;
|
||
color: #0b1c34;
|
||
box-shadow: 0 4px 10px rgba(0,0,0,0.05);
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 25px;
|
||
}
|
||
|
||
.form-group label {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
color: #1f3f60;
|
||
font-weight: 600;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.form-group label i {
|
||
color: #3b82f6;
|
||
width: 20px;
|
||
}
|
||
|
||
.form-group input {
|
||
width: 100%;
|
||
padding: 16px 20px;
|
||
border: 2px solid #dee9f5;
|
||
border-radius: 30px;
|
||
font-size: 16px;
|
||
transition: 0.2s;
|
||
}
|
||
|
||
.form-group input:focus {
|
||
border-color: #3b82f6;
|
||
outline: none;
|
||
box-shadow: 0 0 0 4px rgba(59,130,246,0.15);
|
||
}
|
||
|
||
.btn-submit {
|
||
width: 100%;
|
||
background: #0f2b4f;
|
||
color: white;
|
||
border: none;
|
||
padding: 18px;
|
||
border-radius: 50px;
|
||
font-weight: 700;
|
||
font-size: 18px;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 10px;
|
||
transition: 0.2s;
|
||
}
|
||
|
||
.btn-submit:hover {
|
||
background: #1b3f6b;
|
||
}
|
||
|
||
.auth-footer {
|
||
text-align: center;
|
||
margin-top: 25px;
|
||
color: #4f7092;
|
||
}
|
||
|
||
.auth-footer a {
|
||
color: #0b1c34;
|
||
font-weight: 600;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.error-message {
|
||
background: #fee2e2;
|
||
color: #b91c1c;
|
||
padding: 12px 20px;
|
||
border-radius: 30px;
|
||
margin-bottom: 20px;
|
||
display: none;
|
||
}
|
||
|
||
.success-message {
|
||
background: #e0f2e0;
|
||
color: #166534;
|
||
padding: 12px 20px;
|
||
border-radius: 30px;
|
||
margin-bottom: 20px;
|
||
display: none;
|
||
}
|
||
|
||
.back-link {
|
||
display: inline-block;
|
||
margin-top: 20px;
|
||
color: #4f7092;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.back-link i {
|
||
margin-right: 5px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="auth-card">
|
||
<div class="auth-header">
|
||
<h1>
|
||
<i class="fas fa-briefcase"></i>
|
||
МП.Ярмарка
|
||
</h1>
|
||
<p>Вход в личный кабинет</p>
|
||
</div>
|
||
|
||
<div class="auth-form">
|
||
<div class="tabs">
|
||
<div class="tab active" onclick="switchTab('login')">Вход</div>
|
||
<div class="tab" onclick="switchTab('register')">Регистрация</div>
|
||
</div>
|
||
|
||
<div id="errorMessage" class="error-message"></div>
|
||
<div id="successMessage" class="success-message"></div>
|
||
|
||
<!-- Форма входа -->
|
||
<form id="loginForm" onsubmit="handleLogin(event)">
|
||
<div class="form-group">
|
||
<label><i class="fas fa-envelope"></i> Email</label>
|
||
<input type="email" id="loginEmail" placeholder="ivan@example.com" required>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label><i class="fas fa-lock"></i> Пароль</label>
|
||
<input type="password" id="loginPassword" placeholder="Введите пароль" required>
|
||
</div>
|
||
|
||
<button type="submit" class="btn-submit">
|
||
<i class="fas fa-sign-in-alt"></i> Войти
|
||
</button>
|
||
</form>
|
||
|
||
<!-- Форма регистрации (скрыта по умолчанию) -->
|
||
<form id="registerForm" style="display: none;" onsubmit="handleRegister(event)">
|
||
<div class="form-group">
|
||
<label><i class="fas fa-user"></i> ФИО</label>
|
||
<input type="text" id="regFullName" placeholder="Иванов Иван Иванович" required>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label><i class="fas fa-envelope"></i> Email</label>
|
||
<input type="email" id="regEmail" placeholder="ivan@example.com" required>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label><i class="fas fa-phone"></i> Телефон</label>
|
||
<input type="tel" id="regPhone" placeholder="+7 999 123 45 67" required>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label><i class="fab fa-telegram"></i> Telegram (опционально)</label>
|
||
<input type="text" id="regTelegram" placeholder="@username">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label><i class="fas fa-lock"></i> Пароль</label>
|
||
<input type="password" id="regPassword" placeholder="Минимум 6 символов" required>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label><i class="fas fa-user-tag"></i> Я</label>
|
||
<select id="regRole" style="width: 100%; padding: 16px 20px; border: 2px solid #dee9f5; border-radius: 30px;">
|
||
<option value="employee">Соискатель</option>
|
||
<option value="employer">Работодатель</option>
|
||
</select>
|
||
</div>
|
||
|
||
<button type="submit" class="btn-submit">
|
||
<i class="fas fa-check-circle"></i> Зарегистрироваться
|
||
</button>
|
||
</form>
|
||
|
||
<div class="auth-footer">
|
||
<a href="/" class="back-link"><i class="fas fa-arrow-left"></i> На главную</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
const API_BASE_URL = 'http://localhost:8000/api';
|
||
|
||
function switchTab(tab) {
|
||
const tabs = document.querySelectorAll('.tab');
|
||
const loginForm = document.getElementById('loginForm');
|
||
const registerForm = document.getElementById('registerForm');
|
||
|
||
tabs.forEach(t => t.classList.remove('active'));
|
||
|
||
if (tab === 'login') {
|
||
tabs[0].classList.add('active');
|
||
loginForm.style.display = 'block';
|
||
registerForm.style.display = 'none';
|
||
} else {
|
||
tabs[1].classList.add('active');
|
||
loginForm.style.display = 'none';
|
||
registerForm.style.display = 'block';
|
||
}
|
||
}
|
||
|
||
function showError(message) {
|
||
const errorEl = document.getElementById('errorMessage');
|
||
errorEl.textContent = message;
|
||
errorEl.style.display = 'block';
|
||
setTimeout(() => {
|
||
errorEl.style.display = 'none';
|
||
}, 5000);
|
||
}
|
||
|
||
function showSuccess(message) {
|
||
const successEl = document.getElementById('successMessage');
|
||
successEl.textContent = message;
|
||
successEl.style.display = 'block';
|
||
setTimeout(() => {
|
||
successEl.style.display = 'none';
|
||
}, 3000);
|
||
}
|
||
|
||
async function handleLogin(event) {
|
||
event.preventDefault();
|
||
|
||
const email = document.getElementById('loginEmail').value;
|
||
const password = document.getElementById('loginPassword').value;
|
||
|
||
try {
|
||
const response = await fetch(`${API_BASE_URL}/login`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({ email, password })
|
||
});
|
||
|
||
const data = await response.json();
|
||
|
||
if (!response.ok) {
|
||
throw new Error(data.detail || 'Ошибка входа');
|
||
}
|
||
|
||
// Сохраняем токен
|
||
localStorage.setItem('accessToken', data.access_token);
|
||
localStorage.setItem('userId', data.user_id);
|
||
localStorage.setItem('userRole', data.role);
|
||
localStorage.setItem('userName', data.full_name);
|
||
|
||
showSuccess('Вход выполнен успешно!');
|
||
|
||
// Перенаправляем в зависимости от роли
|
||
setTimeout(() => {
|
||
if (data.role === 'employer') {
|
||
window.location.href = '/profile';
|
||
} else {
|
||
window.location.href = '/profile';
|
||
}
|
||
}, 1000);
|
||
|
||
} catch (error) {
|
||
showError(error.message);
|
||
}
|
||
}
|
||
|
||
async function handleRegister(event) {
|
||
event.preventDefault();
|
||
|
||
const userData = {
|
||
full_name: document.getElementById('regFullName').value,
|
||
email: document.getElementById('regEmail').value,
|
||
phone: document.getElementById('regPhone').value,
|
||
telegram: document.getElementById('regTelegram').value || null,
|
||
password: document.getElementById('regPassword').value,
|
||
role: document.getElementById('regRole').value
|
||
};
|
||
|
||
// Валидация
|
||
if (userData.password.length < 6) {
|
||
showError('Пароль должен быть не менее 6 символов');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`${API_BASE_URL}/register`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify(userData)
|
||
});
|
||
|
||
const data = await response.json();
|
||
|
||
if (!response.ok) {
|
||
throw new Error(data.detail || 'Ошибка регистрации');
|
||
}
|
||
|
||
// Сохраняем токен
|
||
localStorage.setItem('accessToken', data.access_token);
|
||
localStorage.setItem('userId', data.user_id);
|
||
localStorage.setItem('userRole', data.role);
|
||
localStorage.setItem('userName', data.full_name);
|
||
|
||
showSuccess('Регистрация успешна!');
|
||
|
||
// Перенаправляем в профиль
|
||
setTimeout(() => {
|
||
window.location.href = '/profile';
|
||
}, 1000);
|
||
|
||
} catch (error) {
|
||
showError(error.message);
|
||
}
|
||
}
|
||
|
||
// Проверяем, может пользователь уже залогинен
|
||
if (localStorage.getItem('accessToken')) {
|
||
window.location.href = '/profile';
|
||
}
|
||
</script>
|
||
</body>
|
||
</html> |