Update Add user hospital portal

This commit is contained in:
ivan-sim
2024-05-21 10:36:39 +07:00
parent 0cd2cf71fc
commit f50a4f6409
14 changed files with 366 additions and 114 deletions

View File

@@ -93,27 +93,6 @@ class AuthController extends Controller
}
public function verifyEmail(Request $request)
{
$request->validate([
'email' => 'required|email',
]);
$user = User::query()
->where('email', $request->email)
->first();
if (!$user) {
return response(['Message' => 'User Tidak Ditemukan'], 404);
}
Event(new ForgetPassword($user));
// Mail::to($user->email)->send(new SendVerifyEmail($user));
return response()->json($user);
}
public function forgotPassword(Request $request)
{
$data = [
'email' => $request->email,
@@ -144,7 +123,7 @@ class AuthController extends Controller
'user_id' => $user->id,
'email' => $emailTo,
'title' => 'Forgot Password',
'description' => 'Request forgot password from App Doctor',
'description' => 'Request forgot password from Hospital Portal',
'type' => 1,
'isUnRead' => true,
'created_by' => auth()->check() ? auth()->user()->id : null,
@@ -168,7 +147,7 @@ class AuthController extends Controller
$dataEmail = [
'email' => $emailTo,
'name' => $nameTo,
'subject' => 'Request Forgot Password from App Doctor Date '. date('Y-m-d H:i:s'),
'subject' => 'Request Forgot Password from Hospital Portal Date '. date('Y-m-d H:i:s'),
'body' => View::make('email/forgot_password', ['token' => $token])->render(),
];
Helper::sendEmail($dataEmail);
@@ -176,7 +155,7 @@ class AuthController extends Controller
$res = DB::table('password_resets')
->where('email', '=', $request->email)
->where('token', '=', $token)
->get();
->first();
return ApiResponse::apiResponse("Success", $res, trans('Message.success'), 200);
}
@@ -186,4 +165,131 @@ class AuthController extends Controller
}
}
}
public function verifCode(Request $request)
{
$data = [
'email' => $request->email,
'token' => $request->token,
];
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'token' => 'required|numeric',
], [
'email.required' => trans('Validation.required',['attribute' => 'Email']),
'email.email' => trans('Validation.email'),
'token.required' => trans('Validation.required',['attribute' => 'Token']),
'token.numeric' => trans('Validation.required',['attribute' => 'Code Numeric']),
]);
if ($validator->fails())
{
return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400);
}
else
{
//Check Time
$check = DB::table('password_resets')
->where('email', '=', $request->email)
->where('token', '=', $request->token)
->select('created_at')
->first();
if($check)
{
$created_at = strtotime($check->created_at); // Konversi string waktu ke UNIX timestamp
$now = time(); // Waktu sekarang dalam UNIX timestamp
// Hitung selisih waktu dalam menit
$diffInMinutes = ($now - $created_at) / 60;
if ($diffInMinutes > 60) {
return ApiResponse::apiResponse('Not Found', $data, trans('Message.token_expired'), 404);
} else {
// Lanjutkan dengan proses pemulihan kata sandi
return ApiResponse::apiResponse("Success", $data, trans('Message.success'), 200);
}
}
else
{
return ApiResponse::apiResponse('Not Found', $data, trans('Message.not_found'), 404);
}
}
}
public function forgetPassword(Request $request)
{
$data = [
'email' => $request->email,
'token' => $request->token,
'new_password' => $request->new_password
];
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'token' => 'required|numeric',
'new_password' => [
'required',
'min:8',
'regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/'
]
], [
'email.required' => trans('Validation.required',['attribute' => 'Email']),
'email.email' => trans('Validation.email'),
'token.required' => trans('Validation.required',['attribute' => 'Token']),
'new_password.required' => trans('Validation.required',['attribute' => 'New Password']),
'new_password.min' => trans('Validation.min',['attribute' => 'New Password']),
'new_password.regex' => trans('Validation.regex',['attribute' => 'New Password']),
]);
if($request->new_password != $request->confirm_new_password)
{
return ApiResponse::apiResponse('Bad Request', $data, 'Confirm password is not the same', 400);
}
else if ($validator->fails())
{
return ApiResponse::apiResponse('Bad Request', $data, $validator->errors(), 400);
}
else
{
//Check Time
$check = DB::table('password_resets')
->where('email', '=', $request->email)
->where('token', '=', $request->token)
->select('created_at')
->first();
if($check)
{
$created_at = strtotime($check->created_at); // Konversi string waktu ke UNIX timestamp
$now = time(); // Waktu sekarang dalam UNIX timestamp
// Hitung selisih waktu dalam menit
$diffInMinutes = ($now - $created_at) / 60;
if ($diffInMinutes > 60) {
return ApiResponse::apiResponse('Not Found', $data, trans('Message.token_expired'), 404);
} else {
// Lanjutkan dengan proses pemulihan kata sandi
$user = User::where('email', $request->email)->first();
if ($user)
{
$newPassword = Hash::make($request->new_password);
$user->password = $newPassword;
$user->save();
return ApiResponse::apiResponse("Success", $data, trans('Message.success'), 200);
}
else
{
return ApiResponse::apiResponse('Not Found', $data, trans('Message.token_expired'), 404);
}
}
}
else
{
return ApiResponse::apiResponse('Not Found', $data, trans('Message.not_found'), 404);
}
}
}
}

