feat: resend verification code button
This commit is contained in:
59
components/ResendVerificationCode/ResendVerificationCode.tsx
Normal file
59
components/ResendVerificationCode/ResendVerificationCode.tsx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { FC, useEffect, useState } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { Button } from "@mantine/core";
|
||||||
|
import { setLastSendTime } from "@/lib/features/verification/verificationSlice";
|
||||||
|
import { RootState } from "@/lib/store";
|
||||||
|
import { MAX_COUNTDOWN } from "@/constants/verification";
|
||||||
|
|
||||||
|
const ResendVerificationCode: FC = () => {
|
||||||
|
const [countdown, setCountdown] = useState(0);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const lastSendTime = useSelector(
|
||||||
|
(state: RootState) => state.verification.lastSendTime
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(setLastSendTime(Date.now()));
|
||||||
|
setCountdown(MAX_COUNTDOWN);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (lastSendTime) {
|
||||||
|
const elapsed = Math.floor((Date.now() - lastSendTime) / 1000);
|
||||||
|
const remaining = Math.max(0, MAX_COUNTDOWN - elapsed);
|
||||||
|
setCountdown(remaining);
|
||||||
|
}
|
||||||
|
}, [lastSendTime]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (countdown > 0) {
|
||||||
|
const timer = setTimeout(() => setCountdown(countdown - 1), 1000);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}
|
||||||
|
}, [countdown]);
|
||||||
|
|
||||||
|
const sendCode = () => {
|
||||||
|
if (countdown > 0) return;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleResend = () => {
|
||||||
|
sendCode();
|
||||||
|
dispatch(setLastSendTime(Date.now()));
|
||||||
|
setCountdown(MAX_COUNTDOWN);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant={"outline"}
|
||||||
|
disabled={countdown > 0}
|
||||||
|
onClick={handleResend}>
|
||||||
|
{countdown > 0
|
||||||
|
? `Отправить код через ${countdown}с`
|
||||||
|
: "Отправить код"}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ResendVerificationCode;
|
||||||
@ -4,6 +4,7 @@ import { FC } from "react";
|
|||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { Button, PinInput, Stack } from "@mantine/core";
|
import { Button, PinInput, Stack } from "@mantine/core";
|
||||||
import { useForm } from "@mantine/form";
|
import { useForm } from "@mantine/form";
|
||||||
|
import ResendVerificationCode from "@/components/ResendVerificationCode/ResendVerificationCode";
|
||||||
import style from "@/components/VerifyPhoneForm/VerifyPhone.module.css";
|
import style from "@/components/VerifyPhoneForm/VerifyPhone.module.css";
|
||||||
|
|
||||||
type VerifyNumberForm = {
|
type VerifyNumberForm = {
|
||||||
@ -48,6 +49,7 @@ const VerifyPhoneForm: FC = () => {
|
|||||||
disabled={form.values.code.length !== 6}>
|
disabled={form.values.code.length !== 6}>
|
||||||
Подтвердить
|
Подтвердить
|
||||||
</Button>
|
</Button>
|
||||||
|
<ResendVerificationCode />
|
||||||
<Button
|
<Button
|
||||||
variant={"outline"}
|
variant={"outline"}
|
||||||
onClick={navigateToLogin}>
|
onClick={navigateToLogin}>
|
||||||
|
|||||||
1
constants/verification.ts
Normal file
1
constants/verification.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const MAX_COUNTDOWN = 30;
|
||||||
@ -1,8 +1,10 @@
|
|||||||
import { combineReducers } from "@reduxjs/toolkit";
|
import { combineReducers } from "@reduxjs/toolkit";
|
||||||
import targetServiceReducer from "@/lib/features/targetService/targetServiceSlice";
|
import targetServiceReducer from "@/lib/features/targetService/targetServiceSlice";
|
||||||
|
import verificationReducer from "@/lib/features/verification/verificationSlice";
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
targetService: targetServiceReducer,
|
targetService: targetServiceReducer,
|
||||||
|
verification: verificationReducer,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default rootReducer;
|
export default rootReducer;
|
||||||
|
|||||||
23
lib/features/verification/verificationSlice.ts
Normal file
23
lib/features/verification/verificationSlice.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
|
interface VerificationState {
|
||||||
|
lastSendTime: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: VerificationState = {
|
||||||
|
lastSendTime: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const verificationSlice = createSlice({
|
||||||
|
name: "verification",
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
setLastSendTime: (state, action: PayloadAction<number>) => {
|
||||||
|
state.lastSendTime = action.payload;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { setLastSendTime } = verificationSlice.actions;
|
||||||
|
|
||||||
|
export default verificationSlice.reducer;
|
||||||
@ -7,7 +7,7 @@ import rootReducer from "@/lib/features/rootReducer";
|
|||||||
const persistConfig = {
|
const persistConfig = {
|
||||||
key: "root",
|
key: "root",
|
||||||
storage,
|
storage,
|
||||||
whitelist: ["targetService"],
|
whitelist: ["targetService", "verification"],
|
||||||
};
|
};
|
||||||
|
|
||||||
const persistedReducer = persistReducer(persistConfig, rootReducer);
|
const persistedReducer = persistReducer(persistConfig, rootReducer);
|
||||||
|
|||||||
Reference in New Issue
Block a user