Set up a subscription page with subscription info and the subscribe button, taking that logic out of the payments page.

This commit is contained in:
Scott Erickson 2014-12-10 13:42:12 -08:00
parent 84cdc5d150
commit 02953d0e6c
11 changed files with 133 additions and 51 deletions

View file

@ -24,6 +24,7 @@ module.exports = class CocoRouter extends Backbone.Router
'account/unsubscribe': go('account/UnsubscribeView')
'account/profile': go('user/JobProfileView') # legacy URL, sent in emails
'account/payments': go('account/PaymentsView')
'account/subscription': go('account/SubscriptionView')
'admin': go('admin/MainAdminView')
'admin/candidates': go('admin/CandidatesView')

View file

@ -811,13 +811,21 @@
recently_played: "Recently Played"
no_recent_games: "No games played during the past two weeks."
payments: "Payments"
purchased: "Purchased"
subscription: "Subscription"
service_apple: "Apple"
service_web: "Web"
paid_on: "Paid On"
service: "Service"
price: "Price"
gems: "Gems"
status_subscribed: "You're currently subscribed at $9.99 USD/mo. Thanks for your support!"
active: "Active"
subscribed: "Subscribed"
unsubscribed: "Unsubscribed"
active_until: "Active Until"
cost: "Cost"
next_payment: "Next Payment"
card: "Card"
status_unsubscribed_active: "You're not subscribed and won't be billed, but your account is still active for now."
status_unsubscribed: "Get access to new levels, heroes, items, and bonus gems with a CodeCombat subscription!"
@ -878,6 +886,7 @@
clas: "CLAs"
play_counts: "Play Counts"
feedback: "Feedback"
payment_info: "Payment Info"
delta:
added: "Added"

View file

@ -1,11 +0,0 @@
@import "app/styles/mixins"
@import "app/styles/bootstrap/variables"
#payments-view
.start-subscription-button, .end-subscription-button
margin-bottom: 20px
float: left
.payment-status
float: left
margin: 15px

View file

@ -0,0 +1,5 @@
#subscription-view
.start-subscription-button, .end-subscription-button
margin-bottom: 20px
float: left
width: 100%

View file

@ -18,4 +18,6 @@ block content
li.list-group-item
a.btn.btn-lg.btn-primary(href="/account/settings", data-i18n="play.settings")
li.list-group-item
a.btn.btn-lg.btn-primary(href="/account/payments", data-i18n="account.payments")
a.btn.btn-lg.btn-primary(href="/account/payments", data-i18n="account.payments")
li.list-group-item
a.btn.btn-lg.btn-primary(href="/account/subscription", data-i18n="account.subscription")

View file

@ -10,19 +10,10 @@ block content
a(href="/account", data-i18n="nav.account")
li.active(data-i18n="account.payments")
if subscribed
button.end-subscription-button.btn.btn-lg.btn-warning(data-i18n="subscribe.unsubscribe") Unsubscribe
.payment-status(data-i18n="account.status_subscribed")
else if !me.isAnonymous()
button.start-subscription-button.btn.btn-lg.btn-success(data-i18n="subscribe.subscribe_title") Subscribe
if active
.payment-status(data-i18n="account.status_unsubscribed_active")
else
.payment-status(data-i18n="account.status_unsubscribed")
if payments.models.length
table.table.table-striped
tr
th(data-i18n="account.purchased")
th(data-i18n="account.paid_on")
th(data-i18n="account.service")
th(data-i18n="account.price")
@ -30,7 +21,11 @@ block content
for payment in payments.models
- var service = payment.get('service')
tr
td= moment(payment.getCreationDate()).format('lll')
if payment.get('productID')
td(data-i18n='account.gems')
else
td(data-i18n='subscribe.stripe_description')
td= moment(payment.getCreationDate()).format('l')
if service === 'ios'
td(data-i18n="account.service_apple")
td= payment.get('ios').localPrice

View file

@ -0,0 +1,49 @@
extends /templates/base
block content
ol.breadcrumb
li
a(href="/")
span.glyphicon.glyphicon-home
li
a(href="/account", data-i18n="nav.account")
li.active(data-i18n="account.subscription")
.panel.panel-default
.panel-heading
if subscribed
button.end-subscription-button.btn.btn-lg.btn-warning(data-i18n="subscribe.unsubscribe") Unsubscribe
else if !me.isAnonymous()
button.start-subscription-button.btn.btn-lg.btn-success(data-i18n="subscribe.subscribe_title") Subscribe
.panel-body
table.table.table-striped
tr
th Status
td
if subscribed
strong(data-i18n="account.subscribed")
else
if active
strong(data-i18n="account.active")
.text-muted(data-i18n="account.status_unsubscribed_active")
else
strong(data-i18n="account.unsubscribed")
.text-muted(data-i18n="account.status_unsubscribed")
if activeUntil
tr
th(data-i18n="account.active_until")
td= moment(activeUntil).format('l')
if nextPaymentDate
tr
th(data-i18n="account.next_paymthn")
td= moment(nextPaymentDate).format('l')
if cost
tr
th(data-i18n="account.cost")
td= cost
if card
tr
th(data-i18n="account.card")
td= card