View File

@@ -29,8 +29,9 @@ Route::prefix('v1')->group(function() {
});
});
Route::post('forgot-password', [AuthController::class, 'forgotPassword']);
// Route::post('verify-email', [AuthController::class, 'verifyEmail'])->name('verify-email');
Route::post('forget-password', [AuthController::class, 'forgetPassword']);
Route::post('verify-email', [AuthController::class, 'verifyEmail'])->name('verify-email');
Route::post('verify-code', [AuthController::class, 'verifCode']);
Route::middleware('auth:sanctum')->group(function () {

View File

@@ -60,5 +60,23 @@
"txtDialogConfirmation": "Are you sure you want to proceed with this action?",
"txtStartDate": "Start Date",
"txtEndDate": "End Date",
"txtHelp1" : "Has problem with your account?"
"txtHelp1" : "Has problem with your account?",
"txtLupaSandi": "Forgot password?",
"txtIngatkanSaya": "Remember me",
"txtLogin": "Login",
"txtForgotYourPassword": "Forgot your password?",
"txtPleaseEnterPassword": "Please enter the email address associated with your account and We will email you a code to reset your password.",
"txtBack": "Back",
"txtSuccessSend": "Request sent successfully",
"txtCodeConfirm": "We have sent a confirmation email to",
"txtPleasCheck": "Please check your email.",
"txtCheckEmail": "Please check your email!",
"txtEmail": "We have emailed a 6-digit confirmation code and check spam folder, please enter the code in below box to verify your email.",
"txtDont": "Dont have a code?",
"txtResendCode": "Resend code",
"txtSecond": "Second",
"txtPleaseInput": "Please enter your new password.",
"txtNewPassword": "New Password",
"txtConfPassword": "Confirm Kata Sandi"
}

View File

@@ -60,5 +60,22 @@
"txtDialogConfirmation": "Apakah Anda yakin ingin melanjutkan tindakan ini?",
"txtStartDate": "Tanggal Mulai",
"txtEndDate": "Tanggal Akhir",
"txtHelp1" : "Punya masalah dengan akun Anda?"
"txtHelp1" : "Punya masalah dengan akun Anda?",
"txtLupaSandi": "Lupa sandi?",
"txtIngatkanSaya": "Ingatkan saya",
"txtLogin": "Masuk",
"txtForgotYourPassword": "Lupa password anda?",
"txtPleaseEnterPassword": "Silakan masukkan alamat email yang terkait dengan akun Anda dan Kami akan mengirimkan email berisi kode untuk mengatur ulang kata sandi Anda.",
"txtBack": "Kembali",
"txtSuccessSend": "Permintaan berhasil dikirim",
"txtCodeConfirm": "Kami telah mengirimkan email konfirmasi ke",
"txtPleasCheck": "Mohon cek email Anda.",
"txtCheckEmail": "Mohon periksa email Anda!",
"txtEmail": "Kami telah mengirimkan kode konfirmasi 6 digit melalui email cek juga difolder spam, silakan masukkan kode di kotak bawah ini untuk memverifikasi email Anda.",
"txtDont": "Tidak mendapatkan kode?",
"txtResendCode": "Kirim ulang kode",
"txtSecond": "Detik",
"txtPleaseInput": "Mohon masukan kata sandi baru Anda.",
"txtNewPassword": "Kata Sandi Baru",
"txtConfPassword": "Konfirmasi Kata Sandi"
}

