From 17e7e51473d97f1f2969dc6f63aea1174ce28993 Mon Sep 17 00:00:00 2001 From: garvthakre Date: Thu, 23 Apr 2026 13:31:08 +0530 Subject: [PATCH] feat : add update profile name feature --- client/src/pages/user/Profile.jsx | 76 +++++++++++++++++++++++++++++-- client/src/redux/apiSlice.js | 10 +++- 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/client/src/pages/user/Profile.jsx b/client/src/pages/user/Profile.jsx index 6678d98..f5acae4 100644 --- a/client/src/pages/user/Profile.jsx +++ b/client/src/pages/user/Profile.jsx @@ -5,11 +5,11 @@ import BottomBar from '../../components/constants/Bottombar'; import Navbar from '../../components/constants/Navbar'; import { useNavigate } from 'react-router-dom'; import { useGetPostsByUserQuery } from '../../redux/posts/postApi'; -import { useUpdatePasswordMutation, useLogoutMutation } from '../../redux/apiSlice'; +import { useUpdatePasswordMutation, useUpdateFullNameMutation, useLogoutMutation } from '../../redux/apiSlice'; import { useGetMyApplicationQuery } from '../../redux/opportunities/opportunity-api'; import { setCurrentUser } from '../../redux/user/userSlice'; import InfiniteScroll from 'react-infinite-scroll-component'; -import { BadgeCheck, Calendar, ChevronRight } from 'lucide-react'; +import { BadgeCheck, Calendar, ChevronRight, Pencil, Check, X } from 'lucide-react'; const Profile = () => { const [logout] = useLogoutMutation(); @@ -18,6 +18,11 @@ const Profile = () => { const [password, setPassword] = useState(''); const [activeTab, setActiveTab] = useState('posts'); const [updatePassword, { isLoading: isUpdating, error: updateError }] = useUpdatePasswordMutation(); + const [updateFullName, { isLoading: isUpdatingName }] = useUpdateFullNameMutation(); + + // Name editing state + const [isEditingName, setIsEditingName] = useState(false); + const [nameInput, setNameInput] = useState(''); const { currentUser } = useSelector((state) => state.user); const [page, setPage] = useState(1); @@ -64,6 +69,28 @@ const Profile = () => { } }; + const handleNameEdit = () => { + setNameInput(currentUser.name || ''); + setIsEditingName(true); + }; + + const handleNameSave = async () => { + const trimmed = nameInput.trim(); + if (!trimmed) return; + try { + await updateFullName(trimmed).unwrap(); + dispatch(setCurrentUser({ ...currentUser, name: trimmed })); + setIsEditingName(false); + } catch (error) { + console.error('Failed to update name:', error); + } + }; + + const handleNameCancel = () => { + setIsEditingName(false); + setNameInput(''); + }; + const tabs = [ { key: 'posts', label: 'My Posts' }, { key: 'applied', label: 'Applied Opps' }, @@ -75,7 +102,50 @@ const Profile = () => {
Profile -

{currentUser.admissionNumber}

+ + {/* ── Inline Name Edit ── */} + {isEditingName ? ( +
+ setNameInput(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') handleNameSave(); + if (e.key === 'Escape') handleNameCancel(); + }} + autoFocus + maxLength={50} + className="text-2xl md:text-4xl font-bold text-center border-b-2 border-[#6a7cff] bg-transparent outline-none w-48 md:w-64" + /> + + +
+ ) : ( +
+

+ {currentUser.name || currentUser.admissionNumber} +

+ +
+ )} +

{currentUser?.year}-{parseInt((currentUser?.year)) + 4}

{(currentUser.isAuthenticated) && diff --git a/client/src/redux/apiSlice.js b/client/src/redux/apiSlice.js index 6ea0501..8579f1b 100644 --- a/client/src/redux/apiSlice.js +++ b/client/src/redux/apiSlice.js @@ -32,6 +32,14 @@ export const authApi = createApi({ body: { newPassword }, // Correctly wrapping in an object }), }), + // UpdateFullName + updateFullName: builder.mutation({ + query: (fullname) => ({ + url: `/auth/updatefullname`, + method: 'POST', + body: { fullname }, + }), + }), logout: builder.mutation({ query: () => ({ url: '/auth/logout', @@ -43,4 +51,4 @@ export const authApi = createApi({ }); -export const { useSignUpMutation, useSignInMutation, useUpdatePasswordMutation, useLogoutMutation } = authApi; +export const { useSignUpMutation, useSignInMutation, useUpdatePasswordMutation,useUpdateFullNameMutation, useLogoutMutation } = authApi;