mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-17 23:44:39 -05:00
Refined multiple products change plan flow
refs https://github.com/TryGhost/Team/issues/824 - updates the change plan flow for multiple products flag - adds new plan components for change plan flow - updates helpers - updates fixtures
This commit is contained in:
parent
cdfbd18dbb
commit
d34d9c2489
7 changed files with 170 additions and 91 deletions
|
@ -18,7 +18,7 @@ const React = require('react');
|
||||||
const DEV_MODE_DATA = {
|
const DEV_MODE_DATA = {
|
||||||
showPopup: true,
|
showPopup: true,
|
||||||
site: Fixtures.site,
|
site: Fixtures.site,
|
||||||
member: Fixtures.member.free,
|
member: Fixtures.member.paid,
|
||||||
page: 'accountHome'
|
page: 'accountHome'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import AppContext from '../../AppContext';
|
||||||
import {ReactComponent as CheckmarkIcon} from '../../images/icons/checkmark.svg';
|
import {ReactComponent as CheckmarkIcon} from '../../images/icons/checkmark.svg';
|
||||||
import calculateDiscount from '../../utils/discount';
|
import calculateDiscount from '../../utils/discount';
|
||||||
import {isCookiesDisabled, formatNumber, hasOnlyFreePlan, hasMultipleProductsFeature, getFreeBenefits, getProductBenefits} from '../../utils/helpers';
|
import {isCookiesDisabled, formatNumber, hasOnlyFreePlan, hasMultipleProductsFeature, getFreeBenefits, getProductBenefits} from '../../utils/helpers';
|
||||||
import ProductsSection from './ProductsSection';
|
import ProductsSection, {ChangeProductSection} from './ProductsSection';
|
||||||
|
|
||||||
export const PlanSectionStyles = `
|
export const PlanSectionStyles = `
|
||||||
.gh-portal-plans-container {
|
.gh-portal-plans-container {
|
||||||
|
@ -28,6 +28,11 @@ export const PlanSectionStyles = `
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gh-portal-change-plan-section {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.gh-portal-plans-container.disabled .gh-portal-plan-section {
|
.gh-portal-plans-container.disabled .gh-portal-plan-section {
|
||||||
cursor: auto;
|
cursor: auto;
|
||||||
}
|
}
|
||||||
|
@ -64,6 +69,11 @@ export const PlanSectionStyles = `
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gh-portal-plans-container.is-change-plan.has-multiple-products .gh-portal-plan-section::before {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.gh-portal-plans-container.disabled .gh-portal-plan-section.checked::before {
|
.gh-portal-plans-container.disabled .gh-portal-plan-section.checked::before {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
@ -353,6 +363,11 @@ export const PlanSectionStyles = `
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gh-portal-plans-container.has-multiple-products.is-change-plan {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.gh-portal-plan-product {
|
.gh-portal-plan-product {
|
||||||
border: 1px solid var(--grey11);
|
border: 1px solid var(--grey11);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
@ -572,6 +587,19 @@ export function MultipleProductsPlansSection({products, selectedPlan, onPlanSele
|
||||||
onPlanSelect = () => {};
|
onPlanSelect = () => {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changePlan) {
|
||||||
|
return (
|
||||||
|
<section className="gh-portal-plans">
|
||||||
|
<div>
|
||||||
|
<ChangeProductSection
|
||||||
|
products={products}
|
||||||
|
onPlanSelect={onPlanSelect}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="gh-portal-plans">
|
<section className="gh-portal-plans">
|
||||||
<div>
|
<div>
|
||||||
|
@ -585,7 +613,7 @@ export function MultipleProductsPlansSection({products, selectedPlan, onPlanSele
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SingleProductPlansSection({product, plans, showLabel = true, selectedPlan, onPlanSelect, changePlan = false}) {
|
export function SingleProductPlansSection({product, plans, selectedPlan, onPlanSelect, changePlan = false}) {
|
||||||
const {site} = useContext(AppContext);
|
const {site} = useContext(AppContext);
|
||||||
if (!product || hasOnlyFreePlan({plans})) {
|
if (!product || hasOnlyFreePlan({plans})) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -609,6 +637,65 @@ export function SingleProductPlansSection({product, plans, showLabel = true, sel
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getChangePlanClassNames({cookiesDisabled, site}) {
|
||||||
|
let className = 'gh-portal-plans-container is-change-plan hide-checkbox';
|
||||||
|
if (cookiesDisabled) {
|
||||||
|
className += ' disabled';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasMultipleProductsFeature({site})) {
|
||||||
|
className += ' has-multiple-products';
|
||||||
|
}
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ChangePlanOptions({plans, selectedPlan, onPlanSelect, changePlan}) {
|
||||||
|
addDiscountToPlans(plans);
|
||||||
|
|
||||||
|
return plans.map(({name, currency_symbol: currencySymbol, amount, description, interval, id}) => {
|
||||||
|
const price = amount / 100;
|
||||||
|
const isChecked = selectedPlan === id;
|
||||||
|
let displayName = interval === 'month' ? 'Monthly' : 'Yearly';
|
||||||
|
|
||||||
|
let planClass = (isChecked ? 'gh-portal-plan-section checked' : 'gh-portal-plan-section');
|
||||||
|
planClass += ' gh-portal-change-plan-section';
|
||||||
|
const planNameClass = 'gh-portal-plan-name no-description';
|
||||||
|
const featureClass = 'gh-portal-plan-featurewrapper';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={planClass} key={id} onClick={e => onPlanSelect(e, id)}>
|
||||||
|
<h4 className={planNameClass}>{displayName}</h4>
|
||||||
|
<PriceLabel currencySymbol={currencySymbol} price={price} interval={interval} />
|
||||||
|
<div className={featureClass} style={{border: 'none', paddingTop: '3px'}}>
|
||||||
|
{(changePlan && selectedPlan === id ? <span className='gh-portal-plan-current'>Current plan</span> : '')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ChangeProductPlansSection({product, plans, selectedPlan, onPlanSelect, changePlan = false}) {
|
||||||
|
const {site} = useContext(AppContext);
|
||||||
|
if (!product || hasOnlyFreePlan({plans})) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cookiesDisabled = isCookiesDisabled();
|
||||||
|
/**Don't allow plans selection if cookies are disabled */
|
||||||
|
if (cookiesDisabled) {
|
||||||
|
onPlanSelect = () => {};
|
||||||
|
}
|
||||||
|
const className = getChangePlanClassNames({cookiesDisabled, site});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="gh-portal-plans">
|
||||||
|
<div className={className}>
|
||||||
|
<ChangePlanOptions plans={plans} onPlanSelect={onPlanSelect} selectedPlan={selectedPlan} changePlan={changePlan} />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function PlansSection({plans, showLabel = true, selectedPlan, onPlanSelect, changePlan = false}) {
|
function PlansSection({plans, showLabel = true, selectedPlan, onPlanSelect, changePlan = false}) {
|
||||||
const {site} = useContext(AppContext);
|
const {site} = useContext(AppContext);
|
||||||
if (hasOnlyFreePlan({plans})) {
|
if (hasOnlyFreePlan({plans})) {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import React, {useContext, useEffect, useState} from 'react';
|
import React, {useContext, useEffect, useState} from 'react';
|
||||||
import Switch from '../common/Switch';
|
import Switch from '../common/Switch';
|
||||||
import {ReactComponent as CheckmarkIcon} from '../../images/icons/checkmark.svg';
|
import {ReactComponent as CheckmarkIcon} from '../../images/icons/checkmark.svg';
|
||||||
import {getSiteProducts, getCurrencySymbol, getPriceString, getStripeAmount, isCookiesDisabled} from '../../utils/helpers';
|
import {getSiteProducts, getCurrencySymbol, getPriceString, getStripeAmount, isCookiesDisabled, getPricesFromProducts, getMemberActivePrice} from '../../utils/helpers';
|
||||||
import AppContext from '../../AppContext';
|
import AppContext from '../../AppContext';
|
||||||
|
import {ChangeProductPlansSection} from './PlansSection';
|
||||||
|
|
||||||
export const ProductsSectionStyles = ({site}) => {
|
export const ProductsSectionStyles = ({site}) => {
|
||||||
const products = getSiteProducts({site});
|
const products = getSiteProducts({site});
|
||||||
|
@ -678,4 +679,54 @@ 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 selectedPlan = getMemberActivePrice({member});
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className={cardClass} key={product.id}>
|
||||||
|
<div className="gh-portal-product-card-header" style={{
|
||||||
|
gridTemplateColumns: 'auto auto'
|
||||||
|
}}>
|
||||||
|
<h4 className="gh-portal-product-name">{product.name}</h4>
|
||||||
|
<div className="gh-portal-product-description" style={{
|
||||||
|
gridColumn: '1/2'
|
||||||
|
}}>{product.description}</div>
|
||||||
|
<ProductBenefitsContainer product={product} />
|
||||||
|
</div>
|
||||||
|
{/* <ProductCardFooter product={product} /> */}
|
||||||
|
<ProductBenefitsContainer product={product} showVertical={true} />
|
||||||
|
</div>
|
||||||
|
<ChangeProductPlansSection
|
||||||
|
product={product}
|
||||||
|
plans={plans}
|
||||||
|
selectedPlan={selectedPlan?.id}
|
||||||
|
changePlan={true}
|
||||||
|
onPlanSelect={onPlanSelect}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ChangeProductCards({products, onPlanSelect}) {
|
||||||
|
return products.map((product) => {
|
||||||
|
if (product.id === 'free') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ChangeProductCard product={product} key={product.id} onPlanSelect={onPlanSelect} />
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ChangeProductSection({products, onPlanSelect}) {
|
||||||
|
return (
|
||||||
|
<div className="gh-portal-products-grid">
|
||||||
|
<ChangeProductCards products={products} onPlanSelect={onPlanSelect} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default ProductsSection;
|
export default ProductsSection;
|
||||||
|
|
|
@ -192,7 +192,7 @@ const ChangePlanSection = ({plans, selectedPlan, onPlanSelect, onCancelSubscript
|
||||||
showLabel={false}
|
showLabel={false}
|
||||||
plans={plans}
|
plans={plans}
|
||||||
selectedPlan={selectedPlan}
|
selectedPlan={selectedPlan}
|
||||||
onPlanSelect={(e, priceId) => onPlanSelect(e, priceId)}
|
onPlanSelect={onPlanSelect}
|
||||||
changePlan={true}
|
changePlan={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -205,13 +205,22 @@ function PlansOrProductSection({showLabel, plans, selectedPlan, onPlanSelect, ch
|
||||||
const {site, member} = useContext(AppContext);
|
const {site, member} = useContext(AppContext);
|
||||||
const products = getUpgradeProducts({site, member});
|
const products = getUpgradeProducts({site, member});
|
||||||
if (hasMultipleProductsFeature({site})) {
|
if (hasMultipleProductsFeature({site})) {
|
||||||
if (hasMultipleProducts({site})) {
|
if (changePlan === true) {
|
||||||
|
return (
|
||||||
|
<MultipleProductsPlansSection
|
||||||
|
products={products}
|
||||||
|
selectedPlan={selectedPlan}
|
||||||
|
changePlan={true}
|
||||||
|
onPlanSelect={onPlanSelect}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else if (hasMultipleProducts({site})) {
|
||||||
return (
|
return (
|
||||||
<MultipleProductsPlansSection
|
<MultipleProductsPlansSection
|
||||||
products={products}
|
products={products}
|
||||||
selectedPlan={selectedPlan}
|
selectedPlan={selectedPlan}
|
||||||
changePlan={changePlan}
|
changePlan={changePlan}
|
||||||
onPlanSelect={(e, priceId) => onPlanSelect(e, priceId)}
|
onPlanSelect={onPlanSelect}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -220,7 +229,7 @@ function PlansOrProductSection({showLabel, plans, selectedPlan, onPlanSelect, ch
|
||||||
product={products?.[0]}
|
product={products?.[0]}
|
||||||
plans={plans}
|
plans={plans}
|
||||||
selectedPlan={selectedPlan}
|
selectedPlan={selectedPlan}
|
||||||
onPlanSelect={(e, priceId) => onPlanSelect(e, priceId)}
|
onPlanSelect={onPlanSelect}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -231,7 +240,7 @@ function PlansOrProductSection({showLabel, plans, selectedPlan, onPlanSelect, ch
|
||||||
plans={plans}
|
plans={plans}
|
||||||
selectedPlan={selectedPlan}
|
selectedPlan={selectedPlan}
|
||||||
changePlan={changePlan}
|
changePlan={changePlan}
|
||||||
onPlanSelect={(e, priceId) => onPlanSelect(e, priceId)}
|
onPlanSelect={onPlanSelect}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -380,7 +389,7 @@ export default class AccountPlanPage extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onPlanSelect(e, priceId) {
|
onPlanSelect = (e, priceId) => {
|
||||||
e?.preventDefault();
|
e?.preventDefault();
|
||||||
|
|
||||||
const {member} = this.context;
|
const {member} = this.context;
|
||||||
|
@ -466,7 +475,7 @@ export default class AccountPlanPage extends React.Component {
|
||||||
{...{plans, selectedPlan, showConfirmation, confirmationPlan, confirmationType}}
|
{...{plans, selectedPlan, showConfirmation, confirmationPlan, confirmationType}}
|
||||||
onConfirm={(...args) => this.onConfirm(...args)}
|
onConfirm={(...args) => this.onConfirm(...args)}
|
||||||
onCancelSubscription = {data => this.onCancelSubscription(data)}
|
onCancelSubscription = {data => this.onCancelSubscription(data)}
|
||||||
onPlanSelect = {(e, name) => this.onPlanSelect(e, name)}
|
onPlanSelect = {this.onPlanSelect}
|
||||||
onPlanCheckout = {(e, name) => this.onPlanCheckout(e, name)}
|
onPlanCheckout = {(e, name) => this.onPlanCheckout(e, name)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -183,12 +183,12 @@ export const SignupPageStyles = `
|
||||||
.gh-portal-popup-wrapper.multiple-products footer.gh-portal-signin-footer {
|
.gh-portal-popup-wrapper.multiple-products footer.gh-portal-signin-footer {
|
||||||
padding-top: 24px;
|
padding-top: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gh-portal-popup-wrapper.multiple-products.signin .gh-portal-powered {
|
.gh-portal-popup-wrapper.multiple-products.signin .gh-portal-powered {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.gh-portal-popup-wrapper.multiple-products footer.gh-portal-signup-footer,
|
.gh-portal-popup-wrapper.multiple-products footer.gh-portal-signup-footer,
|
||||||
.gh-portal-popup-wrapper.multiple-products footer.gh-portal-signin-footer {
|
.gh-portal-popup-wrapper.multiple-products footer.gh-portal-signin-footer {
|
||||||
|
|
|
@ -50,30 +50,6 @@ const products = [
|
||||||
type: 'recurring',
|
type: 'recurring',
|
||||||
interval: 'year'
|
interval: 'year'
|
||||||
},
|
},
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
id: '6086d2c776909b1a2382369a',
|
|
||||||
stripe_price_id: '7d6c89c0289ca1731226e86b95b5a162085b8561ca0d10d3a4f03afd3e3e6ba6',
|
|
||||||
stripe_product_id: '109c85c734fb9992e7bc30a26af66c22f5c94d8dc62e0a33cb797be902c06b2d',
|
|
||||||
active: 1,
|
|
||||||
nickname: 'Monthly',
|
|
||||||
currency: 'usd',
|
|
||||||
amount: 500,
|
|
||||||
type: 'recurring',
|
|
||||||
interval: 'month'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '6086eff0823dd7240afc8083',
|
|
||||||
stripe_price_id: 'price_1IkXgCFToJelIqAsTP3V1paQ',
|
|
||||||
stripe_product_id: 'prod_JNGGBrrogUXcoM',
|
|
||||||
active: 1,
|
|
||||||
nickname: 'Yearly',
|
|
||||||
currency: 'usd',
|
|
||||||
amount: 5000,
|
|
||||||
type: 'recurring',
|
|
||||||
interval: 'year'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
benefits: [
|
benefits: [
|
||||||
{
|
{
|
||||||
id: 'a1',
|
id: 'a1',
|
||||||
|
@ -123,30 +99,6 @@ const products = [
|
||||||
type: 'recurring',
|
type: 'recurring',
|
||||||
interval: 'year'
|
interval: 'year'
|
||||||
},
|
},
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
id: '6086d2c776909b1a2382369a',
|
|
||||||
stripe_price_id: '7d6c89c0289ca1731226e86b95b5a162085b8561ca0d10d3a4f03afd3e3e6ba6',
|
|
||||||
stripe_product_id: '109c85c734fb9992e7bc30a26af66c22f5c94d8dc62e0a33cb797be902c06b2d',
|
|
||||||
active: 1,
|
|
||||||
nickname: 'Monthly',
|
|
||||||
currency: 'usd',
|
|
||||||
amount: 1200,
|
|
||||||
type: 'recurring',
|
|
||||||
interval: 'month'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '6086eff0823dd7240afc8083',
|
|
||||||
stripe_price_id: 'price_1IkXgCFToJelIqAsTP3V1paQ',
|
|
||||||
stripe_product_id: 'prod_JNGGBrrogUXcoM',
|
|
||||||
active: 1,
|
|
||||||
nickname: 'Yearly',
|
|
||||||
currency: 'usd',
|
|
||||||
amount: 12000,
|
|
||||||
type: 'recurring',
|
|
||||||
interval: 'year'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
benefits: [
|
benefits: [
|
||||||
{
|
{
|
||||||
id: 'b1',
|
id: 'b1',
|
||||||
|
@ -192,30 +144,6 @@ const products = [
|
||||||
type: 'recurring',
|
type: 'recurring',
|
||||||
interval: 'year'
|
interval: 'year'
|
||||||
},
|
},
|
||||||
prices: [
|
|
||||||
{
|
|
||||||
id: '6086d2c776909b1a2382369a',
|
|
||||||
stripe_price_id: '7d6c89c0289ca1731226e86b95b5a162085b8561ca0d10d3a4f03afd3e3e6ba6',
|
|
||||||
stripe_product_id: '109c85c734fb9992e7bc30a26af66c22f5c94d8dc62e0a33cb797be902c06b2d',
|
|
||||||
active: 1,
|
|
||||||
nickname: 'Monthly',
|
|
||||||
currency: 'usd',
|
|
||||||
amount: 1200,
|
|
||||||
type: 'recurring',
|
|
||||||
interval: 'month'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '6086eff0823dd7240afc8083',
|
|
||||||
stripe_price_id: 'price_1IkXgCFToJelIqAsTP3V1paQ',
|
|
||||||
stripe_product_id: 'prod_JNGGBrrogUXcoM',
|
|
||||||
active: 1,
|
|
||||||
nickname: 'Yearly',
|
|
||||||
currency: 'usd',
|
|
||||||
amount: 12000,
|
|
||||||
type: 'recurring',
|
|
||||||
interval: 'year'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
benefits: [
|
benefits: [
|
||||||
{
|
{
|
||||||
id: 'c1',
|
id: 'c1',
|
||||||
|
@ -292,17 +220,17 @@ export const member = {
|
||||||
id: 'fd43b943666b97640188afb382cca39479de30f799985679dd7a71ad2925ac6c',
|
id: 'fd43b943666b97640188afb382cca39479de30f799985679dd7a71ad2925ac6c',
|
||||||
nickname: 'Yearly',
|
nickname: 'Yearly',
|
||||||
interval: 'year',
|
interval: 'year',
|
||||||
amount: 1500,
|
amount: 7000,
|
||||||
currency: 'USD'
|
currency: 'USD'
|
||||||
},
|
},
|
||||||
price: {
|
price: {
|
||||||
id: 'price_1IkXLAFToJelIqAseQdK4WSU',
|
id: 'price_1IkXgCFToJelIqAsTP3V1paQ',
|
||||||
price_id: '6086ead8070218227791fe4f',
|
price_id: '6086eff0823dd7240afc8012',
|
||||||
nickname: 'Yearly',
|
nickname: 'Yearly',
|
||||||
currency: 'usd',
|
currency: 'usd',
|
||||||
amount: 1500,
|
amount: 7000,
|
||||||
type: 'recurring',
|
type: 'recurring',
|
||||||
interval: 'month',
|
interval: 'year',
|
||||||
product: {
|
product: {
|
||||||
id: 'prod_JNGGBrrogUXcoM',
|
id: 'prod_JNGGBrrogUXcoM',
|
||||||
name: 'Main Product',
|
name: 'Main Product',
|
||||||
|
|
|
@ -264,7 +264,11 @@ export function getProductBenefits({product}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPricesFromProducts({site, products = null}) {
|
export function getPricesFromProducts({site = null, products = null}) {
|
||||||
|
if (!site && !products) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const availableProducts = products || getAvailableProducts({site});
|
const availableProducts = products || getAvailableProducts({site});
|
||||||
const prices = availableProducts.reduce((accumPrices, product) => {
|
const prices = availableProducts.reduce((accumPrices, product) => {
|
||||||
if (product.monthlyPrice && product.yearlyPrice) {
|
if (product.monthlyPrice && product.yearlyPrice) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue