La partie frontend est très simple par rapport à la partie backend. Tout ce que j'ai à faire est de créer un modal et de l'utiliser pour envoyer des données deux fois.
Pour créer le modal, j'ai copié du code, les classNames pour l'encapsulation d'un modal, du composant MessageModal de mon projet précédent Chat-Nat.
J'ajouterai un message « Mot de passe oublié ? » sur la page de connexion et définissez le gestionnaire onClick pour ouvrir le modal
Je dois utiliser un état booléen pour indiquer si l'OTP a été envoyé à l'adresse e-mail de l'utilisateur avant de le demander. Je nomme l'état isOTPSent
Voici quelques composants et hooks que je réutilise à partir du frontend existant de ce projet :
Voici le code complet du modal :
// src/components/PasswordResetModal.tsx import React, { useState } from "react" import AuthForm from "./AuthForm"; import FormInput from "./FormInput"; import Box from "./Box"; import { useAxios } from "../hooks/useAxios"; interface FormData { email: string, new_password: string, otp: string, } interface Props { isVisible: boolean, onClose: () => void, } const PasswordResetModal: React.FC<Props> = ({ isVisible, onClose }) => { const [formData, setFormData] = useState<FormData>({ email: "", new_password: "", otp: "" }); const [isLoading, setLoading] = useState<boolean>(false); const [isOTPSent, setOTPSent] = useState<boolean>(false); const { apiReq } = useAxios(); const handleClose = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => { if ((e.target as HTMLElement).id === "wrapper") { onClose(); // could have setOTPSent(false), but avoiding it in case user misclicks outside } }; const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const { name, value } = e.target; setFormData({ ...formData, [name]: value, }); }; const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); setLoading(true); if (!isOTPSent) { // first request for sending otp, const response = await apiReq<unknown, FormData>("post", "/api/reset-password", formData) if (response) { alert("OTP has been sent to your email"); setOTPSent(true); } } else { // then using otp to change password const response = await apiReq<unknown, FormData>("put", "/api/reset-password", formData) if (response) { alert("Password has been successfully reset\nPlease log in again"); // clear the form setFormData({ email: "", otp: "", new_password: "", }) // close modal onClose(); } } setLoading(false); }; if (!isVisible) return null; return ( <div id="wrapper" className="fixed inset-0 bg-black bg-opacity-25 backdrop-blur-sm flex justify-center items-center" onClick={handleClose}> <Box title="Password Reset"> <AuthForm submitHandler={handleSubmit} isLoading={isLoading} buttonText={isOTPSent ? "Change Password" : "Send OTP"}> <FormInput id="email" label="Your email" type="email" value={formData.email} changeHandler={handleChange} isRequired /> {isOTPSent && (<> <FormInput id="otp" label="OTP" type="text" value={formData.otp} changeHandler={handleChange} isRequired /> <FormInput id="new_password" label="New Password" type="password" value={formData.new_password} changeHandler={handleChange} isRequired /> </>)} </AuthForm> </Box> </div> ) } export default PasswordResetModal
Et voici comment le rendu conditionnel du modal est géré dans le formulaire de connexion
// src/pages/auth/Login.tsx import PasswordResetModal from "../../components/PasswordResetModal"; const Login: React.FC = () => { const [showModal, setShowModal] = useState<boolean>(false); return ( <Section> <Box title="Login"> <div className="grid grid-flow-col"> {/* link to the register page here */} <button type="button" onClick={() => setShowModal(true)} className="text-blue-700 hover:text-white border border-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-2 text-center me-2 mb-2 dark:border-blue-500 dark:text-blue-500 dark:hover:text-white dark:hover:bg-blue-500 dark:focus:ring-blue-800"> Forgot Password? </button> <PasswordResetModal isVisible={showModal} onClose={() => setShowModal(false)} /> </div> </Box> </Section> )
C'est fini ! C'est du moins ce que je pensais.
Lors de l'exécution de l'application dans mon environnement de développement, j'ai découvert un bug empêchant les e-mails de passer si le backend fonctionnait depuis longtemps.
Nous corrigerons ce bug dans le prochain post
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!