@@ -41,6 +41,7 @@ class DomainSettings extends DashboardView {
4141
4242 isUserVerified : false ,
4343 canChangeCustomDomain : false ,
44+ canChangeSubdomain : false ,
4445 showCardValidation : true ,
4546
4647 subdomainName : '' ,
@@ -57,19 +58,12 @@ class DomainSettings extends DashboardView {
5758 updating : false ,
5859 isEditing : false ,
5960 hasToggleChanged : false ,
60- canEdit : false ,
61+ canEdit : true ,
6162
6263 errorCustomDomain : null ,
6364 successCustomDomain : null ,
6465 errorUpdateWebHost : null ,
6566 successUpdateWebHost : null ,
66-
67- // Session verification states
68- isVerifyingSession : false ,
69- sessionVerificationError : null ,
70- verifiedSessionId : null ,
71- showSuccessMessage : false ,
72-
7367 } ;
7468 this . onRefresh = this . onRefresh . bind ( this ) ;
7569 this . handleSubdomainChange = this . handleSubdomainChange . bind ( this ) ;
@@ -80,8 +74,6 @@ class DomainSettings extends DashboardView {
8074
8175 componentWillMount ( ) {
8276 this . loadData ( ) ;
83- this . checkForStripeSession ( ) ;
84- this . getOwner ( ) ;
8577 }
8678
8779 componentWillReceiveProps ( nextProps , nextContext ) {
@@ -103,13 +95,11 @@ class DomainSettings extends DashboardView {
10395 this . loadData ( ) ;
10496 }
10597
106- getOwner ( ) {
107- this . setState ( { canEdit : ! ! this . context . isOwner } ) ;
108- }
109-
11098 async loadData ( ) {
99+ console . log ( "STATE" , this . state ) ;
111100 try {
112101 const response = await this . context . getCustomDomain ( ) ;
102+ console . log ( "RESPONSE" , response ) ;
113103 this . setState ( { domainSettings : response } ) ;
114104 await this . loadHostSettings ( response ) ;
115105 } catch ( error ) {
@@ -120,7 +110,7 @@ class DomainSettings extends DashboardView {
120110 }
121111
122112 async loadHostSettings ( response ) {
123- const { hostSettings : appHostSettings , domains, canChangeCustomDomain, createdAt } = response ;
113+ const { hostSettings : appHostSettings , domains, canChangeCustomDomain, canChangeSubdomain , createdAt } = response ;
124114
125115 let customDomainArray = [ ] ;
126116 let subdomainName = '' ;
@@ -129,7 +119,6 @@ class DomainSettings extends DashboardView {
129119 let isActivated = false ;
130120 let hasPermission = false ;
131121 let isUserVerified = false ;
132- let alertValidationCreditCard = true ;
133122
134123 if ( domains && domains . length > 0 ) {
135124 customDomainArray = domains ;
@@ -151,36 +140,34 @@ class DomainSettings extends DashboardView {
151140 }
152141
153142 hasPermission = ( ! response . featuresPermission || response . featuresPermission . webHostLiveQuery === 'Write' ) ;
143+
144+ console . log ( "response" , createdAt ) ;
145+
154146 if ( response && ( ( appHostSettings . serverURL && appHostSettings . activated ) || ( createdAt && ( ( new Date ( ) - new Date ( createdAt ) ) > ( 6 * 30 * 24 * 60 * 60 * 1000 ) ) ) ) ) {
155147 isUserVerified = true ;
156- alertValidationCreditCard = false ;
157148 }
158149
159150 if ( ! isUserVerified ) {
160151 try {
161152 const plan = await this . context . getAppPlanData ( ) ;
162153 if ( plan && plan . planName && ( plan . planName . indexOf ( 'Free' ) < 0 ) && ( plan . planName . indexOf ( 'Public' ) < 0 ) ) {
163154 isUserVerified = true ;
164- alertValidationCreditCard = false ;
165155 } else {
166156 const currentUser = AccountManager . currentUser ( ) ;
167157 if ( currentUser && currentUser . verification . cardValidation ) {
168158 isUserVerified = true ;
169- alertValidationCreditCard = false ;
170159 }
171160 }
172161 } catch ( planError ) {
173162 const currentUser = AccountManager . currentUser ( ) ;
174163 if ( currentUser && currentUser . verification . cardValidation ) {
175164 isUserVerified = true ;
176- alertValidationCreditCard = false ;
177165 }
178166 }
179167 }
180168
181169 this . setState ( {
182170 isUserVerified,
183- showCardValidation : alertValidationCreditCard ,
184171
185172 subdomainName,
186173 currentSubdomain,
@@ -192,6 +179,7 @@ class DomainSettings extends DashboardView {
192179
193180 hasPermission,
194181 canChangeCustomDomain,
182+ canChangeSubdomain,
195183 } ) ;
196184 }
197185
@@ -296,7 +284,9 @@ class DomainSettings extends DashboardView {
296284 } , 5000 ) ;
297285 } ) ;
298286 } catch ( error ) {
299- this . setState ( { errorUpdateWebHost : error . message || 'Something went wrong!' } , ( ) => {
287+ console . error ( 'error updating web host' , error ) ;
288+
289+ this . setState ( { errorUpdateWebHost : error || 'Something went wrong!' } , ( ) => {
300290 setTimeout ( ( ) => {
301291 this . setState ( { errorUpdateWebHost : null } ) ;
302292 } , 5000 ) ;
@@ -309,124 +299,54 @@ class DomainSettings extends DashboardView {
309299 async verifyUser ( ) {
310300 try {
311301 const user = await back4app2 . me ( ) ;
312- if ( user && user . verification . cardValidation ) {
313- this . setState ( { isUserVerified : true , showCardValidation : false } ) ;
302+ if ( user ) {
303+ this . setState ( { isUserVerified : true } ) ;
314304 }
315305 } catch ( e ) {
316306 console . log ( 'user validation failed!' )
317307 }
318308 }
319309
320- checkForStripeSession ( ) {
321- const urlParams = new URLSearchParams ( window . location . search ) ;
322- const sessionId = urlParams . get ( 'session_id' ) ;
323-
324- if ( sessionId && sessionId !== this . state . verifiedSessionId ) {
325- this . verifyStripeSession ( sessionId ) ;
326- }
327- }
328-
329- async verifyStripeSession ( sessionId ) {
330- try {
331- this . setState ( {
332- isVerifyingSession : true ,
333- sessionVerificationError : null
334- } ) ;
335-
336- await back4app2 . stripeSessionStatus ( sessionId ) ;
337-
338- // Session verification successful
339- this . setState ( {
340- isVerifyingSession : false ,
341- verifiedSessionId : sessionId ,
342- showSuccessMessage : true
343- } ) ;
344-
345- const user = AccountManager . currentUser ( ) ;
346- user . verification . cardValidation = true ;
347- AccountManager . setCurrentUser ( { user } ) ;
348-
349- // Show success message for 2 seconds, then close modal and update state
350- setTimeout ( ( ) => {
351- this . setState ( {
352- showSuccessMessage : false ,
353- isUserVerified : true ,
354- showCardValidation : false
355- } ) ;
356- } , 2000 ) ;
357-
358- } catch ( error ) {
359- console . error ( 'Error verifying stripe session:' , error ) ;
360-
361- this . setState ( {
362- isVerifyingSession : false ,
363- sessionVerificationError : error . message || 'Failed to verify payment. Please try again.' ,
364- showCardValidation : true
365- } ) ;
366- } finally {
367- // Clean up URL regardless of success or error
368- const url = new URL ( window . location ) ;
369- url . searchParams . delete ( 'session_id' ) ;
370- window . history . replaceState ( { } , '' , url ) ;
371- }
372- }
373-
374310 getDisplayContent ( ) {
375311 let content = null ;
376312
377- if ( this . state . isVerifyingSession || this . state . showSuccessMessage ) {
378- content = < B4aModal
379- type = { B4aModal . Types . DEFAULT }
380- title = { this . state . showSuccessMessage ? 'Payment Verified' : 'Verifying payment' }
381- subtitle = { this . state . showSuccessMessage ? 'Your payment has been successfully verified!' : 'Please wait while we verify your payment...' }
382- width = { '60vw' }
383- customFooter = { < div > </ div > }
384- >
385- < div className = { styles . paymentVerificationModal } >
386- { this . state . showSuccessMessage ? (
387- < div className = { styles . successContainer } >
388- < Icon name = "b4a-success-check" width = { 24 } height = { 24 } />
389- < div className = { styles . successText } > Payment verification successful!</ div >
390- </ div >
391- ) : (
392- < div className = { styles . spinnerContainer } >
393- < div className = { styles . spinner } > </ div >
394- < div className = { styles . spinnerText } > Loading...</ div >
395- </ div >
396- ) }
397- </ div >
398- </ B4aModal >
399- } else if ( this . state . showCardValidation ) {
313+ if (
314+ ! this . state . canChangeSubdomain && ! this . state . isActivated && this . state . currentSubdomain . trim ( ) . length === 0 && this . state . customDomainArray . length === 0 ) {
400315 content = < Fieldset >
401316 < Field
402- label = { < Label text = "Verify your card " dark = { true } description = "You must verify your card to activate your web hosting." /> }
317+ label = { < Label text = "Upgrade your plan " dark = { true } description = "Please upgrade your plan to activate your web hosting." /> }
403318 input = { < div style = { { width : '100%' , padding : '0 1rem' , textAlign : 'right' } } >
404- < StripeValidateCard
405- onClick = { ( ) => this . setState ( { cardValidationError : null , sessionVerificationError : null } ) }
406- onError = { ( err ) => this . setState ( { cardValidationError : err . message || 'Something went wrong!' } ) }
407- onSuccess = { ( ) => this . verifyUser ( ) }
408- />
319+ < Link to = { `/apps/${ this . context . slug } /plan-usage` } >
320+ < Button
321+ value = "Upgrade Plan"
322+ primary = { true }
323+ />
324+ </ Link >
409325 </ div > }
410326 theme = { Field . Theme . BLUE }
411327 />
412- { ( this . state . cardValidationError || this . state . sessionVerificationError ) && (
413- < div className = { styles . error } >
414- { this . state . cardValidationError || this . state . sessionVerificationError }
415- </ div >
416- ) }
417328 </ Fieldset >
418329 } else if ( this . state . isUserVerified ) {
419330 content = < > < Fieldset >
420331 < Field
421332 label = { < Label text = "Activate Web Hosting" dark = { true } description = "Toggle to enable or disable web hosting for your app." /> }
422333 input = {
423334 < div style = { { width : '100%' , padding : '0 1rem' , textAlign : 'right' } } >
424- < B4aToggle
425- value = { this . state . activated }
426- onChange = { this . handleToggleChange }
427- type = { B4aToggle . Types . YES_NO }
428- disabled = { ! this . state . canEdit }
429- />
335+ { this . state . canChangeSubdomain || this . state . currentSubdomain . trim ( ) . length > 0 ? (
336+ < B4aToggle
337+ value = { this . state . activated }
338+ onChange = { this . handleToggleChange }
339+ type = { B4aToggle . Types . YES_NO }
340+ disabled = { ! this . state . canChangeSubdomain && this . state . currentSubdomain . trim ( ) . length === 0 }
341+ />
342+ ) : (
343+ < Link to = { `/apps/${ this . context . slug } /plan-usage` } >
344+ < Button
345+ value = "Upgrade Plan"
346+ primary = { true }
347+ />
348+ </ Link >
349+ ) }
430350 </ div >
431351 }
432352 theme = { Field . Theme . BLUE }
@@ -484,7 +404,7 @@ class DomainSettings extends DashboardView {
484404 </ option >
485405 ) ) }
486406 </ select > ) : ( < span style = { { display :'inline-block' , marginLeft : '0.5rem' } } > { this . state . currentDomain } </ span > ) }
487- { this . state . canEdit ? (
407+ { this . state . canChangeSubdomain || this . state . currentSubdomain . trim ( ) . length > 0 ? (
488408 < >
489409 < Button
490410 value = { this . state . updating ? 'saving...' : 'save' }
@@ -505,7 +425,7 @@ class DomainSettings extends DashboardView {
505425 </ > : (
506426 < >
507427 < span className = { styles . subdomainContainer } > < a className = { styles . subdomain } href = { `https://${ this . state . domainSettings . hostSettings . webhost } ` } target = "_blank" rel = "noopener noreferrer" > { this . state . domainSettings . hostSettings . webhost } </ a > </ span >
508- { this . state . canEdit ? (
428+ { this . state . canChangeSubdomain || this . state . currentSubdomain . trim ( ) . length > 0 ? (
509429 < Button
510430 value = { 'Edit' }
511431 color = "blue"
@@ -526,30 +446,44 @@ class DomainSettings extends DashboardView {
526446 </ Fieldset >
527447
528448 < Fieldset legend = "Custom Domain" description = { this . state . canChangeCustomDomain ? 'Configure a custom address to your app.' : 'Upgrade to Pay as You Go Plan to add your custom domain.' } >
529- { ! this . state . canChangeCustomDomain && < Link to = { `/apps/${ this . context . slug } /plan-usage` } >
530- < Button
531- value = "Upgrade Plan"
532- primary = { true }
533- />
534- </ Link > }
535449
536- < div style = { { marginTop : this . state . canChangeCustomDomain ? '0' : '1rem' , opacity : this . state . canChangeCustomDomain ? 1 : 0.5 , pointerEvents : this . state . canChangeCustomDomain ? 'auto' : 'none' } } >
450+ < div style = { { marginTop : this . state . canChangeCustomDomain ? '0' : '1rem' } } >
537451 < Field
538452 label = { < Label text = "Custom domain" dark = { true } description = "Enter your custom domain" /> }
539- input = { < div style = { { width : '100%' , padding : '0 1rem' , textAlign : 'right' , display : 'flex' , gap : '0.5rem' , alignItems : 'center' } } >
540- < TextInput
541- value = { this . state . customDomain }
542- onChange = { ( val ) => this . setState ( { customDomain : val } ) }
543- disabled = { this . state . updating || ! this . state . canChangeCustomDomain || ! this . state . canEdit }
544- placeholder = "example.com"
545- />
546- < Button
547- value = "Add"
548- color = "green"
549- onClick = { this . handleAddCustomDomain }
550- disabled = { this . state . updating || ! this . state . canChangeCustomDomain || this . state . customDomain . trim ( ) . length === 0 || ! this . state . canEdit }
551- additionalStyles = { { background : 'transparent' , border : '1px solid #4CAF50' , color : '#4CAF50' , borderRadius : '4px' , padding : '0.5rem 1rem' , fontSize : '14px' , minWidth : '80px' } }
552- />
453+ input = { < div style = { {
454+ width : '100%' ,
455+ padding : '0 1rem' ,
456+ textAlign : 'right' ,
457+ display : 'flex' ,
458+ gap : '0.5rem' ,
459+ alignItems : 'center' ,
460+ justifyContent : this . state . canChangeCustomDomain ? 'space-between' : 'flex-end'
461+ } } >
462+ { this . state . canChangeCustomDomain ? (
463+ < >
464+ < TextInput
465+ value = { this . state . customDomain }
466+ onChange = { ( val ) => this . setState ( { customDomain : val } ) }
467+ disabled = { this . state . updating }
468+ placeholder = "example.com"
469+ />
470+ < Button
471+ value = "Add"
472+ color = "green"
473+ onClick = { this . handleAddCustomDomain }
474+ disabled = { this . state . updating }
475+ additionalStyles = { { background : 'transparent' , border : '1px solid #4CAF50' , color : '#4CAF50' , borderRadius : '4px' , padding : '0.5rem 1rem' , fontSize : '14px' , minWidth : '80px' } }
476+ />
477+ </ >
478+ ) : (
479+ < Link to = { `/apps/${ this . context . slug } /plan-usage` } >
480+ < Button
481+ value = "Upgrade Plan"
482+ primary = { true }
483+ />
484+ </ Link >
485+ ) }
486+
553487 </ div > }
554488 theme = { Field . Theme . BLUE }
555489 />
@@ -582,7 +516,7 @@ class DomainSettings extends DashboardView {
582516 additionalStyles = { {
583517 padding : '0 0.5rem' ,
584518 } }
585- disabled = { this . state . updating || ! this . state . canEdit }
519+ disabled = { this . state . updating || ( ! this . state . canChangeCustomDomain && this . state . customDomainArray . length === 0 ) }
586520 />
587521 </ div >
588522 ) )
@@ -599,7 +533,6 @@ class DomainSettings extends DashboardView {
599533 < div className = { styles . domainSettingsContainer } >
600534 < div className = { styles . heading } > Web Hosting</ div >
601535 < div className = { styles . subheading } > You can use this section to enable a subdomain to host your pages and create your own custom domain.</ div >
602- { ! this . state . canEdit && < div className = { styles . helperText } > Only the app owner can edit this section.</ div > }
603536 < div className = { styles . formContainer } >
604537 { content }
605538 </ div >
0 commit comments