Skip to content

Commit f5158fc

Browse files
committed
chore: Add reset password functionality
1 parent 42302c9 commit f5158fc

File tree

9 files changed

+140
-16
lines changed

9 files changed

+140
-16
lines changed

src/context/auth-context.tsx

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import {
1010
getAuth,
1111
browserLocalPersistence,
1212
setPersistence,
13-
sendEmailVerification
13+
sendEmailVerification,
14+
sendPasswordResetEmail
1415
} from 'firebase/auth';
1516

1617
import { collection, doc, setDoc } from 'firebase/firestore';
@@ -64,17 +65,13 @@ export function AuthProvider({ children }) {
6465
}
6566
}
6667
}
67-
68-
// sendPasswordResetEmail(auth, email)
69-
// .then(() => {
70-
// // Password reset email sent!
71-
// // ..
72-
// })
73-
// .catch(error => {
74-
// const errorCode = error.code;
75-
// const errorMessage = error.message;
76-
// // ..
77-
// });
68+
function resetPassword(email: string) {
69+
sendPasswordResetEmail(auth, email).catch(error => {
70+
const errorCode = error.code;
71+
const errorMessage = error.message;
72+
console.error(errorCode, errorMessage);
73+
});
74+
}
7875
function signUserOut() {
7976
return signOut(auth);
8077
}
@@ -99,7 +96,8 @@ export function AuthProvider({ children }) {
9996
signUp,
10097
signUserOut,
10198
setRememberMe,
102-
loading
99+
loading,
100+
resetPassword
103101
};
104102

105103
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;

src/routeTree.gen.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { Route as AuthIndexImport } from './routes/_auth.index'
2222
const VerifyEmailLazyImport = createFileRoute('/verify-email')()
2323
const SignupLazyImport = createFileRoute('/signup')()
2424
const SigninLazyImport = createFileRoute('/signin')()
25+
const ResetPasswordLazyImport = createFileRoute('/reset-password')()
2526
const AuthTodosLazyImport = createFileRoute('/_auth/todos')()
2627
const AuthNotesLazyImport = createFileRoute('/_auth/notes')()
2728

@@ -42,6 +43,13 @@ const SigninLazyRoute = SigninLazyImport.update({
4243
getParentRoute: () => rootRoute,
4344
} as any).lazy(() => import('./routes/signin.lazy').then((d) => d.Route))
4445

