@@ -35,6 +35,23 @@ const updateUserMutation: any = graphql(`
3535 }
3636` ) ;
3737
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+ } ;
54+
3855const UserProfile = ( ) => {
3956 const params = useParams < { entityType : string ; entitySlug : string } > ( ) ;
4057
@@ -70,9 +87,11 @@ const UserProfile = () => {
7087
7188 const { mutate, isLoading : editMutationLoading } = useMutation (
7289 ( input : { input : UpdateUserInput } ) =>
73- GraphQL ( updateUserMutation , {
74- [ params . entityType ] : params . entitySlug ,
75- } , input ) ,
90+ GraphQL (
91+ updateUserMutation ,
92+ { [ params . entityType ] : params . entitySlug } ,
93+ input
94+ ) ,
7695 {
7796 onSuccess : ( res : any ) => {
7897 toast ( 'User details updated successfully' ) ;
@@ -92,8 +111,36 @@ const UserProfile = () => {
92111 me : res . updateUser ,
93112 } ) ;
94113 } ,
114+
95115 onError : ( error : any ) => {
96- 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.' ) ;
97144 } ,
98145 }
99146 ) ;
@@ -112,24 +159,36 @@ const UserProfile = () => {
112159 if ( ! formValidation ) {
113160 toast ( 'Please fill all the required fields' ) ;
114161 return ;
115- } else {
116- const inputData : UpdateUserInput = {
117- firstName : formData . firstName ,
118- lastName : formData . lastName ,
119- bio : formData . bio ,
120- email : formData . email ,
121- githubProfile : formData . githubProfile ,
122- linkedinProfile : formData . linkedinProfile ,
123- twitterProfile : formData . twitterProfile ,
124- location : formData . location ,
125- } ;
126-
127- // Only add logo if it has changed
128- if ( formData . profilePicture instanceof File ) {
129- inputData . profilePicture = formData . profilePicture ;
130- }
131- mutate ( { input : inputData } ) ;
132162 }
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+ }
175+
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+ } ;
186+
187+ // Only add logo if it has changed
188+ if ( formData . profilePicture instanceof File ) {
189+ inputData . profilePicture = formData . profilePicture ;
190+ }
191+ mutate ( { input : inputData } ) ;
133192 } ;
134193
135194 return (
@@ -182,20 +241,23 @@ const UserProfile = () => {
182241 label = "Github Profile"
183242 name = "githubProfile"
184243 type = "url"
244+ placeholder = "https://github.com/username"
185245 value = { formData . githubProfile }
186246 onChange = { ( e ) => setFormData ( { ...formData , githubProfile : e } ) }
187247 />
188248 < TextField
189249 label = "Linkedin Profile"
190250 name = "linkedinProfile"
191251 type = "url"
252+ placeholder = "https://linkedin.com/in/username"
192253 value = { formData . linkedinProfile }
193254 onChange = { ( e ) => setFormData ( { ...formData , linkedinProfile : e } ) }
194255 />
195256 < TextField
196257 label = "Twitter Profile"
197258 name = "twitterProfile"
198259 type = "url"
260+ placeholder = "https://twitter.com/username"
199261 value = { formData . twitterProfile }
200262 onChange = { ( e ) => setFormData ( { ...formData , twitterProfile : e } ) }
201263 />
0 commit comments