mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-25 00:28:31 -05:00
fec3ac38e9
Admins can generate a prepaid code, which a user can use to subscribe for free via the account/subscription page. The subscription will be identical to the normal monthly subscription (e.g. 3500 gems per month), except they won’t be charged. Does not require the recipient to enter billing information. Can be applied to an existing subscription, which will be converted to free. Prepaid code can only be used once. Prepaid subscription cannot be unsubscribed via the UI.
164 lines
5.7 KiB
CoffeeScript
164 lines
5.7 KiB
CoffeeScript
ModalView = require 'views/core/ModalView'
|
|
template = require 'templates/core/subscribe-modal'
|
|
stripeHandler = require 'core/services/stripe'
|
|
utils = require 'core/utils'
|
|
AuthModal = require 'views/core/AuthModal'
|
|
|
|
module.exports = class SubscribeModal extends ModalView
|
|
id: 'subscribe-modal'
|
|
template: template
|
|
plain: true
|
|
closesOnClickOutside: false
|
|
product:
|
|
amount: 999
|
|
planID: 'basic'
|
|
|
|
subscriptions:
|
|
'stripe:received-token': 'onStripeReceivedToken'
|
|
|
|
events:
|
|
'click #close-modal': 'hide'
|
|
'click #parent-send': 'onClickParentSendButton'
|
|
'click .purchase-button': 'onClickPurchaseButton'
|
|
|
|
constructor: (options) ->
|
|
super(options)
|
|
@state = 'standby'
|
|
|
|
getRenderData: ->
|
|
c = super()
|
|
c.state = @state
|
|
c.stateMessage = @stateMessage
|
|
c.price = @product.amount / 100
|
|
#c.price = 3.99 # Sale
|
|
return c
|
|
|
|
afterRender: ->
|
|
super()
|
|
@setupParentButtonPopover()
|
|
@setupParentInfoPopover()
|
|
|
|
setupParentButtonPopover: ->
|
|
popoverTitle = $.i18n.t 'subscribe.parent_email_title'
|
|
popoverTitle += '<button type="button" class="close" onclick="$('.parent-button').popover('hide');">×</button>'
|
|
popoverContent = "<div id='email-parent-form'>"
|
|
popoverContent += "<p>#{$.i18n.t('subscribe.parent_email_description')}</p>"
|
|
popoverContent += "<form>"
|
|
popoverContent += " <div class='form-group'>"
|
|
popoverContent += " <label>#{$.i18n.t('subscribe.parent_email_input_label')}</label>"
|
|
popoverContent += " <input id='parent-input' type='email' class='form-control' placeholder='#{$.i18n.t('subscribe.parent_email_input_placeholder')}'/>"
|
|
popoverContent += " <div id='parent-email-validator' class='email_invalid'>#{$.i18n.t('subscribe.parent_email_input_invalid')}</div>"
|
|
popoverContent += " </div>"
|
|
popoverContent += " <button id='parent-send' type='submit' class='btn btn-default'>#{$.i18n.t('subscribe.parent_email_send')}</button>"
|
|
popoverContent += "</form>"
|
|
popoverContent += "</div>"
|
|
popoverContent += "<div id='email-parent-complete'>"
|
|
popoverContent += " <p>#{$.i18n.t('subscribe.parent_email_sent')}</p>"
|
|
popoverContent += " <button type='button' onclick='$('.parent-button').popover('hide');'>#{$.i18n.t('modal.close')}</button>"
|
|
popoverContent += "</div>"
|
|
|
|
@$el.find('.parent-button').popover(
|
|
animation: true
|
|
html: true
|
|
placement: 'top'
|
|
trigger: 'click'
|
|
title: popoverTitle
|
|
content: popoverContent
|
|
container: @$el
|
|
).on 'shown.bs.popover', =>
|
|
application.tracker?.trackEvent 'Subscription ask parent button click'
|
|
|
|
setupParentInfoPopover: ->
|
|
popoverTitle = $.i18n.t 'subscribe.parents_title'
|
|
popoverContent = "<p>" + $.i18n.t('subscribe.parents_blurb1') + "</p>"
|
|
popoverContent += "<p>" + $.i18n.t('subscribe.parents_blurb2') + "</p>"
|
|
popoverContent += "<p>" + $.i18n.t('subscribe.parents_blurb3') + "</p>"
|
|
#popoverContent = popoverContent.replace /9[.,]99/g, '3.99' # Sale
|
|
@$el.find('#parents-info').popover(
|
|
animation: true
|
|
html: true
|
|
placement: 'top'
|
|
trigger: 'hover'
|
|
title: popoverTitle
|
|
content: popoverContent
|
|
container: @$el
|
|
).on 'shown.bs.popover', =>
|
|
application.tracker?.trackEvent 'Subscription parent hover'
|
|
|
|
onClickParentSendButton: (e) ->
|
|
# TODO: Popover sometimes dismisses immediately after send
|
|
|
|
email = $('#parent-input').val()
|
|
unless /[\w\.]+@\w+\.\w+/.test email
|
|
$('#parent-input').parent().addClass('has-error')
|
|
$('#parent-email-validator').show()
|
|
return false
|
|
|
|
request = @supermodel.addRequestResource 'send_one_time_email', {
|
|
url: '/db/user/-/send_one_time_email'
|
|
data: {email: email, type: 'subscribe modal parent'}
|
|
method: 'POST'
|
|
}, 0
|
|
request.load()
|
|
|
|
$('#email-parent-form').hide()
|
|
$('#email-parent-complete').show()
|
|
false
|
|
|
|
onClickPurchaseButton: (e) ->
|
|
@playSound 'menu-button-click'
|
|
return @openModalView new AuthModal() if me.get('anonymous')
|
|
application.tracker?.trackEvent 'Started subscription purchase'
|
|
options = {
|
|
description: $.i18n.t('subscribe.stripe_description')
|
|
amount: @product.amount
|
|
alipay: 'auto'
|
|
alipayReusable: true
|
|
}
|
|
|
|
# SALE LOGIC
|
|
# overwrite amount with sale price
|
|
# maybe also put in another description with details about how long it lasts, etc
|
|
# NOTE: Do not change this price without updating the context.price in getRenderData
|
|
# NOTE: And, the popover content if necessary
|
|
#options = {
|
|
# description: 'Monthly Subscription (HoC sale)'
|
|
# amount: 399
|
|
#}
|
|
|
|
@purchasedAmount = options.amount
|
|
|
|
stripeHandler.open(options)
|
|
|
|
onStripeReceivedToken: (e) ->
|
|
@state = 'purchasing'
|
|
@render()
|
|
|
|
stripe = _.clone(me.get('stripe') ? {})
|
|
stripe.planID = @product.planID
|
|
stripe.token = e.token.id
|
|
me.set 'stripe', stripe
|
|
|
|
@listenToOnce me, 'sync', @onSubscriptionSuccess
|
|
@listenToOnce me, 'error', @onSubscriptionError
|
|
me.patch({headers: {'X-Change-Plan': 'true'}})
|
|
|
|
onSubscriptionSuccess: ->
|
|
application.tracker?.trackEvent 'Finished subscription purchase', revenue: @purchasedAmount / 100
|
|
Backbone.Mediator.publish 'subscribe-modal:subscribed', {}
|
|
@playSound 'victory'
|
|
@hide()
|
|
|
|
onSubscriptionError: (user, response, options) ->
|
|
console.error 'We got an error subscribing with Stripe from our server:', response
|
|
stripe = me.get('stripe') ? {}
|
|
delete stripe.token
|
|
delete stripe.planID
|
|
# TODO: Need me.set('stripe', stripe) here?
|
|
xhr = options.xhr
|
|
if xhr.status is 402
|
|
@state = 'declined'
|
|
else
|
|
@state = 'unknown_error'
|
|
@stateMessage = "#{xhr.status}: #{xhr.responseText}"
|
|
@render()
|