@@ -35,7 +35,22 @@ const updateUserMutation: any = graphql(`
3535 }
3636` ) ;
3737
38- const urlRegex = / ^ ( h t t p s ? : \/ \/ ) ( [ \w - ] + \. ) + [ \w - ] { 2 , } ( \/ \S * ) ? $ / ;
38+ const githubRegex = / ^ h t t p s : \/ \/ g i t h u b \. c o m \/ [ a - z A - Z 0 - 9 ] (?: [ a - z A - Z 0 - 9 ] | - (? = [ a - z A - Z 0 - 9 ] ) ) { 0 , 38 } $ / ;
39+ const linkedinRegex = / ^ h t t p s : \/ \/ (?: w w w \. ) ? l i n k e d i n \. c o m \/ i n \/ [ a - z A - Z 0 - 9 - ] + \/ ? $ / ;
40+ const twitterRegex = / ^ h t t p s : \/ \/ (?: w w w \. ) ? (?: t w i t t e r \. c o m | x \. c o m ) \/ [ a - z A - Z 0 - 9 _ ] + \/ ? $ / ;
41+
42+ const prettyField = ( f : string ) => {
43+ switch ( f ) {
44+ case 'github_profile' :
45+ return 'GitHub URL' ;
46+ case 'linkedin_profile' :
47+ return 'LinkedIn URL' ;
48+ case 'twitter_profile' :
49+ return 'Twitter URL' ;
50+ default :
51+ return f . replace ( / _ / g, ' ' ) . replace ( / \b \w / g, ( c ) => c . toUpperCase ( ) ) ;
52+ }
53+ } ;
3954
4055const UserProfile = ( ) => {
4156 const params = useParams < { entityType : string ; entitySlug : string } > ( ) ;
@@ -72,9 +87,11 @@ const UserProfile = () => {
7287
7388 const { mutate, isLoading : editMutationLoading } = useMutation (
7489 ( input : { input : UpdateUserInput } ) =>
75- GraphQL ( updateUserMutation , {
76- [ params . entityType ] : params . entitySlug ,
77- } , input ) ,
90+ GraphQL (
91+ updateUserMutation ,
92+ { [ params . entityType ] : params . entitySlug } ,
93+ input
94+ ) ,
7895 {
7996 onSuccess : ( res : any ) => {
8097 toast ( 'User details updated successfully' ) ;
@@ -94,8 +111,36 @@ const UserProfile = () => {
94111 me : res . updateUser ,
95112 } ) ;
96113 } ,
114+
97115 onError : ( error : any ) => {
98- toast ( `Error: ${ error . message } ` ) ;
116+ if ( typeof error ?. message === 'string' ) {
117+ const message : string = error . message ;
118+
119+ // Try to extract field errors
120+ const tryField = ( field : string ) => {
121+ const m = message . match (
122+ new RegExp ( `'${ field } '\\s*:\\s*\\['([^']+)'\\]` )
123+ ) ;
124+ if ( m ?. [ 1 ] ) {
125+ const prettyName = prettyField ( field ) ;
126+ const errorMsg = `${ prettyName } : ${ m [ 1 ] } ` ;
127+ toast . error ( errorMsg ) ;
128+ }
129+ return Boolean ( m ?. [ 1 ] ) ;
130+ } ;
131+
132+ const anyMatched =
133+ tryField ( 'github_profile' ) ||
134+ tryField ( 'linkedin_profile' ) ||
135+ tryField ( 'twitter_profile' ) ;
136+
137+ if ( ! anyMatched ) {
138+ toast . error ( `Error: ${ message } ` ) ;
139+ }
140+ return ;
141+ }
142+
143+ toast . error ( 'An unexpected error occurred.' ) ;
99144 } ,
100145 }
101146 ) ;
@@ -114,39 +159,36 @@ const UserProfile = () => {
114159 if ( ! formValidation ) {
115160 toast ( 'Please fill all the required fields' ) ;
116161 return ;
117- }
118- if ( formData . githubProfile && ! urlRegex . test ( formData . githubProfile ) ) {
119- toast . error ( 'Enter a valid GitHub URL' ) ;
120- return ;
121- }
122-
123- if ( formData . linkedinProfile && ! urlRegex . test ( formData . linkedinProfile ) ) {
124- toast . error ( 'Enter a valid LinkedIn URL' ) ;
125- return ;
126- }
162+ }
163+ if ( formData . githubProfile && ! githubRegex . test ( formData . githubProfile ) ) {
164+ toast . error ( 'GitHub URL: Enter a valid URL.' ) ;
165+ return ;
166+ }
167+ if ( formData . linkedinProfile && ! linkedinRegex . test ( formData . linkedinProfile ) ) {
168+ toast . error ( 'LinkedIn URL: Enter a valid URL.' ) ;
169+ return ;
170+ }
171+ if ( formData . twitterProfile && ! twitterRegex . test ( formData . twitterProfile ) ) {
172+ toast . error ( 'Twitter URL: Enter a valid URL.' ) ;
173+ return ;
174+ }
127175
128- if ( formData . twitterProfile && ! urlRegex . test ( formData . twitterProfile ) ) {
129- toast . error ( 'Enter a valid Twitter URL' ) ;
130- return ;
131- }
132- else {
133- const inputData : UpdateUserInput = {
134- firstName : formData . firstName ,
135- lastName : formData . lastName ,
136- bio : formData . bio ,
137- email : formData . email ,
138- githubProfile : formData . githubProfile ,
139- linkedinProfile : formData . linkedinProfile ,
140- twitterProfile : formData . twitterProfile ,
141- location : formData . location ,
142- } ;
176+ const inputData : UpdateUserInput = {
177+ firstName : formData . firstName ,
178+ lastName : formData . lastName ,
179+ bio : formData . bio ,
180+ email : formData . email ,
181+ githubProfile : formData . githubProfile ,
182+ linkedinProfile : formData . linkedinProfile ,
183+ twitterProfile : formData . twitterProfile ,
184+ location : formData . location ,
185+ } ;
143186
144- // Only add logo if it has changed
145- if ( formData . profilePicture instanceof File ) {
146- inputData . profilePicture = formData . profilePicture ;
147- }
148- mutate ( { input : inputData } ) ;
187+ // Only add logo if it has changed
188+ if ( formData . profilePicture instanceof File ) {
189+ inputData . profilePicture = formData . profilePicture ;
149190 }
191+ mutate ( { input : inputData } ) ;
150192 } ;
151193
152194 return (
@@ -199,20 +241,23 @@ const UserProfile = () => {
199241 label = "Github Profile"
200242 name = "githubProfile"
201243 type = "url"
244+ placeholder = "https://github.com/username"
202245 value = { formData . githubProfile }
203246 onChange = { ( e ) => setFormData ( { ...formData , githubProfile : e } ) }
204247 />
205248 < TextField
206249 label = "Linkedin Profile"
207250 name = "linkedinProfile"
208251 type = "url"
252+ placeholder = "https://linkedin.com/in/username"
209253 value = { formData . linkedinProfile }
210254 onChange = { ( e ) => setFormData ( { ...formData , linkedinProfile : e } ) }
211255 />
212256 < TextField
213257 label = "Twitter Profile"
214258 name = "twitterProfile"
215259 type = "url"
260+ placeholder = "https://twitter.com/username"
216261 value = { formData . twitterProfile }
217262 onChange = { ( e ) => setFormData ( { ...formData , twitterProfile : e } ) }
218263 />
0 commit comments