diff options
Diffstat (limited to 'moneyjsx/src/upgrade.tsx')
| -rw-r--r-- | moneyjsx/src/upgrade.tsx | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/moneyjsx/src/upgrade.tsx b/moneyjsx/src/upgrade.tsx new file mode 100644 index 0000000..ab29e34 --- /dev/null +++ b/moneyjsx/src/upgrade.tsx @@ -0,0 +1,206 @@ +import * as JSX from './jsx'; +import * as user from './user'; +import * as api from './api'; +import $ from 'jquery'; + +import { Page, GroupBox, Spinner } from './components'; + +let stripe = null; +let card = null; +let selected_product = 2; + +async function loadStripe() { + return new Promise( function (resolve, reject ) { + const s = document.createElement( 'script' ); + s.src = 'https://js.stripe.com/v3/'; + s.onload = resolve; + s.onerror = reject; + document.head.appendChild( s ); + } ); +} + +function showError( text: string ) { + $( "#payment-error" ).show(); + $( "#payment-error" ).text( text ); +} + +async function onFormSubmit( e: Event ) { + e.preventDefault(); + const { paymentMethod, error } = await stripe.createPaymentMethod( { + type: 'card', + card + } ); + + if( error ) + return showError( error.message ); + + const res = await api.post( 'create-payment-intent', { + token: localStorage.getItem( 'session' ), + paymentMethodId: paymentMethod.id, + subLength: selected_product + } ); + + if( res.status == 'ok' ) { + const intent = res.paymentIntent; + if( intent.status == 'succeeded' ) + return JSX.navigateParams( '/payment-success', {} ); + else + return showError( "Payment failed. Contact support if the issue persists." ); + } + else if( res.msg ) + return showError( "Error: " + res.msg ); + else + return showError( "Payment failed. Contact support if the issue persists." ); +} + +function waitForStripe() { + const iframes = $( 'iframe' ); + if( !iframes.length ) + return setTimeout( waitForStripe, 50 ); + + for( let iframe of iframes ) { + if( iframe.attributes.getNamedItem( 'name' ).value == 'hcaptcha-invisible' ) { + $( '#upgrade-loading' ).remove(); + $( '#upgrade-inner' ).show(); + + return; + } + } + + setTimeout( waitForStripe, 50 ); +} + +async function initStripe() { + stripe = window['Stripe']( 'pk_live_51Q9JG602rmv2yeiGYNNfwFkqp5ntpXIDIMIoiwDoEOrB5IsC75WDy3XOqekvuwY6PecviSSo5ERt0umrdBdUtqhd00FyYZe5p3' ); + const font = user.settings.site_prefs.font; + + const params = { + mode: 'billing', + style: { + base: { + color: '#fff', + fontFamily: font, + fontSize: '15px', + '::placeholder': { + color: '#ccc', + }, + }, + }, + } + + const el = getComputedStyle( document.body ); + const back = el.getPropertyValue( '--back' ); + const front = el.getPropertyValue( '--front' ); + const appearance = { + theme: 'stripe', + disableAnimations: true, + + variables: { + colorPrimary: front, + colorBackground: back, + colorText: '#fff', + fontFamily: font, + fontSizeBase: '15px', + fontSizeSm: '13px', + spacingUnit: '2px', + borderRadius: '0px', + }, + rules: { + ".Input": { + border: 'none' + } + } + } + + const elements = stripe.elements( { appearance } ); + const name = elements.create( 'address', { mode: 'billing', appearance } ); + name.mount( '#name-element' ); + + card = elements.create( 'card', params ); + card.mount( '#card-element' ); +} + +function onProductChange( e: Event ) { + selected_product = parseInt( (e.target as HTMLInputElement).value ); +} + +function SelectionRadio( params: any ) { + return <div style="display: flex"> + { params.checked && + <input type="radio" + name="product" + value={ params.value } + onChange={ onProductChange } + checked="checked" + /> + } + { !params.checked && + <input type="radio" + name="product" + value={ params.value } + onChange={ onProductChange } + /> + } + <label class="radio-label" style="margin-left: 5px"> + { params.text } <span style="color: var(--front)">-- ${ params.price }</span> + </label> + </div> +} + +function UpgradeLoaded() { + return <GroupBox + title="Account upgrade" + style="width: 90%; max-width: 550px; display: none" + innerStyle="width: calc( 100% - 10px )" + id="upgrade-inner" + > + <div style="border-bottom: 1px solid var(--front);"> + <h2 style="padding: 8px 0px; margin: 0px; font-size: 28px">Summary</h2> + <div style="width: 60%"> + <h3 style="margin: 5px 0;"> + Product: + </h3> + <h4 style="margin: 5px 0"> + <span id="product-name">Axonbox premium account upgrade</span><br /> + <SelectionRadio text="1 week" price="2.70" value="1"/> + <SelectionRadio text="1 month" price="10" value="2" checked="checked"/> + <SelectionRadio text="1 year" price="100" value="3"/> + </h4> + </div> + </div> + <div> + <h3 style="margin: 5px 0"> + Payment information + </h3> + </div> + <form id="upgrade-form" method="POST" action="" onsubmit={ onFormSubmit }> + <div> + <label for="name-element">Contact information</label> + <div id="name-element"></div> + <label for="card-element">Credit or debit card</label> + <div id="card-element" style="padding: 10px 0"></div> + <div id="card-errors" role="alert"></div> + </div> + <div> + <span style="display:none" id='payment-error'></span> + </div> + <button type="submit">Submit</button> + </form> + </GroupBox> +} + +export default function Upgrade() { + setTimeout( () => { + loadStripe().then( () => { + $( <UpgradeLoaded /> ).insertAfter( "#upgrade-loading" ); + initStripe(); + waitForStripe(); + } ); + } ); + + return <Page> + <GroupBox title="Account upgrade" id="upgrade-loading"> + <span>Loading... <Spinner style="display: inline" /></span> + </GroupBox> + </Page> +} |