View file

@ -34,6 +34,8 @@ block header
a(href="/account/settings", data-i18n="play.settings")
li
a(href="/account/payments", data-i18n="account.payments")
li
a(href="/account/subscription", data-i18n="account.subscription")
li
a#logout-button(data-i18n="login.log_out")

View file

@ -2,19 +2,11 @@ RootView = require 'views/core/RootView'
template = require 'templates/account/payments-view'
CocoCollection = require 'collections/CocoCollection'
Payment = require 'models/Payment'
SubscribeModal = require 'views/play/modal/SubscribeModal'
module.exports = class PaymentsView extends RootView
id: "payments-view"
template: template
events:
'click .start-subscription-button': 'onClickStartSubscription'
'click .end-subscription-button': 'onClickEndSubscription'
subscriptions:
'subscribe-modal:subscribed': 'onSubscribed'
constructor: (options) ->
super(options)
@payments = new CocoCollection([], { url: '/db/payment', model: Payment, comparator:'_id' })
@ -23,21 +15,4 @@ module.exports = class PaymentsView extends RootView
getRenderData: ->
c = super()
c.payments = @payments
c.subscribed = me.get('stripe')?.planID
c.active = me.isPremium()
c
onClickStartSubscription: (e) ->
@openModalView new SubscribeModal()
window.tracker?.trackEvent 'Show subscription modal', category: 'Subscription', label: 'payments view'
window.tracker?.trackPageView "subscription/show-modal", ['Google Analytics']
onSubscribed: ->
document.location.reload()
onClickEndSubscription: (e) ->
stripe = _.clone(me.get('stripe'))
delete stripe.planID
me.set('stripe', stripe)
me.patch({headers: {'X-Change-Plan': 'true'}})
@listenToOnce me, 'sync', -> document.location.reload()
c

View file

@ -0,0 +1,55 @@
RootView = require 'views/core/RootView'
template = require 'templates/account/subscription-view'
CocoCollection = require 'collections/CocoCollection'
SubscribeModal = require 'views/play/modal/SubscribeModal'
module.exports = class SubscriptionView extends RootView
id: "subscription-view"
template: template
events:
'click .start-subscription-button': 'onClickStartSubscription'
'click .end-subscription-button': 'onClickEndSubscription'
subscriptions:
'subscribe-modal:subscribed': 'onSubscribed'
constructor: (options) ->
super(options)
if me.get('stripe')
options = { url: "/db/user/#{me.id}/stripe" }
options.success = (@stripeInfo) =>
@supermodel.addRequestResource('payment_info', options).load()
getRenderData: ->
c = super()
if @stripeInfo
if subscription = @stripeInfo.subscriptions?.data?[0]
periodEnd = new Date((subscription.trial_end or subscription.current_period_end) * 1000)
if subscription.cancel_at_period_end
c.activeUntil = periodEnd
else
c.nextPaymentDate = periodEnd
c.cost = "$#{(subscription.plan.amount/100).toFixed(2)}"
if card = @stripeInfo.cards?.data?[0]
c.card = "#{card.brand}: x#{card.last4}"
c.stripeInfo = @stripeInfo
c.subscribed = me.get('stripe')?.planID
c.active = me.isPremium()
c
onClickStartSubscription: (e) ->
@openModalView new SubscribeModal()
window.tracker?.trackEvent 'Show subscription modal', category: 'Subscription', label: 'account subscription view'
window.tracker?.trackPageView "subscription/show-modal", ['Google Analytics']
onSubscribed: ->
document.location.reload()
onClickEndSubscription: (e) ->
stripe = _.clone(me.get('stripe'))
delete stripe.planID
me.set('stripe', stripe)
me.patch({headers: {'X-Change-Plan': 'true'}})
@listenToOnce me, 'sync', -> document.location.reload()

View file

@ -238,7 +238,7 @@ UserHandler = class UserHandler extends Handler
@getDocumentForIdOrSlug handle, (err, user) =>
return @sendNotFoundError(res) if not user
return @sendForbiddenError(res) unless req.user and (req.user.isAdmin() or req.user.get('_id').equals(user.get('_id')))
return @sendNotFoundError(res) #if not customerID = user.get('stripe')?.customerID
return @sendNotFoundError(res) if not customerID = user.get('stripe')?.customerID
stripe.customers.retrieve customerID, (err, customer) =>
return @sendDatabaseError(res, err) if err
@sendSuccess(res, JSON.stringify(customer, null, '\t'))