From 33f1a7d556d99d36b8f59e5a1512044a30161dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20EFF?= <86823724+Nefer-Hotep@users.noreply.github.com> Date: Wed, 14 Feb 2024 11:58:59 +0100 Subject: [PATCH] feat: Add US #4 (Profile) user profile fetching functionality + Profile component refactor + Redux state update --- frontend/src/pages/Profile.jsx | 22 +++++++++++++++++++--- frontend/src/service/store.js | 11 ++++++++--- frontend/src/service/user/userApi.js | 22 ++++++++++++++++++++++ frontend/src/service/user/userSlice.js | 24 ++++++++++++++++++++++-- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/frontend/src/pages/Profile.jsx b/frontend/src/pages/Profile.jsx index ba8c58a59..f4836ccb0 100644 --- a/frontend/src/pages/Profile.jsx +++ b/frontend/src/pages/Profile.jsx @@ -1,11 +1,23 @@ +import { useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { fetchUserProfile } from '../service/user/userApi'; + const Profile = () => { - return ( + const dispatch = useDispatch(); + const profile = useSelector((state) => state.user); + + useEffect(() => { + dispatch(fetchUserProfile()); + }, [dispatch]); + + console.log(profile); + return profile.user ? ( Welcome back - Tony Jarvis! + {profile.user.body.firstName + ' ' + profile.user.body.lastName}! Edit Name @@ -41,7 +53,11 @@ const Profile = () => { + ) : ( + + Loading... + ); }; -export default Profile; \ No newline at end of file +export default Profile; diff --git a/frontend/src/service/store.js b/frontend/src/service/store.js index fbd47fbc8..5d101c6b4 100644 --- a/frontend/src/service/store.js +++ b/frontend/src/service/store.js @@ -1,17 +1,22 @@ import { configureStore } from '@reduxjs/toolkit'; -import authSlice from '../service/user/userSlice'; +import { authReducer, userReducer } from '../service/user/userSlice'; -// The value of isAuthenticated is determined by +// The value of isAuthenticated is determined by // whether there is a 'token' item in the local storage. const preloadedState = { auth: { isAuthenticated: !!localStorage.getItem('token'), }, + user: { + user: null, + loading: false, + }, }; export const store = configureStore({ reducer: { - auth: authSlice, + auth: authReducer, + user: userReducer, }, preloadedState, }); diff --git a/frontend/src/service/user/userApi.js b/frontend/src/service/user/userApi.js index 459fa2f79..be6dbdb82 100644 --- a/frontend/src/service/user/userApi.js +++ b/frontend/src/service/user/userApi.js @@ -22,3 +22,25 @@ export const authenticate = createAsyncThunk( } } ); + +// Async thunk to fetch user profile +export const fetchUserProfile = createAsyncThunk( + 'user/fetchProfile', + async () => { + const token = localStorage.getItem('token'); + const response = await fetch('http://localhost:3001/api/v1/user/profile', { + method: 'POST', + headers: { + Authorization: `Bearer ${token}`, + }, + }); + const data = await response.json(); + if (response.ok) { + console.log(data.message); + return data; + } else { + window.alert(data.message); + throw new Error(data.message); + } + } +); diff --git a/frontend/src/service/user/userSlice.js b/frontend/src/service/user/userSlice.js index 254e2dbe3..d3ffb4353 100644 --- a/frontend/src/service/user/userSlice.js +++ b/frontend/src/service/user/userSlice.js @@ -1,5 +1,5 @@ import { createSlice } from '@reduxjs/toolkit'; -import { authenticate } from './userApi'; +import { authenticate, fetchUserProfile } from './userApi'; // The authSlice reducer manages the state of the user's authentication status. const authSlice = createSlice({ @@ -18,4 +18,24 @@ const authSlice = createSlice({ }, }); -export default authSlice.reducer; +const userSlice = createSlice({ + name: 'user', + initialState: { user: null, loading: false }, + reducers: {}, + extraReducers: (builder) => { + builder + .addCase(fetchUserProfile.pending, (state) => { + state.loading = true; + }) + .addCase(fetchUserProfile.fulfilled, (state, action) => { + state.user = action.payload; + state.loading = false; + }) + .addCase(fetchUserProfile.rejected, (state) => { + state.loading = false; + }); + }, +}); + +export const authReducer = authSlice.reducer; +export const userReducer = userSlice.reducer;