client/components/mma/paymentUpdate/CurrentPaymentDetail.tsx (269 lines of code) (raw):
import { css } from '@emotion/react';
import {
from,
palette,
space,
textSans17,
textSansBold17,
until,
} from '@guardian/source/foundations';
import { InlineError } from '@guardian/source/react-components';
import type { ProductDetail } from '../../../../shared/productResponse';
import {
getMainPlan,
getSpecificProductType,
} from '../../../../shared/productResponse';
import { PaypalLogo } from '../shared/assets/PaypalLogo';
import { CardDisplay } from '../shared/CardDisplay';
import {
DirectDebitDisplay,
sanitiseAccountNumber,
} from '../shared/DirectDebitDisplay';
import { getObfuscatedPayPalId } from '../shared/PaypalDisplay';
function cardExpired(year: number, month: number) {
const expiryTimestamp = new Date(year, month);
const now = new Date();
return expiryTimestamp < now;
}
export const CurrentPaymentDetails = (productDetail: ProductDetail) => {
const { subscription } = productDetail;
const mainPlan = getMainPlan(subscription);
const hasCancellationPending: boolean = subscription.cancelledAt;
const specificProductType = getSpecificProductType(productDetail.tier);
const keyValuePairCss = css`
list-style: none;
margin: 0;
padding: 0;
`;
const keyCss = css`
${textSansBold17};
padding: 0 ${space[2]}px 0 0;
display: inline-block;
vertical-align: top;
width: 14ch;
`;
const valueCss = css`
${textSans17};
padding: 0;
display: inline-block;
vertical-align: top;
width: calc(100% - 15ch);
text-align: right;
${from.tablet} {
text-align: left;
}
`;
const hasPaymentFailure: boolean = !!productDetail.alertText;
return (
<div
css={css`
border: 1px solid ${palette.neutral[86]};
margin-bottom: ${space[4]}px;
`}
>
<div
css={css`
display: flex;
justify-content: space-between;
align-items: start;
background-color: ${hasCancellationPending
? palette.neutral[97]
: palette.brand[400]};
${from.mobileLandscape} {
align-items: center;
}
`}
>
<h2
css={css`
font-size: 17px;
font-weight: bold;
margin: 0;
padding: ${space[3]}px;
color: ${hasCancellationPending
? palette.neutral[7]
: palette.neutral[100]};
${until.mobileLandscape} {
padding: ${space[3]}px;
}
${from.tablet} {
font-size: 20px;
padding: ${space[3]}px ${space[5]}px;
}
`}
>
{specificProductType.productTitle(mainPlan)}
</h2>
<div
css={css`
display: flex;
align-items: center;
padding: ${space[3]}px 0;
${until.mobileLandscape} {
flex-direction: column;
align-items: end;
}
`}
></div>
</div>
<div
css={css`
padding: ${space[5]}px ${space[3]}px;
${from.tablet} {
padding: ${space[5]}px;
display: flex;
}
`}
>
<div
css={css`
padding-bottom: ${space[3]}px;
${from.tablet} {
flex: 1;
display: flex;
flex-flow: column nowrap;
padding: 0;
margin: 0;
}
`}
>
{productDetail.isPaidTier && (
<>
<ul css={keyValuePairCss}>
<li css={keyCss}>Payment method</li>
<li css={valueCss} data-qm-masking="blocklist">
{subscription.card && (
<CardDisplay
inErrorState={hasPaymentFailure}
cssOverrides={css`
margin: 0;
justify-content: flex-end;
${from.tablet} {
justify-content: left;
}
`}
{...subscription.card}
/>
)}
{subscription.payPalEmail && <PaypalLogo />}
{subscription.sepaMandate && (
<div>SEPA</div>
)}
{subscription.mandate && (
<span
css={css`
text-align: right;
${from.tablet} {
text-align: left;
}
`}
>
{sanitiseAccountNumber(
subscription.mandate
.accountNumber,
false,
)}
</span>
)}
{subscription.stripePublicKeyForCardAddition && (
<span>No Payment Method</span>
)}
</li>
</ul>
</>
)}
</div>
<div
css={css`
padding: ${space[3]}px 0 0 0;
border-top: 1px solid ${palette.neutral[86]};
${subscription.mandate ? 'text-align: right;' : ''}
${from.tablet} {
flex: 1;
display: inline-block;
flex-flow: column nowrap;
padding: 0 0 0 ${space[5]}px;
margin: 0;
text-align: center;
border-top: none;
}
ul:last-of-type {
margin-bottom: ${space[5]}px;
}
`}
>
{subscription.card && subscription.card.expiry && (
<>
<span
css={css`
${keyCss};
${from.tablet} {
text-align: right;
}
`}
>
{cardExpired(
subscription.card.expiry.year,
subscription.card.expiry.month,
) ? (
<InlineError>Expired</InlineError>
) : (
<>Expiry</>
)}
</span>
<span
data-qm-masking="blocklist"
css={css`
${valueCss};
color: ${hasPaymentFailure
? palette.error[400]
: palette.neutral[7]};
`}
>
{subscription.card.expiry.month} /{' '}
{subscription.card.expiry.year}
</span>
</>
)}
{subscription.sepaMandate && (
<span
css={css`
${valueCss};
`}
>
<div>
{subscription.sepaMandate.accountName}
<br />
{subscription.sepaMandate.iban}
</div>
</span>
)}
{subscription.mandate && (
<span
css={css`
${valueCss};
color: ${hasPaymentFailure
? palette.error[400]
: palette.neutral[7]};
`}
>
<DirectDebitDisplay
{...subscription.mandate}
onlySortCode
/>
</span>
)}
{subscription.payPalEmail && (
<span
css={css`
${valueCss};
`}
>
{getObfuscatedPayPalId(subscription.payPalEmail)}
</span>
)}
</div>
</div>
</div>
);
};