Forgot Password - Copy this React, Tailwind Component to your project
/* eslint disable no unused vars */ import React, { useState } from "react"; import { Button, Form, Input } from "antd"; import { HeartIcon, Mail, Phone } from "lucide react"; // Import Mail cho email, Phone cho số điện thoại import { toast } from "react toastify"; import { useNavigate } from "react router dom"; import api from "../configs/config axios"; // Điều chỉnh lại đường dẫn api nếu cần // Không import logo HouseHappy nếu không dùng function ForgotPasswordPage() { const navigate = useNavigate(); const [loading, setLoading] = useState(false); // Regex cơ bản cho email và số điện thoại Việt Nam const emailRegex = /^[a zA Z0 9._%+ ]+@[a zA Z0 9. ]+\.[a zA Z]{2,}$/; const phoneRegex = /^(0|\+84)(3|5|7|8|9)\d{8}$/; // Regex cho số điện thoại Việt Nam const onFinish = async (values) => { setLoading(true); console.log("Forgot password request:", values); try { // Giả định API endpoint cho gửi OTP là /send otp forgot password const response = await api.post("send otp forgot password", values); if (response.data && response.data.message) { toast.success(response.data.message || "Mã OTP đã được gửi!"); // Có thể điều hướng đến trang xác nhận OTP // navigate("/verify otp", { state: { contactInfo: values.contact } }); } else { toast.error("Gửi yêu cầu thất bại. Vui lòng thử lại."); } } catch (e) { console.error("Lỗi gửi yêu cầu OTP:", e); const errorMessage = e.response && e.response.data && e.response.data.message ? e.response.data.message : "Gửi yêu cầu thất bại. Vui lòng thử lại!"; toast.error(errorMessage); } finally { setLoading(false); } }; const onFinishFailed = (errorInfo) => { console.log("Failed:", errorInfo); toast.error("Vui lòng nhập tên đăng nhập hoặc email!"); }; return ( // Toàn bộ trang nền xanh nhạt, căn giữa nội dung <div className="min h screen flex flex col items center justify center bg light blue bg font sans p 4"> {" "} {/* Thêm justify center */} {/* Không có header ở đây */} {/* Card chứa form */} <div className="bg white card p 10 rounded lg shadow xl w full max w md text center"> <div className="flex justify center items center"> {" "} {/* Thêm lớp này để căn giữa nội dung bên trong */} <HeartIcon className="h 8 w 8 text blue 600" />{" "} {/* Loại bỏ txt center */} </div> <h2 className="text primary black text 2xl font bold mb 2"> Welcome ! </h2> <p className="text primary black text 3xl font bold mb 8"> Đăng ký lại mật khẩu </p> <Form name="forgot_password_otp" layout="vertical" onFinish={onFinish} onFinishFailed={onFinishFailed} autoComplete="off" className="space y 6" > {/* Label phía trên và chấp nhận Email hoặc Số điện thoại */} <Form.Item label={ <span className="block text left text sm font medium text primary black mb 1"> Email hoặc Số điện thoại </span> } name="contact" rules={[ { required: true, message: "Vui lòng nhập tên đăng nhập, Email hoặc Số điện thoại!", }, { validator: (_, value) => { if (!value) return Promise.resolve(); const isEmail = emailRegex.test(value); const isPhone = phoneRegex.test(value); if (isEmail || isPhone) { return Promise.resolve(); } return Promise.reject( new Error( "Vui lòng nhập định dạng email hoặc số điện thoại hợp lệ!" ) ); }, }, { max: 50, message: "Giá trị nhập vào không được vượt quá 50 ký tự!", }, ]} > <Input prefix={<Mail size={18} className="text text gray light" />} placeholder="Enter your user name or Email or Phone number" className="bg white card border border gray 300 text primary black py 3 px 4 rounded md focus:ring blue 400 focus:border blue 400" /> </Form.Item> {/* Nút "Gửi OTP" */} <Form.Item> <Button type="primary" htmlType="submit" loading={loading} className="w full py 3 bg button black text white text lg font semibold rounded md hover:bg gray 800 transition colors" > Gửi OTP </Button> </Form.Item> </Form> {/* Link quay lại trang đăng nhập */} <div className="mt 6 text center"> <a href="/login" className="text blue 600 hover:underline text sm"> Quay lại đăng nhập </a> </div> </div> </div> ); }
