Maison > développement back-end > Golang > le corps du texte

Fonctionnalité de réinitialisation du mot de passe : Frontend

DDD
Libérer: 2024-10-02 12:07:01
original
995 Les gens l'ont consulté

Password Reset Feature: Frontend

L'extrémité avant

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.

  • Envoyez d'abord un e-mail pour envoyer OTP à
  • Envoyez ensuite l'OTP et le nouveau mot de passe pour le changer

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.

Planification

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

  • Si !isOTPSent -> demandez simplement l'adresse e-mail, envoyez une demande d'API, puis en cas de succès, setOTPSent (true)
  • Si isOTPSent -> demandez maintenant également l'OTP et le nouveau mot de passe, puis en cas de succès, fermez le modal

Voici quelques composants et hooks que je réutilise à partir du frontend existant de ce projet :

  • Boîte -> Il a soigneusement enveloppé mes pages de connexion et d'enregistrement dans une carte, centrée sur la page, réutilisée ici avec le titre "Réinitialisation du mot de passe".
  • AuthForm -> Juste un formulaire mais je l'ai codé pour désactiver le bouton de soumission et définir le texte du bouton sur "Chargement..." lorsque nous attendons une réponse du serveur
  • EntréeFormulaire -> Champ de saisie avec sa propre étiquette, avec un définisseur de valeurs et un gestionnaire onChange, éventuellement avec un booléen isRequired
  • utiliserAxios -> Hook personnalisé pour gérer les réponses du serveur qui nécessite une actualisation du jeton. Fonction apiReq pour l'envoi normal de la requête, une gestion des erreurs personnalisée pour afficher une alerte () et un jeton d'actualisation, fonction rafraîchirReq pour actualiser le jeton d'authentification et réessayer la requête initiale.

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
Copier après la connexion

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>
    )
Copier après la connexion

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!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal