1
1
"use client" ;
2
2
3
- import { useSession } from "@/hooks/useSession" ;
4
- import { Card , CardContent , CardHeader , CardTitle } from "@call/ui/components/card" ;
5
- import { Avatar , AvatarFallback , AvatarImage } from "@call/ui/components/avatar" ;
6
- import { Label } from "@call/ui/components/label" ;
7
- import { Input } from "@call/ui/components/input" ;
3
+ import { useSession } from "@/components/providers/session" ;
4
+ import { authClient } from "@call/auth/auth-client" ;
8
5
import { Button } from "@call/ui/components/button" ;
9
- import { useState , useRef } from "react" ;
6
+ import {
7
+ Card ,
8
+ CardContent ,
9
+ CardHeader ,
10
+ CardTitle ,
11
+ } from "@call/ui/components/card" ;
12
+ import { Input } from "@call/ui/components/input" ;
13
+ import { Label } from "@call/ui/components/label" ;
14
+ import { UserProfile } from "@call/ui/components/use-profile" ;
15
+ import { useRef , useState } from "react" ;
10
16
import { toast } from "sonner" ;
11
- import { authClient } from "@call/auth/auth-client" ;
12
- import { Camera } from "lucide-react" ;
13
17
14
18
export default function ProfilePage ( ) {
15
- const { session , isLoading } = useSession ( ) ;
19
+ const { user } = useSession ( ) ;
16
20
const [ isEditing , setIsEditing ] = useState ( false ) ;
17
- const [ name , setName ] = useState ( session ?. user ? .name || "" ) ;
21
+ const [ name , setName ] = useState ( user . name || "" ) ;
18
22
const [ loading , setLoading ] = useState ( false ) ;
19
23
const [ imageLoading , setImageLoading ] = useState ( false ) ;
20
24
const fileInputRef = useRef < HTMLInputElement > ( null ) ;
21
25
22
- if ( isLoading ) {
23
- return (
24
- < div className = "flex items-center justify-center h-[calc(100vh-4rem)]" >
25
- < p className = "text-muted-foreground" > Loading...</ p >
26
- </ div >
27
- ) ;
28
- }
29
-
30
- if ( ! session ?. user ) {
31
- return (
32
- < div className = "flex items-center justify-center h-[calc(100vh-4rem)]" >
33
- < p className = "text-muted-foreground" > Please sign in to view your profile.</ p >
34
- </ div >
35
- ) ;
36
- }
37
-
38
26
const handleUpdateProfile = async ( ) => {
39
27
if ( ! name . trim ( ) ) {
40
28
toast . error ( "Name cannot be empty" ) ;
@@ -43,26 +31,25 @@ export default function ProfilePage() {
43
31
44
32
setLoading ( true ) ;
45
33
try {
46
- const res = await fetch ( `http://${ process . env . NEXT_PUBLIC_BACKEND_URL } /api/auth/update-profile` , {
47
- method : "PATCH" ,
48
- headers : {
49
- "Content-Type" : "application/json" ,
50
- } ,
51
- credentials : "include" ,
52
- body : JSON . stringify ( { name } ) ,
53
- } ) ;
34
+ const res = await fetch (
35
+ `http://${ process . env . NEXT_PUBLIC_BACKEND_URL } /api/auth/update-profile` ,
36
+ {
37
+ method : "PATCH" ,
38
+ headers : {
39
+ "Content-Type" : "application/json" ,
40
+ } ,
41
+ credentials : "include" ,
42
+ body : JSON . stringify ( { name } ) ,
43
+ }
44
+ ) ;
54
45
55
46
if ( ! res . ok ) {
56
47
throw new Error ( "Failed to update profile" ) ;
57
48
}
58
-
59
- // Refresh the session to get the updated user data
60
49
await authClient . getSession ( ) ;
61
-
50
+
62
51
toast . success ( "Profile updated successfully" ) ;
63
52
setIsEditing ( false ) ;
64
-
65
- // Force a page refresh to update all components with new session data
66
53
window . location . reload ( ) ;
67
54
} catch ( error ) {
68
55
toast . error ( "Failed to update profile" ) ;
@@ -96,21 +83,24 @@ export default function ProfilePage() {
96
83
const formData = new FormData ( ) ;
97
84
formData . append ( "image" , file ) ;
98
85
99
- const res = await fetch ( `http://${ process . env . NEXT_PUBLIC_BACKEND_URL } /api/auth/update-profile-image` , {
100
- method : "PATCH" ,
101
- credentials : "include" ,
102
- body : formData ,
103
- } ) ;
86
+ const res = await fetch (
87
+ `http://${ process . env . NEXT_PUBLIC_BACKEND_URL } /api/auth/update-profile-image` ,
88
+ {
89
+ method : "PATCH" ,
90
+ credentials : "include" ,
91
+ body : formData ,
92
+ }
93
+ ) ;
104
94
105
95
if ( ! res . ok ) {
106
96
throw new Error ( "Failed to update profile image" ) ;
107
97
}
108
98
109
99
// Refresh the session to get the updated user data
110
100
await authClient . getSession ( ) ;
111
-
101
+
112
102
toast . success ( "Profile image updated successfully" ) ;
113
-
103
+
114
104
// Force a page refresh to update all components with new session data
115
105
window . location . reload ( ) ;
116
106
} catch ( error ) {
@@ -121,23 +111,15 @@ export default function ProfilePage() {
121
111
} ;
122
112
123
113
return (
124
- < div className = "max-w-2xl mx-auto mt-8" >
114
+ < div className = "mx-auto mt-8 max-w-2xl " >
125
115
< Card >
126
116
< CardHeader >
127
117
< CardTitle > Profile</ CardTitle >
128
118
</ CardHeader >
129
119
< CardContent className = "space-y-6" >
130
120
< div className = "flex items-center gap-4" >
131
- < div className = "relative group" >
132
- < Avatar className = "h-20 w-20 cursor-pointer transition-opacity group-hover:opacity-75" onClick = { handleImageClick } >
133
- < AvatarImage src = { session . user . image || undefined } />
134
- < AvatarFallback >
135
- { session . user . name ?. charAt ( 0 ) . toUpperCase ( ) || "U" }
136
- </ AvatarFallback >
137
- < div className = "absolute inset-0 flex items-center justify-center bg-black/40 opacity-0 transition-opacity group-hover:opacity-100 rounded-full" >
138
- < Camera className = "h-6 w-6 text-white" />
139
- </ div >
140
- </ Avatar >
121
+ < div className = "group relative" >
122
+ < UserProfile name = { user . name } url = { user . image } />
141
123
< input
142
124
type = "file"
143
125
ref = { fileInputRef }
@@ -147,22 +129,22 @@ export default function ProfilePage() {
147
129
disabled = { imageLoading }
148
130
/>
149
131
{ imageLoading && (
150
- < div className = "absolute inset-0 flex items-center justify-center bg-black/40 rounded-full " >
132
+ < div className = "absolute inset-0 flex items-center justify-center rounded-full bg-black/40" >
151
133
< div className = "h-5 w-5 animate-spin rounded-full border-2 border-white border-t-transparent" />
152
134
</ div >
153
135
) }
154
136
</ div >
155
137
< div >
156
- < h2 className = "text-xl font-semibold" > { session . user . name } </ h2 >
157
- < p className = "text-sm text- muted-foreground" > { session . user . email } </ p >
138
+ < h2 className = "text-xl font-semibold" > { user . name } </ h2 >
139
+ < p className = "text-muted-foreground text-sm " > { user . email } </ p >
158
140
</ div >
159
141
</ div >
160
142
161
143
< div className = "space-y-4" >
162
144
< div >
163
145
< Label htmlFor = "name" > Name</ Label >
164
146
{ isEditing ? (
165
- < div className = "flex gap-2 mt-1 " >
147
+ < div className = "mt-1 flex gap-2" >
166
148
< Input
167
149
id = "name"
168
150
value = { name }
@@ -176,16 +158,16 @@ export default function ProfilePage() {
176
158
variant = "outline"
177
159
onClick = { ( ) => {
178
160
setIsEditing ( false ) ;
179
- setName ( session . user . name ) ;
161
+ setName ( user . name ) ;
180
162
} }
181
163
disabled = { loading }
182
164
>
183
165
Cancel
184
166
</ Button >
185
167
</ div >
186
168
) : (
187
- < div className = "flex items-center justify-between mt-1 " >
188
- < p className = "text-sm" > { session . user . name } </ p >
169
+ < div className = "mt-1 flex items-center justify-between" >
170
+ < p className = "text-sm" > { user . name } </ p >
189
171
< Button variant = "outline" onClick = { ( ) => setIsEditing ( true ) } >
190
172
Edit
191
173
</ Button >
@@ -195,10 +177,12 @@ export default function ProfilePage() {
195
177
196
178
< div >
197
179
< Label htmlFor = "email" > Email</ Label >
198
- < div className = "flex items-center justify-between mt-1" >
199
- < p className = "text-sm" > { session . user . email } </ p >
200
- { session . user . emailVerified ? (
201
- < span className = "text-xs text-green-600 font-medium" > Verified</ span >
180
+ < div className = "mt-1 flex items-center justify-between" >
181
+ < p className = "text-sm" > { user . email } </ p >
182
+ { user . emailVerified ? (
183
+ < span className = "text-xs font-medium text-green-600" >
184
+ Verified
185
+ </ span >
202
186
) : (
203
187
< Button variant = "outline" size = "sm" >
204
188
Verify Email
@@ -209,13 +193,13 @@ export default function ProfilePage() {
209
193
210
194
< div >
211
195
< Label > Account Created</ Label >
212
- < p className = "text-sm mt-1" >
213
- { new Date ( session . user . createdAt ) . toLocaleDateString ( ) }
196
+ < p className = "mt-1 text-sm " >
197
+ { new Date ( user . createdAt ) . toLocaleDateString ( ) }
214
198
</ p >
215
199
</ div >
216
200
</ div >
217
201
</ CardContent >
218
202
</ Card >
219
203
</ div >
220
204
) ;
221
- }
205
+ }
0 commit comments