View File

@@ -12,6 +12,8 @@ import Iconify from '@/components/Iconify';
// sections
import { ForgetPasswordForm } from '@/sections/auth/forget-password';
import { useSearchParams } from 'react-router-dom';
import { useState, useContext, useEffect } from 'react';
import { LanguageContext } from '@/contexts/LanguageContext';
// ----------------------------------------------------------------------
@@ -25,6 +27,8 @@ const RootStyle = styled('div')(({ theme }) => ({
// ----------------------------------------------------------------------
export default function ForgetPassword() {
const { localeData } = useContext(LanguageContext);
const [searchParams, setSearchParams] = useSearchParams();
const token = searchParams.get('token');
@@ -42,12 +46,12 @@ export default function ForgetPassword() {
startIcon={<Iconify icon={'eva:arrow-ios-back-fill'} width={20} height={20} />}
sx={{ mb: 3 }}
>
Back
{localeData.txtBack}
</Button>
<Typography variant="h3" paragraph></Typography>
<Typography sx={{ color: 'text.secondary' }}>
Please enter your new password.
{localeData.txtPleaseInput}
</Typography>
<Box sx={{ mt: 5, mb: 3 }}>

View File

@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useState, useContext } from 'react';
import { Link as RouterLink } from 'react-router-dom';
// @mui
import { styled } from '@mui/material/styles';
@@ -13,6 +13,9 @@ import Page from '@/components/Page';
import { ResetPasswordForm } from '@/sections/auth/reset-password';
// assets
import { SentIcon } from '@/assets';
import { LanguageContext } from '@/contexts/LanguageContext';
import { useNavigate } from 'react-router-dom'; // Import useNavigate
// ----------------------------------------------------------------------
@@ -27,10 +30,17 @@ const RootStyle = styled('div')(({ theme }) => ({
// ----------------------------------------------------------------------
export default function ResetPassword() {
const { localeData } = useContext(LanguageContext);
const [email, setEmail] = useState('');
const [sent, setSent] = useState(false);
const navigate = useNavigate();
const handleSent = () => {
setSent(true);
};
return (
<Page title="Reset Password" sx={{ height: 1 }}>
<RootStyle>
@@ -41,16 +51,15 @@ export default function ResetPassword() {
{!sent ? (
<>
<Typography variant="h3" paragraph>
Forgot your password?
{localeData.txtForgotYourPassword}
</Typography>
<Typography sx={{ color: 'text.secondary', mb: 5 }}>
Please enter the email address associated with your account and We will email you
a link to reset your password.
{localeData.txtPleaseEnterPassword}
</Typography>
<ResetPasswordForm
onSent={() => setSent(true)}
onSent={handleSent}
onGetEmail={(value) => setEmail(value)}
/>
@@ -61,7 +70,7 @@ export default function ResetPassword() {
to={PATH_AUTH.login}
sx={{ mt: 3 }}
>
Back
{localeData.txtBack}
</Button>
</>
) : (
@@ -69,24 +78,24 @@ export default function ResetPassword() {
<SentIcon sx={{ mb: 5, mx: 'auto', height: 160 }} />
<Typography variant="h3" gutterBottom>
Request sent successfully
{localeData.txtSuccessSend}
</Typography>
<Typography>
We have sent a confirmation email to &nbsp;
{localeData.txtCodeConfirm} &nbsp;
<strong>{email}</strong>
<br />
Please check your email.
{localeData.txtPleasCheck}
</Typography>
<Button
size="large"
variant="contained"
component={RouterLink}
to={PATH_AUTH.login}
to={PATH_AUTH.verify}
sx={{ mt: 5 }}
>
Back
Next
</Button>
</Box>
)}

View File

@@ -1,4 +1,4 @@
import { Link as RouterLink } from 'react-router-dom';
import { Link as RouterLink, useLocation } from 'react-router-dom';
// @mui
import { styled } from '@mui/material/styles';
import { Box, Button, Link, Container, Typography } from '@mui/material';
@@ -11,6 +11,9 @@ import Page from '@/components/Page';
import Iconify from '@/components/Iconify';
// sections
import { VerifyCodeForm } from '@/sections/auth/verify-code';
import { useState, useContext, useEffect } from 'react';
import { LanguageContext } from '@/contexts/LanguageContext';
import axios from '@/utils/axios';
// ----------------------------------------------------------------------
@@ -21,9 +24,41 @@ const RootStyle = styled('div')(({ theme }) => ({
padding: theme.spacing(12, 0),
}));
function useQuery() {
return new URLSearchParams(useLocation().search);
}
// ----------------------------------------------------------------------
export default function VerifyCode() {
const { localeData } = useContext(LanguageContext);
const query = useQuery();
const email = query.get('email');
const [timer, setTimer] = useState(60); // Initialize timer with 60 seconds
const [canResend, setCanResend] = useState(false); // State to control resend button visibility
useEffect(() => {
const interval = setInterval(() => {
setTimer((prev) => {
if (prev > 0) {
return prev - 1;
} else {
clearInterval(interval);
setCanResend(true); // Enable resend button when timer reaches 0
return 0;
}
});
}, 1000);
return () => clearInterval(interval); // Cleanup interval on component unmount
}, []);
const handleResend = () => {
setCanResend(false);
setTimer(60); // Reset timer to 60 seconds
// Add logic to resend the code here
axios.post('/verify-email', {email: email});
};
return (
<Page title="Verify" sx={{ height: 1 }}>
<RootStyle>
@@ -34,30 +69,42 @@ export default function VerifyCode() {
<Button
size="small"
component={RouterLink}
to={PATH_AUTH.login}
to={PATH_AUTH.resetPassword}
startIcon={<Iconify icon={'eva:arrow-ios-back-fill'} width={20} height={20} />}
sx={{ mb: 3 }}
>
Back
{localeData.txtBack}
</Button>
<Typography variant="h3" paragraph>
Please check your email!
{localeData.txtCheckEmail}
</Typography>
<Typography variant='subtitle1'>{email}</Typography>
<Typography sx={{ color: 'text.secondary' }}>
We have emailed a 6-digit confirmation code to acb@domain, please enter the code in
below box to verify your email.
{localeData.txtEmail}
</Typography>
<Box sx={{ mt: 5, mb: 3 }}>
<VerifyCodeForm />
<VerifyCodeForm
onGetEmail={email}
/>
</Box>
<Typography variant="body2" align="center">
{/* <Typography variant="body2" align="center">
Dont have a code? &nbsp;
<Link variant="subtitle2" underline="none" onClick={() => {}}>
Resend code
</Link>
</Typography> */}
<Typography variant="body2" align="center">
{localeData.txtDont} &nbsp;
{canResend ? (
<Link sx={{cursor: 'pointer'}} variant="subtitle2" underline="none" onClick={handleResend}>
{localeData.txtResendCode}
</Link>
) : (
<span>{`${localeData.txtResendCode} ${timer} ${localeData.txtSecond}`}</span>
)}
</Typography>
</Box>
</Container>

View File

@@ -52,9 +52,9 @@ export default function Router() {
},
// { path: 'login-unprotected', element: <Login /> },
// { path: 'register-unprotected', element: <Register /> },
{ path: 'forgot-password', element: <ResetPassword /> },
{ path: 'reset-password', element: <ResetPassword /> },
{ path: 'forget-password', element: <ForgetPassword /> },
// { path: 'verify', element: <VerifyCode /> },
{ path: 'verify', element: <VerifyCode /> },
],
},
// {
@@ -117,7 +117,7 @@ export default function Router() {
}
const Login = Loadable(lazy(() => import('@/pages/auth/Login')));
const ResetPassword = Loadable(lazy(() => import('@/pages/auth/VerifyCode')));
const ResetPassword = Loadable(lazy(() => import('@/pages/auth/ResetPassword')));
const ForgetPassword = Loadable(lazy(() => import('@/pages/auth/ForgetPassword')));
// Dashboard

View File

@@ -12,5 +12,5 @@ export const PATH_AUTH = {
loginUnprotected: path(ROOTS_AUTH, '/login-unprotected'),
registerUnprotected: path(ROOTS_AUTH, '/register-unprotected'),
verify: path(ROOTS_AUTH, '/verify'),
resetPassword: path(ROOTS_AUTH, '/forgot-password'),
resetPassword: path(ROOTS_AUTH, '/reset-password'),
};

View File

@@ -2,8 +2,8 @@ import * as Yup from 'yup';
// form
import { yupResolver } from '@hookform/resolvers/yup';
import { useForm } from 'react-hook-form';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Link as RouterLink, useNavigate } from 'react-router-dom';
import { useCallback, useEffect, useContext, useMemo, useRef, useState } from 'react';
import { Link as RouterLink, useNavigate, useLocation } from 'react-router-dom';
// @mui
import { Alert, IconButton, InputAdornment, Stack, Typography } from '@mui/material';
@@ -14,6 +14,9 @@ import useIsMountedRef from '@/hooks/useIsMountedRef';
import { FormProvider, RHFTextField } from '@/components/hook-form';
import axios from '@/utils/axios';
import Iconify from '@/components/Iconify';
import { LanguageContext } from '@/contexts/LanguageContext';
import { useSnackbar } from 'notistack';
// ----------------------------------------------------------------------
@@ -26,9 +29,19 @@ type Props = {
token: string;
};
function useQuery() {
return new URLSearchParams(useLocation().search);
}
export default function ForgetPasswordForm({ token }: Props) {
const { localeData } = useContext(LanguageContext);
const isMountedRef = useIsMountedRef();
const navigate = useNavigate();
const query = useQuery();
const email = query.get('email');
const token_ = query.get('token');
const { enqueueSnackbar } = useSnackbar();
const [showPasswordNew, setShowPasswordNew] = useState(false);
const [showPasswordConfirmNew, setShowPasswordConfirmNew] = useState(false);
@@ -47,19 +60,19 @@ export default function ForgetPasswordForm({ token }: Props) {
const onSubmit = async (data: FormValuesProps) => {
try {
await axios.post('/forget-password', { ...data, token });
console.log(data);
await axios.post('/forget-password', { ...data, email:email, token:token_ });
// await new Promise((resolve) => setTimeout(resolve, 500));
await new Promise((resolve) => setTimeout(resolve, 500));
if (isMountedRef.current) {
enqueueSnackbar('Password reset was successful', { variant: 'success' });
navigate('/auth/login', { replace: true });
}
} catch (error) {
console.log(error.response.data);
if (isMountedRef.current) {
setError('afterSubmit', { ...error, message: error.response.data.message });
setError('afterSubmit', { ...error, message: error.response.data.meta.message });
}
}
};
@@ -68,10 +81,10 @@ export default function ForgetPasswordForm({ token }: Props) {
<FormProvider methods={methods} onSubmit={handleSubmit(onSubmit)}>
<Stack spacing={3}>
{!!errors.afterSubmit && <Alert severity="error">{errors.afterSubmit.message}</Alert>}
<Typography>Kata Sandi Baru</Typography>
<Typography>{localeData.txtNewPassword}</Typography>
<RHFTextField
name="new_password"
label="Kata Sandi Baru"
label={localeData.txtNewPassword}
type={showPasswordNew ? 'text' : 'password'}
InputProps={{
endAdornment: (
@@ -83,10 +96,10 @@ export default function ForgetPasswordForm({ token }: Props) {
),
}}
/>
<Typography>Konfirmasi Kata Sandi </Typography>
<Typography>{localeData.txtConfPassword}</Typography>
<RHFTextField
name="confirm_new_password"
label="Konfirmasi Kata Sandi"
label={localeData.txtConfPassword}
type={showPasswordConfirmNew ? 'text' : 'password'}
InputProps={{
endAdornment: (

View File

@@ -100,9 +100,9 @@ export default function LoginForm() {
</Stack>
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ my: 2 }}>
<RHFCheckbox name="remember" label="Remember me"/>
<RHFCheckbox name="remember" label={localeData.txtIngatkanSaya}/>
<Link component={RouterLink} variant="subtitle2" to={PATH_AUTH.resetPassword}>
Forgot password?
{localeData.txtLupaSandi}
</Link>
</Stack>
@@ -114,7 +114,7 @@ export default function LoginForm() {
loading={isSubmitting}
sx={{ marginTop: 2 }}
>
Login
{localeData.txtLogin}
</LoadingButton>
</FormProvider>
);

View File

@@ -10,6 +10,7 @@ import useIsMountedRef from '@/hooks/useIsMountedRef';
// components
import { FormProvider, RHFTextField } from '@/components/hook-form';
import axios from '@/utils/axios';
import { useNavigate } from 'react-router-dom';
// ----------------------------------------------------------------------
@@ -26,6 +27,8 @@ type Props = {
export default function ResetPasswordForm({ onSent, onGetEmail }: Props) {
const isMountedRef = useIsMountedRef();
const navigate = useNavigate();
const ResetPasswordSchema = Yup.object().shape({
email: Yup.string().email('Email must be a valid email address').required('Email is required'),
});
@@ -43,19 +46,22 @@ export default function ResetPasswordForm({ onSent, onGetEmail }: Props) {
const onSubmit = async (data: FormValuesProps) => {
try {
await axios.post('/verify-email', data);
console.log(data);
const response = await axios.post('/verify-email', data);
if(response.data.data.email)
{
onGetEmail(response.data.data.email);
navigate(`/auth/verify?email=${response.data.data.email}`);
}
// await new Promise((resolve) => setTimeout(resolve, 500));
await new Promise((resolve) => setTimeout(resolve, 500));
if (isMountedRef.current) {
onSent();
onGetEmail(data.email);
onGetEmail(response.data.data.email);
}
} catch (error) {
console.log(error.response.data);
if (isMountedRef.current) {
setError('afterSubmit', { ...error, message: error.response.data.message });
setError('afterSubmit', { ...error, message: error.response.data.meta.message });
}
}
};

View File

@@ -6,9 +6,12 @@ import { useEffect } from 'react';
import { useForm, Controller } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
// @mui
import { OutlinedInput, Stack } from '@mui/material';
import { OutlinedInput, Alert, Stack } from '@mui/material';
import useIsMountedRef from '@/hooks/useIsMountedRef';
import { LoadingButton } from '@mui/lab';
import { FormProvider, RHFTextField } from '@/components/hook-form';
// routes
import axios from '@/utils/axios';
// import { PATH_DASHBOARD } from '@/routes/paths';
// ----------------------------------------------------------------------
@@ -23,8 +26,11 @@ type FormValuesProps = {
};
type ValueNames = 'code1' | 'code2' | 'code3' | 'code4' | 'code5' | 'code6';
export default function VerifyCodeForm() {
type Props = {
onGetEmail: (value: string) => void;
};
export default function VerifyCodeForm({ onGetEmail }: Props) {
const isMountedRef = useIsMountedRef();
const navigate = useNavigate();
const { enqueueSnackbar } = useSnackbar();
@@ -51,8 +57,9 @@ export default function VerifyCodeForm() {
watch,
control,
setValue,
setError,
handleSubmit,
formState: { isSubmitting, isValid },
formState: { isSubmitting, isValid , errors},
} = useForm({
mode: 'onBlur',
resolver: yupResolver(VerifyCodeSchema),
@@ -67,16 +74,36 @@ export default function VerifyCodeForm() {
}, []);
const onSubmit = async (data: FormValuesProps) => {
// try {
// await new Promise((resolve) => setTimeout(resolve, 500));
// console.log('code:', Object.values(data).join(''));
// enqueueSnackbar('Verify success!', { variant: 'success' });
// navigate('/dashboard', { replace: true });
// } catch (error) {
// console.error(error);
// }
try {
await new Promise((resolve) => setTimeout(resolve, 500));
console.log('code:', Object.values(data).join(''));
enqueueSnackbar('Verify success!', { variant: 'success' });
navigate('/dashboard', { replace: true });
} catch (error) {
console.error(error);
}
const response = await axios.post('/verify-code', {email: onGetEmail, token: Object.values(data).join('')});
// await new Promise((resolve) => setTimeout(resolve, 500));
await new Promise((resolve) => setTimeout(resolve, 500));
if(response.data.meta.code === 200)
{
navigate(`/auth/forget-password?email=${response.data.data.email}&token=${response.data.data.token}`);
}
if (isMountedRef.current) {
if(response.data.meta.code === 404)
{
setError('afterSubmit', { ...response, message: response.data.meta.message });
}
}
} catch (error) {
if (isMountedRef.current) {
setError('afterSubmit', { ...error, message: error.response.data.meta.message });
}
}
};
const handlePasteClipboard = (event: ClipboardEvent) => {
@@ -115,35 +142,38 @@ export default function VerifyCodeForm() {
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Stack direction="row" spacing={2} justifyContent="center">
{Object.keys(values).map((name, index) => (
<Controller
key={name}
name={`code${index + 1}` as ValueNames}
control={control}
render={({ field }) => (
<OutlinedInput
{...field}
id="field-code"
autoFocus={index === 0}
placeholder="-"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
handleChangeWithNextField(event, field.onChange)
}
inputProps={{
maxLength: 1,
sx: {
p: 0,
textAlign: 'center',
width: { xs: 36, sm: 56 },
height: { xs: 36, sm: 56 },
},
}}
/>
)}
/>
))}
</Stack>
<Stack spacing={3}>
{!!errors.afterSubmit && <Alert severity="error">{errors.afterSubmit.message}</Alert>}
<Stack direction="row" spacing={2} justifyContent="center">
{Object.keys(values).map((name, index) => (
<Controller
key={name}
name={`code${index + 1}` as ValueNames}
control={control}
render={({ field }) => (
<OutlinedInput
{...field}
id="field-code"
autoFocus={index === 0}
placeholder="-"
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
handleChangeWithNextField(event, field.onChange)
}
inputProps={{
maxLength: 1,
sx: {
p: 0,
textAlign: 'center',
width: { xs: 36, sm: 56 },
height: { xs: 36, sm: 56 },
},
}}
/>
)}
/>
))}
</Stack>
</Stack>
<LoadingButton
fullWidth

View File

@@ -25,7 +25,8 @@ import axios from './axios';
// }, timeLeft);
// };
let expiredCookie = '12 * 60';
// let expiredCookie = 1/24/60; 1 menit
let expiredCookie = 12/24; //12 jam
const setCookie = (name:any, value:any, days:any) => {
let expires = "";