mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03:00
Refined multiple product flows
closes https://github.com/TryGhost/Team/issues/835 - updates change flow to consider portal_plans setting - updates confirm subscription screen to show product name - removed discount benefit on yearly if only one plan
This commit is contained in:
parent
db12a9976f
commit
bda6f36a3c
@ -1,7 +1,7 @@
|
||||
import React, {useContext, useEffect, useState} from 'react';
|
||||
import Switch from '../common/Switch';
|
||||
import {ReactComponent as CheckmarkIcon} from '../../images/icons/checkmark.svg';
|
||||
import {getSiteProducts, getCurrencySymbol, getPriceString, getStripeAmount, isCookiesDisabled, getPricesFromProducts, getMemberActivePrice} from '../../utils/helpers';
|
||||
import {getSiteProducts, getCurrencySymbol, getPriceString, getStripeAmount, isCookiesDisabled, getMemberActivePrice, getAvailablePrices} from '../../utils/helpers';
|
||||
import AppContext from '../../AppContext';
|
||||
import {ChangeProductPlansSection} from './PlansSection';
|
||||
|
||||
@ -331,7 +331,7 @@ export const ProductsSectionStyles = ({site}) => {
|
||||
grid-gap: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.gh-portal-upgrade-product .gh-portal-products-grid:not(.change-plan) {
|
||||
padding: 32px 0 0;
|
||||
}
|
||||
@ -710,7 +710,8 @@ function ProductsSection({onPlanSelect, products, type = null}) {
|
||||
function ChangeProductCard({product, onPlanSelect}) {
|
||||
const {member} = useContext(AppContext);
|
||||
const cardClass = 'gh-portal-product-card';
|
||||
const plans = getPricesFromProducts({products: [product]});
|
||||
const {site} = useContext(AppContext);
|
||||
const plans = getAvailablePrices({site, products: [product]});
|
||||
const selectedPlan = getMemberActivePrice({member});
|
||||
return (
|
||||
<div>
|
||||
|
@ -5,7 +5,7 @@ import CloseButton from '../common/CloseButton';
|
||||
import BackButton from '../common/BackButton';
|
||||
import PlansSection, {MultipleProductsPlansSection, SingleProductPlansSection} from '../common/PlansSection';
|
||||
import {getDateString} from '../../utils/date-time';
|
||||
import {formatNumber, getAvailablePrices, getFilteredPrices, getMemberActivePrice, getMemberSubscription, getPriceFromSubscription, getSubscriptionFromId, getUpgradeProducts, hasMultipleProducts, hasMultipleProductsFeature, isPaidMember} from '../../utils/helpers';
|
||||
import {formatNumber, getAvailablePrices, getFilteredPrices, getMemberActivePrice, getMemberSubscription, getPriceFromSubscription, getProductFromPrice, getSubscriptionFromId, getUpgradeProducts, hasMultipleProducts, hasMultipleProductsFeature, isPaidMember} from '../../utils/helpers';
|
||||
|
||||
export const AccountPlanPageStyles = `
|
||||
.gh-portal-accountplans-main {
|
||||
@ -103,7 +103,7 @@ const CancelSubscriptionButton = ({member, onCancelSubscription, action, brandCo
|
||||
|
||||
// For confirmation flows
|
||||
const PlanConfirmationSection = ({plan, type, onConfirm}) => {
|
||||
const {action, member, brandColor} = useContext(AppContext);
|
||||
const {site, action, member, brandColor} = useContext(AppContext);
|
||||
const [reason, setReason] = useState('');
|
||||
const subscription = getMemberSubscription({member});
|
||||
const isRunning = ['updateSubscription:running', 'checkoutPlan:running', 'cancelSubscription:running'].includes(action);
|
||||
@ -115,6 +115,8 @@ const PlanConfirmationSection = ({plan, type, onConfirm}) => {
|
||||
}
|
||||
const priceString = formatNumber(plan.price);
|
||||
const planStartMessage = `${plan.currency_symbol}${priceString}/${plan.interval} – Starting ${planStartDate}`;
|
||||
const product = getProductFromPrice({site, priceId: plan?.id});
|
||||
const priceLabel = hasMultipleProductsFeature({site}) ? product.name : 'Price';
|
||||
if (type === 'changePlan') {
|
||||
return (
|
||||
<>
|
||||
@ -127,7 +129,7 @@ const PlanConfirmationSection = ({plan, type, onConfirm}) => {
|
||||
</section>
|
||||
<section>
|
||||
<div className='gh-portal-list-detail'>
|
||||
<h3>Price</h3>
|
||||
<h3>{priceLabel}</h3>
|
||||
<p>{planStartMessage}</p>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -244,15 +244,16 @@ export function getFreeBenefits() {
|
||||
}];
|
||||
}
|
||||
|
||||
export function getProductBenefits({product}) {
|
||||
export function getProductBenefits({product, site = null}) {
|
||||
if (product?.monthlyPrice && product?.yearlyPrice) {
|
||||
const availablePrices = getAvailablePrices({site, products: [product]});
|
||||
const yearlyDiscount = calculateDiscount(product.monthlyPrice.amount, product.yearlyPrice.amount);
|
||||
const productBenefits = product?.benefits || [];
|
||||
const monthlyBenefits = product?.benefits?.length > 0 ? [...productBenefits] : [{
|
||||
name: 'Full access'
|
||||
}];
|
||||
const yearlyBenefits = [...monthlyBenefits];
|
||||
if (yearlyDiscount > 0) {
|
||||
if (yearlyDiscount > 0 && availablePrices.length > 1) {
|
||||
yearlyBenefits.push({
|
||||
name: `${yearlyDiscount}% discount`
|
||||
});
|
||||
@ -288,7 +289,14 @@ export function hasFreeProductPrice({site}) {
|
||||
return allowSelfSignup && portalPlans.includes('free');
|
||||
}
|
||||
|
||||
export function getAvailablePrices({site}) {
|
||||
export function getProductFromPrice({site, priceId}) {
|
||||
const products = getAvailableProducts({site});
|
||||
return products.find((product) => {
|
||||
return (product?.monthlyPrice?.id === priceId) || (product?.yearlyPrice?.id === priceId);
|
||||
});
|
||||
}
|
||||
|
||||
export function getAvailablePrices({site, products = null}) {
|
||||
const {
|
||||
portal_plans: portalPlans = [],
|
||||
is_stripe_configured: isStripeConfigured
|
||||
@ -298,7 +306,7 @@ export function getAvailablePrices({site}) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const productPrices = getPricesFromProducts({site});
|
||||
const productPrices = getPricesFromProducts({site, products});
|
||||
|
||||
return productPrices.filter((d) => {
|
||||
return !!(d && d.id);
|
||||
|
Loading…
Reference in New Issue
Block a user