Skip to content

Commit 67348b7

Browse files
signout functionality/forgot password page
1 parent 834bc67 commit 67348b7

File tree

10 files changed

+151
-8
lines changed

10 files changed

+151
-8
lines changed

src/App.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import OrderSuccessPage from "./pages/OrderSuccessPage";
2424
import UserOrderPage from "./pages/UserOrderPage";
2525
import UserProfilePage from "./pages/UserProfilePage";
2626
import { fetchLoggedInUserAsync } from "./features/user/userSlice";
27+
import LogOut from "./features/auth/components/LogOut";
28+
import ForgotPasswordPage from "./pages/ForgotPasswordPage";
2729
const router = createBrowserRouter([
2830
{
2931
path: "/",
@@ -78,6 +80,14 @@ const router = createBrowserRouter([
7880
path: "/profile",
7981
element: <UserProfilePage></UserProfilePage>,
8082
},
83+
{
84+
path: "/logout",
85+
element: <LogOut></LogOut>,
86+
},
87+
{
88+
path: "/forgot-paasword",
89+
element: <ForgotPasswordPage></ForgotPasswordPage>,
90+
},
8191
{
8292
path: "*",
8393
element: <PageNotFound></PageNotFound>,

src/features/auth/authAPI.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// create user
12
export function createUser(userData) {
23
return new Promise(async (resolve) => {
34
const response = await fetch("http://localhost:8080/users", {
@@ -10,6 +11,7 @@ export function createUser(userData) {
1011
resolve({ data });
1112
});
1213
}
14+
// check user
1315
export function checkUser(loginInfo) {
1416
return new Promise(async (resolve, reject) => {
1517
const email = loginInfo.email;
@@ -31,3 +33,10 @@ export function checkUser(loginInfo) {
3133
// TODO:on server it will only return some info of user (not password)
3234
});
3335
}
36+
// remove user
37+
export function signOut(userId) {
38+
return new Promise(async (resolve) => {
39+
// TODO: on server we will remove user session info
40+
resolve({ data: "success" });
41+
});
42+
}

src/features/auth/authSlice.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
2-
import { checkUser, createUser } from "./authAPI";
2+
import { checkUser, createUser, signOut } from "./authAPI";
33
import { updateUser } from "../user/userAPI";
44

55
const initialState = {
@@ -32,6 +32,11 @@ export const checkUserAsync = createAsyncThunk(
3232
return response.data;
3333
}
3434
);
35+
export const signOutAsync = createAsyncThunk("user/signOut", async (userId) => {
36+
const response = await signOut(userId);
37+
// The value we return becomes the `fulfilled` action payload
38+
return response.data;
39+
});
3540

3641
export const authSlice = createSlice({
3742
name: "user",
@@ -67,6 +72,13 @@ export const authSlice = createSlice({
6772
.addCase(updateUserAsync.fulfilled, (state, action) => {
6873
state.status = "idle";
6974
state.loggedInUser = action.payload;
75+
})
76+
.addCase(signOutAsync.pending, (state) => {
77+
state.status = "loading";
78+
})
79+
.addCase(signOutAsync.fulfilled, (state, action) => {
80+
state.status = "idle";
81+
state.loggedInUser = null;
7082
});
7183
},
7284
});
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { useForm } from "react-hook-form";
2+
import { Link } from "react-router-dom";
3+
4+
export default function ForgotPassword() {
5+
const {
6+
register,
7+
handleSubmit,
8+
formState: { errors },
9+
} = useForm();
10+
11+
console.log(errors);
12+
return (
13+
<>
14+
<div className="flex min-h-full flex-1 flex-col justify-center px-6 py-12 lg:px-8">
15+
<div className="sm:mx-auto sm:w-full sm:max-w-sm">
16+
<img
17+
className="mx-auto h-10 w-auto"
18+
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
19+
alt="Your Company"
20+
/>
21+
<h2 className="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
22+
Enter Email to Reset Password
23+
</h2>
24+
</div>
25+
26+
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
27+
<form
28+
noValidate
29+
className="space-y-6"
30+
onSubmit={handleSubmit((data) => {
31+
console.log(data);
32+
// TODO: implementation on backend with email
33+
})}
34+
>
35+
<div>
36+
<label
37+
htmlFor="email"
38+
className="block text-sm font-medium leading-6 text-gray-900"
39+
>
40+
Email address
41+
</label>
42+
<div className="mt-2">
43+
<input
44+
id="email"
45+
{...register("email", {
46+
required: "email is required",
47+
pattern: {
48+
value: /\b[\w\.-]+@[\w\.-]+\.\w{2,4}\b/gi,
49+
message: "email is not valid",
50+
},
51+
})}
52+
type="email"
53+
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"
54+
/>
55+
{errors.email && (
56+
<p className="text-red-500">{errors.email.message}</p>
57+
)}
58+
</div>
59+
</div>
60+
61+
<div>
62+
<button
63+
type="submit"
64+
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"
65+
>
66+
Log in
67+
</button>
68+
</div>
69+
</form>
70+
71+
<p className="mt-10 text-center text-sm text-gray-500">
72+
Send me back to{" "}
73+
<Link
74+
to="/login"
75+
className="font-semibold leading-6 text-indigo-600 hover:text-indigo-500"
76+
>
77+
Login
78+
</Link>
79+
</p>
80+
</div>
81+
</div>
82+
</>
83+
);
84+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { useEffect } from "react";
2+
import { selectLoggedInUser, signOutAsync } from "../authSlice";
3+
import { useDispatch, useSelector } from "react-redux";
4+
import { Navigate } from "react-router-dom";
5+
6+
function LogOut() {
7+
const dispatch = useDispatch();
8+
const user = useSelector(selectLoggedInUser);
9+
useEffect(() => {
10+
dispatch(signOutAsync());
11+
});
12+
//but useEffect runs after render, so we have to delay
13+
return <>{!user && <Navigate to="/login" replace={true}></Navigate>}</>;
14+
}
15+
16+
export default LogOut;

src/features/auth/components/Login.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ export default function Login() {
7676
Password
7777
</label>
7878
<div className="text-sm">
79-
<a
80-
href="#"
79+
<Link
80+
to="/forgot-paasword"
8181
className="font-semibold text-indigo-600 hover:text-indigo-500"
8282
>
8383
Forgot password?
84-
</a>
84+
</Link>
8585
</div>
8686
</div>
8787
<div className="mt-2">

src/features/auth/components/Signup.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@ export default function Signup() {
7979
Password
8080
</label>
8181
<div className="text-sm">
82-
<a
83-
href="#"
82+
<Link
83+
to="/forgot-paasword"
8484
className="font-semibold text-indigo-600 hover:text-indigo-500"
8585
>
8686
Forgot password?
87-
</a>
87+
</Link>
8888
</div>
8989
</div>
9090
<div className="mt-2">

src/features/navbar/Navbar.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const navigation = [
2222
const userNavigation = [
2323
{ name: "My Profile", link: "/profile" },
2424
{ name: "My Orders", link: "/orders" },
25-
{ name: "Sign out", link: "/login" },
25+
{ name: "Sign out", link: "/logout" },
2626
];
2727

2828
function classNames(...classes) {

src/features/user/components/UserProfile.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ export default function UserProfile() {
88
const user = useSelector(selectUserInfo);
99
const [selectedEditIndex, setSelectedEditIndex] = useState(-1);
1010
const [showAddressForm, setshowAddressForm] = useState(false);
11+
12+
// TODO: we will add payment section when we work on backend
1113
const {
1214
register,
1315
handleSubmit,

src/pages/ForgotPasswordPage.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import ForgotPassword from "../features/auth/components/ForgotPassword";
2+
function ForgotPasswordPage() {
3+
return (
4+
<div>
5+
<ForgotPassword></ForgotPassword>
6+
</div>
7+
);
8+
}
9+
10+
export default ForgotPasswordPage;

0 commit comments

Comments
 (0)