46+
const ResetPasswordLazyRoute = ResetPasswordLazyImport.update({
47+
path: '/reset-password',
48+
getParentRoute: () => rootRoute,
49+
} as any).lazy(() =>
50+
import('./routes/reset-password.lazy').then((d) => d.Route),
51+
)
52+
4553
const LoginRoute = LoginImport.update({
4654
path: '/login',
4755
getParentRoute: () => rootRoute,
@@ -85,6 +93,13 @@ declare module '@tanstack/react-router' {
8593
preLoaderRoute: typeof LoginImport
8694
parentRoute: typeof rootRoute
8795
}
96+
'/reset-password': {
97+
id: '/reset-password'
98+
path: '/reset-password'
99+
fullPath: '/reset-password'
100+
preLoaderRoute: typeof ResetPasswordLazyImport
101+
parentRoute: typeof rootRoute
102+
}
88103
'/signin': {
89104
id: '/signin'
90105
path: '/signin'
@@ -139,6 +154,7 @@ export const routeTree = rootRoute.addChildren({
139154
AuthIndexRoute,
140155
}),
141156
LoginRoute,
157+
ResetPasswordLazyRoute,
142158
SigninLazyRoute,
143159
SignupLazyRoute,
144160
VerifyEmailLazyRoute,
@@ -154,6 +170,7 @@ export const routeTree = rootRoute.addChildren({
154170
"children": [
155171
"/_auth",
156172
"/login",
173+
"/reset-password",
157174
"/signin",
158175
"/signup",
159176
"/verify-email"
@@ -170,6 +187,9 @@ export const routeTree = rootRoute.addChildren({
170187
"/login": {
171188
"filePath": "login.tsx"
172189
},
190+
"/reset-password": {
191+
"filePath": "reset-password.lazy.tsx"
192+
},
173193
"/signin": {
174194
"filePath": "signin.lazy.tsx"
175195
},

src/routes/_auth.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import { createFileRoute, redirect } from '@tanstack/react-router';
33

44
export const Route = createFileRoute('/_auth')({
55
beforeLoad: async ({ context }) => {
6-
console.log('🚀 ~ context:', context.auth?.user);
7-
86
if (!context.auth?.user?.emailVerified) {
97
throw redirect({
108
to: RoutesDef.LOGIN

src/routes/reset-password.lazy.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { ResetPassword } from '@notes/views';
2+
import { createLazyFileRoute } from '@tanstack/react-router';
3+
4+
export const Route = createLazyFileRoute('/reset-password')({
5+
component: ResetPassword
6+
});

src/types/contexts.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ export type TContextAuth = {
77
signUserOut: () => Promise<void>;
88
setRememberMe: React.Dispatch<React.SetStateAction<boolean>>
99
loading: boolean;
10+
resetPassword: (email: string) => Promise<void>;
1011
};

src/utils/routes-def.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ export enum RoutesDef {
66
TODOS = '/todos',
77
VERIFY_EMAIL = '/verify-email',
88
TAKEN = '/taken-email',
9-
HOME = '/'
9+
HOME = '/',
10+
RESET_PASSWORD = '/reset-password'
1011
}

src/views/auth/reset-password.tsx

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { Paper, Flex, rem, Title, Button, TextInput } from '@mantine/core';
2+
import { RoutesDef } from '@notes/utils';
3+
import { IconLogin2, IconMailCheck } from '@tabler/icons-react';
4+
import { useForm } from '@tanstack/react-form';
5+
import { Link } from '@tanstack/react-router';
6+
import { zodValidator } from '@tanstack/zod-form-adapter';
7+
import { z } from 'zod';
8+
import classes from './style.module.css';
9+
import { useAuthContext } from '@notes/hooks';
10+
11+
export function ResetPassword() {
12+
const { resetPassword } = useAuthContext();
13+
14+
const { Field, Subscribe, handleSubmit, state } = useForm({
15+
defaultValues: { email: '' },
16+
validatorAdapter: zodValidator(),
17+
onSubmit: async () => {
18+
resetPassword(state.values.email);
19+
}
20+
});
21+
22+
return (
23+
<Paper shadow="sm" p="xl" w="fit-content" bg={'var(--dark-bg-color)'} maw={'600px'} m="40px auto">
24+
<Flex direction={'column'} align={'center'}>
25+
<IconMailCheck color={'var(--primary)'} style={{ width: rem(40), height: rem(40) }} />
26+
<br />
27+
{state.isSubmitted ? (
28+
<Title order={3} c={'var(--white)'} mb={'xl'}>
29+
We have sent you a verification link to provided e-mail. Please click on it to reset your password.
30+
</Title>
31+
) : (
32+
<form
33+
onSubmit={e => {
34+
e.preventDefault();
35+
e.stopPropagation();
36+
handleSubmit();
37+
}}
38+
>
39+
<Title order={2} c={'var(--white'} mb={'xl'}>
40+
Please provide your e-mail.
41+
</Title>
42+
<Field
43+
name="email"
44+
validators={{
45+
onSubmit: z.string().email('Invalid e-mail').trim(),
46+
onBlur: z.string().email('Invalid e-mail')
47+
}}
48+
children={({ state, handleChange, handleBlur }) => {
49+
return (
50+
<TextInput
51+
className={classes.textInput}
52+
data-autofocus
53+
size="md"
54+
defaultValue={state.value}
55+
onChange={e => handleChange(e.target.value)}
56+
onBlur={handleBlur}
57+
withAsterisk
58+
label="E-mail"
59+
placeholder="Enter e-mail address"
60+
error={state.meta?.errors[0]}
61+
/>
62+
);
63+
}}
64+
/>
65+
<Flex justify={'flex-end'} mt={5} align={'center'}>
66+
<Subscribe
67+
selector={state => [state.canSubmit, state.isSubmitting]}
68+
children={([canSubmit, isSubmitting]) => {
69+
return (
70+
<Button
71+
size="medium"
72+
right={0}
73+
type="submit"
74+
variant="notes-transparent-border"
75+
loading={isSubmitting}
76+
disabled={!canSubmit}
77+
loaderProps={{ color: 'var(--white)', size: 20 }}
78+
>
79+
<IconLogin2 stroke={1.5} />
80+
</Button>
81+
);
82+
}}
83+
/>
84+
</Flex>
85+
</form>
86+
)}
87+
<br />
88+
<Button component={Link} variant="notes-transparent-border" size="md" fz={'md'} to={RoutesDef.SIGNIN}>
89+
Go to Sign In{' '}
90+
</Button>
91+
</Flex>
92+
</Paper>
93+
);
94+
}

src/views/auth/sign-in.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ export const SignIn = () => {
148148
>
149149
Go back to sign-up page
150150
</Button>
151+
<Flex justify={'center'}>
152+
<Button component={Link} size="xs" fz={'md'} variant="transparent" to={RoutesDef.RESET_PASSWORD}>
153+
Forgot password?
154+
</Button>
155+
</Flex>
151156
</form>
152157
</>
153158
);

src/views/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export * from './home/home'
22
export * from './home/login'
33
export * from './auth/sign-up'
44
export * from './auth/sign-in'
5+
export * from './auth/reset-password'
56
export * from './auth/verify-email'
67
export * from './pages/notes'
78
export * from './pages/todos'

0 commit comments

Comments
 (0)