Skip to content

Instantly share code, notes, and snippets.

@flavienbonvin
Created July 10, 2019 12:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flavienbonvin/5eefa0b970a417337f06edbdcbc11182 to your computer and use it in GitHub Desktop.
Save flavienbonvin/5eefa0b970a417337f06edbdcbc11182 to your computer and use it in GitHub Desktop.
import React, { Component } from 'react'
import { Card, Col } from 'antd'
import { $, key } from '../../localization/localization'
import { Pricing } from '../../models/Pricing'
class PricingCol extends Component {
render () {
const {title, onClick, className, iconType, numberOfPlans, status, hoverable} = this.props
return <Col span={8} type={'flex'} align={'middle'}>
<Card title={title} hoverable={hoverable} onClick={onClick} className={className}>
<img src={process.env.PUBLIC_URL + iconType} style={{height: '80px', width: '80px', marginBottom: '17px'}} alt='icon_basic'/>
<p style={{marginBottom: '37px'}}>{numberOfPlans}</p>
<p style={{marginBottom: '0px'}}>{Pricing.priceWithCurrentCurrency(status)}</p>
<p style={{padding: '20px'}}>{$(key.pricingModalChargedHow, Pricing.annualPriceWithCurrentCurrency(status))}</p>
</Card>
</Col>
}
}
export default PricingCol
import React, { Component } from 'react'
import { USER_STATUS_BASIC, USER_STATUS_PREMIUM, USER_STATUS_STARTER } from '../../models/User'
import withCurrentUser from '../currentUser/withCurrentUser'
import { compose } from 'recompose'
import { Button, Col, Modal, Row, Spin } from 'antd'
import { track } from '../../helpers/trackerHelper'
import axios from 'axios'
import firebase from 'firebase/app'
import { $, key } from '../../localization/localization'
import { getCustomerCardInformation } from '../../helpers/customerCardInformation'
import { Pricing } from '../../models/Pricing'
import { StripeForm } from './StripeForm'
import PricingCol from './PricingCol'
const displayLoading = () => {
return <div className="loader-modal">
<Spin size='large'/>
</div>
}
const displayPricingInformation = (onCardClick, classPremium, classStarter, classBasic, hoverablePremium, hoverableStarter, hoverableBasic) => {
return <div>
<Row gutter={16}>
<Col span={24} type={'flex'} align={'middle'} style={{paddingBottom: 40}}>{$(key.pricingModalDescription)}</Col>
<PricingCol title={$(key.pricingModalBasicTitle)}
onClick={() => onCardClick(USER_STATUS_BASIC)}
hoverable={hoverableBasic}
className={classBasic}
iconType={'/images/icon_basic.png'}
numberOfPlans={$(key.pricingModalBasicNumberPlans)}
status={USER_STATUS_BASIC}/>
<PricingCol title={$(key.pricingModalPremiumTitle)}
onClick={() => onCardClick(USER_STATUS_PREMIUM)}
hoverable={hoverablePremium}
className={classPremium}
iconType={'/images/icon_premium.png'}
numberOfPlans={$(key.pricingModalPremiumNumberPlans)}
status={USER_STATUS_PREMIUM}/>
<PricingCol title={$(key.pricingModalStarterTitle)}
onClick={() => onCardClick(USER_STATUS_STARTER)}
hoverable={hoverableStarter}
className={classStarter}
iconType={'/images/icon_starter.png'}
numberOfPlans={$(key.pricingModalStarterNumberPlans)}
status={USER_STATUS_STARTER}/>
</Row>
</div>
}
class PricingModal extends Component {
constructor (props) {
super(props)
this.initialState = {
pricingModalVisible: false,
loading: false,
selectedStatus: USER_STATUS_PREMIUM,
cardInformation: {},
classBasic: '',
classStarter: '',
classPremium: 'pricing-selected',
hoverableBasic: true,
hoverableStarter: true,
hoverablePremium: true,
}
this.state = this.initialState
}
onCardClick = (e) => {
const {currentUser} = this.props
if (e === currentUser.status) return
else if (currentUser.status === USER_STATUS_STARTER && (e === USER_STATUS_BASIC || e === USER_STATUS_PREMIUM)) return
switch (e) {
case USER_STATUS_PREMIUM:
this.setState({
classBasic: this.state.classBasic === 'pricing-disabled' ? 'pricing-disabled' : '',
classPremium: 'pricing-selected',
classStarter: ''
})
break
case USER_STATUS_STARTER:
this.setState({
classBasic: this.state.classBasic === 'pricing-disabled' ? 'pricing-disabled' : '',
classPremium: '',
classStarter: 'pricing-selected'
})
break
case USER_STATUS_BASIC:
this.setState({
classBasic: 'pricing-selected',
classPremium: '',
classStarter: ''
})
break
default:
break
}
this.setState({selectedStatus: e})
}
pricingModalDisplay = () => {
this.setState({pricingModalVisible: true})
this.setInitialStatus()
track('pricing_modal', {from: this.props.from})
axios.post(`${process.env.REACT_APP_FUNCTION_URL}/updateStripeName`, {
userId: this.props.currentUser.id,
name: firebase.auth().currentUser.displayName
})
}
pricingModalCancel = () => this.setState(this.initialState)
componentWillMount () {
getCustomerCardInformation(this.props.currentUser.id).then(cardInformation => {
this.setState({cardInformation: cardInformation})
})
}
onToken = (token, planId) => {
this.setState({loading: true})
axios.post(`${process.env.REACT_APP_FUNCTION_URL}/createStripeSubscription`, {
userId: this.props.currentUser.id,
stripeCustomerId: this.props.currentUser.stripeCustomerId,
stripePlanId: planId,
token: token.id
})
.then(() => {
track('user_subscribed', {plan: Pricing.planTypeFor(planId)})
this.setState(this.initialState)
})
.catch(() => {
this.setState(this.initialState)
})
}
upgradeTo = (status) => {
this.setState({loading: true})
const planId = Pricing.planIdForCurrentCurrency(status)
axios.post(`${process.env.REACT_APP_FUNCTION_URL}/updateStripeSubscription`, {
userId: this.props.currentUser.id,
stripeCustomerId: this.props.currentUser.stripeCustomerId,
stripeSubscriptionId: this.props.currentUser.stripeSubscriptionId,
stripePlanId: planId,
})
.then(() => {
track('user_upgraded', {plan: Pricing.planTypeFor(planId)})
this.setState(this.initialState)
})
.catch(() => {
this.setState(this.initialState)
})
}
setInitialStatus = () => {
const {currentUser} = this.props
switch (currentUser.status) {
case USER_STATUS_PREMIUM:
this.setState({
classPremium: 'pricing-disabled',
classStarter: 'pricing-disabled',
classBasic: 'pricing-disabled',
hoverablePremium: false,
hoverableStarter: false,
hoverableBasic: false,
})
break
case USER_STATUS_STARTER:
this.setState({
classPremium: 'pricing-selected',
classStarter: 'pricing-disabled',
classBasic: 'pricing-disabled',
hoverablePremium: true,
hoverableStarter: false,
hoverableBasic: false,
})
break
case USER_STATUS_BASIC:
this.setState({
classPremium: 'pricing-selected',
classStarter: '',
classBasic: 'pricing-disabled',
hoverablePremium: true,
hoverableStarter: true,
hoverableBasic: false,
})
break
default:
break
}
}
render () {
const {buttonRendering, currentUser} = this.props
const {cardRegistered} = this.state.cardInformation
const {pricingModalVisible, loading, selectedStatus, classPremium, classStarter, classBasic, hoverablePremium, hoverableStarter, hoverableBasic} = this.state
const upgradeButton =
cardRegistered ? <Button key='buy' type='primary' onClick={() => this.upgradeTo(selectedStatus)}>{$(key.pricingModalUpgradePlanCTA)}</Button>
: currentUser.stripeSubscriptionId
? <StripeForm key='buy' status={selectedStatus} onToken={() => this.upgradeTo(selectedStatus)}/>
: <StripeForm key='buy' status={selectedStatus} onToken={this.onToken}/>
if (currentUser.status === USER_STATUS_PREMIUM && !currentUser.hasOutdatedSubscription()) {
return null
} else {
return (
<div>
<Modal
visible={pricingModalVisible}
onCancel={this.pricingModalCancel}
title={$(key.pricingModalTitle)}
width={893}
footer={loading
? null
: [
<Button key='cancel' className="cancel-button" onClick={this.pricingModalCancel}>{$(key.cancel)}</Button>,
upgradeButton
]}>
{loading
? displayLoading()
: displayPricingInformation(this.onCardClick, classPremium, classStarter, classBasic, hoverablePremium, hoverableStarter, hoverableBasic)
}
</Modal>
<div onClick={this.pricingModalDisplay}>
{buttonRendering}
</div>
</div>
)
}
}
}
export default compose(
withCurrentUser
)(PricingModal)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment