444 lines
19 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import React, { useState } from "react"
import { useHistory } from "react-router-dom"
import manImage from "../assets/man.svg" // Reverted to original import
import { connect } from '../confconnect';
import axios from 'axios';
export default function LoginPage() {
const history = useHistory()
// Стейты для формы входа
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const [showPassword, setShowPassword] = useState(false)
const [rememberMe, setRememberMe] = useState(false)
const [activeTab, setActiveTab] = useState<"login" | "register">("login")
// Состояние и обработчики регистрационной формы / локальное состояние
const [registerFormData, setRegisterFormData] = useState({
email: "", // Removed firstName, lastName
password: "",
confirmPassword: "",
name: "",
})
const [showRegisterPassword, setShowRegisterPassword] = useState(false)
const [showConfirmRegisterPassword, setShowConfirmRegisterPassword] = useState(false)
// Обработчик входа
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault();
console.log('Перед отправкой:', { email, password });
try {
const response = await connect.post('/auth/api/login', {
email,
password,
rememberMe,
});
if (response.status === 200 || response.status === 204 || response.status === 201) {
// Предположим, что сервер возвращает данные с токеном
const data = response.data;
// Сохраняем данные в localStorage
localStorage.setItem('authToken', data.token);
localStorage.setItem('userEmail', data.user_email);
localStorage.setItem('userId', String(data.user_id));
// Можно сохранить флаг входа
localStorage.setItem('isLoggedIn', 'true');
// Перенаправляем пользователя
history.push("/home");
} else {
console.log('Ответ:', response);
}
} catch (error) {
if (axios.isAxiosError(error)) {
console.error('Ошибка при входе:', error.message);
if (error.response) {
console.error('Статус:', error.response.status);
console.error('Данные ответа:', error.response.data);
if (error.response.status === 400) {
alert('Неверные данные для входа');
}
}
} else {
console.error('Неожиданная ошибка:', error);
}
alert('Ошибка при входе');
}
};
// Обработчик регистрации
const handleRegisterSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (registerFormData.password !== registerFormData.confirmPassword) {
alert("Пароли не совпадают")
return
}
try {
const response = await connect.post('/auth/api/register', {
email: registerFormData.email,
name: registerFormData.email,
password: registerFormData.password,
})
// Предположим, что ответ содержит объект с токеном и другой информацией
const data = response.data
// Сохраняем нужные данные в localStorage
localStorage.setItem('authToken', data.token)
localStorage.setItem('userEmail', data.user_email)
localStorage.setItem('userId', String(data.user_id))
localStorage.setItem('userName', data.user_name)
console.log('Данные сохранены в localStorage')
alert('Вы успешно зерегистрировались!')
console.log('Отправляемые данные:', { email, password });
// После этого можно перейти или показать сообщение
history.push("/home")
} catch (error) {
console.error('Ошибка при регистрации:', error)
alert('Ошибка при регистрации')
}
}
const handleRegisterInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setRegisterFormData({
...registerFormData,
[e.target.name]: e.target.value,
})
}
return (
<div className="min-h-screen bg-gradient-to-br from-[#3ABBC7] to-[#0D212C] flex items-center justify-center p-4">
<div className="bg-white h-[58%] w-full z-0 absolute bottom-0"></div>
<div className="relative z-10 w-full max-w-md">
{/* Header Section */}
<div className="flex items-center justify-center gap-4 mb-8">
<img className="h-20 w-auto flex-shrink-0" src={manImage || "/placeholder.svg"} alt="man" />
<div className="flex flex-col text-white">
<h1 className="text-4xl font-bold mb-1">Реабилитация</h1>
<div className="w-full bg-white h-0.5 mb-1"></div>
<p className="font-medium text-lg">Восстановление после травмы</p>
</div>
</div>
{/* Login/Register Form Container */}
<div className="bg-white/5 backdrop-blur-lg glass-morphism rounded-3xl p-8 border border-white/20 shadow-2xl">
{/* Tab Buttons Container */}
<div className="flex justify-center gap-2 mb-8 bg-white/10 backdrop-blur-lg rounded-xl px-2 py-2 shadow-inner">
<button
type="button"
onClick={() => setActiveTab("login")}
className={`flex-1 px-3 py-3 rounded-xl text-lg font-semibold transition-all duration-300 ${
activeTab === "login"
? "bg-white text-gray-800 shadow-lg"
: "text-white/80 hover:text-white hover:bg-white/10"
}`}
>
Вход
</button>
<button
type="button"
onClick={() => setActiveTab("register")}
className={`flex-1 px-3 py-3 rounded-xl text-lg font-semibold transition-all duration-300 ${
activeTab === "register"
? "bg-white text-gray-800 shadow-lg"
: "text-white/80 hover:text-white hover:bg-white/10"
}`}
>
Регистрация
</button>
</div>
{activeTab === "login" && (
<form onSubmit={handleLogin} className="space-y-6">
<p className="text-gray-700 text-center text-lg font-medium mb-4">Введите логин и пароль</p>
{/* Email Input */}
<div>
<label htmlFor="email" className="block text-gray-700 text-sm font-semibold mb-2 sr-only">
Электронная почта
</label>
<div className="relative">
<input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full bg-white rounded-xl px-4 py-3 text-gray-800 placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[#2BACBE] focus:border-transparent transition-all shadow-sm"
placeholder="Электронная почта"
required
/>
<svg
className="absolute right-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-500"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="2"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
/>
</svg>
</div>
</div>
{/* Password Input */}
<div>
<label htmlFor="password" className="block text-gray-700/90 text-sm font-semibold mb-2 sr-only">
Пароль
</label>
<div className="relative">
<input
id="password"
type={showPassword ? "text" : "password"}
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full bg-white rounded-xl px-4 py-3 text-gray-800 placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[#2BACBE] focus:border-transparent transition-all shadow-sm"
placeholder="Пароль"
required
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-700 transition-colors"
aria-label={showPassword ? "Hide password" : "Show password"}
>
{showPassword ? (
<svg
className="w-5 h-5"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="2"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L3 3m6.878 6.878L21 21"
/>
</svg>
) : (
<svg
className="w-5 h-5"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="2"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v3"
/>
</svg>
)}
</button>
</div>
</div>
{/* Remember Me & Forgot Password */}
<div className="flex justify-between items-center text-sm mt-4">
<label htmlFor="remember-me" className="flex items-center text-gray-700/80 cursor-pointer">
<input
type="checkbox"
id="remember-me"
checked={rememberMe}
onChange={(e) => setRememberMe(e.target.checked)}
className="mr-2 h-4 w-4 text-[#2BACBE] rounded border-gray-300 focus:ring-[#2BACBE] accent-[#2BACBE]"
/>
Запомнить
</label>
<button
type="button"
onClick={() => history.push("/forgot-password")}
className="text-[#2BACBE] font-medium hover:text-[#2099A8] transition-colors"
>
Забыли пароль?
</button>
</div>
{/* Login Button */}
<button
type="submit"
className="w-full bg-[#2BACBE] hover:bg-[#2099A8] text-white font-bold py-3 px-6 rounded-xl border border-[#2BACBE] transition-all duration-300 transform hover:scale-105 shadow-lg mt-6"
>
Войти
</button>
</form>
)}
{/* Регистрация */}
{activeTab === "register" && (
<form onSubmit={handleRegisterSubmit} className="space-y-4">
<p className="text-gray-700 text-center text-lg font-medium mb-4">Создайте новый аккаунт</p>
{/* Email */}
<div>
<label htmlFor="registerEmail" className="block text-gray-700 text-sm font-semibold mb-2 sr-only">
Электронная почта
</label>
<input
id="registerEmail"
type="email"
name="email"
value={registerFormData.email}
onChange={handleRegisterInputChange}
className="w-full bg-white rounded-xl px-4 py-3 text-gray-800 placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[#2BACBE] focus:border-transparent transition-all shadow-sm"
placeholder="Электронная почта"
required
/>
</div>
{/* Password */}
<div>
<label htmlFor="registerPassword" className="block text-gray-700/90 text-sm font-semibold mb-2 sr-only">
Пароль
</label>
<div className="relative">
<input
id="registerPassword"
type={showRegisterPassword ? "text" : "password"}
name="password"
value={registerFormData.password}
onChange={handleRegisterInputChange}
className="w-full bg-white rounded-xl px-4 py-3 text-gray-800 placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[#2BACBE] focus:border-transparent transition-all shadow-sm"
placeholder="Пароль"
required
/>
<button
type="button"
onClick={() => setShowRegisterPassword(!showRegisterPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-700 transition-colors"
aria-label={showRegisterPassword ? "Hide password" : "Show password"}
>
{showRegisterPassword ? (
<svg
className="w-5 h-5"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="2"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L3 3m6.878 6.878L21 21"
/>
</svg>
) : (
<svg
className="w-5 h-5"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="2"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v3"
/>
</svg>
)}
</button>
</div>
</div>
{/* Confirm Password */}
<div>
<label htmlFor="confirmPassword" className="block text-gray-700/90 text-sm font-semibold mb-2 sr-only">
Подтвердите пароль
</label>
<div className="relative">
<input
id="confirmPassword"
type={showConfirmRegisterPassword ? "text" : "password"}
name="confirmPassword"
value={registerFormData.confirmPassword}
onChange={handleRegisterInputChange}
className="w-full bg-white rounded-xl px-4 py-3 text-gray-800 placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-[#2BACBE] focus:border-transparent transition-all shadow-sm"
placeholder="Подтвердите пароль"
required
/>
<button
type="button"
onClick={() => setShowConfirmRegisterPassword(!showConfirmRegisterPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-500 hover:text-gray-700 transition-colors"
aria-label={showConfirmRegisterPassword ? "Hide password" : "Show password"}
>
{showConfirmRegisterPassword ? (
<svg
className="w-5 h-5"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="2"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.878 9.878L3 3m6.878 6.878L21 21"
/>
</svg>
) : (
<svg
className="w-5 h-5"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="2"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v3"
/>
</svg>
)}
</button>
</div>
</div>
{/* Register Button */}
<button
type="submit"
className="w-full bg-[#2BACBE] hover:bg-[#2099A8] text-white font-bold py-3 px-6 rounded-xl border border-[#2BACBE] transition-all duration-300 transform hover:scale-105 shadow-lg mt-6"
>
Зарегистрироваться
</button>
</form>
)}
{/* Login/Register Link (always visible) */}
<div className="text-center mt-6">
<p className="text-gray-700/80 text-sm">
{activeTab === "login" ? "Нет аккаунта?" : "Уже есть аккаунт?"}{" "}
<button
onClick={() => setActiveTab(activeTab === "login" ? "register" : "login")} // Toggle tab instead of pushing to new route
className="text-gray-700 font-semibold hover:underline"
>
{activeTab === "login" ? "Зарегистрироваться" : "Войти"}
</button>
</p>
</div>
</div>
</div>
</div>
)
}