Ghost/ghost/admin/app/components/modal-member-product.js
Rishabh Garg 86b55b0f81 Added new free tier card with custom description/benefits (#2203)
refs https://github.com/TryGhost/Team/issues/1037

Adds new free tier card with option to add custom description and benefits for free tier, behind the tiers beta flag. Also:

- updates formatting of tier prices
- changes "Free" section to "Default"
- updates price formatting of membership tiers in admin
- updates currency code handling for product card
- updates default paid product handling

Co-authored-by: Djordje Vlaisavljevic <dzvlais@gmail.com>
Co-authored-by: Peter Zimon <peter.zimon@gmail.com>
2022-01-18 00:23:43 +05:30

110 lines
2.9 KiB
JavaScript

import ModalComponent from 'ghost-admin/components/modal-base';
import {action} from '@ember/object';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency-decorators';
import {tracked} from '@glimmer/tracking';
export default class ModalMemberProduct extends ModalComponent {
@service store;
@service ghostPaths;
@service ajax;
@tracked price;
@tracked product;
@tracked products = [];
@tracked selectedProduct = null;
@tracked loadingProducts = false;
@task({drop: true})
*fetchProducts() {
this.products = yield this.store.query('product', {filter: 'type:paid', include: 'monthly_price,yearly_price,benefits'});
this.loadingProducts = false;
if (this.products.length > 0) {
this.selectedProduct = this.products.firstObject.id;
}
}
get activeSubscriptions() {
const subscriptions = this.member.get('subscriptions') || [];
return subscriptions.filter((sub) => {
return ['active', 'trialing', 'unpaid', 'past_due'].includes(sub.status);
});
}
get member() {
return this.model;
}
get cannotAddPrice() {
return !this.price || this.price.amount !== 0;
}
@action
setup() {
this.loadingProducts = true;
this.fetchProducts.perform();
}
@action
setProduct(productId) {
this.selectedProduct = productId;
}
@action
setPrice(price) {
this.price = price;
}
@action
confirmAction() {
return this.addProduct.perform();
}
@action
close(event) {
event?.preventDefault?.();
this.closeModal();
}
@task({drop: true})
*addProduct() {
let url = this.ghostPaths.url.api(`members/${this.member.get('id')}`);
// Cancel existing active subscriptions for member
for (let i = 0; i < this.activeSubscriptions.length; i++) {
const subscription = this.activeSubscriptions[i];
const cancelUrl = this.ghostPaths.url.api(`members/${this.member.get('id')}/subscriptions/${subscription.id}`);
yield this.ajax.put(cancelUrl, {
data: {
status: 'canceled'
}
});
}
let response = yield this.ajax.put(url, {
data: {
members: [{
id: this.member.get('id'),
email: this.member.get('email'),
products: [{
id: this.selectedProduct
}]
}]
}
});
this.store.pushPayload('member', response);
this.closeModal();
return response;
}
actions = {
confirm() {
this.confirmAction(...arguments);
},
// needed because ModalBase uses .send() for keyboard events
closeModal() {
this.close();
}
}
}