NDHC
Ngô Dương Hoàng Châu

Auth Page - Copy this React, Tailwind Component to your project

import { useState } from "react"; import { FiMail, FiLock, FiUser } from "react-icons/fi"; import api from "../../api"; const AuthPage = () => { const [activeTab, setActiveTab] = useState("login"); const [formData, setFormData] = useState({ fullName: "", email: "", password: "", confirmPassword: "", }); const [errors, setErrors] = useState({}); const validateForm = () => { const newErrors = {}; if (activeTab === "register") { if (!formData.fullName) newErrors.fullName = "Full name is required"; if (formData.password !== formData.confirmPassword) { newErrors.confirmPassword = "Passwords do not match"; } } if (!formData.email) { newErrors.email = "Email is required"; } else if (!/\S+@\S+\.\S+/.test(formData.email)) { newErrors.email = "Email is invalid"; } if (!formData.password) { newErrors.password = "Password is required"; } else if (formData.password.length < 6) { newErrors.password = "Password must be at least 6 characters"; } return newErrors; }; const handleSubmit = async (e) => { e.preventDefault(); const newErrors = validateForm(); if (Object.keys(newErrors).length === 0) { // Promise trong JavaScript const response = await api.post("register", formData); console.log("Form submitted", formData); console.log("Server response", response); // Không xảy ra ngay lập tức, cần thời gian để xử lý // Có nhiều trạng thái: Pending, Fulfilled, Rejected } else { setErrors(newErrors); } }; const handleChange = (e) => { const { name, value } = e.target; setFormData((prev) => ({ ...prev, [name]: value, })); }; return ( <div className="min-h-screen bg-gray-100 flex items-center justify-center px-4 sm:px-6 lg:px-8"> <div className="max-w-md w-full space-y-8 bg-white p-6 rounded-lg shadow-lg"> <div className="flex justify-center"> <img className="h-12 w-auto" src="https://images.unsplash.com/photo-1633409361618-c73427e4e206" alt="Logo" /> </div> <div className="flex border-b border-gray-200"> <button className={`flex-1 py-4 px-6 text-center ${ activeTab === "login" ? "border-b-2 border-blue-500 text-blue-500" : "text-gray-500 hover:text-gray-700" }`} onClick={() => setActiveTab("login")} > Login </button> <button className={`flex-1 py-4 px-6 text-center ${ activeTab === "register" ? "border-b-2 border-blue-500 text-blue-500" : "text-gray-500 hover:text-gray-700" }`} onClick={() => setActiveTab("register")} > Register </button> </div> <form onSubmit={handleSubmit} className="mt-8 space-y-6"> {activeTab === "register" && ( <div> <label htmlFor="fullName" className="block text-sm font-medium text-gray-700" > Full Name </label> <div className="mt-1 relative rounded-md shadow-sm"> <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> <FiUser className="h-5 w-5 text-gray-400" /> </div> <input type="text" name="fullName" id="fullName" value={formData.fullName} onChange={handleChange} className={`block w-full pl-10 pr-3 py-2 border ${ errors.fullName ? "border-red-500" : "border-gray-300" } rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500`} /> </div> {errors.fullName && ( <p className="mt-2 text-sm text-red-600">{errors.fullName}</p> )} </div> )} <div> <label htmlFor="email" className="block text-sm font-medium text-gray-700" > Email Address </label> <div className="mt-1 relative rounded-md shadow-sm"> <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> <FiMail className="h-5 w-5 text-gray-400" /> </div> <input type="email" name="email" id="email" value={formData.email} onChange={handleChange} className={`block w-full pl-10 pr-3 py-2 border ${ errors.email ? "border-red-500" : "border-gray-300" } rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500`} /> </div> {errors.email && ( <p className="mt-2 text-sm text-red-600">{errors.email}</p> )} </div> <div> <label htmlFor="password" className="block text-sm font-medium text-gray-700" > Password </label> <div className="mt-1 relative rounded-md shadow-sm"> <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> <FiLock className="h-5 w-5 text-gray-400" /> </div> <input type="password" name="password" id="password" value={formData.password} onChange={handleChange} className={`block w-full pl-10 pr-3 py-2 border ${ errors.password ? "border-red-500" : "border-gray-300" } rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500`} /> </div> {errors.password && ( <p className="mt-2 text-sm text-red-600">{errors.password}</p> )} </div> {activeTab === "register" && ( <div> <label htmlFor="confirmPassword" className="block text-sm font-medium text-gray-700" > Confirm Password </label> <div className="mt-1 relative rounded-md shadow-sm"> <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> <FiLock className="h-5 w-5 text-gray-400" /> </div> <input type="password" name="confirmPassword" id="confirmPassword" value={formData.confirmPassword} onChange={handleChange} className={`block w-full pl-10 pr-3 py-2 border ${ errors.confirmPassword ? "border-red-500" : "border-gray-300" } rounded-md focus:outline-none focus:ring-blue-500 focus:border-blue-500`} /> </div> {errors.confirmPassword && ( <p className="mt-2 text-sm text-red-600"> {errors.confirmPassword} </p> )} </div> )} <div> <button type="submit" className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" > {activeTab === "login" ? "Sign In" : "Register"} </button> </div> {activeTab === "login" && ( <div className="text-center"> <a href="#" className="font-medium text-blue-600 hover:text-blue-500" > Forgot your password? </a> </div> )} </form> </div> </div> ); }; export default AuthPage;

Prompt

About

AuthPage - A user-friendly interface with tabs for login and registration, built with React and Tailwind. Easy navigation and responsi. Get instant access!

Share

Last updated 1 month ago