habitica-self-host/website/client/src/components/group-plans/billing.vue
Matteo Pagliazzi 6d34319455
Stripe: upgrade module and API, switch to Checkout (#12785)
* upgrade stripe module

* switch stripe api to latest version

* fix api version in tests

* start upgrading client and server

* client: switch to redirect

* implement checkout session creation for gems, start implementing webhooks

* stripe: start refactoring one time payments

* working gems and gift payments

* start adding support for subscriptions

* stripe: migrate subscriptions and fix cancelling sub

* allow upgrading group plans

* remove console.log statements

* group plans: upgrade from static page / create new one

* fix #11885, correct group plan modal title

* silence more stripe webhooks

* fix group plans redirects

* implement editing payment method

* start cleaning up code

* fix(stripe): update in-code docs, fix eslint issues

* subscriptions tests

* remove and skip old tests

* skip integration tests

* fix client build

* stripe webhooks: throw error if request fails

* subscriptions: correctly pass groupId

* remove console.log

* stripe: add unit tests for one time payments

* wip: stripe checkout tests

* stripe createCheckoutSession unit tests

* stripe createCheckoutSession unit tests

* stripe createCheckoutSession unit tests (editing card)

* fix existing webhooks tests

* add new webhooks tests

* add more webhooks tests

* fix lint

* stripe integration tests

* better error handling when retrieving customer from stripe

* client: remove unused strings and improve error handling

* payments: limit gift message length (server)

* payments: limit gift message length (client)

* fix redirects when payment is cancelled

* add back "subUpdateCard" string

* fix redirects when editing a sub card, use proper names for products, check subs when gifting
2020-12-14 15:59:17 +01:00

134 lines
4.3 KiB
Vue

<template>
<div
v-if="groupIsSubscribed && isLeader"
class="row standard-page"
>
<div class="col-12 col-md-6 offset-md-3">
<table class="table alert alert-info">
<tr v-if="group.purchased.plan.dateTerminated">
<td class="alert alert-warning">
<span class="noninteractive-button btn-danger">{{ $t('canceledGroupPlan') }}</span>
<i class="glyphicon glyphicon-time">{{ $t('groupPlanCanceled') }}</i>
<strong>{{ dateTerminated }}</strong>
</td>
</tr>
<tr v-if="!group.purchased.plan.dateTerminated">
<td>
<h3>{{ $t('paymentDetails') }}</h3>
<p v-if="group.purchased.plan.planId">
{{ $t('groupSubscriptionPrice') }}
</p>
</td>
</tr>
<tr v-if="group.purchased.plan.extraMonths">
<td>
<span class="glyphicon glyphicon-credit-card"></span>
{{ $t('purchasedGroupPlanPlanExtraMonths', purchasedGroupPlanPlanExtraMonths) }}
</td>
</tr>
<tr
v-if="group.purchased.plan.consecutive.count || group.purchased.plan.consecutive.offset"
>
<td>
<span class="glyphicon glyphicon-forward"></span>
{{ $t('consecutiveSubscription') }}
<ul class="list-unstyled">
<li>{{ $t('consecutiveMonths') }} {{ group.purchased.plan.consecutive.count + group.purchased.plan.consecutive.offset }}</li> <!-- eslint-disable-line max-len -->
<li>{{ $t('gemCapExtra') }} {{ group.purchased.plan.consecutive.gemCapExtra }}</li>
<li>{{ $t('mysticHourglasses') }} {{ group.purchased.plan.consecutive.trinkets }}</li>
</ul>
</td>
</tr>
</table>
</div>
<div class="col-12 col-md-6 offset-md-3">
<button
v-if="group.purchased.plan.dateTerminated"
class="btn btn-success btn-success"
@click="upgradeGroup()"
>
{{ $t('upgrade') }}
</button>
<div
v-if="!group.purchased.plan.dateTerminated
&& group.purchased.plan.paymentMethod === 'Stripe'"
class="btn btn-primary"
@click="redirectToStripeEdit({groupId: group.id})"
>
{{ $t('subUpdateCard') }}
</div>
<div
v-if="!group.purchased.plan.dateTerminated"
class="btn btn-sm btn-danger"
@click="cancelSubscriptionConfirm({group: group})"
>
{{ $t('cancelGroupSub') }}
</div>
</div>
</div>
</template>
<script>
import moment from 'moment';
import { mapState } from '@/libs/store';
import paymentsMixin from '@/mixins/payments';
import { CONSTANTS, getLocalSetting, removeLocalSetting } from '@/libs/userlocalManager';
export default {
mixins: [paymentsMixin],
props: ['groupId'],
data () {
return {
group: {},
};
},
computed: {
...mapState({ user: 'user.data' }),
isLeader () {
return this.user._id === this.group.leader._id;
},
groupIsSubscribed () {
return this.group.purchased && this.group.purchased.plan
&& this.group.purchased.plan.customerId;
},
dateTerminated () {
if (!this.user.preferences || !this.user.preferences.dateFormat) {
return moment(this.group.purchased.plan.dateTerminated);
}
return moment(this.group.purchased.plan.dateTerminated)
.format(this.user.preferences.dateFormat.toUpperCase());
},
purchasedGroupPlanPlanExtraMonths () {
return {
months: parseFloat(this.group.purchased.plan.extraMonths).toFixed(2),
};
},
},
async mounted () {
await this.loadGroup();
let appState = getLocalSetting(CONSTANTS.savedAppStateValues.SAVED_APP_STATE);
if (appState) {
appState = JSON.parse(appState);
if (appState.groupPlanCanceled) {
removeLocalSetting(CONSTANTS.savedAppStateValues.SAVED_APP_STATE);
this.$root.$emit('habitica:subscription-canceled', {
dateTerminated: this.dateTerminated,
isGroup: true,
});
}
}
},
methods: {
async loadGroup () {
const group = await this.$store.dispatch('guilds:getGroup', { groupId: this.groupId });
this.group = { ...group };
},
upgradeGroup () {
this.$store.state.upgradingGroup = this.group;
this.$router.push('/group-plans');
},
},
};
</script>