setWish(state => !state)}
+ // onClick={() => setWish(state => !state)}
+ onClick={handleNavigate}
className='rounded-full transition-all ease-in-out delay-100 hover:bg-grayColor active:bg-greenColor p-1 active:text-blackColor hover:text-blackColor'
>
-
+
+
{wish && (
{
@@ -148,31 +164,18 @@ const Navbar: React.FC = () => {
}}
className='absolute top-0 md:h-[115px] w-screen right-0 h-[100px] bg-[#0000000] z-40'
>
-
+
)}
SetCartOpen(state => !state)}
diff --git a/src/components/navbar/notifications/Notifications.tsx b/src/components/navbar/notifications/Notifications.tsx
index 8cf6652..d46c146 100644
--- a/src/components/navbar/notifications/Notifications.tsx
+++ b/src/components/navbar/notifications/Notifications.tsx
@@ -12,8 +12,8 @@ import { useEffect, useRef, useState } from 'react';
import { FaSpinner } from 'react-icons/fa6';
export const Notifications = () => {
- const userId = useSelector((state: any) => state.userId) || localStorage.getItem('userId');
- // const userId = '06e0d866-2544-4cfa-83b0-2c3cede7a2f0';
+ const user = useSelector((state: any) => state.user);
+ const userId = user.userId ? user.userId.replace(/"/g, '') : '';
const [mainMenuClicked, setMainMenuClicked] = useState(false);
const mainMenuRef = useRef
(null);
diff --git a/src/components/navbar/wishNav/WishNav.tsx b/src/components/navbar/wishNav/WishNav.tsx
index fc175fd..f6bc288 100644
--- a/src/components/navbar/wishNav/WishNav.tsx
+++ b/src/components/navbar/wishNav/WishNav.tsx
@@ -1,27 +1,54 @@
-import React from 'react'
-import { Link } from 'react-router-dom';
-
+import React from 'react';
+import { BiLoader } from 'react-icons/bi';
+import { LuUser } from 'react-icons/lu';
+import { useDispatch } from 'react-redux';
+import { Link, useNavigate } from 'react-router-dom';
+import { clearUserData } from '../../../redux/slices/userSlice';
interface WishNav {
- setWish: React.Dispatch>
+ setWish: React.Dispatch>;
+ isLoading: boolean;
+ userInfo: string[];
}
-const WishNav: React.FC = () => {
- return (
- <>
-
-
-
- Not Ange?
-
-
+const WishNav: React.FC
= ({ isLoading, userInfo }) => {
+ const navigate = useNavigate();
+ const dispatch = useDispatch();
+ const [firstName, lastName] = userInfo;
+ const handleSignOut = () => {
+ dispatch(clearUserData());
+ navigate('/');
+ };
+ return (
+ <>
+
+ {isLoading ? (
+
+
+
+ ) : (
+ <>
+
+
{firstName + ' ' + lastName}
+
+ {' '}
+
+ Account Settings
+
+
- >
- )
-}
+
+
+
+ >
+ )}
+
+ >
+ );
+};
-export default WishNav
\ No newline at end of file
+export default WishNav;
diff --git a/src/components/profile/Profile.tsx b/src/components/profile/Profile.tsx
new file mode 100644
index 0000000..bba5fc4
--- /dev/null
+++ b/src/components/profile/Profile.tsx
@@ -0,0 +1,188 @@
+import React, { useEffect, useState } from 'react';
+import { useForm, SubmitHandler } from 'react-hook-form';
+import { useGetUserByIdQuery, useUpdateUserMutation } from '../../services/userApi';
+import Input from '../common/Input';
+import { useSelector } from 'react-redux';
+
+export interface UserFormValues {
+ firstName: string;
+ lastName: string;
+ phoneNumber: string;
+ email: string;
+ photoUrl?: any;
+}
+
+const Profile: React.FC = () => {
+ const [isEditing, setIsEditing] = useState(false);
+ const [showSuccessMessage, setShowSuccessMessage] = useState(false);
+ const id = useSelector((state: any) => state.user.userId);
+
+ const { data } = useGetUserByIdQuery(id);
+ const [userData, setUserData] = useState(data?.message);
+
+ const {
+ register,
+ handleSubmit,
+ setValue,
+ formState: { errors, isSubmitting },
+ } = useForm();
+
+ useEffect(() => {
+ if (data?.message) {
+ setUserData(data.message);
+ }
+ }, [data]);
+
+ useEffect(() => {
+ if (userData) {
+ setValue('firstName', userData.firstName);
+ setValue('lastName', userData.lastName);
+ setValue('email', userData.email);
+ setValue('phoneNumber', userData.phoneNumber);
+ }
+ }, [userData, setValue]);
+
+ const [updateUser, { isLoading, isError, error }] = useUpdateUserMutation();
+
+ const onSubmit: SubmitHandler = async data => {
+ const formData = new FormData();
+ formData.append('firstName', data.firstName);
+ formData.append('lastName', data.lastName);
+ formData.append('phoneNumber', data.phoneNumber);
+ formData.append('email', data.email);
+ formData.append('profileImage', data.photoUrl[0]);
+ // if (data.photoUrl && data.photoUrl[0]) {
+ // formData.append('photoUrl', data.photoUrl[0]);
+ // }
+
+ try {
+ const response = await updateUser(formData).unwrap();
+ setUserData(response.message);
+ setIsEditing(false);
+ setShowSuccessMessage(true);
+ setTimeout(() => setShowSuccessMessage(false), 3000); // Hide message after 3 seconds
+ } catch (err) {
+ console.error('Failed to update profile:', err);
+ }
+ };
+
+ const getErrorMessage = (error: any) => {
+ if ('data' in error) {
+ return error.data?.message || 'Error updating profile';
+ } else {
+ return 'An unexpected error occurred';
+ }
+ };
+
+ return (
+
+
+ {showSuccessMessage && (
+
+ Profile updated successfully!
+
+ )}
+
My Profile
+
+
+
+
+
+
+ {userData?.firstName} {userData?.lastName}
+
+
{userData?.role}
+
+
+
+
+
+ {isEditing && (
+
+
Personal Information
+ {isError && error && (
+
{getErrorMessage(error)}
+ )}
+
+
+ )}
+
+
+ );
+};
+
+export default Profile;
diff --git a/src/pages/EditUserProfile.tsx b/src/pages/EditUserProfile.tsx
new file mode 100644
index 0000000..b817625
--- /dev/null
+++ b/src/pages/EditUserProfile.tsx
@@ -0,0 +1,13 @@
+import Navbar from '../components/navbar/Navbar';
+import UserProfileEdit from '../components/profile/Profile';
+
+const EditUserProfile = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default EditUserProfile;
diff --git a/src/redux/slices/editUserSlice.ts b/src/redux/slices/editUserSlice.ts
new file mode 100644
index 0000000..2a591a5
--- /dev/null
+++ b/src/redux/slices/editUserSlice.ts
@@ -0,0 +1,15 @@
+interface UserState {
+ user?: {
+ firstName: string;
+ lastName: string;
+ gender: string;
+ contactNumber: string;
+ email: string;
+ changePassword: boolean;
+ currentPassword: string;
+ newPassword: string;
+ };
+ isLoading: boolean;
+ error?: string;
+}
+
\ No newline at end of file
diff --git a/src/redux/slices/userSlice.ts b/src/redux/slices/userSlice.ts
index 951418b..29169ad 100644
--- a/src/redux/slices/userSlice.ts
+++ b/src/redux/slices/userSlice.ts
@@ -28,6 +28,7 @@ const userSlice = createSlice({
state.userId = action.payload;
if (action.payload) {
localStorage.setItem('user', JSON.stringify(action.payload));
+ localStorage.setItem('user', action.payload);
} else {
localStorage.removeItem('user');
}
diff --git a/src/services/index.ts b/src/services/index.ts
index 777788a..6986bbb 100644
--- a/src/services/index.ts
+++ b/src/services/index.ts
@@ -1,9 +1,18 @@
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
+import { RootState } from '../redux/store';
export const mavericksApi = createApi({
reducerPath: 'mavericksApi',
baseQuery: fetchBaseQuery({
baseUrl: 'https://e-commerce-mavericcks-bn-staging-istf.onrender.com/api/',
+ // baseUrl: 'localhost:5000',
+ prepareHeaders: (headers, { getState }) => {
+ const token = (getState() as RootState).user.token;
+ if (token) {
+ headers.set('authorization', `${token.replace(/"/g, '')!}`);
+ }
+ return headers;
+ },
}),
tagTypes: ['Notifications'],
endpoints: () => ({}),
diff --git a/src/services/userApi.ts b/src/services/userApi.ts
index 21de108..8b668c4 100644
--- a/src/services/userApi.ts
+++ b/src/services/userApi.ts
@@ -1,4 +1,5 @@
import { mavericksApi } from '.';
+const id = localStorage.getItem('user');
export const userApi = mavericksApi.injectEndpoints({
endpoints: builder => ({
@@ -10,8 +11,20 @@ export const userApi = mavericksApi.injectEndpoints({
},
}),
}),
+ updateUser: builder.mutation({
+ query: data => ({
+ url: `/users/edit/${id}`,
+ method: 'PATCH',
+ headers: {
+ authorization: localStorage.getItem('token') || '',
+ },
+ body: data,
+ formData: true,
+ }),
+ }),
}),
+
overrideExisting: false,
});
-export const { useGetUserByIdQuery } = userApi;
+export const { useGetUserByIdQuery, useUpdateUserMutation } = userApi;