diff --git a/pages/forgot-password.tsx b/pages/forgot-password.tsx
new file mode 100644
index 000000000..8d4b1e570
--- /dev/null
+++ b/pages/forgot-password.tsx
@@ -0,0 +1,10 @@
+import { FormForgot, Layout } from 'src/components/common'
+
+export default function NotFound() {
+ return (
+
+
+
+ )
+}
+NotFound.Layout = Layout
diff --git a/pages/reset-password.tsx b/pages/reset-password.tsx
new file mode 100644
index 000000000..bc8905da3
--- /dev/null
+++ b/pages/reset-password.tsx
@@ -0,0 +1,10 @@
+import { FormResetPassword, Layout } from 'src/components/common'
+
+export default function NotFound() {
+ return (
+
+
+
+ )
+}
+NotFound.Layout = Layout
diff --git a/src/components/common/ForgotPassword/FormForgot/FormForgot.module.scss b/src/components/common/ForgotPassword/FormForgot/FormForgot.module.scss
new file mode 100644
index 000000000..57b39c56c
--- /dev/null
+++ b/src/components/common/ForgotPassword/FormForgot/FormForgot.module.scss
@@ -0,0 +1,22 @@
+@import '../../../../styles/utilities';
+.formAuthen{
+ width: 50%;
+ margin: 0 auto;
+ padding: 4rem 0 ;
+ .title{
+ @apply font-heading heading-3;
+ padding: 0 1.6rem 0 0.8rem;
+ margin-bottom: 2rem;
+ }
+ .bottom {
+ @apply flex justify-between items-center;
+ margin: 4rem auto;
+ .remembered {
+ @apply font-bold cursor-pointer;
+ color: var(--primary);
+ }
+ }
+ .socialAuthen{
+ margin-bottom: 3rem;
+ }
+}
diff --git a/src/components/common/ForgotPassword/FormForgot/FormForgot.tsx b/src/components/common/ForgotPassword/FormForgot/FormForgot.tsx
new file mode 100644
index 000000000..834c65919
--- /dev/null
+++ b/src/components/common/ForgotPassword/FormForgot/FormForgot.tsx
@@ -0,0 +1,89 @@
+import { Form, Formik } from 'formik';
+import React, { useRef } from 'react';
+import { ButtonCommon, InputFiledInForm } from 'src/components/common';
+import { useModalCommon } from 'src/components/hooks';
+import useRequestPasswordReset from 'src/components/hooks/auth/useRequestPasswordReset';
+import { CustomInputCommon } from 'src/utils/type.utils';
+import * as Yup from 'yup';
+import ModalAuthenticate from '../../ModalAuthenticate/ModalAuthenticate';
+import { default as s, default as styles } from './FormForgot.module.scss';
+import { useMessage } from 'src/components/contexts'
+import { LANGUAGE } from 'src/utils/language.utils'
+
+interface Props {
+
+}
+const DisplayingErrorMessagesSchema = Yup.object().shape({
+ email: Yup.string().email('Your email was wrong').required('Required')
+})
+
+const FormForgot = ({ }: Props) => {
+ const {requestPassword} = useRequestPasswordReset();
+ const { showMessageSuccess, showMessageError } = useMessage();
+
+ const emailRef = useRef(null);
+
+ const { visible: visibleModalAuthen,closeModal: closeModalAuthen, openModal: openModalAuthen } = useModalCommon({ initialValue: false });
+
+ const onForgot = (values: { email: string }) => {
+ requestPassword({email: values.email},onForgotPasswordCallBack);
+ }
+
+ const onForgotPasswordCallBack = (isSuccess: boolean, message?: string) => {
+ if (isSuccess) {
+ showMessageSuccess("Request forgot password successfully. Please verify your email to login.")
+ } else {
+ showMessageError(message || LANGUAGE.MESSAGE.ERROR)
+ }
+ }
+
+ return (
+
+
+
+
Forgot Password
+
+ {({ errors, touched, isValid, submitForm }) => (
+
+ )}
+
+
+
+
+
+ )
+
+
+}
+
+
+export default FormForgot;
\ No newline at end of file
diff --git a/src/components/common/ForgotPassword/FormResetPassword/FormResetPassword.module.scss b/src/components/common/ForgotPassword/FormResetPassword/FormResetPassword.module.scss
new file mode 100644
index 000000000..faf1b7f06
--- /dev/null
+++ b/src/components/common/ForgotPassword/FormResetPassword/FormResetPassword.module.scss
@@ -0,0 +1,27 @@
+@import '../../../../styles/utilities';
+.formAuthen{
+ width: 50%;
+ margin: 0 auto;
+ padding: 4rem 0 ;
+ .title{
+ @apply font-heading heading-3;
+ padding: 0 1.6rem 0 0.8rem;
+ margin-bottom: 2rem;
+ }
+ .passwordNote {
+ @apply text-center caption text-label;
+ margin-top: 0.8rem;
+ }
+ .bottom {
+ @apply flex justify-center items-center;
+ margin: 4rem auto;
+ .remembered {
+ @apply font-bold cursor-pointer;
+ color: var(--primary);
+ }
+ }
+ .confirmPassword{
+ margin-top: 2rem;
+ }
+
+}
diff --git a/src/components/common/ForgotPassword/FormResetPassword/FormResetPassword.tsx b/src/components/common/ForgotPassword/FormResetPassword/FormResetPassword.tsx
new file mode 100644
index 000000000..ad41396ab
--- /dev/null
+++ b/src/components/common/ForgotPassword/FormResetPassword/FormResetPassword.tsx
@@ -0,0 +1,108 @@
+import { Form, Formik } from 'formik';
+import React, { useRef } from 'react';
+import { ButtonCommon, InputPasswordFiledInForm } from 'src/components/common';
+import { useMessage } from 'src/components/contexts';
+import useRequestPasswordReset from 'src/components/hooks/auth/useRequestPasswordReset';
+import { LANGUAGE } from 'src/utils/language.utils';
+import { CustomInputCommon } from 'src/utils/type.utils';
+import * as Yup from 'yup';
+import { useRouter } from 'next/router'
+import { default as s, default as styles } from './FormResetPassword.module.scss';
+import { useResetPassword } from 'src/components/hooks/auth';
+
+interface Props {
+
+}
+const DisplayingErrorMessagesSchema = Yup.object().shape({
+ password: Yup.string()
+ .matches(
+ /^(?=.{8,})(?=.*[a-z])(?=.*[A-Z])((?=.*[0-9!@#$%^&*()\-_=+{};:,<.>]){1}).*$/,
+ 'Must contain 8 characters with at least 1 uppercase and 1 lowercase letter and either 1 number or 1 special character.'
+ )
+ .max(30, 'Password is too long')
+ .required('Required'),
+ confirmPassword: Yup.string()
+ .label('Password Confirm')
+ .required()
+ .oneOf([Yup.ref('password')], 'Passwords does not match'),
+})
+
+const FormResetPassword = ({ }: Props) => {
+ const router = useRouter();
+
+ const {resetPassword} = useResetPassword();
+
+ const { showMessageSuccess, showMessageError } = useMessage();
+
+ const onReset = (values: {password: string }) => {
+ const { token } = router.query;
+ resetPassword({token:token,password: values.password},onResetPasswordCallBack);
+ }
+
+ const onResetPasswordCallBack = (isSuccess: boolean, message?: string) => {
+ if (isSuccess) {
+ showMessageSuccess("Reset password successfully. Please to login.")
+ } else {
+ showMessageError(message || LANGUAGE.MESSAGE.ERROR)
+ }
+ }
+
+ return (
+
+
+
+
Reset Password
+
+ {({ errors, touched, isValid, submitForm }) => (
+
+ )}
+
+
+
+
+ )
+}
+
+
+export default FormResetPassword;
\ No newline at end of file
diff --git a/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx b/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx
index 4f7e5d21a..5922e5017 100644
--- a/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx
+++ b/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx
@@ -60,6 +60,10 @@ const HeaderMenu = memo(
onClick: openModalRegister,
name: 'Create account',
},
+ {
+ link: '/forgot-password',
+ name: 'Forgot Password',
+ },
],
[openModalLogin, openModalRegister]
)
diff --git a/src/components/common/index.ts b/src/components/common/index.ts
index eaa33176c..42d326690 100644
--- a/src/components/common/index.ts
+++ b/src/components/common/index.ts
@@ -51,5 +51,7 @@ export { default as LayoutCheckout} from './LayoutCheckout/LayoutCheckout'
export { default as InputPasswordFiledInForm} from './InputPasswordFiledInForm/InputPasswordFiledInForm'
export { default as InputFiledInForm} from './InputFiledInForm/InputFiledInForm'
export { default as MessageCommon} from './MessageCommon/MessageCommon'
+export { default as FormForgot} from './ForgotPassword/FormForgot/FormForgot'
+export { default as FormResetPassword} from './ForgotPassword/FormResetPassword/FormResetPassword'
diff --git a/src/components/hooks/auth/index.ts b/src/components/hooks/auth/index.ts
index 845617bcd..ffd93b6e6 100644
--- a/src/components/hooks/auth/index.ts
+++ b/src/components/hooks/auth/index.ts
@@ -3,4 +3,6 @@ export { default as useLogin } from './useLogin'
export { default as useLogout } from './useLogout'
export { default as useVerifyCustomer } from './useVerifyCustomer'
export { default as useActiveCustomer } from './useActiveCustomer'
+export { default as useRequestPasswordReset } from './useRequestPasswordReset'
+export { default as useResetPassword } from './useResetPassword'
diff --git a/src/components/hooks/auth/useRequestPasswordReset.tsx b/src/components/hooks/auth/useRequestPasswordReset.tsx
new file mode 100644
index 000000000..f30c1ab44
--- /dev/null
+++ b/src/components/hooks/auth/useRequestPasswordReset.tsx
@@ -0,0 +1,50 @@
+import { useState } from 'react'
+import useActiveCustomer from './useActiveCustomer'
+import fetcher from 'src/utils/fetcher'
+import { CommonError } from 'src/domains/interfaces/CommonError'
+import { requestPasswordReset } from '@framework/utils/mutations/request-password-reset-mutation'
+import { RequestPasswordReset } from '@framework/schema'
+
+interface ForgotPassword {
+ email: string
+}
+
+const useRequestPasswordReset = () => {
+ const [loading, setLoading] = useState(false)
+ const [error, setError] = useState(null)
+ // const { mutate } = useActiveCustomer()
+
+ const requestPassword = (
+ {email}: ForgotPassword,
+ fCallBack: (isSuccess: boolean, message?: string) => void
+ ) => {
+ setError(null)
+ setLoading(true)
+ fetcher({
+ query: requestPasswordReset,
+ variables: {
+ emailAddress: email
+ },
+ })
+ .then((data) => {
+ if (data.requestPasswordReset.__typename !== 'Success') {
+ throw CommonError.create(
+ data.requestPasswordReset.message,
+ data.requestPasswordReset.errorCode
+ )
+ }
+ // mutate()
+ fCallBack(true)
+ return data
+ })
+ .catch((error) => {
+ setError(error)
+ fCallBack(false, error.message)
+ })
+ .finally(() => setLoading(false))
+ }
+
+ return { loading, requestPassword, error }
+}
+
+export default useRequestPasswordReset
diff --git a/src/components/hooks/auth/useResetPassword.tsx b/src/components/hooks/auth/useResetPassword.tsx
new file mode 100644
index 000000000..788d496df
--- /dev/null
+++ b/src/components/hooks/auth/useResetPassword.tsx
@@ -0,0 +1,52 @@
+import { useState } from 'react'
+import useActiveCustomer from './useActiveCustomer'
+import fetcher from 'src/utils/fetcher'
+import { CommonError } from 'src/domains/interfaces/CommonError'
+import { resetPasswordMutation } from '@framework/utils/mutations/reset-password-mutation'
+import { ResetPasswordMutation } from '@framework/schema'
+
+interface Props {
+ token?: string| string[] ,
+ password:string
+}
+
+const useResetPassword = () => {
+ const [loading, setLoading] = useState(false)
+ const [error, setError] = useState(null)
+// const { mutate } = useActiveCustomer()
+
+ const resetPassword = (
+ {token,password}: Props,
+ fCallBack: (isSuccess: boolean, message?: string) => void
+ ) => {
+ setError(null)
+ setLoading(true)
+ fetcher({
+ query: resetPasswordMutation,
+ variables: {
+ token: token,
+ password:password
+ },
+ })
+ .then((data) => {
+ if (data.resetPassword.__typename !== 'CurrentUser') {
+ throw CommonError.create(
+ data.resetPassword.message,
+ data.resetPassword.errorCode
+ )
+ }
+ // mutate()
+ fCallBack(true)
+ return data
+ })
+ .catch((error) => {
+ setError(error)
+ fCallBack(false, error.message)
+ })
+ .finally(() => setLoading(false))
+ }
+
+ return { loading, resetPassword, error }
+}
+
+export default useResetPassword