diff --git a/frontend/index.html b/frontend/index.html
index 049321b84..6ad02d922 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -1,10 +1,18 @@
-
+
-
-
+
+
ArgentBank
diff --git a/frontend/src/assets/css/main.css b/frontend/src/assets/css/main.css
index 7c08d53aa..62ed02509 100644
--- a/frontend/src/assets/css/main.css
+++ b/frontend/src/assets/css/main.css
@@ -205,6 +205,19 @@ body {
font-size: 1.2rem;
}
+.edit-input {
+ display: flex;
+ justify-content: center;
+ gap: 1rem;
+ font-size: 1.2rem;
+ margin-bottom: 1rem;
+}
+
+.edit-input input {
+ padding: 5px;
+ font-size: 1.2rem;
+}
+
.footer {
display: flex;
justify-content: center;
@@ -260,6 +273,13 @@ body {
color: #fff;
font-weight: bold;
padding: 10px;
+ width: 110px;
+}
+
+.edit-button-wrapper {
+ display: flex;
+ justify-content: center;
+ gap: 1rem;
}
.header {
diff --git a/frontend/src/layout/NavBar.jsx b/frontend/src/layout/NavBar.jsx
index fdec75448..99dda62d9 100644
--- a/frontend/src/layout/NavBar.jsx
+++ b/frontend/src/layout/NavBar.jsx
@@ -5,8 +5,11 @@ import { authenticate } from '../service/user/userApi';
const Navbar = () => {
const dispatch = useDispatch();
+ // Get the isAuthenticated and user state from the store
const isAuthenticated = useSelector((state) => state.auth.isAuthenticated);
+ const user = useSelector((state) => state.user.user);
+ // Handle the sign in and sign out functionality
const handleAuth = () => {
if (isAuthenticated) {
localStorage.removeItem('token'); // Remove the token from local storage
@@ -25,13 +28,23 @@ const Navbar = () => {
Argent Bank
+
+
+ {user && isAuthenticated ? `${user.body.firstName}` : null}
+
-
- {isAuthenticated ? 'Sign Out' : 'Sign In'}
+ {isAuthenticated ? (
+ <>
+
+ Sign Out
+ >
+ ) : (
+ 'Sign In'
+ )}
diff --git a/frontend/src/pages/Login.jsx b/frontend/src/pages/Login.jsx
index 98366039f..a0b854272 100644
--- a/frontend/src/pages/Login.jsx
+++ b/frontend/src/pages/Login.jsx
@@ -15,6 +15,7 @@ const Login = () => {
dispatch(authenticate({ email, password }));
};
+ // If the user is authenticated, redirect to the profile page
useEffect(() => {
if (isAuthenticated) {
navigate('/profile');
diff --git a/frontend/src/pages/Profile.jsx b/frontend/src/pages/Profile.jsx
index f4836ccb0..b8bfa6dd9 100644
--- a/frontend/src/pages/Profile.jsx
+++ b/frontend/src/pages/Profile.jsx
@@ -1,25 +1,83 @@
-import { useEffect } from 'react';
+import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
-import { fetchUserProfile } from '../service/user/userApi';
+import { fetchUserProfile, updateUserProfile } from '../service/user/userApi';
const Profile = () => {
+ const user = useSelector((state) => state.user.user);
+ const [firstName, setFirstName] = useState('');
+ const [lastName, setLastName] = useState('');
+ const [isEditing, setIsEditing] = useState(false);
const dispatch = useDispatch();
- const profile = useSelector((state) => state.user);
+ // Fetch the user profile on component mount
useEffect(() => {
dispatch(fetchUserProfile());
}, [dispatch]);
- console.log(profile);
- return profile.user ? (
+ // Set the first and last name from the user object
+ useEffect(() => {
+ if (user) {
+ const { firstName: userFirstName, lastName: userLastName } = user.body;
+ setFirstName(userFirstName);
+ setLastName(userLastName);
+ }
+ }, [user]);
+
+ // Update the user profile
+ const handleUpdate = (e) => {
+ e.preventDefault();
+ dispatch(updateUserProfile({ firstName, lastName }));
+ setIsEditing(false);
+ };
+
+ return user ? (
Welcome back
- {profile.user.body.firstName + ' ' + profile.user.body.lastName}!
+ {`${firstName} ${lastName}`}!
-
+ {isEditing ? (
+
+ ) : (
+
+ )}
Accounts
diff --git a/frontend/src/service/store.js b/frontend/src/service/store.js
index 5d101c6b4..8f981968a 100644
--- a/frontend/src/service/store.js
+++ b/frontend/src/service/store.js
@@ -13,6 +13,7 @@ const preloadedState = {
},
};
+// The store is created with the auth and user reducers.
export const store = configureStore({
reducer: {
auth: authReducer,
diff --git a/frontend/src/service/user/userApi.js b/frontend/src/service/user/userApi.js
index be6dbdb82..4cde6f18e 100644
--- a/frontend/src/service/user/userApi.js
+++ b/frontend/src/service/user/userApi.js
@@ -44,3 +44,27 @@ export const fetchUserProfile = createAsyncThunk(
}
}
);
+
+// Async thunk to update user profile
+export const updateUserProfile = createAsyncThunk(
+ 'user/updateProfile',
+ async ({ firstName, lastName }) => {
+ const token = localStorage.getItem('token');
+ const response = await fetch('http://localhost:3001/api/v1/user/profile', {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ },
+ body: JSON.stringify({ firstName, lastName }),
+ });
+ 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 d3ffb4353..8056b6d30 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, fetchUserProfile } from './userApi';
+import { authenticate, fetchUserProfile, updateUserProfile } from './userApi';
// The authSlice reducer manages the state of the user's authentication status.
const authSlice = createSlice({
@@ -18,6 +18,7 @@ const authSlice = createSlice({
},
});
+// The userSlice reducer manages the state of the user's profile and loading status.
const userSlice = createSlice({
name: 'user',
initialState: { user: null, loading: false },
@@ -33,6 +34,15 @@ const userSlice = createSlice({
})
.addCase(fetchUserProfile.rejected, (state) => {
state.loading = false;
+ })
+ .addCase(updateUserProfile.pending, (state) => {
+ state.loading = true;
+ })
+ .addCase(updateUserProfile.fulfilled, (state, action) => {
+ state.user = action.payload;
+ state.loading = false;
+ }).addCase(updateUserProfile.rejected, (state) => {
+ state.loading = false;
});
},
});