login qua ung

import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import axios from 'axios'; import toast, { Toaster } from 'react-hot-toast'; import { Eye, EyeOff } from 'lucide-react'; function Login() { const [isLoginMode, setIsLoginMode] = useState(true); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [isDarkMode, setIsDarkMode] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); const [showPassword, setShowPassword] = useState(false); const [errors, setErrors] = useState({}); const navigate = useNavigate(); const validateForm = () => { const newErrors = {}; if (!username || username.length < 3 || username.length > 20) { newErrors.username = 'Tên người dùng phải từ 3 đến 20 ký tự'; } if (!/^[a-zA-Z0-9]+$/.test(username)) { newErrors.username = 'Tên người dùng chỉ chứa chữ cái và số'; } if (!password || password.length < 6 || password.length > 20) { newErrors.password = 'Mật khẩu phải từ 6 đến 20 ký tự'; } if (!/[0-9]/.test(password)) { newErrors.password = 'Mật khẩu phải chứa ít nhất một số'; } if (!isLoginMode && password !== confirmPassword) { newErrors.confirmPassword = 'Mật khẩu xác nhận không khớp'; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const handleSubmit = async (e) => { e.preventDefault(); if (!validateForm()) { toast.error('Vui lòng kiểm tra lại thông tin!'); return; } setIsSubmitting(true); try { const endpoint = isLoginMode ? 'https://backend-rockefeller-finance.onrender.com/api/login' : 'https://backend-rockefeller-finance.onrender.com/api/register'; const response = await axios.post(endpoint, { username, password }); if (isLoginMode) { localStorage.setItem('token', response.data.token); toast.success('Đăng nhập thành công!'); setTimeout(() => navigate('/home'), 1000); } else { toast.success('Đăng ký thành công! Đang chuyển sang đăng nhập...'); setIsLoginMode(true); setPassword(''); setConfirmPassword(''); setTimeout(async () => { try { const loginResponse = await axios.post( 'https://backend-rockefeller-finance.onrender.com/api/login', { username, password } ); localStorage.setItem('token', loginResponse.data.token); navigate('/home'); } catch (err) { toast.error(err.response?.data?.error || 'Lỗi đăng nhập tự động'); } }, 1000); } setErrors({}); } catch (err) { toast.error(err.response?.data?.error || (isLoginMode ? 'Lỗi đăng nhập' : 'Lỗi đăng ký')); } finally { setIsSubmitting(false); } }; const handleForgotPassword = () => { toast('Vui lòng liên hệ hỗ trợ tại support@rockefeller-finance.com để đặt lại mật khẩu.', { duration: 5000, }); }; const toggleDarkMode = () => { setIsDarkMode(!isDarkMode); }; return (

{isLoginMode ? 'Đăng nhập' : 'Đăng ký'}

*32 Lá Thư*: "Kỷ luật tài chính bắt đầu từ việc quản lý thông tin cá nhân an toàn. Hãy sử dụng mật khẩu mạnh!"

setUsername(e.target.value)} className={`w-full p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500 transition ${ isDarkMode ? 'bg-gray-700 text-white border-gray-600' : 'bg-white text-gray-800 border-gray-300' } ${errors.username ? 'border-red-500' : ''}`} placeholder="Nhập tên người dùng" disabled={isSubmitting} /> {errors.username &&

{errors.username}

}
setPassword(e.target.value)} className={`w-full p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500 transition ${ isDarkMode ? 'bg-gray-700 text-white border-gray-600' : 'bg-white text-gray-800 border-gray-300' } ${errors.password ? 'border-red-500' : ''}`} placeholder="Nhập mật khẩu" disabled={isSubmitting} /> {errors.password &&

{errors.password}

}
{!isLoginMode && (
setConfirmPassword(e.target.value)} className={`w-full p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500 transition ${ isDarkMode ? 'bg-gray-700 text-white border-gray-600' : 'bg-white text-gray-800 border-gray-300' } ${errors.confirmPassword ? 'border-red-500' : ''}`} placeholder="Xác nhận mật khẩu" disabled={isSubmitting} /> {errors.confirmPassword &&

{errors.confirmPassword}

}
)}
{isLoginMode && ( )}
); } export default Login;
Huyền

Một Blog Anime chia sẻ những bộ anime hay download về để xem chất lượng cao nhất. neyuhv.blogspot.com does not host any files, it merely links to 3rd party services. Legal issues should be taken up with the file hosts and providers. neyuhv.blogspot.com is not responsible for any media files shown by the video providers.

Mới hơn Cũ hơn