From b2a75a527bf0e756095ec7a109fe58ca98e96064 Mon Sep 17 00:00:00 2001 From: Kininaru Date: Thu, 20 May 2021 21:09:12 +0800 Subject: [PATCH] feat: intergrate verification code countdown as a component Signed-off-by: Kininaru --- web/src/ResetModal.js | 32 ++++++++------------ web/src/auth/SignupPage.js | 17 +++++++++-- web/src/reusable/CountDownInput.js | 48 ++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 22 deletions(-) create mode 100644 web/src/reusable/CountDownInput.js diff --git a/web/src/ResetModal.js b/web/src/ResetModal.js index e83e6fe8..4d35f8ec 100644 --- a/web/src/ResetModal.js +++ b/web/src/ResetModal.js @@ -17,12 +17,11 @@ import i18next from "i18next"; import React from "react"; import * as Setting from "./Setting" import * as UserBackend from "./backend/UserBackend" +import {CountDownInput} from "./reusable/CountDownInput"; export const ResetModal = (props) => { const [visible, setVisible] = React.useState(false); const [confirmLoading, setConfirmLoading] = React.useState(false); - const [sendButtonText, setSendButtonText] = React.useState(i18next.t("user:Send Code")); - const [sendCodeCoolDown, setCoolDown] = React.useState(false); const [dest, setDest] = React.useState(""); const [code, setCode] = React.useState(""); const {buttonText, destType, coolDownTime, org} = props; @@ -56,18 +55,7 @@ export const ResetModal = (props) => { }) } - const countDown = (second) => { - if (second <= 0) { - setSendButtonText(i18next.t("user:Send Code")); - setCoolDown(false); - return; - } - setSendButtonText(second); - setTimeout(() => countDown(second - 1), 1000); - } - const sendCode = () => { - if (sendCodeCoolDown) return; if (dest === "") { Setting.showMessage("error", i18next.t("user:Empty " + destType)); return; @@ -76,8 +64,6 @@ export const ResetModal = (props) => { UserBackend.sendCode(dest, destType, orgId).then(res => { if (res.status === "ok") { Setting.showMessage("success", i18next.t("user:Code Sent")); - setCoolDown(true); - countDown(coolDownTime); } else { Setting.showMessage("error", i18next.t("user:" + res.msg)); } @@ -105,13 +91,21 @@ export const ResetModal = (props) => { > - setDest(e.target.value)} - addonAfter={} + setDest(e.target.value)} /> - - setCode(e.target.value)}/> + diff --git a/web/src/auth/SignupPage.js b/web/src/auth/SignupPage.js index c8e46f64..16f0dc65 100644 --- a/web/src/auth/SignupPage.js +++ b/web/src/auth/SignupPage.js @@ -22,6 +22,7 @@ import * as Util from "./Util"; import {authConfig} from "./Auth"; import * as ApplicationBackend from "../backend/ApplicationBackend"; import * as UserBackend from "../backend/UserBackend"; +import {CountDownInput} from "../reusable/CountDownInput"; const formItemLayout = { labelCol: { @@ -63,7 +64,9 @@ class SignupPage extends React.Component { applicationName: props.match.params.applicationName !== undefined ? props.match.params.applicationName : authConfig.appName, application: null, email: "", - phone: "" + phone: "", + emailCode: "", + phoneCode: "" }; this.form = React.createRef(); @@ -250,7 +253,11 @@ class SignupPage extends React.Component { message: i18next.t("signup:Please input your verification code!"), }]} > - this.sendCode("email")} style={{backgroundColor: "#fafafa", border: "none"}}>{i18next.t("signup:send code")}} /> + this.sendCode("email")} + coolDownTime={60} + /> - this.sendCode("phone")} style={{border: "none", backgroundColor: "#fafafa"}}>{i18next.t("signup:send code")}}/> + this.sendCode("phone")} + coolDownTime={60} + /> diff --git a/web/src/reusable/CountDownInput.js b/web/src/reusable/CountDownInput.js new file mode 100644 index 00000000..b9ac41f4 --- /dev/null +++ b/web/src/reusable/CountDownInput.js @@ -0,0 +1,48 @@ +// Copyright 2021 The casbin Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Input } from "antd"; +import React from "react"; +import * as Setting from "../Setting"; +import i18next from "i18next"; + +export const CountDownInput = (props) => { + const {defaultButtonText, textBefore, placeHolder, onChange, onButtonClick, coolDownTime} = props; + const [buttonText, setButtonText] = React.useState(defaultButtonText); + let coolDown = false; + + const countDown = (leftTime) => { + if (leftTime === 0) { + coolDown = false; + setButtonText(defaultButtonText); + return; + } + setButtonText(`${leftTime} s`); + setTimeout(() => countDown(leftTime - 1), 1000); + } + + const clickButton = () => { + if (coolDown) { + Setting.showMessage("error", i18next.t("general:Cooling down")); + return; + } + onButtonClick(); + coolDown = true; + countDown(coolDownTime); + } + + return ( + onChange(e.target.value)} addonAfter={}/> + ); +} \ No newline at end of file