首頁  >  文章  >  後端開發  >  密碼重設功能:前端

密碼重設功能:前端

DDD
DDD原創
2024-10-02 12:07:01996瀏覽

Password Reset Feature: Frontend

前端

與後端部分相比,前端部分非常簡單。我需要做的就是創建一個模式,並使用它發送資料兩次。

  • 先發送電子郵件將OTP發送至
  • 然後發送OTP和新密碼進行更改

為了建立模式,我從我早期專案 Chat-Nat 的 MessageModal 元件中複製了一些程式碼,即用於封裝模式的類別名稱。

規劃

我將新增「忘記密碼?」登入頁面上的按鈕,並設定 onClick 處理程序以開啟模態

在請求之前,我需要使用布林狀態來表示 OTP 是否已發送到使用者的電子郵件。我將狀態命名為 OTPSent

  • 如果! isOTPSent ->只需詢問電子郵件地址,發送 api 請求,然後如果成功 setOTPSent(true)
  • 如果是OTPS發送->現在也要求提供 OTP 和新密碼,如果成功,則關閉模式

以下是我從該專案的現有前端重用的一些元件和掛鉤:

  • 盒子->它將我的登入和註冊頁面整齊地包裝到一張卡片中,位於頁面中央,並在此處重用,標題為“密碼重置”
  • 驗證表單->只是一個表單,但我對其進行了編碼以在我們等待伺服器回應時禁用提交按鈕並將按鈕文字設定為“正在加載...”
  • 表單輸入->具有自己的標籤的輸入字段,具有值設定器和 onChange 處理程序,可選地具有 isRequired 布林值
  • 使用Axios->自訂掛鉤來處理來自需要令牌刷新的伺服器的回應。 apiReq 函數用於正常請求傳送,一些自訂錯誤處理用於顯示alert() 和刷新令牌,refreshReq 函數用於刷新身份驗證令牌並再次嘗試初始請求。

這是模態的完整程式碼:

// 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

這是在登入表單中處理模式的條件渲染的方式

// 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>
    )

我們完成了!至少我是這麼想的。

在我的開發環境中運行該應用程式時,我發現了一個錯誤,如果後端已經運行很長時間,則電子郵件將無法通過。

我們將在下一篇文章中修正此錯誤

以上是密碼重設功能:前端的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn