1- import { Alert , Box , Button , DialogActions } from "@mui/material" ;
1+ import { Alert , Box , Button , DialogActions , TextField } from "@mui/material" ;
22import RequiredTextField from "../../../src/components/RequiredTextField.jsx" ;
33import ImageUpload from '../../../src/components/ImageUpload.jsx' ;
44import { useState } from "react" ;
55import { getCookie } from '../../../src/utils.js' ;
66import { useAppContext } from '../../../src/render.jsx' ;
77
8- function OrganizationForm ( { successCallback, failureCallback, cancelCallback, createMode, initialName, initialDescription, initialLogoUrl, organizationId } ) {
8+ function OrganizationForm ( { successCallback, failureCallback, cancelCallback, createMode, initialName, initialDescription, initialLogoUrl, initialWebsite , initialLinkedinPage , initialYoutubeChannel , organizationId } ) {
99 const [ name , setName ] = useState ( initialName || "" ) ;
1010 const [ description , setDescription ] = useState ( initialDescription || "" ) ;
11+ const [ website , setWebsite ] = useState ( initialWebsite || "" ) ;
12+ const [ linkedinPage , setLinkedinPage ] = useState ( initialLinkedinPage || "" ) ;
13+ const [ youtubeChannel , setYoutubeChannel ] = useState ( initialYoutubeChannel || "" ) ;
1114 const [ nameHelperText , setNameHelperText ] = useState ( "" ) ;
1215 const [ descriptionHelperText , setDescriptionHelperText ] = useState ( "" ) ;
16+ const [ websiteHelperText , setWebsiteHelperText ] = useState ( "" ) ;
17+ const [ linkedinPageHelperText , setLinkedinPageHelperText ] = useState ( "" ) ;
18+ const [ youtubeChannelHelperText , setYoutubeChannelHelperText ] = useState ( "" ) ;
1319 const [ logoServerPath , setLogoServerPath ] = useState ( null ) ;
1420 const [ errorMessage , setErrorMessage ] = useState ( ) ;
1521 const { localeMessages, apiBaseUrl } = useAppContext ( ) ;
1622
23+ const validateOptionalUrl = ( value ) => {
24+ const trimmedValue = value . trim ( ) ;
25+
26+ if ( ! trimmedValue ) {
27+ return true ;
28+ }
29+
30+ try {
31+ const parsedUrl = new URL ( trimmedValue ) ;
32+
33+ return [ "http:" , "https:" ] . includes ( parsedUrl . protocol ) && Boolean ( parsedUrl . hostname ) ;
34+ } catch {
35+ return false ;
36+ }
37+ } ;
38+
1739 const validateForm = ( ) => {
1840 let valid = true ;
41+ setErrorMessage ( undefined ) ;
42+
1943 if ( ! name . trim ( ) ) {
2044 setNameHelperText ( localeMessages [ "name_required" ] ) ;
2145 valid = false ;
@@ -30,6 +54,27 @@ function OrganizationForm({ successCallback, failureCallback, cancelCallback, cr
3054 setDescriptionHelperText ( "" ) ;
3155 }
3256
57+ if ( ! validateOptionalUrl ( website ) ) {
58+ setWebsiteHelperText ( "Enter a valid URL starting with http:// or https://" ) ;
59+ valid = false ;
60+ } else {
61+ setWebsiteHelperText ( "" ) ;
62+ }
63+
64+ if ( ! validateOptionalUrl ( linkedinPage ) ) {
65+ setLinkedinPageHelperText ( "Enter a valid URL starting with http:// or https://" ) ;
66+ valid = false ;
67+ } else {
68+ setLinkedinPageHelperText ( "" ) ;
69+ }
70+
71+ if ( ! validateOptionalUrl ( youtubeChannel ) ) {
72+ setYoutubeChannelHelperText ( "Enter a valid URL starting with http:// or https://" ) ;
73+ valid = false ;
74+ } else {
75+ setYoutubeChannelHelperText ( "" ) ;
76+ }
77+
3378 return valid ;
3479 }
3580
@@ -40,8 +85,11 @@ function OrganizationForm({ successCallback, failureCallback, cancelCallback, cr
4085 }
4186
4287 let payload = {
43- name : name ,
44- description : description ,
88+ name : name . trim ( ) ,
89+ description : description . trim ( ) ,
90+ website : website . trim ( ) ,
91+ linkedin_page : linkedinPage . trim ( ) ,
92+ youtube_channel : youtubeChannel . trim ( ) ,
4593 } ;
4694
4795 if ( logoServerPath ) {
@@ -90,9 +138,12 @@ function OrganizationForm({ successCallback, failureCallback, cancelCallback, cr
90138 'X-CSRFToken' : getCookie ( 'csrftoken' ) ,
91139 } ,
92140 body : JSON . stringify ( {
93- name : name ,
94- description : description ,
141+ name : name . trim ( ) ,
142+ description : description . trim ( ) ,
95143 logo : logoServerPath ,
144+ website : website . trim ( ) ,
145+ linkedin_page : linkedinPage . trim ( ) ,
146+ youtube_channel : youtubeChannel . trim ( ) ,
96147 } ) ,
97148 } )
98149 . then ( response => {
@@ -107,7 +158,8 @@ function OrganizationForm({ successCallback, failureCallback, cancelCallback, cr
107158 successCallback ( data ) ;
108159 } )
109160 . catch ( error => {
110- setErrorMessages ( localeMessages [ "error_try_again" ] ) ;
161+ setErrorMessage ( localeMessages [ "error_try_again" ] ) ;
162+ failureCallback ( error ) ;
111163 } ) ;
112164 }
113165
@@ -116,10 +168,13 @@ function OrganizationForm({ successCallback, failureCallback, cancelCallback, cr
116168 { errorMessage && < Alert severity = "error" sx = { { mb : 2 } } > { errorMessage } </ Alert > }
117169 < RequiredTextField label = { localeMessages [ "name" ] } helperText = { nameHelperText } fullWidth margin = "normal" value = { name } onChange = { ( e ) => setName ( e . target . value ) } />
118170 < RequiredTextField label = { localeMessages [ "description" ] } helperText = { descriptionHelperText } fullWidth margin = "normal" multiline rows = { 4 } value = { description } onChange = { ( e ) => setDescription ( e . target . value ) } />
171+ < TextField label = "Website" type = "url" fullWidth margin = "normal" value = { website } error = { Boolean ( websiteHelperText ) } helperText = { websiteHelperText } onChange = { ( e ) => setWebsite ( e . target . value ) } />
172+ < TextField label = "LinkedIn page" type = "url" fullWidth margin = "normal" value = { linkedinPage } error = { Boolean ( linkedinPageHelperText ) } helperText = { linkedinPageHelperText } onChange = { ( e ) => setLinkedinPage ( e . target . value ) } />
173+ < TextField label = "YouTube channel" type = "url" fullWidth margin = "normal" value = { youtubeChannel } error = { Boolean ( youtubeChannelHelperText ) } helperText = { youtubeChannelHelperText } onChange = { ( e ) => setYoutubeChannel ( e . target . value ) } />
119174 < ImageUpload initialUrl = { initialLogoUrl } onUploadSuccess = { ( data ) => {
120175 setLogoServerPath ( data . file_path ) ;
121176 } } onUploadError = { ( error ) => {
122- setErrorMessages ( localeMessages [ "logo_upload_failed" ] ) ;
177+ setErrorMessage ( localeMessages [ "logo_upload_failed" ] ) ;
123178 } } />
124179 < DialogActions >
125180 < Button onClick = { cancelCallback } > { localeMessages [ "cancel" ] } </ Button >
0 commit comments