diff --git a/src/App.tsx b/src/App.tsx
index 6edfc25..95972e6 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -12,6 +12,8 @@ import Loans from "./pages/Loans"
import { Toaster } from "./components/ui/toaster"
import PrivateRoute from './PrivateRoute';
import SignIn from "./pages/SignIn"
+import RecoverPassword from "./pages/RecoverPassword"
+import ChangePassword from "./pages/ChangePassword"
function App() {
return (
@@ -22,6 +24,8 @@ function App() {
} />
} />
} />
+ } />
+ } />
} />
} />
} />
diff --git a/src/hooks/useApi/index.tsx b/src/hooks/useApi/index.tsx
index 15a2712..f7412f5 100644
--- a/src/hooks/useApi/index.tsx
+++ b/src/hooks/useApi/index.tsx
@@ -71,6 +71,26 @@ const useApi = () => {
.catch((err) => resolve(getDefaultErrorUseAPIMessage(err)));
});
},
+ recoverPassword: (email: string): Promise<{ data: any }> => {
+ return new Promise((resolve) => {
+ api
+ .post(`/auth/recover-password/${email}`)
+ .then((res) => resolve(res))
+ .catch((err) => resolve(getDefaultErrorUseAPIMessage(err)));
+ });
+ },
+ changePassword: (password: string, token: string): Promise<{ data: any }> => {
+ return new Promise((resolve) => {
+ api
+ .post(`/auth/change-password`, { password }, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ })
+ .then((res) => resolve(res))
+ .catch((err) => resolve(getDefaultErrorUseAPIMessage(err)));
+ });
+ },
editProfile: async (id: string, data: {
firstName: string;
lastName: string;
diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx
index e2628c7..9c5c60d 100644
--- a/src/hooks/useAuth.tsx
+++ b/src/hooks/useAuth.tsx
@@ -34,6 +34,8 @@ type AuthContextType = {
signUp: (userToSignUp: SignUpParams) => Promise;
signIn: (userToSignIn: SignInParams) => Promise;
editProfile: (id: string, profileToEdit: EditProfileParams) => Promise;
+ recoverPassword: (email: string) => Promise;
+ changePassword: (password: string, token: string) => Promise;
};
const AuthContext = createContext({} as AuthContextType);
@@ -43,6 +45,8 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
signUp: authSignUp,
signIn: authSignIn,
editProfile: authEditProfile,
+ recoverPassword: authRecoverPassword,
+ changePassword: authChangePassword,
} = useApi();
const localToken =
@@ -87,6 +91,40 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
return true;
}
+ async function recoverPassword(email: string): Promise {
+ const { data } = await authRecoverPassword(email);
+ if (data.id) {
+ toaster.create({
+ title: 'E-mail enviado para recuperação de senha!',
+ type: 'success',
+ })
+ return true;
+ };
+ toaster.create({
+ title: 'Erro ao requisitar recuperação de senha',
+ description: 'Verifique os campos e tente novamente.',
+ type: 'error',
+ })
+ return false;
+ }
+
+ async function changePassword(password: string, token: string): Promise {
+ const { data } = await authChangePassword(password, token);
+ if (data.id) {
+ toaster.create({
+ title: 'Senha alterada com sucesso! Você será redirecionado para o login...',
+ type: 'success',
+ })
+ return true;
+ };
+ toaster.create({
+ title: 'Erro ao alterar a senha',
+ description: 'Verifique os campos e tente novamente.',
+ type: 'error',
+ })
+ return false;
+ }
+
async function editProfile(id: string, profileToEdit: EditProfileParams): Promise {
const { data } = await authEditProfile(id, profileToEdit);
if (data.id) {
@@ -120,6 +158,8 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
signUp,
editProfile,
signIn,
+ recoverPassword,
+ changePassword,
}}
>
{children}
diff --git a/src/pages/ChangePassword/ChangePasswordForm/index.tsx b/src/pages/ChangePassword/ChangePasswordForm/index.tsx
new file mode 100644
index 0000000..70a847c
--- /dev/null
+++ b/src/pages/ChangePassword/ChangePasswordForm/index.tsx
@@ -0,0 +1,75 @@
+import { useState } from 'react';
+import { useAuth } from '../../../hooks/useAuth';
+import { Stack } from '@chakra-ui/react';
+import { useForm } from 'react-hook-form';
+import { Button } from '../../../components/ui/button';
+import { Field } from '../../../components/ui/field';
+import { PasswordInput } from '../../../components/ui/password-input';
+import { useLocation } from 'react-router';
+
+interface FormValues {
+ password: string;
+ passwordConfirmation: string;
+}
+
+function useQuery() {
+ return new URLSearchParams(useLocation().search);
+}
+
+function ChangePasswordForm() {
+ const query = useQuery();
+ const [loading, setLoading] = useState(false);
+
+ const token = query.get('token');
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors, isValid },
+ } = useForm();
+
+ const { changePassword } = useAuth();
+
+ const onSubmit = handleSubmit(async (data: FormValues) => {
+ if (!token) return;
+ setLoading(true);
+ await changePassword(data.password, token);
+ setLoading(false);
+ })
+
+ return (
+
+ );
+}
+
+export default ChangePasswordForm
diff --git a/src/pages/ChangePassword/ChangePasswordHeader/index.tsx b/src/pages/ChangePassword/ChangePasswordHeader/index.tsx
new file mode 100644
index 0000000..4a84929
--- /dev/null
+++ b/src/pages/ChangePassword/ChangePasswordHeader/index.tsx
@@ -0,0 +1,12 @@
+import { Stack, Text } from '@chakra-ui/react';
+
+function RecoverPasswordHeader() {
+ return (
+
+ Nova senha
+ Deseja criar uma nova senha? Insira sua senha e confirme-a.
+
+ );
+}
+
+export default RecoverPasswordHeader
diff --git a/src/pages/ChangePassword/index.tsx b/src/pages/ChangePassword/index.tsx
new file mode 100644
index 0000000..af45e53
--- /dev/null
+++ b/src/pages/ChangePassword/index.tsx
@@ -0,0 +1,18 @@
+import { Box, Center, Stack } from '@chakra-ui/react';
+import ChangePasswordForm from './ChangePasswordForm';
+import ChangePasswordHeader from './ChangePasswordHeader';
+
+function ChangePassword() {
+ return (
+
+
+
+
+
+
+
+
+ );
+}
+
+export default ChangePassword
diff --git a/src/pages/RecoverPassword/RecoverPasswordForm/index.tsx b/src/pages/RecoverPassword/RecoverPasswordForm/index.tsx
new file mode 100644
index 0000000..91dfd4b
--- /dev/null
+++ b/src/pages/RecoverPassword/RecoverPasswordForm/index.tsx
@@ -0,0 +1,63 @@
+import { useState } from 'react';
+import { useAuth } from '../../../hooks/useAuth';
+import { Input, Stack } from '@chakra-ui/react';
+import { useForm } from 'react-hook-form';
+import { Button } from '../../../components/ui/button';
+import { Field } from '../../../components/ui/field';
+
+interface FormValues {
+ email: string;
+}
+
+function RecoverPasswordForm() {
+ const [loading, setLoading] = useState(false);
+
+ const {
+ register,
+ handleSubmit,
+ formState: { errors, isValid },
+ } = useForm();
+
+ const { recoverPassword } = useAuth();
+
+ const onSubmit = handleSubmit(async (data: FormValues) => {
+ setLoading(true);
+ await recoverPassword(data.email);
+ setLoading(false);
+ })
+
+ return (
+
+ );
+}
+
+export default RecoverPasswordForm
diff --git a/src/pages/RecoverPassword/RecoverPasswordHeader/index.tsx b/src/pages/RecoverPassword/RecoverPasswordHeader/index.tsx
new file mode 100644
index 0000000..b6f8a9e
--- /dev/null
+++ b/src/pages/RecoverPassword/RecoverPasswordHeader/index.tsx
@@ -0,0 +1,12 @@
+import { Stack, Text } from '@chakra-ui/react';
+
+function RecoverPasswordHeader() {
+ return (
+
+ Recuperação de Senha
+ Para recuperar o acesso a sua conta, vamos enviar um código para seu e-mail.
+
+ );
+}
+
+export default RecoverPasswordHeader
diff --git a/src/pages/RecoverPassword/index.tsx b/src/pages/RecoverPassword/index.tsx
new file mode 100644
index 0000000..7ee1054
--- /dev/null
+++ b/src/pages/RecoverPassword/index.tsx
@@ -0,0 +1,18 @@
+import { Box, Center, Stack } from '@chakra-ui/react';
+import RecoverPasswordForm from './RecoverPasswordForm';
+import RecoverPasswordHeader from './RecoverPasswordHeader';
+
+function RecoverPassword() {
+ return (
+
+
+
+
+
+
+
+
+ );
+}
+
+export default RecoverPassword