diff --git a/Client/src/Features/Auth/authSlice.js b/Client/src/Features/Auth/authSlice.js
new file mode 100644
index 000000000..f8bc106e5
--- /dev/null
+++ b/Client/src/Features/Auth/authSlice.js
@@ -0,0 +1,50 @@
+import axios from "axios";
+import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
+import { jwtDecode } from "jwt-decode";
+const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL;
+
+const initialState = {
+ isLoading: false,
+ user: "",
+ success: null,
+ msg: null,
+};
+
+export const register = createAsyncThunk(
+ "auth/register",
+ async (form, thunkApi) => {
+ try {
+ const res = await axios.post(`${BASE_URL}/auth/register`, form);
+ return res.data;
+ } catch (error) {
+ return thunkApi.rejectWithValue(error.response.data);
+ }
+ }
+);
+
+const authSlice = createSlice({
+ name: "auth",
+ initialState,
+ reducers: {},
+ extraReducers: (builder) => {
+ builder
+ .addCase(register.pending, (state, action) => {
+ state.isLoading = true;
+ })
+ .addCase(register.fulfilled, (state, action) => {
+ state.isLoading = false;
+ state.success = action.payload.success;
+ state.msg = action.payload.msg;
+ const decodedToken = jwtDecode(action.payload.data);
+ const user = { ...decodedToken };
+ state.user = user;
+ })
+ .addCase(register.rejected, (state, action) => {
+ state.isLoading = false;
+ state.success = action.payload.success;
+ state.msg = action.payload.msg;
+ });
+ },
+});
+
+export default authSlice.reducer;
diff --git a/Client/src/Layouts/HomeLayout/index.jsx b/Client/src/Layouts/HomeLayout/index.jsx
index 3a4a03dca..d7a7c2977 100644
--- a/Client/src/Layouts/HomeLayout/index.jsx
+++ b/Client/src/Layouts/HomeLayout/index.jsx
@@ -4,22 +4,23 @@ import DashboardSidebar from "../../Components/DashboardSidebar";
import "./index.css";
// Demo, remove me
-import { jwtDecode } from "jwt-decode";
+import { useSelector } from "react-redux";
// Emd Demo
const HomeLayout = () => {
- const token = localStorage.getItem("token");
- const decodedToken = token && jwtDecode(token);
+ const authState = useSelector((state) => state.auth);
+ const { user, msg } = authState;
+ console.log(user, msg);
return (
{/* Remove me later */}
- {token &&
You are logged in
}
- {token &&
First Name: {decodedToken.firstname}
}
- {token &&
Last Name: {decodedToken.lastname}
}
- {token &&
Email: {decodedToken.email}
}
+ {user &&
{user.firstname}
}
+ {user &&
{user.lastname}
}
+ {user &&
{user.email}
}
+ {msg &&
Msg: {msg}
}
{/* I am a demo */}
diff --git a/Client/src/Pages/Demo/Demo.jsx b/Client/src/Pages/Demo/Demo.jsx
index ec7875167..f2af76fb4 100644
--- a/Client/src/Pages/Demo/Demo.jsx
+++ b/Client/src/Pages/Demo/Demo.jsx
@@ -1,5 +1,4 @@
import React from "react";
-import axios from "axios";
import Button from "../../Components/Button/";
import Link from "../../Components/Link";
import {
diff --git a/Client/src/Pages/Register/index.jsx b/Client/src/Pages/Register/index.jsx
index 7b33e8a3c..bd1b63760 100644
--- a/Client/src/Pages/Register/index.jsx
+++ b/Client/src/Pages/Register/index.jsx
@@ -13,9 +13,13 @@ import Button from "../../Components/Button";
import Google from "../../assets/Images/Google.png";
import { registerValidation } from "../../Validation/validation";
+import { useDispatch } from "react-redux";
+import { register } from "../../Features/Auth/authSlice";
+
const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL;
const Register = () => {
+ const dispatch = useDispatch();
const navigate = useNavigate();
// TODO If possible, change the IDs of these fields to match the backend
@@ -55,23 +59,31 @@ const Register = () => {
};
const handleSubmit = async () => {
- console.log("submitting");
try {
await registerValidation.validateAsync(form, { abortEarly: false });
+ const action = await dispatch(register(form));
- const result = await axios.post(`${BASE_URL}/auth/register`, form);
- const token = result.data.data;
- localStorage.setItem("token", token);
- navigate("/"); // Redirect to home page
+ if (action.meta.requestStatus === "fulfilled") {
+ const token = action.payload.data;
+ localStorage.setItem("token", token);
+ navigate("/");
+ }
+
+ if (action.meta.requestStatus === "rejected") {
+ const error = new Error("Request rejected");
+ error.response = action.payload;
+ throw error;
+ }
} catch (error) {
- // TODO User friendly error display
if (error.name === "ValidationError") {
+ // TODO Handle validation errors
console.log(error);
alert("Invalid input");
} else if (error.response) {
- console.log(error);
- alert(error.response.data.msg);
+ // TODO handle dispatch errors
+ alert(error.response.msg);
} else {
+ // TODO handle unknown errors
console.log(error);
alert("Unknown error");
}
diff --git a/Client/src/store.js b/Client/src/store.js
index e8409d993..385448c6e 100644
--- a/Client/src/store.js
+++ b/Client/src/store.js
@@ -1,6 +1,7 @@
import { configureStore } from "@reduxjs/toolkit";
import monitorsReducer from "./Features/Monitors/monitorsSlice";
+import authReducer from "./Features/Auth/authSlice";
export default configureStore({
- reducer: { monitors: monitorsReducer },
+ reducer: { monitors: monitorsReducer, auth: authReducer },
});