client/components/mma/switch/complete/SwitchComplete.tsx (200 lines of code) (raw):

import { css } from '@emotion/react'; import { from, headlineBold24, headlineBold28, palette, space, textSans17, textSansBold17, textSansBold20, until, } from '@guardian/source/foundations'; import { LinkButton, Stack, SvgCalendar, SvgClock, SvgEnvelope, themeButtonReaderRevenueBrand, } from '@guardian/source/react-components'; import { useContext } from 'react'; import { Navigate, useLocation } from 'react-router'; import type { PaidSubscriptionPlan } from '../../../../../shared/productResponse'; import { buttonCentredCss } from '../../../../styles/ButtonStyles'; import { iconListCss, sectionSpacing, whatHappensNextIconCss, } from '../../../../styles/GenericStyles'; import { formatAmount } from '../../../../utilities/utils'; import { Heading } from '../../shared/Heading'; import type { SwitchContextInterface, SwitchRouterState, } from '../SwitchContainer'; import { SwitchContext } from '../SwitchContainer'; import { SwitchSignInImage } from './SwitchSignInImage'; export const SwitchComplete = () => { const switchContext = useContext(SwitchContext) as SwitchContextInterface; const { mainPlan, monthlyOrAnnual, supporterPlusTitle, thresholds } = switchContext; const { thresholdForBillingPeriod: threshold, isAboveThreshold } = thresholds; const newAmount = Math.max(threshold, mainPlan.price / 100); const newAmountAndCurrency = `${mainPlan.currency}${formatAmount( newAmount, )}`; const location = useLocation(); const routerState = location.state as SwitchRouterState; const amountPayableToday = routerState?.amountPayableToday; const nextPaymentDate = routerState?.nextPaymentDate; if (amountPayableToday === undefined || !nextPaymentDate) { return <Navigate to=".." />; } return ( <> {switchContext.isFromApp ? ( <AppThankYouBanner newAmount={newAmountAndCurrency} newProduct={supporterPlusTitle.toLowerCase()} aboveThreshold={isAboveThreshold} /> ) : ( <section css={sectionSpacing}> <ThankYouMessaging mainPlan={mainPlan} newAmount={newAmount} aboveThreshold={isAboveThreshold} /> </section> )} <section css={sectionSpacing}> <WhatHappensNext currency={mainPlan.currency} amountPayableToday={amountPayableToday} nextPaymentAmount={newAmount} billingPeriod={monthlyOrAnnual.toLowerCase()} email={switchContext.user?.email ?? ''} isFromApp={switchContext.isFromApp} nextPaymentDate={nextPaymentDate} /> </section> {!switchContext.isFromApp && ( <section css={sectionSpacing}> <Stack space={6}> <SignInBanner /> <div> <LinkButton href="https://www.theguardian.com/"> Continue reading the Guardian </LinkButton> </div> </Stack> </section> )} </> ); }; const thankYouBannerCss = css` margin-top: -1px; margin-left: -${space[3]}px; margin-right: -${space[3]}px; padding: ${space[6]}px ${space[3]}px; color: ${palette.neutral[100]}; background-color: ${palette.brand[500]}; ${from.tablet} { margin-left: -${space[5]}px; margin-right: -${space[5]}px; } ${from.desktop} { margin-top: ${space[9]}px; margin-left: 0; margin-right: 0; padding: ${space[4]}px ${space[4]}px; } `; const thankYouBannerHeadingCss = css` ${headlineBold24}; margin-top: 0; margin-bottom: ${space[5]}px; max-width: 30ch; `; const thankYouBannerSubheadingCss = css` ${textSansBold20}; margin: 0; border-top: 1px solid rgba(255, 255, 255, 0.6); `; const thankYouBannerCopyCss = css` ${textSans17}; margin: 0; max-width: 45ch; `; const thankYouBannerButtonCss = css` margin-top: ${space[6]}px; margin-bottom: ${space[5]}px; ${until.tablet} { display: flex; flex-direction: column; } `; const AppThankYouBanner = (props: { newAmount: string; newProduct: string; aboveThreshold: boolean; }) => { return ( <section css={thankYouBannerCss}> <h2 css={thankYouBannerHeadingCss}> Thank you for {props.aboveThreshold ? 'changing' : 'upgrading'}{' '} to {props.newAmount} {props.newProduct} </h2> <p css={thankYouBannerSubheadingCss}>One last step ...</p> <div css={thankYouBannerButtonCss}> <LinkButton theme={themeButtonReaderRevenueBrand} href="x-gu://mma/success" cssOverrides={buttonCentredCss} > Activate full app access now </LinkButton> </div> <p css={thankYouBannerCopyCss}> If you don’t complete this step, you may be unable to access the app in full for up to one hour </p> </section> ); }; const WhatHappensNext = (props: { currency: string; amountPayableToday: number; nextPaymentAmount: number; billingPeriod: string; email: string; isFromApp: boolean; nextPaymentDate: string; }) => { return ( <Stack space={4}> <Heading sansSerif>What happens next?</Heading> <ul css={[iconListCss, whatHappensNextIconCss]}> <li> <SvgEnvelope size="medium" /> <span data-qm-masking="blocklist"> You will receive a confirmation email to {props.email} </span> </li> <li> <SvgCalendar size="medium" /> <span> Your first billing date is today and you will be charged{' '} {props.currency} {formatAmount(props.amountPayableToday)}. From{' '} {props.nextPaymentDate}, your ongoing{' '} {props.billingPeriod} payment will be {props.currency} {formatAmount(props.nextPaymentAmount)} </span> </li> {!props.isFromApp && ( <li> <SvgClock size="medium" /> <span> Your new support will start today. It can take up to an hour for your support to be activated </span> </li> )} </ul> </Stack> ); }; const thankYouCss = css` ${headlineBold24}; margin-top: 0; margin-bottom: 0; ${from.tablet} { ${headlineBold28}; span { display: block; color: ${palette.brand['500']}; } } `; const ThankYouMessaging = (props: { mainPlan: PaidSubscriptionPlan; newAmount: number; aboveThreshold: boolean; }) => { return ( <h2 css={thankYouCss}> {props.aboveThreshold ? ( <>Thank you for changing your support type.</> ) : ( <> Thank you for upgrading to {props.mainPlan.currency} {formatAmount(props.newAmount)} per{' '} {props.mainPlan.billingPeriod}. </> )}{' '} <span>Enjoy your exclusive extras</span> </h2> ); }; const signInCss = css` display: grid; overflow: hidden; background-color: ${palette.brand[500]}; border-radius: 8px; > * { grid-area: 1 / 1; } > svg { place-self: end; height: 0; min-height: 100%; } ${from.tablet} { border-radius: 0; } `; const signInContentContainerCss = css` padding: ${space[3]}px; color: ${palette.neutral[100]}; `; const signInHeadingCss = css` ${textSansBold17}; margin: 0; `; const signInParaCss = css` ${textSans17}; margin: 0; max-width: 64%; `; const SignInBanner = () => ( <div css={signInCss}> <SwitchSignInImage /> <div css={signInContentContainerCss}> <h2 css={signInHeadingCss}>Sign in on all your devices</h2> <p css={signInParaCss}> To access your exclusive extras on our website and app, please sign in. It takes less than a minute. </p> </div> </div> );