summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src-migrate/common/stores/useRegisterStore.ts28
-rw-r--r--src-migrate/common/types/auth.ts10
-rw-r--r--src-migrate/common/validations/auth.ts13
-rw-r--r--src-migrate/modules/account-activation/components/FormEmail.tsx3
-rw-r--r--src-migrate/modules/account-activation/components/FormOTP.tsx12
-rw-r--r--src-migrate/modules/account-activation/components/FormToken.tsx19
-rw-r--r--src-migrate/modules/register/components/Form.tsx19
-rw-r--r--src/lib/auth/components/LoginDesktop.jsx82
-rw-r--r--src/lib/auth/components/LoginMobile.jsx99
-rw-r--r--src/styles/globals.css6
10 files changed, 186 insertions, 105 deletions
diff --git a/src-migrate/common/stores/useRegisterStore.ts b/src-migrate/common/stores/useRegisterStore.ts
index 725bbfda..d6c7db2a 100644
--- a/src-migrate/common/stores/useRegisterStore.ts
+++ b/src-migrate/common/stores/useRegisterStore.ts
@@ -1,8 +1,13 @@
import { create } from 'zustand';
import { RegisterProps } from '../types/auth';
+import { registerSchema } from '../validations/auth';
+import { ValidationError } from 'yup';
type State = {
form: RegisterProps;
+ errors: {
+ [key in keyof RegisterProps]?: string;
+ };
isValid: boolean;
isCheckedTNC: boolean;
isOpenTNC: boolean;
@@ -15,9 +20,10 @@ type Action = {
toggleCheckTNC: () => void;
openTNC: () => void;
closeTNC: () => void;
+ validate: () => void;
};
-export const useRegisterStore = create<State & Action>((set) => ({
+export const useRegisterStore = create<State & Action>((set, get) => ({
form: {
company: '',
name: '',
@@ -25,6 +31,26 @@ export const useRegisterStore = create<State & Action>((set) => ({
password: '',
phone: '',
},
+ errors: {},
+ validate: () =>
+ registerSchema
+ .validate(get().form, { abortEarly: false })
+ .then(() => {
+ set({
+ errors: {},
+ isValid: false,
+ });
+ })
+ .catch((err: ValidationError) => {
+ const validationErrors: State['errors'] = {};
+ err.inner.forEach(
+ (e) => (validationErrors[e.path as keyof RegisterProps] = e.message)
+ );
+ set({
+ errors: validationErrors,
+ isValid: false,
+ });
+ }),
isValid: false,
isCheckedTNC: false,
isOpenTNC: false,
diff --git a/src-migrate/common/types/auth.ts b/src-migrate/common/types/auth.ts
index ca7b562a..5909584a 100644
--- a/src-migrate/common/types/auth.ts
+++ b/src-migrate/common/types/auth.ts
@@ -1,4 +1,6 @@
+import { registerSchema } from '../validations/auth';
import { OdooApiProps } from './odoo';
+import * as yup from 'yup';
export type AuthProps = {
id: number;
@@ -17,13 +19,7 @@ export type AuthProps = {
export type AuthApiProps = OdooApiProps & { result: AuthProps };
-export type RegisterProps = {
- name: string;
- email: string;
- password: string;
- company: string;
- phone: string;
-};
+export type RegisterProps = yup.InferType<typeof registerSchema>;
export type RegisterResApiProps = {
register: boolean;
diff --git a/src-migrate/common/validations/auth.ts b/src-migrate/common/validations/auth.ts
new file mode 100644
index 00000000..94b40849
--- /dev/null
+++ b/src-migrate/common/validations/auth.ts
@@ -0,0 +1,13 @@
+import { object, string } from 'yup';
+
+export const registerSchema = object({
+ name: string().required('Nama harus diisi'),
+ email: string()
+ .email('Email harus menggunakan format example@mail.com')
+ .required('Email harus diisi'),
+ password: string()
+ .min(6, 'Password minimal 6 karakter')
+ .required('Password harus diisi'),
+ company: string().optional(),
+ phone: string().required('Nomor telepon harus diisi'),
+});
diff --git a/src-migrate/modules/account-activation/components/FormEmail.tsx b/src-migrate/modules/account-activation/components/FormEmail.tsx
index cd917bc9..ec300ba4 100644
--- a/src-migrate/modules/account-activation/components/FormEmail.tsx
+++ b/src-migrate/modules/account-activation/components/FormEmail.tsx
@@ -43,7 +43,8 @@ const FormEmail = () => {
if (mutation.data?.activation_request === true) {
const urlParams = new URLSearchParams({
activation: 'otp',
- email
+ email,
+ redirect: (router.query?.redirect || '/') as string
})
router.push(`${router.route}?${urlParams}`)
}
diff --git a/src-migrate/modules/account-activation/components/FormOTP.tsx b/src-migrate/modules/account-activation/components/FormOTP.tsx
index a4775d61..47c69329 100644
--- a/src-migrate/modules/account-activation/components/FormOTP.tsx
+++ b/src-migrate/modules/account-activation/components/FormOTP.tsx
@@ -54,8 +54,9 @@ const FormOTP = () => {
useEffect(() => {
if (mutationActivation.data?.user) {
setAuth(mutationActivation.data.user)
+ router.push((query?.redirect || '/') as string)
}
- }, [mutationActivation.data])
+ }, [mutationActivation.data, router, query.redirect])
return (
<Modal active={active} className="w-10/12 md:w-fit px-10" mode="desktop">
@@ -78,10 +79,6 @@ const FormOTP = () => {
<span className="text-red-700">Mohon maaf kode OTP yand anda masukan salah</span>
)
}
-
- {mutationActivation.data?.activation && (
- <span className="text-success-700">Akun anda berhasil diaktifkan, selamat berbelanja di Indoteknik.</span>
- )}
</div>
{!mutationActivation.data?.activation && (
@@ -108,11 +105,6 @@ const FormOTP = () => {
</>
)}
- {mutationActivation.data?.activation && (
- <Link href='/' className="text-success-700 underline">Kembali ke halaman utama</Link>
- )}
-
-
</div>
</div>
</Modal>
diff --git a/src-migrate/modules/account-activation/components/FormToken.tsx b/src-migrate/modules/account-activation/components/FormToken.tsx
index a1525fe6..b68b244f 100644
--- a/src-migrate/modules/account-activation/components/FormToken.tsx
+++ b/src-migrate/modules/account-activation/components/FormToken.tsx
@@ -10,7 +10,8 @@ import { activationUserToken } from "~/services/auth"
import { setAuth } from "~/common/libs/auth"
const FormToken = () => {
- const { query } = useRouter()
+ const router = useRouter()
+ const { query } = router
const [active, setActive] = useState<boolean>(false)
const mutation = useMutation({
@@ -28,8 +29,9 @@ const FormToken = () => {
useEffect(() => {
if (mutation.data?.user) {
setAuth(mutation.data.user)
+ router.push((query?.redirect || '/') as string)
}
- }, [mutation.data])
+ }, [mutation.data, router, query.redirect])
return (
<Modal active={active} mode="desktop">
@@ -41,7 +43,7 @@ const FormToken = () => {
</>
)}
- {!mutation.isLoading && (
+ {!mutation.isLoading && !mutation.data?.activation && (
<Alert
status={mutation.data?.activation ? 'success' : 'error'}
flexDirection="column"
@@ -53,17 +55,10 @@ const FormToken = () => {
>
<AlertIcon boxSize="40px" mr={0} />
<AlertTitle className="mt-4 mb-1 text-h-sm">
- Aktivasi akun {mutation.data?.activation ? 'berhasil' : 'gagal'}
+ Aktivasi akun gagal
</AlertTitle>
<AlertDescription maxWidth="sm">
- {mutation.data?.activation && (
- <>
- Akun anda berhasil diaktifkan, selamat berbelanja di Indoteknik.
- <Link href='/' className="block mt-8 text-success-700 underline">Kembali ke halaman utama</Link>
- </>
- )}
-
- {!mutation.data?.activation && mutation.data?.reason === 'INVALID_TOKEN' && (
+ {mutation.data?.reason === 'INVALID_TOKEN' && (
<>
Token sudah kadaluwarsa, silahkan coba kembali.
<Link href='/register?activation=email' className="block mt-8 text-red-700 underline">Aktivasi Akun</Link>
diff --git a/src-migrate/modules/register/components/Form.tsx b/src-migrate/modules/register/components/Form.tsx
index 3227a549..5b51d6f4 100644
--- a/src-migrate/modules/register/components/Form.tsx
+++ b/src-migrate/modules/register/components/Form.tsx
@@ -8,6 +8,7 @@ import FormCaptcha from "./FormCaptcha";
import { useRouter } from "next/router";
import { UseToastOptions, useToast } from "@chakra-ui/react";
import Link from "next/link";
+import { registerSchema } from "~/common/validations/auth";
const Form = () => {
const {
@@ -15,7 +16,9 @@ const Form = () => {
isValid,
isCheckedTNC,
isValidCaptcha,
+ errors,
updateForm,
+ validate,
} = useRegisterStore()
const router = useRouter()
const toast = useToast()
@@ -23,6 +26,7 @@ const Form = () => {
const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
updateForm(name, value)
+ validate()
}
const mutation = useMutation({
@@ -37,7 +41,8 @@ const Form = () => {
if (response?.register === true) {
const urlParams = new URLSearchParams({
activation: 'otp',
- email: form.email
+ email: form.email,
+ redirect: (router.query?.next || '/') as string
})
router.push(`${router.route}?${urlParams}`)
}
@@ -97,7 +102,10 @@ const Form = () => {
placeholder='Masukan nama lengkap anda'
value={form.name}
onChange={handleInputChange}
+ aria-invalid={!!errors.name}
/>
+
+ {!!errors.name && <span className="form-msg-danger">{errors.name}</span>}
</div>
<div>
@@ -111,7 +119,10 @@ const Form = () => {
placeholder='08xxxxxxxx'
value={form.phone}
onChange={handleInputChange}
+ aria-invalid={!!errors.phone}
/>
+
+ {!!errors.phone && <span className="form-msg-danger">{errors.phone}</span>}
</div>
<div>
@@ -126,7 +137,10 @@ const Form = () => {
value={form.email}
onChange={handleInputChange}
autoComplete="username"
+ aria-invalid={!!errors.email}
/>
+
+ {!!errors.email && <span className="form-msg-danger">{errors.email}</span>}
</div>
<div>
@@ -140,7 +154,10 @@ const Form = () => {
value={form.password}
onChange={handleInputChange}
autoComplete="current-password"
+ aria-invalid={!!errors.password}
/>
+
+ {!!errors.password && <span className="form-msg-danger">{errors.password}</span>}
</div>
<FormCaptcha />
diff --git a/src/lib/auth/components/LoginDesktop.jsx b/src/lib/auth/components/LoginDesktop.jsx
index d22da6f8..1333db14 100644
--- a/src/lib/auth/components/LoginDesktop.jsx
+++ b/src/lib/auth/components/LoginDesktop.jsx
@@ -1,46 +1,54 @@
-import DesktopView from '@/core/components/views/DesktopView'
-import useLogin from '../hooks/useLogin'
-import Link from '@/core/components/elements/Link/Link'
-import PageContent from '@/lib/content/components/PageContent'
-import Alert from '@/core/components/elements/Alert/Alert'
-import { useSession, signIn, SignOut } from 'next-auth/react'
-import Image from 'next/image'
-import { useRouter } from 'next/router'
-import { useContext, useEffect, useState } from 'react'
-import { getAuth, setAuth } from '@/core/utils/auth'
-import { setCookie } from 'cookies-next'
-import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
-import Spinner from '@/core/components/elements/Spinner/Spinner'
-import LogoSpinner from '@/core/components/elements/Spinner/LogoSpinner'
-import odooApi from '@/core/api/odooApi'
+import DesktopView from '@/core/components/views/DesktopView';
+import useLogin from '../hooks/useLogin';
+import Link from '@/core/components/elements/Link/Link';
+import PageContent from '@/lib/content/components/PageContent';
+import Alert from '@/core/components/elements/Alert/Alert';
+import { useSession, signIn, SignOut } from 'next-auth/react';
+import { useRouter } from 'next/router';
+import { useEffect, useState } from 'react';
+import BottomPopup from '@/core/components/elements/Popup/BottomPopup';
+import LogoSpinner from '@/core/components/elements/Spinner/LogoSpinner';
const LoginDesktop = () => {
- const { handleSubmit, handleChangeInput, isLoading, isValid, alert, emailRef, passwordRef, handleGoogleSubmit } =
- useLogin()
+ const {
+ handleSubmit,
+ handleChangeInput,
+ isLoading,
+ isValid,
+ alert,
+ emailRef,
+ passwordRef,
+ handleGoogleSubmit,
+ } = useLogin();
- const router = useRouter()
- const [query, setQuery] = useState(router?.query?.next || '/')
- const { data: session } = useSession()
+ const router = useRouter();
+ const [query, setQuery] = useState(router?.query?.next || '/');
+ const { data: session } = useSession();
const handleGoogle = async () => {
- const url = query != '/' ? '/login?source=google&next=' + query : '/login?source=google'
- await signIn('google', { callbackUrl: url })
- }
+ const url =
+ query != '/'
+ ? '/login?source=google&next=' + query
+ : '/login?source=google';
+ await signIn('google', { callbackUrl: url });
+ };
useEffect(() => {
if (session) {
- handleGoogleSubmit(session)
+ handleGoogleSubmit(session);
}
- }, [session])
+ }, [session]);
if (router.query.source) {
return (
<BottomPopup active={true} close=''>
- <div className='leading-7 text-gray_r-12/80 flex justify-center'>Mohon Tunggu</div>
+ <div className='leading-7 text-gray_r-12/80 flex justify-center'>
+ Mohon Tunggu
+ </div>
<div className='container flex justify-center my-4'>
<LogoSpinner width={48} height={48} />
</div>
</BottomPopup>
- )
+ );
}
return (
@@ -48,7 +56,9 @@ const LoginDesktop = () => {
<div className='container mx-auto'>
<div className='grid grid-cols-2 gap-x-10 pt-16'>
<div>
- <h1 className='text-2xl font-semibold'>Selamat Datang di Indoteknik</h1>
+ <h1 className='text-2xl font-semibold'>
+ Selamat Datang di Indoteknik
+ </h1>
<h2 className='text-gray_r-11 font-normal mt-1 mb-4'>
Masuk ke akun kamu untuk mulai transaksi!
</h2>
@@ -59,7 +69,10 @@ const LoginDesktop = () => {
</Alert>
)}
- <form className='w-full mt-6 flex flex-col gap-y-4' onSubmit={handleSubmit}>
+ <form
+ className='w-full mt-6 flex flex-col gap-y-4'
+ onSubmit={handleSubmit}
+ >
<div>
<label htmlFor='email'>Alamat Email</label>
<input
@@ -118,7 +131,10 @@ const LoginDesktop = () => {
<div className='text-gray_r-11 mt-10'>
Belum punya akun Indoteknik?{' '}
- <Link href='/register' className='inline'>
+ <Link
+ href={`/register?${new URLSearchParams(router.query)}`}
+ className='inline'
+ >
Daftar akun baru
</Link>
</div>
@@ -129,7 +145,7 @@ const LoginDesktop = () => {
</div>
</div>
</DesktopView>
- )
-}
+ );
+};
-export default LoginDesktop
+export default LoginDesktop;
diff --git a/src/lib/auth/components/LoginMobile.jsx b/src/lib/auth/components/LoginMobile.jsx
index 6e1831d4..58ae4e6e 100644
--- a/src/lib/auth/components/LoginMobile.jsx
+++ b/src/lib/auth/components/LoginMobile.jsx
@@ -1,19 +1,17 @@
-import Image from 'next/image'
-import IndoteknikLogo from '@/images/logo.png'
-import Link from '@/core/components/elements/Link/Link'
-import Alert from '@/core/components/elements/Alert/Alert'
-import MobileView from '@/core/components/views/MobileView'
-import useLogin from '../hooks/useLogin'
+import Image from 'next/image';
+import IndoteknikLogo from '@/images/logo.png';
+import Link from '@/core/components/elements/Link/Link';
+import Alert from '@/core/components/elements/Alert/Alert';
+import MobileView from '@/core/components/views/MobileView';
+import useLogin from '../hooks/useLogin';
-import { useSession, signIn, SignOut } from 'next-auth/react'
-import { useRouter } from 'next/router'
-import { useEffect, useState } from 'react'
-import { setCookie } from 'cookies-next'
-import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
-import LogoSpinner from '@/core/components/elements/Spinner/LogoSpinner'
-import odooApi from '@/core/api/odooApi'
-import { getAuth } from '@/core/utils/auth'
-import PageContent from '@/lib/content/components/PageContent'
+import { useSession, signIn, SignOut } from 'next-auth/react';
+import { useRouter } from 'next/router';
+import { useEffect, useState } from 'react';
+import BottomPopup from '@/core/components/elements/Popup/BottomPopup';
+import LogoSpinner from '@/core/components/elements/Spinner/LogoSpinner';
+import { getAuth } from '@/core/utils/auth';
+import PageContent from '@/lib/content/components/PageContent';
const LoginMobile = () => {
const {
@@ -24,43 +22,55 @@ const LoginMobile = () => {
alert,
emailRef,
passwordRef,
- handleGoogleSubmit
- } = useLogin()
+ handleGoogleSubmit,
+ } = useLogin();
- const router = useRouter()
- const [query, setQuery] = useState(router?.query?.next || '/')
- const { data: session } = useSession()
- const auth = getAuth()
+ const router = useRouter();
+ const [query, setQuery] = useState(router?.query?.next || '/');
+ const { data: session } = useSession();
+ const auth = getAuth();
const handleGoogle = async () => {
- const url = query != '/' ? '/login?source=google&next=' + query : '/login?source=google'
- await signIn('google', { callbackUrl: url })
- }
+ const url =
+ query != '/'
+ ? '/login?source=google&next=' + query
+ : '/login?source=google';
+ await signIn('google', { callbackUrl: url });
+ };
useEffect(() => {
if (session) {
- handleGoogleSubmit(session)
+ handleGoogleSubmit(session);
}
- }, [session])
+ }, [session]);
if (router.query.source) {
return (
<BottomPopup active={true} close={true}>
- <div className='leading-7 text-gray_r-12/80 flex justify-center'>Mohon Tunggu</div>
+ <div className='leading-7 text-gray_r-12/80 flex justify-center'>
+ Mohon Tunggu
+ </div>
<div className='container flex justify-center my-4'>
<LogoSpinner width={48} height={48} />
</div>
</BottomPopup>
- )
+ );
}
return (
<MobileView>
<div className='p-6 pt-10 flex flex-col items-center min-h-screen'>
<Link href='/'>
- <Image src={IndoteknikLogo} alt='Logo Indoteknik' width={150} height={50} />
+ <Image
+ src={IndoteknikLogo}
+ alt='Logo Indoteknik'
+ width={150}
+ height={50}
+ />
</Link>
<h1 className='text-2xl mt-4 font-semibold'>Mulai Belanja Sekarang</h1>
- <h2 className='text-gray_r-11 font-normal mt-1 mb-4'>Masuk ke akun kamu untuk belanja</h2>
+ <h2 className='text-gray_r-11 font-normal mt-1 mb-4'>
+ Masuk ke akun kamu untuk belanja
+ </h2>
{alert && (
<Alert className='text-center' type={alert.type}>
@@ -68,7 +78,10 @@ const LoginMobile = () => {
</Alert>
)}
- <form className='w-full mt-6 flex flex-col gap-y-4' onSubmit={handleSubmit}>
+ <form
+ className='w-full mt-6 flex flex-col gap-y-4'
+ onSubmit={handleSubmit}
+ >
<div>
<label htmlFor='email'>Alamat Email</label>
<input
@@ -96,7 +109,11 @@ const LoginMobile = () => {
placeholder='••••••••••••'
/>
</div>
- <button type='submit' className='btn-yellow w-full mt-2' disabled={!isValid || isLoading}>
+ <button
+ type='submit'
+ className='btn-yellow w-full mt-2'
+ disabled={!isValid || isLoading}
+ >
{!isLoading ? 'Masuk' : 'Loading...'}
</button>
</form>
@@ -123,16 +140,20 @@ const LoginMobile = () => {
<div className='text-gray_r-11 mt-4'>
Belum punya akun Indoteknik?{' '}
- <Link href='/register' className='inline'>
+ <Link
+ href={`/register?${new URLSearchParams(router.query)}`}
+ className='inline'
+ >
Daftar
</Link>
</div>
- {/* <div className='mt-5'>
- <PageContent path='/login' />
- </div> */}
+
+ <section className='my-10 md:my-0'>
+ <PageContent path='/register' />
+ </section>
</div>
</MobileView>
- )
-}
+ );
+};
-export default LoginMobile
+export default LoginMobile;
diff --git a/src/styles/globals.css b/src/styles/globals.css
index ea20b247..bf9fec10 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -107,7 +107,7 @@ button {
disabled:bg-gray_r-5;
}
- .form-input[aria-invalid] {
+ .form-input[aria-invalid="true"] {
@apply border-danger-500
focus:border-danger-500;
}
@@ -116,6 +116,10 @@ button {
@apply py-2;
}
+ .form-msg-danger {
+ @apply text-danger-600 mt-2 block;
+ }
+
.btn-yellow,
.btn-light,
.btn-red,