Skip to content

Commit 505f000

Browse files
committed
feat: enhance profile picture upload with loading states, improved cropping, and refined UI/UX
1 parent 55bf374 commit 505f000

2 files changed

Lines changed: 205 additions & 171 deletions

File tree

client/src/components/Auth/Profile.jsx

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)