ホームページ  >  記事  >  バックエンド開発  >  パスワード リセット機能: フロントエンド

パスワード リセット機能: フロントエンド

DDD
DDDオリジナル
2024-10-02 12:07:01996ブラウズ

Password Reset Feature: Frontend

フロントエンド

フロントエンド部分はバックエンド部分に比べて非常に簡単です。必要なのは、モーダルを作成し、それを使用してデータを 2 回送信することだけです。

  • まず、OTP を送信する電子メールを送信します
  • 次に、OTP と新しいパスワードを送信して変更します

モーダルを作成するために、以前のプロジェクト Chat-Nat の MessageModal コンポーネントから、モーダルをカプセル化するための classNames というコードをコピーしました。

企画

「パスワードをお忘れですか?」を追加します。ログイン ページのボタンをクリックし、モーダル

を開くように onClick ハンドラーを設定します。

OTP を要求する前に、ユーザーの電子メールに OTP が送信されたかどうかをブール状態を使用して示す必要があります。状態に isOTPSent

という名前を付けます
  • !isOTPSent の場合 ->電子メール アドレスを尋ね、API 要求を送信し、成功した場合は setOTPSent(true)
  • OTPSent の場合 ->ここで OTP と新しいパスワードも要求し、成功したらモーダルを閉じます。

このプロジェクトの既存のフロントエンドから再利用しているコンポーネントとフックをいくつか示します:

  • ボックス ->ログインページと登録ページをカードにきちんと包み込み、ページの中央に「パスワードのリセット」というタイトルで再利用しました。
  • 認証フォーム ->ただのフォームですが、サーバーからの応答を待っているときに送信ボタンを無効にし、ボタンのテキストを「読み込み中...」に設定するようにコーディングしました。
  • フォーム入力 ->独自のラベルを持つ入力フィールド、値セッターと onChange ハンドラー、オプションで isRequired ブール値を持つ
  • useAxios ->トークンの更新が必要なサーバーからの応答を処理するカスタム フック。通常のリクエスト送信用の apiReq 関数、alert() とリフレッシュ トークンを表示するためのカスタム エラー処理、認証トークンをリフレッシュして最初のリクエストを再試行するための freshReq 関数。

モーダルのコード全体は次のとおりです:

// 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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。