jam-cloud/web/app/assets/javascripts/react-components/CurrentSubscription.js.jsx....

358 lines
16 KiB
CoffeeScript

context = window
rest = context.JK.Rest()
logger = context.JK.logger
LocationActions = context.LocationActions
SubscriptionActions = context.SubscriptionActions
UserStore = context.UserStore
AppStore = context.AppStore
@CurrentSubscription = React.createClass({
mixins: [Reflux.listenTo(AppStore, "onAppInit")]
getInitialState: () ->
{
selectedPlan: null
updating: false
}
getDisplayNameTier: (plan_code) ->
if plan_code == ''
plan_code = null
for subscriptionCode in gon.global.subscription_codes
if plan_code == subscriptionCode.id
return subscriptionCode.name
return "Unknown plan code=#{plan_code}"
getDisplayNamePrice: (plan_code) ->
if plan_code == ''
plan_code = null
for subscriptionCode in gon.global.subscription_codes
if plan_code == subscriptionCode.id
return subscriptionCode.price
return "Unknown plan code=#{plan_code}"
getDisplayCycle:(plan_code) ->
if plan_code == ''
plan_code = null
for subscriptionCode in gon.global.subscription_codes
if plan_code == subscriptionCode.id
if subscriptionCode.cycle == "year"
return "annual"
else
return subscriptionCode.cycle + "ly"
return "Unknown plan code=#{plan_code}"
onPlanChanged: (e) ->
val = e.target.value
@originalPlan = this.currentPlan()
@setState({selectedPlan: val})
currentPlan: () ->
if this.state.selectedPlan?
this.state.selectedPlan
else
this.props.subscription.desired_plan_code || ''
checkIfPending:() ->
return this.state.selectedPlan?
onSubmit: (event) ->
if event
event.preventDefault()
@prePerformSubmit()
onChangeSubmit: (form) ->
if @state.updating
return
@prePerformSubmit()
cancelChangePlan:() ->
console.log("cancel change plan", @originalPlan)
@setState({selectedPlan: @originalPlan })
# user selects button on main page
onUpdatePaymentMethod: () ->
if gon.isNativeClient
context.JK.popExternalLink("/client#/account/paymentHistory", true)
else
window.location.href = "/client#/account/paymentHistory"
openBrowserToPayment: () ->
if gon.isNativeClient
context.JK.popExternalLink("/client#/account/paymentHistory", true)
else
window.location.href = "/client#/account/paymentHistory"
prePerformSubmit:() ->
if !@state.selectedPlan?
return
message = null
if this.props.subscription.subscription
if this.state.selectedPlan == null || this.state.selectedPlan == ''
message = "<p>You have chosen to go back down to the FREE PLAN. Your subscription will be canceled, and you will keep your plan until the end of the current billing cycle.</p>"
else
message = "<p>You have selected the #{this.getDisplayNameTier(this.state.selectedPlan).toUpperCase()} #{this.getDisplayCycle(this.state.selectedPlan).toUpperCase()} PLAN and will be charged US$#{this.getDisplayNamePrice(this.state.selectedPlan)} on the start of next billing cycle.</p>"
else
if this.state.selectedPlan == null || this.state.selectedPlan == ''
@performSubmit()
return
else
message = "<p>You have selected the #{this.getDisplayNameTier(this.state.selectedPlan).toUpperCase()} #{this.getDisplayCycle(this.state.selectedPlan).toUpperCase()} PLAN and will be charged US$#{this.getDisplayNamePrice(this.state.selectedPlan)} .</p>"
buttons = []
buttons.push({
name: 'CANCEL',
buttonStyle: 'button-grey',
click: (() => (@cancelChangePlan()))
})
buttons.push({
name: 'CONFIRM',
buttonStyle: 'button-orange',
click: (() => (@performSubmit()))
})
context.JK.Banner.show({
title: "Confirm Plan Change",
html: message,
buttons: buttons})
performSubmit: () ->
@setState({updating: true})
#SubscriptionActions.changeSubscription(this.state.selectedPlan)
rest.changeSubscription(this.state.selectedPlan).done((subscription) =>
SubscriptionActions.forceUpdate(subscription)
has_billing_info = subscription.has_billing_info
console.log("subscription change update", subscription)
@setState({updating: false, selectedPlan: null})
if has_billing_info
@props.app.layout.notify({
title: "Subscription updated!",
text: "Thank you for supporting JamKazam!"
})
else
if subscription.desired_plan_code
if gon.isNativeClient
html = context._.template($('#template-payment-still-needed-native').html(), {}, { variable: 'data' })
else
html = context._.template($('#template-payment-still-needed').html(), {}, { variable: 'data' })
buttons = []
buttons.push({name: 'CLOSE', buttonStyle: 'button-grey'})
buttons.push({
name: 'UPDATE PAYMENT METHOD',
buttonStyle: 'button-orange',
click: (() => (@openBrowserToPayment()))
})
context.JK.Banner.show({
title: "Payment Method Needed",
html: html,
buttons: buttons})
else
@props.app.layout.notify({
title: "Subscription updated!",
text: "Thank you for supporting JamKazam!"
})
#@props.app.layout.notify({
# title: "Payment method still needed",
# text: "Please click UPDATE PAYMENT METHOD in the bottom-right of the screen."
#})
)
.fail((jqXHR) =>
@setState({updating: false})
if jqXHR.status == 422
@props.app.layout.notify({
title: "you already have this subscription",
text: "No changes were made to your account."
})
else
@props.app.layout.notify({
title: "unable to update subscription status",
text: "Please contact support@jamkazam.com. Error:\n #{jqXHR.responseText}"
})
)
onCancelPlan: (event) ->
if confirm("Are you sure you want to cancel your plan?")
SubscriptionActions.cancelSubscription()
componentDidMount: () ->
@root = $(@getDOMNode())
document.querySelector('#change-subscription-form').addEventListener('submit', @onChangeSubmit.bind(this))
getTimeRemaining: (t) ->
if t < 0
t = -t
seconds = Math.floor( (t/1000) % 60 );
minutes = Math.floor( (t/1000/60) % 60 );
hours = Math.floor( (t/(1000*60*60)) % 24 );
days = Math.floor( t/(1000*60*60*24) );
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
};
displayTime: (until_time) ->
if until_time < 0
return 'no time'
untilTime = @getTimeRemaining(until_time * 1000)
timeString = ''
if untilTime.days != 0
timeString += "#{untilTime.days} days, "
if untilTime.hours != 0 || timeString.length > 0
timeString += "#{untilTime.hours} hours, "
if untilTime.minutes != 0 || timeString.length > 0
timeString += "#{untilTime.minutes} minutes "
#if untilTime.seconds != 0 || timeString.length > 0
# timeString += "#{untilTime.seconds} seconds"
if timeString == ''
'now!'
timeString
comparePlans: (e) ->
if context.JK.clientType() == 'client'
context.JK.popExternalLink("https://jamkazam.freshdesk.com/support/solutions/articles/66000122535-what-are-jamkazam-s-free-vs-premium-features-")
e.preventDefault()
render: () ->
plan_codes = []
monthlies = []
yearlies = []
for plan in gon.global.subscription_codes
if plan.cycle == 'month'
monthlies.push(plan)
else
yearlies.push(plan)
plan_codes.push(`<option key="monthly" value="monthly" disabled="disabled">-------- MONTHLY PLANS --------</option>`)
for plan in monthlies
plan_codes.push(`<option key={plan.id || ''} value={plan.id || ''}>{plan.name} (${plan.price.toFixed(2)}/{plan.cycle})</option>`)
plan_codes.push(`<option key="yearly" value="yearly" disabled="disabled">-------- YEARLY PLANS --------</option>`)
for plan in yearlies
plan_codes.push(`<option key={plan.id || ''} value={plan.id || ''}>{plan.name} (${plan.price.toFixed(2)}/{plan.cycle})</option>`)
plansJsx = `<select name="plan_code" onChange={this.onPlanChanged} defaultValue={this.currentPlan()} value={this.currentPlan()}>{plan_codes}</select>`
changeClass = 'button-orange update-plan'
if !@state.selectedPlan? || @state.updating
changeClass = changeClass + ' disabled'
if @state.updating
update_plan_text = 'UPDATING PLAN ... PLEASE WAIT'
else
update_plan_text = 'UPDATE PLAN'
recurly_subscription = @props.subscription.subscription
effective_plan_name = `<span className="plan-name">{this.getDisplayNameTier(this.props.subscription.plan_code)}</span>`
desired_plan_name = `<span className="plan-name">{this.getDisplayNameTier(this.props.subscription.desired_plan_code)}</span>`
admin_override_plan_name = `<span className="plan-name">{this.getDisplayNameTier(this.props.subscription.admin_override_plan_code)}</span>`
in_trial = @props.subscription.in_trial
admin_override = @props.subscription.admin_override_plan_code?
effective_is_free = !!this.props.subscription.plan_code
has_pending_subscription = @props.subscription.subscription?.pending_subscription?
cancelled_subscription = @props.subscription.subscription?.remaining_billing_cycles == 0
show_payment_info = null
has_billing_info = @props.subscription.has_billing_info
if admin_override
explanation = `<span>You have a {effective_plan_name} account until your gifted plan ends {context.JK.formatDateShort(this.props.subscription.admin_override_ends_at)}.</span>`
else if in_trial
if @props.subscription.desired_plan_code
if has_billing_info
note = `<span>Billing starts for the {desired_plan_name} plan after the trial ends.</span>`
else
warning = `<p className="uncollectable-msg">You will drop to the <span className="plan-name">Free</span> free plan after the trial ends because you have not yet entered payment info.</p>`
show_payment_info = true
else
if has_billing_info
warning = `<p className="uncollectable-msg">You will drop to the <span className="plan-name">Free</span> free plan after the trial ends because you have not selected a plan.</p>`
else
warning = `<p className="uncollectable-msg">You will drop to the <span className="plan-name">Free</span> free plan after the trial ends because you have not yet entered payment info or selected a plan.</p>`
show_payment_info = true
explanation = `<span>You have a {effective_plan_name} account until your trial ends {context.JK.formatDateShort(this.props.subscription.trial_ends_at)}. {note}</span>`
else
if @props.subscription.desired_plan_code && !@props.subscription.plan_code && !has_billing_info
explanation = `<span>You have successfully upgraded your plan to the {desired_plan_name} level, thank you!</span>`
warning = `<p className="uncollectable-msg">For this plan to take effect, you must provide a payment method (e.g. a credit card), for the monthly subscription charge. Please click the Update Payment Method button to do this now.</p>`
show_payment_info = true
else
if @props.subscription.desired_plan_code
if !has_billing_info
show_payment_info = true
explanation = `<span>You have successfully upgraded your plan to the {desired_plan_name} level, thank you</span>`
warning = `<p className="uncollectable-msg">However, you must provide a payment method (e.g. a credit card), for the monthly subscription charge. Please click the Update Payment Method button to do this now.</p>`
else
explanation = `<span>You are currently on the {effective_plan_name} level, thank you!</span>`
else
# free plan situation - not much to go on about
explanation = `<span>You are currently on the {effective_plan_name} plan.</span>`
if show_payment_info
update_payment_btn = `<a className="button-orange update-payment-method" href="/client#/account/paymentHistory" onClick={this.onUpdatePaymentMethod}>UPDATE PAYMENT METHOD</a>`
if has_pending_subscription
if this.props.subscription.subscription.plan.plan_code != this.props.subscription.plan_code
billingAddendum = `<span>You have paid only for the <span className="plan-name">{this.getDisplayNameTier(this.props.subscription.subscription.plan.plan_code)}</span> level for the current billing cycle, so there will be a change to the <span className="plan-name">{this.getDisplayNameTier(this.props.subscription.subscription.pending_subscription.plan.plan_code)}</span> level on the next billing cycle.</span>`
else
billingAddendum = `<span>And your plan and billing will switch to the <span className="plan-name">{this.getDisplayNameTier(this.props.subscription.subscription.pending_subscription.plan.plan_code)}</span> level on the next billing cycle.</span>`
else if cancelled_subscription && this.props.subscription.desired_plan_code == null && this.props.subscription.plan_code != null
billingAddendum = `<span>However, your cancelled {effective_plan_name} plan is still active until the end of the billing cycle.</span>`# `<span><br/><br/><span>You will be billed a final time at the <span className="plan-name">{this.getDisplayNameTier(this.props.subscription.subscription.plan.plan_code)}</span> at end of this billing cycle.</span></span>`
else
billingAddendum = null
if @props.subscription.subscription_rules.remaining_month_play_time
remaining_month_play_time = @props.subscription.subscription_rules.remaining_month_play_time
until_time = new Date()
until_time = new Date(until_time.getTime() + remaining_month_play_time * 1000)
#until_time.setSeconds(until_time.getSeconds() + @subscriptionRules.remaining_month_play_time)
playtime = `<div className="play-time">
<label>monthly play time remaining:</label>
<p>You have <span className="playtime">{this.displayTime(remaining_month_play_time)}</span> remaining this month. Only the time you spend in a session with 2 or more people uses your session play time.</p>
</div>`
else
playtime = `<div className="play-time">
<label>monthly play time remaining:</label>
<p>You have unlimited play time.</p>
</div>`
`<div className="current-subscription">
<div>
<h2>Subscription:</h2>
<p className="explainer">Your JamKazam subscription is currently set to the plan displayed below. To compare the features available for different subscription plans, click the Compare Plans button below. To change your plan, click the "subscription plan" list box below, select a new plan, and then click the Update Plan button below.</p>
<div className="subscription-plan-and-status">
<div className="subscription-plan">
<form id="change-subscription-form" onSubmit={this.onChangeSubmit} >
<label for="plan_code">subscription plan:</label>
<div className="subscription-actions">
{plansJsx}
<a className="button-grey" onClick={this.comparePlans} target="_blank" href="https://jamkazam.freshdesk.com/support/solutions/articles/66000122535-what-are-jamkazam-s-free-vs-premium-features-">COMPARE PLANS</a>
<button className={changeClass} onClick={this.onSubmit} type="submit">{update_plan_text}</button>
</div>
</form>
</div>
</div>
<div className="effective-subscription">
<div className="explanation">
<p>{explanation} {billingAddendum}</p>
{warning}
</div>
{playtime}
<a className="button-grey" onClick={this.onCancel}>BACK</a>{update_payment_btn}
</div>
</div>
</div>`
})