@@ -153,17 +153,11 @@ const Profile = () => {
153153
154154 const handleProfilePicUpdate = useCallback (
155155 async ( croppedImageUrl , file ) => {
156- try {
157- setLoading ( true )
158-
159- let fileToUpload = file
160- if ( ! fileToUpload && croppedImageUrl ) {
161- const response = await fetch ( croppedImageUrl )
162- const blob = await response . blob ( )
163- fileToUpload = new File ( [ blob ] , "profile.jpg" , { type : "image/jpeg" } )
164- }
156+ setIsDialogOpen ( false )
157+ setLoading ( true )
165158
166- const uploadResult = await uploadToCloudinary ( fileToUpload , "profile" )
159+ try {
160+ const uploadResult = await uploadToCloudinary ( file , "profile" )
167161
168162 const { status, data } = await axios . post (
169163 `${ import . meta. env . VITE_API_URL } /api/update-profilepic` ,
@@ -176,8 +170,7 @@ const Profile = () => {
176170
177171 if ( status === 200 ) {
178172 setUser ( ( prevUser ) => ( { ...prevUser , profilepic : data . profilepic } ) )
179- toast . success ( "Profile picture updated successfully" )
180- setIsDialogOpen ( false )
173+ toast . success ( "Profile picture updated!" )
181174 }
182175 } catch ( error ) {
183176 console . error ( "Error updating profile picture:" , error )
@@ -190,8 +183,9 @@ const Profile = () => {
190183 )
191184
192185 const toggleDialog = useCallback ( ( ) => {
186+ if ( loading ) return
193187 setIsDialogOpen ( ( prev ) => ! prev )
194- } , [ ] )
188+ } , [ loading ] )
195189
196190 return (
197191 < >
@@ -203,22 +197,37 @@ const Profile = () => {
203197 { /* Profile Header */ }
204198 < Card className = "rounded-xl shadow-md p-6 mb-6" >
205199 < div className = "flex flex-col md:flex-row items-center md:items-start" >
206- < div className = "relative mb-6 md:mb-0 md:mr-8" >
207- < Avatar className = "w-48 h-48 rounded-full overflow-hidden shadow-lg relative" >
200+ < div className = "relative mb-6 md:mb-0 md:mr-8 group" >
201+ < Avatar
202+ className = { cn (
203+ "w-48 h-48 rounded-full overflow-hidden shadow-lg relative transition-all duration-300" ,
204+ loading &&
205+ "ring-4 ring-blue-500/50 ring-offset-2 ring-offset-background animate-pulse" ,
206+ ) }
207+ >
208208 < AvatarImage
209209 src = { getProfileCloudinaryUrl ( user ?. profilepic ) }
210210 alt = { user ?. name }
211211 className = "w-full h-full object-cover"
212212 />
213- < AvatarFallback className = "w-full h-full" > CN</ AvatarFallback >
213+ < AvatarFallback className = "w-full h-full text-3xl" >
214+ { user ?. name ?. charAt ( 0 ) ?. toUpperCase ( ) || "U" }
215+ </ AvatarFallback >
214216 </ Avatar >
215217
218+ { loading && (
219+ < div className = "absolute inset-0 flex items-center justify-center bg-black/40 rounded-full backdrop-blur-[2px]" >
220+ < Loader2 size = { 32 } className = "text-white animate-spin" />
221+ </ div >
222+ ) }
223+
216224 < Button
217225 onClick = { toggleDialog }
218226 variant = "ghost"
219- className = "absolute bottom-2 w-10 h-10 right-2 bg-blue-600 text-white p-2 rounded-full hover:bg-blue-700 transition duration-300 shadow-md"
227+ disabled = { loading }
228+ className = "absolute bottom-2 right-2 w-10 h-10 bg-blue-600 text-white p-2 rounded-full hover:bg-blue-700 transition duration-300 shadow-md hover:scale-110"
220229 >
221- < Camera />
230+ < Camera size = { 18 } />
222231 </ Button >
223232 </ div >
224233 < div className = "flex-1" >
@@ -386,9 +395,9 @@ const Profile = () => {
386395
387396 { /* Profile Picture Update Dialog */ }
388397 < Dialog open = { isDialogOpen } onOpenChange = { toggleDialog } >
389- < DialogContent >
398+ < DialogContent className = "sm:max-w-md" >
390399 < DialogHeader > Update Profile Picture</ DialogHeader >
391- < ImageUpload onImageUpdate = { handleProfilePicUpdate } />
400+ < ImageUpload onImageUpdate = { handleProfilePicUpdate } loading = { loading } />
392401 </ DialogContent >
393402 </ Dialog >
394403
0 commit comments