diff --git a/frontend/client-portal/src/contexts/LaravelAuthContext.tsx b/frontend/client-portal/src/contexts/LaravelAuthContext.tsx index 06112bb0..d78a6afc 100755 --- a/frontend/client-portal/src/contexts/LaravelAuthContext.tsx +++ b/frontend/client-portal/src/contexts/LaravelAuthContext.tsx @@ -6,7 +6,7 @@ import { setSession, getSession, getUser } from '../utils/token'; // @types import { ActionMap, AuthState, AuthUser, JWTContextType } from '../@types/auth'; // ---------------------------------------------------------------------- -import { Navigate, useLocation } from 'react-router-dom'; +// import { Navigate, useLocation } from 'react-router-dom'; enum Types { Initial = 'INITIALIZE', diff --git a/frontend/client-portal/src/guards/AuthGuard.tsx b/frontend/client-portal/src/guards/AuthGuard.tsx index 7e470c7d..43a0e91a 100755 --- a/frontend/client-portal/src/guards/AuthGuard.tsx +++ b/frontend/client-portal/src/guards/AuthGuard.tsx @@ -2,8 +2,6 @@ import { useState, ReactNode } from 'react'; import { Navigate, useLocation } from 'react-router-dom'; // hooks import useAuth from '../hooks/useAuth'; -// pages -import Login from '../pages/auth/Login'; // components import LoadingScreen from '../components/LoadingScreen'; @@ -26,7 +24,7 @@ export default function AuthGuard({ children }: AuthGuardProps) { if (pathname !== requestedLocation) { setRequestedLocation(pathname); } - return ; + return ; } if (requestedLocation && pathname !== requestedLocation) { diff --git a/frontend/client-portal/src/pages/auth/Login.tsx b/frontend/client-portal/src/pages/auth/Login.tsx index 6fa930ee..a3686873 100755 --- a/frontend/client-portal/src/pages/auth/Login.tsx +++ b/frontend/client-portal/src/pages/auth/Login.tsx @@ -11,7 +11,8 @@ import Image from '../../components/Image'; import { LoginEmailForm, LoginPhoneForm } from '../../sections/auth/login'; import Logo from '../../components/Logo'; // react -import { useState } from 'react'; +import { useState, useEffect } from 'react'; +import { useLocation } from 'react-router-dom'; // ---------------------------------------------------------------------- @@ -36,13 +37,20 @@ const ContentStyle = styled(Card)(({ theme }) => ({ export default function Login() { const { method } = useAuth(); + const location = useLocation(); const [formPhone, setFormPhone] = useState(false); + // const { setForm } = location.state; const handlerChange = (event: any, setForm: boolean) => { event.preventDefault(); setFormPhone(setForm); }; + useEffect(() => { + console.log('setForm'); + // setFormPhone(setForm ? setForm : true); + }, []); + return ( diff --git a/frontend/client-portal/src/pages/auth/OtpValidation.tsx b/frontend/client-portal/src/pages/auth/OtpValidation.tsx new file mode 100755 index 00000000..cf427ea9 --- /dev/null +++ b/frontend/client-portal/src/pages/auth/OtpValidation.tsx @@ -0,0 +1,134 @@ +import { capitalCase } from 'change-case'; +// @mui +import { styled } from '@mui/material/styles'; +import { + Box, + Button, + Card, + Divider, + Grid, + Link, + Stack, + IconButton, + Typography, +} from '@mui/material'; +// hooks +import useAuth from '../../hooks/useAuth'; +// components +import Page from '../../components/Page'; +import Image from '../../components/Image'; +import Iconify from '../../components/Iconify'; +// sections +import { VerifyCodeForm } from '../../sections/auth/verify-code'; +// react +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; + +// ---------------------------------------------------------------------- + +const RootStyle = styled('div')(({ theme }) => ({ + [theme.breakpoints.up('md')]: { + display: 'flex', + }, + minHeight: '100vh', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', +})); + +const ContentStyle = styled(Card)(({ theme }) => ({ + [theme.breakpoints.up('md')]: { + maxHeight: '600px', + maxWidth: '1000px', + }, +})); + +// ---------------------------------------------------------------------- + +export default function OtpValidation() { + const { method } = useAuth(); + const navigate = useNavigate(); + const formPhone = false; + + const handlerChange = (event: any, setForm: boolean) => { + event.preventDefault(); + // setFormPhone(setForm); + navigate('/auth/login', { state: { setForm: setForm } }); + }; + + const otpRequestHandler = (event: any) => { + event.preventDefault(); + alert('otp sudah dikirim ulang!'); + }; + + return ( + + + + + + login + + + + + + + + Verifikasi OTP + + + {/* */} + + Masukkan kode OTP anda disini + + {/* */} + + + + + + + Tidak Mendapatkan Kode? + + otpRequestHandler(event)} + > + Kirim Ulang Kode OTP + + + + Atau + + + {formPhone === false ? ( + handlerChange(event, true)} + > + Masuk menggunakan nomor handphone + + ) : ( + handlerChange(event, false)} + > + Masuk menggunakan email + + )} + + + + + + + ); +} diff --git a/frontend/client-portal/src/pages/auth/Register.tsx b/frontend/client-portal/src/pages/auth/Register.tsx deleted file mode 100755 index 89a364d3..00000000 --- a/frontend/client-portal/src/pages/auth/Register.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import { capitalCase } from 'change-case'; -import { Link as RouterLink } from 'react-router-dom'; -// @mui -import { styled } from '@mui/material/styles'; -import { Box, Card, Link, Container, Typography, Tooltip } from '@mui/material'; -// hooks -import useAuth from '../../hooks/useAuth'; -import useResponsive from '../../hooks/useResponsive'; -// routes -import { PATH_AUTH } from '../../routes/paths'; -// components -import Page from '../../components/Page'; -import Logo from '../../components/Logo'; -import Image from '../../components/Image'; -// sections -import { RegisterForm } from '../../sections/auth/register'; - -// ---------------------------------------------------------------------- - -const RootStyle = styled('div')(({ theme }) => ({ - [theme.breakpoints.up('md')]: { - display: 'flex', - }, -})); - -const HeaderStyle = styled('header')(({ theme }) => ({ - top: 0, - zIndex: 9, - lineHeight: 0, - width: '100%', - display: 'flex', - alignItems: 'center', - position: 'absolute', - padding: theme.spacing(3), - justifyContent: 'space-between', - [theme.breakpoints.up('md')]: { - alignItems: 'flex-start', - padding: theme.spacing(7, 5, 0, 7), - }, -})); - -const SectionStyle = styled(Card)(({ theme }) => ({ - width: '100%', - maxWidth: 464, - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - margin: theme.spacing(2, 0, 2, 2), -})); - -const ContentStyle = styled('div')(({ theme }) => ({ - maxWidth: 480, - margin: 'auto', - display: 'flex', - minHeight: '100vh', - flexDirection: 'column', - justifyContent: 'center', - padding: theme.spacing(12, 0), -})); - -// ---------------------------------------------------------------------- - -export default function Register() { - const { method } = useAuth(); - - const smUp = useResponsive('up', 'sm'); - - const mdUp = useResponsive('up', 'md'); - - return ( - - - - - {smUp && ( - - Already have an account? {''} - - Login - - - )} - - - {mdUp && ( - - - Manage the job more effectively with Minimal - - register - - )} - - - - - - - Get started absolutely free. - - - Free forever. No credit card needed. - - - - <> - - - - - - - - - By registering, I agree to Minimal  - - Terms of Service - - {''}and{''} - - Privacy Policy - - . - - - {!smUp && ( - - Already have an account?{' '} - - Login - - - )} - - - - - ); -} diff --git a/frontend/client-portal/src/pages/auth/ResetPassword.tsx b/frontend/client-portal/src/pages/auth/ResetPassword.tsx deleted file mode 100755 index bd306e90..00000000 --- a/frontend/client-portal/src/pages/auth/ResetPassword.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { useState } from 'react'; -import { Link as RouterLink } from 'react-router-dom'; -// @mui -import { styled } from '@mui/material/styles'; -import { Box, Button, Container, Typography } from '@mui/material'; -// layouts -import LogoOnlyLayout from '../../layouts/LogoOnlyLayout'; -// routes -import { PATH_AUTH } from '../../routes/paths'; -// components -import Page from '../../components/Page'; -// sections -import { ResetPasswordForm } from '../../sections/auth/reset-password'; -// assets -import { SentIcon } from '../../assets'; - -// ---------------------------------------------------------------------- - -const RootStyle = styled('div')(({ theme }) => ({ - display: 'flex', - minHeight: '100%', - alignItems: 'center', - justifyContent: 'center', - padding: theme.spacing(12, 0), -})); - -// ---------------------------------------------------------------------- - -export default function ResetPassword() { - const [email, setEmail] = useState(''); - - const [sent, setSent] = useState(false); - - return ( - - - - - - - {!sent ? ( - <> - - Forgot your password? - - - - Please enter the email address associated with your account and We will email you - a link to reset your password. - - - setSent(true)} - onGetEmail={(value) => setEmail(value)} - /> - - - - ) : ( - - - - - Request sent successfully - - - - We have sent a confirmation email to   - {email} -
- Please check your email. -
- - -
- )} -
-
-
-
- ); -} diff --git a/frontend/client-portal/src/pages/auth/VerifyCode.tsx b/frontend/client-portal/src/pages/auth/VerifyCode.tsx deleted file mode 100755 index 1ca75352..00000000 --- a/frontend/client-portal/src/pages/auth/VerifyCode.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { Link as RouterLink } from 'react-router-dom'; -// @mui -import { styled } from '@mui/material/styles'; -import { Box, Button, Link, Container, Typography } from '@mui/material'; -// layouts -import LogoOnlyLayout from '../../layouts/LogoOnlyLayout'; -// routes -import { PATH_AUTH } from '../../routes/paths'; -// components -import Page from '../../components/Page'; -import Iconify from '../../components/Iconify'; -// sections -import { VerifyCodeForm } from '../../sections/auth/verify-code'; - -// ---------------------------------------------------------------------- - -const RootStyle = styled('div')(({ theme }) => ({ - display: 'flex', - height: '100%', - alignItems: 'center', - padding: theme.spacing(12, 0), -})); - -// ---------------------------------------------------------------------- - -export default function VerifyCode() { - return ( - - - - - - - - - - Please check your email! - - - We have emailed a 6-digit confirmation code to acb@domain, please enter the code in - below box to verify your email. - - - - - - - - Don’t have a code?   - {}}> - Resend code - - - - - - - ); -} diff --git a/frontend/client-portal/src/routes/index.tsx b/frontend/client-portal/src/routes/index.tsx index 8657227c..9773025a 100755 --- a/frontend/client-portal/src/routes/index.tsx +++ b/frontend/client-portal/src/routes/index.tsx @@ -6,7 +6,6 @@ import LogoOnlyLayout from '../layouts/LogoOnlyLayout'; // components import LoadingScreen from '../components/LoadingScreen'; import GuestGuard from '../guards/GuestGuard'; -import { RegisterForm } from '../sections/auth/register'; import { AuthProvider } from '../contexts/LaravelAuthContext'; import AuthGuard from '../guards/AuthGuard'; @@ -39,11 +38,11 @@ export default function Router() { ), }, { - path: 'register', + path: 'otp-validation', element: ( - + ), @@ -113,6 +112,7 @@ export default function Router() { } const Login = Loadable(lazy(() => import('../pages/auth/Login'))); +const OtpValidation = Loadable(lazy(() => import('../pages/auth/OtpValidation'))); // Dashboard const Dashboard = Loadable(lazy(() => import('../pages/Dashboard'))); diff --git a/frontend/client-portal/src/sections/auth/login/LoginPhoneForm.tsx b/frontend/client-portal/src/sections/auth/login/LoginPhoneForm.tsx index 0ea7346e..f1a35f1a 100755 --- a/frontend/client-portal/src/sections/auth/login/LoginPhoneForm.tsx +++ b/frontend/client-portal/src/sections/auth/login/LoginPhoneForm.tsx @@ -44,8 +44,7 @@ export default function LoginPhoneForm() { const onSubmit = async (data: FormValuesProps) => { try { await axios.post('/otp-request', { phone_or_email: 0 + data.phone }); - // console.log(response); - // navigate('/dashboard'); + navigate('/auth/otp-validation', { state: { phone_or_email: 0 + data.phone } }); } catch (error: any) { reset(); setError('afterSubmit', { ...error, message: error.response.data.message }); diff --git a/frontend/client-portal/src/sections/auth/register/RegisterForm.tsx b/frontend/client-portal/src/sections/auth/register/RegisterForm.tsx deleted file mode 100755 index 6646de5e..00000000 --- a/frontend/client-portal/src/sections/auth/register/RegisterForm.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import * as Yup from 'yup'; -import { useState } from 'react'; -// form -import { useForm } from 'react-hook-form'; -import { yupResolver } from '@hookform/resolvers/yup'; -// @mui -import { Stack, IconButton, InputAdornment, Alert } from '@mui/material'; -import { LoadingButton } from '@mui/lab'; -// hooks -import useAuth from '../../../hooks/useAuth'; -import useIsMountedRef from '../../../hooks/useIsMountedRef'; -// components -import Iconify from '../../../components/Iconify'; -import { FormProvider, RHFTextField } from '../../../components/hook-form'; - -// ---------------------------------------------------------------------- - -type FormValuesProps = { - email: string; - password: string; - firstName: string; - lastName: string; - afterSubmit?: string; -}; - -export default function RegisterForm() { - const { register } = useAuth(); - - const isMountedRef = useIsMountedRef(); - - const [showPassword, setShowPassword] = useState(false); - - const RegisterSchema = Yup.object().shape({ - firstName: Yup.string().required('First name required'), - lastName: Yup.string().required('Last name required'), - email: Yup.string().email('Email must be a valid email address').required('Email is required'), - password: Yup.string().required('Password is required'), - }); - - const defaultValues = { - firstName: '', - lastName: '', - email: '', - password: '', - }; - - const methods = useForm({ - resolver: yupResolver(RegisterSchema), - defaultValues, - }); - - const { - reset, - setError, - handleSubmit, - formState: { errors, isSubmitting }, - } = methods; - - const onSubmit = async (data: FormValuesProps) => { - try { - await register(data.email, data.password, data.firstName, data.lastName); - } catch (error) { - console.error(error); - reset(); - if (isMountedRef.current) { - setError('afterSubmit', { ...error, message: error.message }); - } - } - }; - - return ( - - - {!!errors.afterSubmit && {errors.afterSubmit.message}} - - - - - - - - - - setShowPassword(!showPassword)}> - - - - ), - }} - /> - - - Register - - - - ); -} diff --git a/frontend/client-portal/src/sections/auth/register/index.ts b/frontend/client-portal/src/sections/auth/register/index.ts deleted file mode 100755 index fa2e7cdd..00000000 --- a/frontend/client-portal/src/sections/auth/register/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as RegisterForm } from './RegisterForm'; diff --git a/frontend/client-portal/src/sections/auth/reset-password/ResetPasswordForm.tsx b/frontend/client-portal/src/sections/auth/reset-password/ResetPasswordForm.tsx deleted file mode 100755 index 24ae1d12..00000000 --- a/frontend/client-portal/src/sections/auth/reset-password/ResetPasswordForm.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import * as Yup from 'yup'; -// form -import { yupResolver } from '@hookform/resolvers/yup'; -import { useForm } from 'react-hook-form'; -// @mui -import { Stack } from '@mui/material'; -import { LoadingButton } from '@mui/lab'; -// hooks -import useIsMountedRef from '../../../hooks/useIsMountedRef'; -// components -import { FormProvider, RHFTextField } from '../../../components/hook-form'; - -// ---------------------------------------------------------------------- - -type FormValuesProps = { - email: string; -}; - -type Props = { - onSent: VoidFunction; - onGetEmail: (value: string) => void; -}; - -export default function ResetPasswordForm({ onSent, onGetEmail }: Props) { - const isMountedRef = useIsMountedRef(); - - const ResetPasswordSchema = Yup.object().shape({ - email: Yup.string().email('Email must be a valid email address').required('Email is required'), - }); - - const methods = useForm({ - resolver: yupResolver(ResetPasswordSchema), - defaultValues: { email: 'demo@minimals.cc' }, - }); - - const { - handleSubmit, - formState: { isSubmitting }, - } = methods; - - const onSubmit = async (data: FormValuesProps) => { - try { - await new Promise((resolve) => setTimeout(resolve, 500)); - if (isMountedRef.current) { - onSent(); - onGetEmail(data.email); - } - } catch (error) { - console.error(error); - } - }; - - return ( - - - - - - Reset Password - - - - ); -} diff --git a/frontend/client-portal/src/sections/auth/reset-password/index.ts b/frontend/client-portal/src/sections/auth/reset-password/index.ts deleted file mode 100755 index 296ab36a..00000000 --- a/frontend/client-portal/src/sections/auth/reset-password/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as ResetPasswordForm } from './ResetPasswordForm'; diff --git a/frontend/client-portal/src/sections/auth/verify-code/VerifyCodeForm.tsx b/frontend/client-portal/src/sections/auth/verify-code/VerifyCodeForm.tsx index cfe2ec6a..ffadb2a8 100755 --- a/frontend/client-portal/src/sections/auth/verify-code/VerifyCodeForm.tsx +++ b/frontend/client-portal/src/sections/auth/verify-code/VerifyCodeForm.tsx @@ -1,13 +1,12 @@ import * as Yup from 'yup'; import { useSnackbar } from 'notistack'; -import { useNavigate } from 'react-router-dom'; +import { useNavigate, useLocation } from 'react-router-dom'; import { useEffect } from 'react'; // form import { useForm, Controller } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; // @mui import { OutlinedInput, Stack } from '@mui/material'; -import { LoadingButton } from '@mui/lab'; // routes // import { PATH_DASHBOARD } from '../../../routes/paths'; @@ -18,24 +17,22 @@ type FormValuesProps = { code2: string; code3: string; code4: string; - code5: string; - code6: string; }; -type ValueNames = 'code1' | 'code2' | 'code3' | 'code4' | 'code5' | 'code6'; +type ValueNames = 'code1' | 'code2' | 'code3' | 'code4'; export default function VerifyCodeForm() { const navigate = useNavigate(); - + const location = useLocation(); const { enqueueSnackbar } = useSnackbar(); + const { phone_or_email } = location.state; + const VerifyCodeSchema = Yup.object().shape({ code1: Yup.string().required('Code is required'), code2: Yup.string().required('Code is required'), code3: Yup.string().required('Code is required'), code4: Yup.string().required('Code is required'), - code5: Yup.string().required('Code is required'), - code6: Yup.string().required('Code is required'), }); const defaultValues = { @@ -43,8 +40,6 @@ export default function VerifyCodeForm() { code2: '', code3: '', code4: '', - code5: '', - code6: '', }; const { @@ -62,6 +57,7 @@ export default function VerifyCodeForm() { const values = watch(); useEffect(() => { + console.log('phone number : ' + phone_or_email); document.addEventListener('paste', handlePasteClipboard); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -73,7 +69,7 @@ export default function VerifyCodeForm() { enqueueSnackbar('Verify success!'); - navigate('/dashboard', { replace: true }); + // navigate('/dashboard', { replace: true }); } catch (error) { console.error(error); } @@ -114,7 +110,7 @@ export default function VerifyCodeForm() { }; return ( -
+ {Object.keys(values).map((name, index) => ( ))} - - - Verify -
); }