.
This commit is contained in:
@@ -1,64 +1,63 @@
|
||||
.auth-page {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: calc(100vh - 160px);
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
.auth-container {
|
||||
background: white;
|
||||
padding: 40px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
width: 400px;
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
.auth-container h2 {
|
||||
margin-top: 0;
|
||||
color: #2c3e50;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.auth-btn {
|
||||
width: 100%;
|
||||
padding: 14px;
|
||||
background: #6C63FF;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.auth-switch {
|
||||
margin-top: 25px;
|
||||
text-align: center;
|
||||
color: #7f8c8d;
|
||||
}
|
||||
|
||||
.auth-switch a {
|
||||
color: #6C63FF;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: calc(100vh - 160px);
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
.auth-container {
|
||||
background: white;
|
||||
padding: 40px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
width: 400px;
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
.auth-container h2 {
|
||||
margin-top: 0;
|
||||
color: #2c3e50;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.auth-btn {
|
||||
width: 100%;
|
||||
padding: 14px;
|
||||
background: #6C63FF;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.auth-switch {
|
||||
margin-top: 25px;
|
||||
text-align: center;
|
||||
color: #7f8c8d;
|
||||
}
|
||||
|
||||
.auth-switch a {
|
||||
color: #6C63FF;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -1,78 +1,85 @@
|
||||
import React, { useState } from 'react'; // Хук состояния
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import './AuthForms.css';
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { mockFetch } from './mockFetch';
|
||||
import './AuthForms.css';
|
||||
|
||||
function Login() {
|
||||
// Состояние для хранения данных формы
|
||||
const [formData, setFormData] = useState({
|
||||
email: '',
|
||||
password: ''
|
||||
});
|
||||
|
||||
// Хук для программной навигации
|
||||
export default function Login() {
|
||||
const [formData, setFormData] = useState({ login: '', password: '' }); // Состояние для хранения данных формы
|
||||
const [error, setError] = useState(null);// для хранения сообщения об ошибке
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Обработчик изменений в полях ввода
|
||||
const handleChange = (e) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData(prev => ({
|
||||
...prev, // Сохранение предыдущих значений
|
||||
[name]: value // Динамическое обновление поля
|
||||
}));
|
||||
// Функция, которая вызывается при изменении любого поля формы, обновляет соответствующее поле в formData и сбрасывает ошибку
|
||||
const handleChange = e => {
|
||||
setFormData(prev => ({ ...prev, [e.target.name]: e.target.value }));
|
||||
setError(null);
|
||||
};
|
||||
|
||||
// Обработчик отправки формы
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault(); // Отмена стандартного поведения
|
||||
console.log('Вход:', formData); // Логирование данных (в реальном приложении - запрос к API)
|
||||
navigate('/'); // Перенаправление на главную страницу
|
||||
// Функция, которая вызывается при отправке формы
|
||||
const handleSubmit = async e => {
|
||||
e.preventDefault(); // Отменяем стандартное поведение формы (перезагрузку страницы)
|
||||
|
||||
// Отправляем данные формы через mockFetch на "адрес" /api/login методом POST
|
||||
const response = await mockFetch('/api/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }, // Указываем, что отправляем JSON
|
||||
body: JSON.stringify(formData), // Преобразуем объект с логином и паролем в JSON-строку
|
||||
});
|
||||
|
||||
|
||||
const data = await response.json(); // Получаем ответ в формате JSON
|
||||
|
||||
if (response.ok) {
|
||||
// Если ответ успешный, сохраняем токен в localStorage
|
||||
localStorage.setItem('token', data.token);
|
||||
alert('Вход успешен!');
|
||||
navigate('/');
|
||||
} else {
|
||||
|
||||
setError(data.message);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
// Основной контейнер страницы
|
||||
<div className="auth-page">
|
||||
<div className="auth-container">
|
||||
<h2>Вход</h2>
|
||||
|
||||
<div className="auth-page">
|
||||
<div className="auth-container">
|
||||
<h2>Вход</h2>
|
||||
|
||||
{error && <p style={{ color: 'red', textAlign: 'center' }}>{error}</p>}
|
||||
|
||||
{/* Форма с обработчиком отправки */}
|
||||
<form onSubmit={handleSubmit}>
|
||||
{/* Группа полей для email */}
|
||||
{/* Поле для ввода логина */}
|
||||
<div className="form-group">
|
||||
<label>Email</label>
|
||||
<label htmlFor="login">Логин</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
required // Обязательное поле
|
||||
id="login"
|
||||
name="login"
|
||||
type="text"
|
||||
value={formData.login} // Значение из состояния
|
||||
onChange={handleChange} // Обновляем состояние при изменении
|
||||
required // Поле обязательно для заполнения
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Группа полей для пароля */}
|
||||
|
||||
<div className="form-group">
|
||||
<label>Пароль</label>
|
||||
<label htmlFor="password">Пароль</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
value={formData.password}
|
||||
onChange={handleChange}
|
||||
required
|
||||
type="password"
|
||||
value={formData.password}
|
||||
onChange={handleChange}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Кнопка отправки формы */}
|
||||
<button type="submit" className="auth-btn">
|
||||
Войти
|
||||
</button>
|
||||
|
||||
<button type="submit" className="auth-btn">Войти</button>
|
||||
</form>
|
||||
|
||||
{/* Ссылка для перехода к регистрации */}
|
||||
|
||||
<div className="auth-switch">
|
||||
<span>Нет аккаунта? <a href="/register">Создать</a></span>
|
||||
Нет аккаунта? <a href="/register">Зарегистрироваться</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Login;
|
||||
|
||||
@@ -1,93 +1,96 @@
|
||||
import React, { useState } from 'react'; //для управления состоянием формы
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import './AuthForms.css';
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { mockFetch } from './mockFetch';
|
||||
import './AuthForms.css';
|
||||
|
||||
function Register() {
|
||||
// Состояние для хранения данных формы
|
||||
const [formData, setFormData] = useState({
|
||||
name: '',
|
||||
email: '',
|
||||
password: ''
|
||||
});
|
||||
|
||||
// Хук для навигации между страницами
|
||||
const navigate = useNavigate();
|
||||
export default function Register() {
|
||||
// Состояние для хранения данных формы: логин, email и пароль
|
||||
const [formData, setFormData] = useState({ login: '', email: '', password: '' });
|
||||
const [error, setError] = useState(null);
|
||||
const navigate = useNavigate(); //для программного перехода на другую страницу
|
||||
|
||||
// Обработчик изменений в полях ввода
|
||||
const handleChange = (e) => {
|
||||
const { name, value } = e.target; // Извлекаем имя поля и значение
|
||||
setFormData(prev => ({
|
||||
...prev, // Копируем предыдущее состояние
|
||||
[name]: value // Обновляем конкретное поле
|
||||
}));
|
||||
// Функция вызывается при изменении любого поля формы, обновляет соответствующее поле в formData и сбрасывает ошибку
|
||||
const handleChange = e => {
|
||||
setFormData(prev => ({ ...prev, [e.target.name]: e.target.value }));
|
||||
setError(null);
|
||||
};
|
||||
|
||||
// Обработчик отправки формы
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault(); // Отменяем стандартное поведение формы
|
||||
// Функция вызывается при отправке формы
|
||||
const handleSubmit = async e => {
|
||||
e.preventDefault(); // Отменяем перезагрузку страницы
|
||||
|
||||
// Отправляем данные формы через mockFetch на "адрес" /api/register методом POST
|
||||
const response = await mockFetch('/api/register', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }, // Заголовок, что данные в формате JSON
|
||||
body: JSON.stringify(formData), // Преобразуем объект formData в JSON-строку
|
||||
});
|
||||
|
||||
// В реальном приложении здесь будет запрос к API
|
||||
console.log('Регистрация:', formData);
|
||||
|
||||
// Перенаправляем на главную страницу
|
||||
navigate('/');
|
||||
const data = await response.json(); // для программного перехода на другую страницу
|
||||
|
||||
if (response.ok) {
|
||||
// Если регистрация успешна, показываем сообщение и переходим на страницу входа
|
||||
alert(data.message);
|
||||
navigate('/login');
|
||||
} else {
|
||||
// Если произошла ошибка, сохраняем её в состоянии для отображения
|
||||
setError(data.message);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="auth-page">
|
||||
<div className="auth-container">
|
||||
<h2>Регистрация</h2>
|
||||
|
||||
<form onSubmit={handleSubmit}> {/* Форма с обработчиком отправки */}
|
||||
{/* Группа полей для имени */}
|
||||
<div className="auth-page">
|
||||
<div className="auth-container">
|
||||
<h2>Регистрация</h2>
|
||||
|
||||
{error && <p style={{ color: 'red', textAlign: 'center' }}>{error}</p>}
|
||||
|
||||
{/* Форма с обработчиком отправки */}
|
||||
<form onSubmit={handleSubmit}>
|
||||
|
||||
<div className="form-group">
|
||||
<label>Имя</label>
|
||||
<label htmlFor="login">Логин</label>
|
||||
<input
|
||||
id="login"
|
||||
name="login"
|
||||
type="text"
|
||||
name="name"
|
||||
value={formData.name} // Привязка к состоянию
|
||||
onChange={handleChange} // Обработчик изменений
|
||||
required // Обязательное поле
|
||||
value={formData.login} // Значение из состояния
|
||||
onChange={handleChange} // Обработчик изменения
|
||||
required // Поле обязательно для заполнения
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Группа полей для email */}
|
||||
|
||||
<div className="form-group">
|
||||
<label>Email</label>
|
||||
<label htmlFor="email">Email</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Группа полей для пароля */}
|
||||
|
||||
<div className="form-group">
|
||||
<label>Пароль</label>
|
||||
<label htmlFor="password">Пароль</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
value={formData.password}
|
||||
onChange={handleChange}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Кнопка отправки формы */}
|
||||
<button type="submit" className="auth-btn">
|
||||
Зарегистрироваться
|
||||
</button>
|
||||
|
||||
<button type="submit" className="auth-btn">Зарегистрироваться</button>
|
||||
</form>
|
||||
|
||||
{/* Ссылка для перехода к авторизации */}
|
||||
|
||||
<div className="auth-switch">
|
||||
<span>Уже есть аккаунт? <a href="/login">Войти</a></span>
|
||||
Уже есть аккаунт? <a href="/login">Войти</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Register;
|
||||
|
||||
46
src/pages/mockFetch.js
Normal file
46
src/pages/mockFetch.js
Normal file
@@ -0,0 +1,46 @@
|
||||
export function mockFetch(url, options) {
|
||||
//имитируем асинхронность
|
||||
return new Promise((resolve) => {
|
||||
// задержка 500 мс, запрос "обрабатывается"
|
||||
setTimeout(() => {
|
||||
// извлекаем метод запроса,тело запроса (данные)
|
||||
const { method, body } = options;
|
||||
// если тело есть => преобразуем его из JSON-строки в объект
|
||||
const data = body ? JSON.parse(body) : null;
|
||||
|
||||
if (url === '/api/register' && method === 'POST') {
|
||||
// Возвращаем успешный ответ
|
||||
resolve({
|
||||
ok: true, // статус успешного ответа
|
||||
json: () => Promise.resolve({ message: 'Регистрация успешна' }),
|
||||
});
|
||||
|
||||
|
||||
} else if (url === '/api/login' && method === 'POST') {
|
||||
// Проверяем, совпадают ли логин и пароль
|
||||
if (data.login === '123' && data.password === '123') {
|
||||
// Если совпадают - возвращаем успешный ответ с "токеном"
|
||||
resolve({
|
||||
ok: true,
|
||||
json: () => Promise.resolve({ token: 'fake-token' }),
|
||||
});
|
||||
} else {
|
||||
// Если нет - возвращаем ошибку с сообщением
|
||||
resolve({
|
||||
ok: false,
|
||||
json: () => Promise.resolve({ message: 'Неверный логин или пароль' }),
|
||||
});
|
||||
}
|
||||
|
||||
// Если запрос на неизвестный адрес или с другим методом
|
||||
} else {
|
||||
// Возвращаем ошибку
|
||||
resolve({
|
||||
ok: false,
|
||||
json: () => Promise.resolve({ message: 'Неизвестный адрес' }),
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user