mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 14:03:48 +03:00
Refined member account details to show any applied discounts
refs https://github.com/TryGhost/Team/issues/1195 - shows any applied discounts on subscription on account profile page
This commit is contained in:
parent
cdd1c429df
commit
86a8abdf30
@ -476,6 +476,10 @@ const FrameStyles = `
|
||||
color: var(--grey6);
|
||||
}
|
||||
|
||||
.gh-portal-list-detail .old-price {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.gh-portal-right-arrow {
|
||||
line-height: 1;
|
||||
color: var(--grey8);
|
||||
|
@ -3,9 +3,10 @@ import MemberAvatar from '../common/MemberGravatar';
|
||||
import ActionButton from '../common/ActionButton';
|
||||
import CloseButton from '../common/CloseButton';
|
||||
import Switch from '../common/Switch';
|
||||
import {getMemberSubscription, hasOnlyFreePlan, isComplimentaryMember} from '../../utils/helpers';
|
||||
import {getMemberSubscription, getUpdatedOfferPrice, hasOnlyFreePlan, isComplimentaryMember} from '../../utils/helpers';
|
||||
import {getDateString} from '../../utils/date-time';
|
||||
import {ReactComponent as LoaderIcon} from '../../images/icons/loader.svg';
|
||||
import {ReactComponent as OfferTagIcon} from '../../images/icons/offer-tag.svg';
|
||||
import {useContext} from 'react';
|
||||
|
||||
const React = require('react');
|
||||
@ -137,6 +138,25 @@ const UserHeader = () => {
|
||||
);
|
||||
};
|
||||
|
||||
function getOfferLabel({offer, price, subscriptionStartDate}) {
|
||||
let offerLabel = '';
|
||||
|
||||
if (offer) {
|
||||
const discountDuration = offer.duration;
|
||||
let durationLabel = '';
|
||||
if (discountDuration === 'forever') {
|
||||
durationLabel = `Forever`;
|
||||
} else if (discountDuration === 'repeating') {
|
||||
const durationInMonths = offer.duration_in_months || 0;
|
||||
let offerStartDate = new Date(subscriptionStartDate);
|
||||
let offerEndDate = new Date(offerStartDate.setMonth(offerStartDate.getMonth() + durationInMonths));
|
||||
durationLabel = `Ends ${getDateString(offerEndDate)}`;
|
||||
}
|
||||
offerLabel = `${getUpdatedOfferPrice({offer, price, useFormatted: true})}/${price.interval} - ${durationLabel}`;
|
||||
}
|
||||
return offerLabel;
|
||||
}
|
||||
|
||||
const PaidAccountActions = () => {
|
||||
const {member, site, onAction} = useContext(AppContext);
|
||||
|
||||
@ -155,19 +175,42 @@ const PaidAccountActions = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const PlanLabel = ({price, isComplimentary}) => {
|
||||
const PlanLabel = ({price, isComplimentary, subscription}) => {
|
||||
const {
|
||||
offer,
|
||||
start_date: startDate
|
||||
} = subscription;
|
||||
let label = '';
|
||||
if (price) {
|
||||
const {amount = 0, currency, interval} = price;
|
||||
label = `${Intl.NumberFormat('en', {currency, style: 'currency'}).format(amount / 100)}/${interval}`;
|
||||
}
|
||||
let offerLabelStr = getOfferLabel({price, offer, subscriptionStartDate: startDate});
|
||||
if (isComplimentary) {
|
||||
label = label ? `Complimentary (${label})` : `Complimentary`;
|
||||
}
|
||||
let oldPriceClassName = '';
|
||||
if (offerLabelStr) {
|
||||
oldPriceClassName = 'old-price';
|
||||
}
|
||||
const OfferLabel = () => {
|
||||
if (offerLabelStr) {
|
||||
return (
|
||||
<p>
|
||||
<OfferTagIcon style={{width: '12px', height: '9px', marginLeft: '-10px'}}/>
|
||||
{offerLabelStr}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return (
|
||||
<p>
|
||||
{label}
|
||||
</p>
|
||||
<>
|
||||
<p className={oldPriceClassName}>
|
||||
{label}
|
||||
</p>
|
||||
<OfferLabel />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -216,7 +259,6 @@ const PaidAccountActions = () => {
|
||||
const isComplimentary = isComplimentaryMember({member});
|
||||
if (subscription || isComplimentary) {
|
||||
const {
|
||||
plan,
|
||||
price,
|
||||
default_payment_card_last4: defaultCardLast4
|
||||
} = subscription || {};
|
||||
@ -225,7 +267,7 @@ const PaidAccountActions = () => {
|
||||
<section>
|
||||
<div className='gh-portal-list-detail'>
|
||||
<h3>Plan</h3>
|
||||
<PlanLabel plan={plan} price={price} isComplimentary={isComplimentary} />
|
||||
<PlanLabel price={price} isComplimentary={isComplimentary} subscription={subscription} />
|
||||
</div>
|
||||
<PlanUpdateButton isComplimentary={isComplimentary} />
|
||||
</section>
|
||||
|
4
ghost/portal/src/images/icons/offer-tag.svg
Normal file
4
ghost/portal/src/images/icons/offer-tag.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs>
|
||||
<path d="M22.939 2.56V8.817C22.9391 9.61244 22.6232 10.3754 22.061 10.938L10.5 22.5C10.2187 22.7812 9.83721 22.9392 9.43946 22.9392C9.04172 22.9392 8.66026 22.7812 8.37896 22.5L1.49997 15.62C1.21876 15.3387 1.06079 14.9572 1.06079 14.5595C1.06079 14.1618 1.21876 13.7803 1.49997 13.499L13.061 1.938C13.6236 1.37572 14.3865 1.0599 15.182 1.06H21.439C21.8368 1.06 22.2183 1.21803 22.4996 1.49934C22.7809 1.78064 22.939 2.16217 22.939 2.56V2.56Z" class="a" />
|
||||
<path d="M17.689 7.81C16.8605 7.81 16.189 7.13842 16.189 6.31C16.189 5.48157 16.8605 4.81 17.689 4.81C18.5174 4.81 19.189 5.48157 19.189 6.31C19.189 7.13842 18.5174 7.81 17.689 7.81Z" class="a" />
|
||||
</svg>
|
After Width: | Height: | Size: 893 B |
@ -502,3 +502,29 @@ export function getPriceIdFromPageQuery({site, pageQuery}) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export const getOfferOffAmount = ({offer}) => {
|
||||
if (offer.type === 'fixed') {
|
||||
return `${getCurrencySymbol(offer.currency)}${offer.amount / 100}`;
|
||||
} else if (offer.type === 'percent') {
|
||||
return `${offer.amount}%`;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
export const getUpdatedOfferPrice = ({offer, price, useFormatted = false}) => {
|
||||
const originalAmount = price.amount;
|
||||
let updatedAmount;
|
||||
if (offer.type === 'fixed' && isSameCurrency(offer.currency, price.currency)) {
|
||||
updatedAmount = ((originalAmount - offer.amount)) / 100;
|
||||
updatedAmount = updatedAmount > 0 ? updatedAmount : 0;
|
||||
} else if (offer.type === 'percent') {
|
||||
updatedAmount = (originalAmount - ((originalAmount * offer.amount) / 100)) / 100;
|
||||
} else {
|
||||
updatedAmount = originalAmount / 100;
|
||||
}
|
||||
if (useFormatted) {
|
||||
return Intl.NumberFormat('en', {currency: price?.currency, style: 'currency'}).format(updatedAmount);
|
||||
}
|
||||
return updatedAmount;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user