mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-26 22:13:32 -04:00
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:
parent
84cdc5d150
commit
02953d0e6c
11 changed files with 133 additions and 51 deletions
app
core
locale
styles/account
templates
views/account
server/users
|
@ -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')
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
5
app/styles/account/subscription-view.sass
Normal file
5
app/styles/account/subscription-view.sass
Normal file
|
@ -0,0 +1,5 @@
|
|||
#subscription-view
|
||||
.start-subscription-button, .end-subscription-button
|
||||
margin-bottom: 20px
|
||||
float: left
|
||||
width: 100%
|
|
@ -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")
|
|
@ -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
|
||||
|
|
49
app/templates/account/subscription-view.jade
Normal file
49
app/templates/account/subscription-view.jade
Normal 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
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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
|
55
app/views/account/SubscriptionView.coffee
Normal file
55
app/views/account/SubscriptionView.coffee
Normal 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()
|
|
@ -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'))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue