@@ -5,15 +5,22 @@ import { z } from "zod";
5
5
import { db } from "db" ;
6
6
import { userCommonData , userHackerData } from "db/schema" ;
7
7
import { eq } from "db/drizzle" ;
8
- import { put } from "@vercel/blob" ;
8
+ import { del } from "@vercel/blob" ;
9
9
import { decodeBase64AsFile } from "@/lib/utils/shared/files" ;
10
- import { returnValidationErrors } from "next-safe-action" ;
11
10
import { revalidatePath } from "next/cache" ;
12
- import { getUser , getUserByTag } from "db/functions" ;
13
- import { RegistrationSettingsFormValidator } from "@/validators/shared/RegistrationSettingsForm" ;
11
+ import { UNIQUE_KEY_CONSTRAINT_VIOLATION_CODE } from "@/lib/constants" ;
12
+ import c from "config" ;
13
+ import { DatabaseError } from "db/types" ;
14
+ import {
15
+ registrationSettingsFormValidator ,
16
+ modifyAccountSettingsSchema ,
17
+ profileSettingsSchema ,
18
+ } from "@/validators/settings" ;
19
+ import { clerkClient , type User as ClerkUser } from "@clerk/nextjs/server" ;
20
+ import { PAYLOAD_TOO_LARGE_CODE } from "@/lib/constants" ;
14
21
15
22
export const modifyRegistrationData = authenticatedAction
16
- . schema ( RegistrationSettingsFormValidator )
23
+ . schema ( registrationSettingsFormValidator )
17
24
. action (
18
25
async ( {
19
26
parsedInput : {
@@ -37,12 +44,12 @@ export const modifyRegistrationData = authenticatedAction
37
44
personalWebsite,
38
45
phoneNumber,
39
46
countryOfResidence,
47
+ uploadedFile,
40
48
} ,
41
49
ctx : { userId } ,
42
50
} ) => {
43
- const user = await getUser ( userId ) ;
44
- if ( ! user ) throw new Error ( "User not found" ) ;
45
51
await Promise . all ( [
52
+ // attempts to update both tables with Promise.all
46
53
db
47
54
. update ( userCommonData )
48
55
. set ( {
@@ -56,7 +63,7 @@ export const modifyRegistrationData = authenticatedAction
56
63
phoneNumber,
57
64
countryOfResidence,
58
65
} )
59
- . where ( eq ( userCommonData . clerkID , user . clerkID ) ) ,
66
+ . where ( eq ( userCommonData . clerkID , userId ) ) ,
60
67
db
61
68
. update ( userHackerData )
62
69
. set ( {
@@ -71,9 +78,18 @@ export const modifyRegistrationData = authenticatedAction
71
78
GitHub : github ,
72
79
LinkedIn : linkedin ,
73
80
PersonalWebsite : personalWebsite ,
81
+ resume : uploadedFile ,
74
82
} )
75
- . where ( eq ( userHackerData . clerkID , user . clerkID ) ) ,
76
- ] ) ;
83
+ . where ( eq ( userHackerData . clerkID , userId ) ) ,
84
+ ] ) . catch ( async ( err ) => {
85
+ console . log (
86
+ `Error occured at modify registration data: ${ err } ` ,
87
+ ) ;
88
+ // If there's an error
89
+ return {
90
+ success : false ,
91
+ } ;
92
+ } ) ;
77
93
return {
78
94
success : true ,
79
95
newAge : age ,
@@ -96,99 +112,72 @@ export const modifyRegistrationData = authenticatedAction
96
112
newPersonalWebsite : personalWebsite ,
97
113
newPhoneNumber : phoneNumber ,
98
114
newCountryOfResidence : countryOfResidence ,
115
+ newUploadedFile : uploadedFile ,
99
116
} ;
100
117
} ,
101
118
) ;
102
119
103
- export const modifyResume = authenticatedAction
120
+ export const deleteResume = authenticatedAction
104
121
. schema (
105
122
z . object ( {
106
- resume : z . string ( ) ,
123
+ oldFileLink : z . string ( ) ,
107
124
} ) ,
108
125
)
109
- . action ( async ( { parsedInput : { resume } , ctx : { userId } } ) => {
126
+ . action ( async ( { parsedInput : { oldFileLink } } ) => {
127
+ if ( oldFileLink === c . noResumeProvidedURL ) return null ;
128
+ await del ( oldFileLink ) ;
129
+ } ) ;
130
+
131
+ export const modifyProfileData = authenticatedAction
132
+ . schema ( profileSettingsSchema )
133
+ . action ( async ( { parsedInput, ctx : { userId } } ) => {
110
134
await db
111
- . update ( userHackerData )
112
- . set ( { resume } )
113
- . where ( eq ( userHackerData . clerkID , userId ) ) ;
135
+ . update ( userCommonData )
136
+ . set ( {
137
+ ...parsedInput ,
138
+ skills : parsedInput . skills . map ( ( v ) => v . toLowerCase ( ) ) ,
139
+ } )
140
+ . where ( eq ( userCommonData . clerkID , userId ) ) ;
114
141
return {
115
142
success : true ,
116
- newResume : resume ,
117
143
} ;
118
144
} ) ;
119
145
120
- export const modifyProfileData = authenticatedAction
121
- . schema (
122
- z . object ( {
123
- pronouns : z . string ( ) ,
124
- bio : z . string ( ) ,
125
- skills : z . string ( ) . array ( ) ,
126
- discord : z . string ( ) ,
127
- } ) ,
128
- )
129
- . action (
130
- async ( {
131
- parsedInput : { bio, discord, pronouns, skills } ,
132
- ctx : { userId } ,
133
- } ) => {
134
- const user = await getUser ( userId ) ;
135
- if ( ! user ) {
136
- throw new Error ( "User not found" ) ;
137
- }
138
- await db
139
- . update ( userCommonData )
140
- . set ( { pronouns, bio, skills, discord } )
141
- . where ( eq ( userCommonData . clerkID , user . clerkID ) ) ;
142
- return {
143
- success : true ,
144
- newPronouns : pronouns ,
145
- newBio : bio ,
146
- newSkills : skills ,
147
- newDiscord : discord ,
148
- } ;
149
- } ,
150
- ) ;
151
-
152
- // TODO: Fix after registration enhancements to allow for failure on conflict and return appropriate error message
153
146
export const modifyAccountSettings = authenticatedAction
154
- . schema (
155
- z . object ( {
156
- firstName : z . string ( ) . min ( 1 ) . max ( 50 ) ,
157
- lastName : z . string ( ) . min ( 1 ) . max ( 50 ) ,
158
- hackerTag : z . string ( ) . min ( 1 ) . max ( 50 ) ,
159
- hasSearchableProfile : z . boolean ( ) ,
160
- } ) ,
161
- )
147
+ . schema ( modifyAccountSettingsSchema )
162
148
. action (
163
149
async ( {
164
150
parsedInput : {
165
151
firstName,
166
152
lastName,
167
153
hackerTag,
168
- hasSearchableProfile,
154
+ isSearchable : hasSearchableProfile ,
169
155
} ,
170
156
ctx : { userId } ,
171
157
} ) => {
172
- const user = await getUser ( userId ) ;
173
- if ( ! user ) throw new Error ( "User not found" ) ;
174
- let oldHackerTag = user . hackerTag ; // change when hackertag is not PK on profileData table
175
- if ( oldHackerTag != hackerTag )
176
- if ( await getUserByTag ( hackerTag ) )
177
- //if hackertag changed
178
- // copied from /api/registration/create
158
+ try {
159
+ await db
160
+ . update ( userCommonData )
161
+ . set ( {
162
+ firstName,
163
+ lastName,
164
+ hackerTag,
165
+ isSearchable : hasSearchableProfile ,
166
+ } )
167
+ . where ( eq ( userCommonData . clerkID , userId ) ) ;
168
+ } catch ( err ) {
169
+ console . log ( "modifyAccountSettings error is" , err ) ;
170
+ if (
171
+ err instanceof DatabaseError &&
172
+ err . code === UNIQUE_KEY_CONSTRAINT_VIOLATION_CODE
173
+ ) {
179
174
return {
180
175
success : false ,
181
176
message : "hackertag_not_unique" ,
182
177
} ;
183
- await db
184
- . update ( userCommonData )
185
- . set ( {
186
- firstName,
187
- lastName,
188
- hackerTag,
189
- isSearchable : hasSearchableProfile ,
190
- } )
191
- . where ( eq ( userCommonData . clerkID , userId ) ) ;
178
+ }
179
+ throw err ;
180
+ }
192
181
return {
193
182
success : true ,
194
183
newFirstName : firstName ,
@@ -199,23 +188,43 @@ export const modifyAccountSettings = authenticatedAction
199
188
} ,
200
189
) ;
201
190
191
+ // come back and fix this tmr
202
192
export const updateProfileImage = authenticatedAction
203
193
. schema ( z . object ( { fileBase64 : z . string ( ) , fileName : z . string ( ) } ) )
204
194
. action (
205
195
async ( { parsedInput : { fileBase64, fileName } , ctx : { userId } } ) => {
206
- const image = await decodeBase64AsFile ( fileBase64 , fileName ) ;
207
- const user = await db . query . userCommonData . findFirst ( {
208
- where : eq ( userCommonData . clerkID , userId ) ,
209
- } ) ;
210
- if ( ! user ) throw new Error ( "User not found" ) ;
196
+ const file = await decodeBase64AsFile ( fileBase64 , fileName ) ;
197
+ let clerkUser : ClerkUser ;
198
+ try {
199
+ clerkUser = await clerkClient . users . updateUserProfileImage (
200
+ userId ,
201
+ {
202
+ file,
203
+ } ,
204
+ ) ;
205
+ } catch ( err ) {
206
+ console . log ( `Error updating Clerk profile image: ${ err } ` ) ;
207
+ if (
208
+ typeof err === "object" &&
209
+ err != null &&
210
+ "status" in err &&
211
+ err . status === PAYLOAD_TOO_LARGE_CODE
212
+ ) {
213
+ return {
214
+ success : false ,
215
+ message : "file_too_large" ,
216
+ } ;
217
+ }
218
+ console . log (
219
+ `Unknown Error updating Clerk profile image: ${ err } ` ,
220
+ ) ;
221
+ throw err ;
222
+ }
211
223
212
- const blobUpload = await put ( image . name , image , {
213
- access : "public" ,
214
- } ) ;
215
224
await db
216
225
. update ( userCommonData )
217
- . set ( { profilePhoto : blobUpload . url } )
218
- . where ( eq ( userCommonData . clerkID , user . clerkID ) ) ;
226
+ . set ( { profilePhoto : clerkUser . imageUrl } )
227
+ . where ( eq ( userCommonData . clerkID , userId ) ) ;
219
228
revalidatePath ( "/settings#profile" ) ;
220
229
return { success : true } ;
221
230
} ,
0 commit comments