Skip to content

Commit

Permalink
Part 16: Logout and Forgot Password
Browse files Browse the repository at this point in the history
  • Loading branch information
abhishekrathore committed May 2, 2023
1 parent 07e4d53 commit 1fedc1a
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 31 deletions.
37 changes: 19 additions & 18 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import UserOrdersPage from './pages/UserOrdersPage';
import UserProfile from './features/user/components/UserProfile';
import UserProfilePage from './pages/UserProfilePage';
import { fetchLoggedInUserAsync } from './features/user/userSlice';
import Logout from './features/auth/components/Logout';
import ForgotPasswordPage from './pages/ForgotPasswordPage';
const router = createBrowserRouter([
{
path: '/',
Expand Down Expand Up @@ -69,41 +71,40 @@ const router = createBrowserRouter([
},
{
path: '/order-success/:id',
element: (
<OrderSuccessPage></OrderSuccessPage>
),
element: <OrderSuccessPage></OrderSuccessPage>,
},
{
path: '/orders',
element: (
<UserOrdersPage></UserOrdersPage>
),
element: <UserOrdersPage></UserOrdersPage>,
},
{
path: '/profile',
element: (
<UserProfilePage></UserProfilePage>
),
element: <UserProfilePage></UserProfilePage>,
},
{
path: '/logout',
element: <Logout></Logout>,
},
{
path: '/forgot-password',
element: <ForgotPasswordPage></ForgotPasswordPage>,
},
{
path: '*',
element: (
<PageNotFound></PageNotFound>
),
element: <PageNotFound></PageNotFound>,
},
]);

function App() {

const dispatch = useDispatch();
const user = useSelector(selectLoggedInUser);

useEffect(()=>{
if(user){
dispatch(fetchItemsByUserIdAsync(user.id))
dispatch(fetchLoggedInUserAsync(user.id))
useEffect(() => {
if (user) {
dispatch(fetchItemsByUserIdAsync(user.id));
dispatch(fetchLoggedInUserAsync(user.id));
}
},[dispatch, user])
}, [dispatch, user]);

return (
<div className="App">
Expand Down
7 changes: 7 additions & 0 deletions src/features/auth/authAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,11 @@ export function checkUser(loginInfo) {
});
}

export function signOut(userId) {
return new Promise(async (resolve) => {
// TODO: on server we will remove user session info
resolve({ data: 'success' });
});
}


18 changes: 17 additions & 1 deletion src/features/auth/authSlice.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { checkUser, createUser } from './authAPI';
import { checkUser, createUser, signOut } from './authAPI';
import { updateUser } from '../user/userAPI';


Expand Down Expand Up @@ -37,6 +37,15 @@ export const checkUserAsync = createAsyncThunk(
}
);

export const signOutAsync = createAsyncThunk(
'user/signOut',
async (loginInfo) => {
const response = await signOut(loginInfo);
// The value we return becomes the `fulfilled` action payload
return response.data;
}
);

export const counterSlice = createSlice({
name: 'user',
initialState,
Expand Down Expand Up @@ -72,6 +81,13 @@ export const counterSlice = createSlice({
state.status = 'idle';
state.loggedInUser = action.payload;
})
.addCase(signOutAsync.pending, (state) => {
state.status = 'loading';
})
.addCase(signOutAsync.fulfilled, (state, action) => {
state.status = 'idle';
state.loggedInUser = null;
})

},
});
Expand Down
90 changes: 90 additions & 0 deletions src/features/auth/components/ForgotPassword.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import React, { useState } from 'react';
import { Link, Navigate } from 'react-router-dom';
import { checkUserAsync } from '../authSlice';
import { useForm } from 'react-hook-form';

export default function ForgotPassword() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm();

console.log(errors);

return (
<>
<div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-sm">
<img
className="mx-auto h-10 w-auto"
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
alt="Your Company"
/>
<h2 className="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
Enter email to reset password
</h2>
</div>

<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
<form
noValidate
onSubmit={handleSubmit((data) => {
console.log(data);
// TODO : implementation on backend with email
})}
className="space-y-6"

>
<div>
<label
htmlFor="email"
className="block text-sm font-medium leading-6 text-gray-900"
>
Email address
</label>
<div className="mt-2">
<input
id="email"
{...register('email', {
required: 'email is required',
pattern: {
value: /\b[\w\.-]+@[\w\.-]+\.\w{2,4}\b/gi,
message: 'email not valid',
},
})}
type="email"
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
/>
{errors.email && (
<p className="text-red-500">{errors.email.message}</p>
)}
</div>
</div>



<div>
<button
type="submit"
className="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
Send Email
</button>
</div>
</form>

<p className="mt-10 text-center text-sm text-gray-500">
Send me back to {' '}
<Link
to="/login"
className="font-semibold leading-6 text-indigo-600 hover:text-indigo-500"
>
Login
</Link>
</p>
</div>
</div>
</>
);
}
6 changes: 3 additions & 3 deletions src/features/auth/components/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ export default function Login() {
Password
</label>
<div className="text-sm">
<a
href="#"
<Link
to="/forgot-password"
className="font-semibold text-indigo-600 hover:text-indigo-500"
>
Forgot password?
</a>
</Link>
</div>
</div>
<div className="mt-2">
Expand Down
23 changes: 23 additions & 0 deletions src/features/auth/components/Logout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useEffect } from "react";
import { selectLoggedInUser, signOutAsync } from "../authSlice";
import { useDispatch, useSelector } from "react-redux";
import { Navigate } from "react-router-dom";


function Logout() {
const dispatch = useDispatch();
const user = useSelector(selectLoggedInUser)

useEffect(()=>{
dispatch(signOutAsync())
})

// but useEffect runs after render, so we have to delay navigate part
return (
<>
{!user && <Navigate to='/login' replace={true}></Navigate>}
</>
);
}

export default Logout;
9 changes: 1 addition & 8 deletions src/features/auth/components/Signup.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,7 @@ export default function Signup() {
>
Password
</label>
<div className="text-sm">
<a
href="#"
className="font-semibold text-indigo-600 hover:text-indigo-500"
>
Forgot password?
</a>
</div>

</div>
<div className="mt-2">
<input
Expand Down
2 changes: 1 addition & 1 deletion src/features/navbar/Navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const navigation = [
const userNavigation = [
{ name: 'My Profile', link: '/profile' },
{ name: 'My Orders', link: '/orders' },
{ name: 'Sign out', link: '/login' },
{ name: 'Sign out', link: '/logout' },
];

function classNames(...classes) {
Expand Down
9 changes: 9 additions & 0 deletions src/pages/ForgotPasswordPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import ForgotPassword from "../features/auth/components/ForgotPassword";
import Login from "../features/auth/components/Login";
function ForgotPasswordPage() {
return ( <div>
<ForgotPassword></ForgotPassword>
</div> );
}

export default ForgotPasswordPage;

0 comments on commit 1fedc1a

Please sign in to comment.