LS
Linh Son

Notification System - Copy this React, Tailwind Component to your project

Import { useState } from "react"; import { FcGoogle } from "react icons/fc"; import { FaFacebook, FaEye, FaEyeSlash } from "react icons/fa"; import { motion, AnimatePresence } from "framer motion"; import ReCAPTCHA from "react google recaptcha"; const PasswordStrength = ({ password }) => { const getStrength = (pass) => { let score = 0; if (pass.length >= 8) score++; if (pass.match(/[A Z]/)) score++; if (pass.match(/[0 9]/)) score++; if (pass.match(/[^A Za z0 9]/)) score++; return score; }; const strength = getStrength(password); const getColor = () => { if (strength === 0) return "bg gray 200"; if (strength === 1) return "bg red 500"; if (strength === 2) return "bg yellow 500"; if (strength === 3) return "bg blue 500"; return "bg green 500"; }; return ( <div className="mt 2"> <div className="h 2 w full bg gray 200 rounded full"> <div className={`h full ${getColor()} rounded full transition all duration 300`} style={{ width: `${(strength / 4) * 100}%` }} ></div> </div> <p className="text xs mt 1 text gray 500"> {strength === 0 && "Enter password"} {strength === 1 && "Weak"} {strength === 2 && "Fair"} {strength === 3 && "Good"} {strength === 4 && "Strong"} </p> </div> ); }; const VerificationPage = ({ email, onResend }) => { return ( <div className="text center space y 6"> <h2 className="text 3xl font extrabold text gray 900">Verify your email</h2> <p className="text gray 600">We have sent a verification link to</p> <p className="font medium text gray 800">{email}</p> <p className="text gray 600">Please check your inbox and click the link to verify your account</p> <div className="pt 4"> <button onClick={onResend} className="text blue 600 hover:text blue 800 font medium" > Resend verification email </button> </div> </div> ); }; const AuthPage = () => { const [authState, setAuthState] = useState("login"); const [showPassword, setShowPassword] = useState(false); const [isVerificationSent, setIsVerificationSent] = useState(false); const [formData, setFormData] = useState({ email: "", password: "", confirmPassword: "", fullName: "", username: "", phone: "", rememberMe: false, termsAccepted: false }); const [errors, setErrors] = useState({}); const [captchaValue, setCaptchaValue] = useState(null); const handleCaptchaChange = (value) => { setCaptchaValue(value); }; const validateEmail = (email) => { return email.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/); }; const validatePassword = (password) => { const hasMinLength = password.length >= 8; const hasUpperCase = /[A Z]/.test(password); const hasNumber = /[0 9]/.test(password); const hasSpecialChar = /[^A Za z0 9]/.test(password); return hasMinLength && hasUpperCase && hasNumber && hasSpecialChar; }; const handleInputChange = (e) => { const { name, value, type, checked } = e.target; setFormData(prev => ({ ...prev, [name]: type === "checkbox" ? checked : value })); }; const handleSubmit = (e) => { e.preventDefault(); const newErrors = {}; if (!validateEmail(formData.email)) { newErrors.email = "Please enter a valid email address"; } if (authState !== "forgot" && !validatePassword(formData.password)) { newErrors.password = "Password must be at least 8 characters long and include uppercase, number, and special character"; } if (authState === "register") { if (formData.password !== formData.confirmPassword) { newErrors.confirmPassword = "Passwords do not match"; } if (!formData.fullName) newErrors.fullName = "Full name is required"; if (!formData.username) newErrors.username = "Username is required"; if (!formData.phone) newErrors.phone = "Phone number is required"; if (!formData.termsAccepted) newErrors.terms = "Please accept terms and conditions"; } setErrors(newErrors); if (Object.keys(newErrors).length === 0) { if (authState === "register" || authState === "forgot") { setIsVerificationSent(true); } else { console.log("Form submitted:", formData); } } }; const handleResendVerification = () => { console.log("Resending verification email to:", formData.email); }; const isFormValid = () => { if (authState === "login") { return validateEmail(formData.email) && captchaValue; } else if (authState === "register") { return validateEmail(formData.email) && validatePassword(formData.password) && formData.password === formData.confirmPassword && formData.fullName && formData.username && formData.phone && formData.termsAccepted; } else { return validateEmail(formData.email); } }; return ( <div className="min h screen bg gray 50 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 8 rounded xl shadow lg"> <AnimatePresence mode="wait"> <motion.div key={isVerificationSent ? "verification" : authState} initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: 20 }} transition={{ duration: 0.3 }} > {isVerificationSent ? ( <VerificationPage email={formData.email} onResend={handleResendVerification} /> ) : ( <> <div className="text center"> <h2 className="mt 6 text 3xl font extrabold text gray 900"> {authState === "login" ? "Sign in to your account" : authState === "register" ? "Create your account" : "Reset your password"} </h2> </div> <form className="mt 8 space y 6" onSubmit={handleSubmit}> {authState === "register" && ( <> <div> <label className="block text sm font medium text gray 700">Full Name</label> <input type="text" name="fullName" value={formData.fullName} onChange={handleInputChange} className={`mt 1 block w full px 3 py 2 border ${errors.fullName ? 'border red 500' : 'border gray 300'} rounded md shadow sm focus:outline none focus:ring blue 500 focus:border blue 500`} /> {errors.fullName && <p className="mt 1 text sm text red 500">{errors.fullName}</p>} </div> <div> <label className="block text sm font medium text gray 700">Username</label> <input type="text" name="username" value={formData.username} onChange={handleInputChange} className={`mt 1 block w full px 3 py 2 border ${errors.username ? 'border red 500' : 'border gray 300'} rounded md shadow sm focus:outline none focus:ring blue 500 focus:border blue 500`} /> {errors.username && <p className="mt 1 text sm text red 500">{errors.username}</p>} </div> <div> <label className="block text sm font medium text gray 700">Phone Number</label> <input type="tel" name="phone" value={formData.phone} onChange={handleInputChange} className={`mt 1 block w full px 3 py 2 border ${errors.phone ? 'border red 500' : 'border gray 300'} rounded md shadow sm focus:outline none focus:ring blue 500 focus:border blue 500`} /> {errors.phone && <p className="mt 1 text sm text red 500">{errors.phone}</p>} </div> </> )} <div> <label className="block text sm font medium text gray 700">Email address</label> <input type="email" name="email" value={formData.email} onChange={handleInputChange} className={`mt 1 block w full px 3 py 2 border ${errors.email ? 'border red 500' : 'border gray 300'} rounded md shadow sm focus:outline none focus:ring blue 500 focus:border blue 500`} /> {errors.email && <p className="mt 1 text sm text red 500">{errors.email}</p>} </div> {authState !== "forgot" && ( <div className="relative"> <label className="block text sm font medium text gray 700">Password</label> <div className="mt 1 relative rounded md shadow sm"> <input type={showPassword ? "text" : "password"} name="password" value={formData.password} onChange={handleInputChange} className={`block w full px 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`} /> <button type="button" className="absolute inset y 0 right 0 pr 3 flex items center" onClick={() => setShowPassword(!showPassword)} > {showPassword ? <FaEyeSlash className="text gray 400" /> : <FaEye className="text gray 400" />} </button> </div> {authState === "register" && <PasswordStrength password={formData.password} />} {errors.password && <p className="mt 1 text sm text red 500">{errors.password}</p>} </div> )} {authState === "register" && ( <div> <label className="block text sm font medium text gray 700">Confirm Password</label> <input type="password" name="confirmPassword" value={formData.confirmPassword} onChange={handleInputChange} className={`mt 1 block w full px 3 py 2 border ${errors.confirmPassword ? 'border red 500' : 'border gray 300'} rounded md shadow sm focus:outline none focus:ring blue 500 focus:border blue 500`} /> {errors.confirmPassword && <p className="mt 1 text sm text red 500">{errors.confirmPassword}</p>} </div> )} {authState === "login" && ( <div className="flex items center justify between"> <div className="flex items center"> <input type="checkbox" name="rememberMe" checked={formData.rememberMe} onChange={handleInputChange} className="h 4 w 4 text blue 600 focus:ring blue 500 border gray 300 rounded" /> <label className="ml 2 block text sm text gray 900">Remember me</label> </div> <button type="button" onClick={() => setAuthState("forgot")} className="text sm font medium text blue 600 hover:text blue 500" > Forgot your password? </button> </div> )} {authState === "register" && ( <div className="flex items center"> <input type="checkbox" name="termsAccepted" checked={formData.termsAccepted} onChange={handleInputChange} className="h 4 w 4 text blue 600 focus:ring blue 500 border gray 300 rounded" /> <label className="ml 2 block text sm text gray 900"> I accept the terms and conditions </label> </div> )} {authState === "login" && ( <div className="mt 4"> <ReCAPTCHA sitekey="6LeWqNkpAAAAANkqcg0zDmNz90pyG4FOLP4QiDQv" onChange={handleCaptchaChange} /> {errors.captcha && <p className="mt 1 text sm text red 500">{errors.captcha}</p>} </div> )} <button type="submit" disabled={!isFormValid()} className={`group relative w full flex justify center py 2 px 4 border border transparent text sm font medium rounded md text white ${isFormValid() ? 'bg blue 600 hover:bg blue 700' : 'bg gray 400 cursor not allowed'} focus:outline none focus:ring 2 focus:ring offset 2 focus:ring blue 500`} > {authState === "login" ? "Sign in" : authState === "register" ? "Sign up" : "Send reset link"} </button> {(authState === "login" || authState === "register") && ( <div className="mt 6"> <div className="relative"> <div className="absolute inset 0 flex items center"> <div className="w full border t border gray 300" /> </div> <div className="relative flex justify center text sm"> <span className="px 2 bg white text gray 500">Or continue with</span> </div> </div> <div className="mt 6 grid grid cols 2 gap 3"> <button type="button" className="w full inline flex justify center py 2 px 4 border border gray 300 rounded md shadow sm bg white text sm font medium text gray 500 hover:bg gray 50" > <FcGoogle className="h 5 w 5" /> <span className="ml 2">Google</span> </button> <button type="button" className="w full inline flex justify center py 2 px 4 border border gray 300 rounded md shadow sm bg white text sm font medium text gray 500 hover:bg gray 50" > <FaFacebook className="h 5 w 5 text blue 600" /> <span className="ml 2">Facebook</span> </button> </div> </div> )} </form> <div className="mt 6 text center"> <button type="button" onClick={() => setAuthState(authState === "login" ? "register" : "login")} className="text sm font medium text blue 600 hover:text blue 500" > {authState === "login" ? "Don't have an account? Sign up" : authState === "register" ? "Already have an account? Sign in" : "Back to sign in"} </button> </div> </> )} </motion.div> </AnimatePresence> </div> </div> ); }; export default AuthPage;(Tôi muốn quăng thông báo ra trước khi nào người dùng nhập đủ đáp ứng đủ điều kiện trong đó thì thông bao sẽ ẩn đi)

Prompt
Component Preview

About

NotificationSystem - Display alerts based on user input, showing or hiding messages as conditions are met. Built with React and Tailwin. Copy now for free!

Share

Last updated 1 month ago