Update Add user hospital portal
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 () {
|
||||
|
||||
@@ -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": "Don’t have a code?",
|
||||
"txtResendCode": "Resend code",
|
||||
"txtSecond": "Second",
|
||||
"txtPleaseInput": "Please enter your new password.",
|
||||
"txtNewPassword": "New Password",
|
||||
"txtConfPassword": "Confirm Kata Sandi"
|
||||
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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 }}>
|
||||
|
||||
@@ -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
|
||||
{localeData.txtCodeConfirm}
|
||||
<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>
|
||||
)}
|
||||
|
||||
@@ -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">
|
||||
Don’t have a code?
|
||||
<Link variant="subtitle2" underline="none" onClick={() => {}}>
|
||||
Resend code
|
||||
</Link>
|
||||
</Typography> */}
|
||||
<Typography variant="body2" align="center">
|
||||
{localeData.txtDont}
|
||||
{canResend ? (
|
||||
<Link sx={{cursor: 'pointer'}} variant="subtitle2" underline="none" onClick={handleResend}>
|
||||
{localeData.txtResendCode}
|
||||
</Link>
|
||||
) : (
|
||||
<span>{`${localeData.txtResendCode} ${timer} ${localeData.txtSecond}`}</span>
|
||||
)}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Container>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'),
|
||||
};
|
||||
|
||||
@@ -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: (
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = "";
|
||||
|
||||
Reference in New Issue
Block a user