Skip to content

Commit

Permalink
feat: update learn more modals to support US and UK short term checko…
Browse files Browse the repository at this point in the history
…ut and preapproval (paypal#978)
  • Loading branch information
perco12 authored Dec 12, 2023
1 parent ee4270e commit fa0bca8
Show file tree
Hide file tree
Showing 142 changed files with 739 additions and 63 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ ehthumbs.db
Icon?
Thumbs.db

!*/**/icons
!*/**/icons
4 changes: 1 addition & 3 deletions content/modals/FR/short_term_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@
"<p>Only for private individuals residing in France. French PayPal account required. Pay in 4X is available, subject to acceptance, for purchases between {formattedMinAmount} and {formattedMaxAmount}.</p>"
],

[
"A loan is a binding commitment and must be repaid, check your repayment capacity. "
],
["A loan is a binding commitment and must be repaid, check your repayment capacity. "],
["Terms and Conditions", "https://www.paypal.com/fr/webapps/mpp/ua/pay-in-4x-full"],
[
". Credit offered by PayPal (Europe) S.à r.l. et Cie, S.C.A., 22-24 Boulevard Royal, L-2449, Luxembourg, Trade and Companies Register of Luxembourg B 118 349, which is duly licensed as a Luxembourg credit institution and falls under the oversight of the supervisory authority of Luxembourg, Commission de Surveillance du Secteur Financier. This information is provided by PayPal."
Expand Down
56 changes: 56 additions & 0 deletions content/modals/GB/short_term_xo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"meta": {
"product": "PAY_LATER_SHORT_TERM",
"periodicPayment": "{formattedPeriodicPayment}",
"minAmount": "{minAmount}",
"maxAmount": "{maxAmount}",
"qualifying": "{qualifying_offer}",
"amount": "{transaction_amount}",
"apr": "{apr}",
"preapproved": "false",
"variables": {
"transaction_amount": "${eval(transaction_amount ? transaction_amount : '-')}",
"qualifying_offer": "${eval(CREDIT_OFFERS_DS.qualifying_offer ? CREDIT_OFFERS_DS.qualifying_offer : 'false')}",
"financing_code": "${CREDIT_OFFERS_DS.financing_code}",
"formattedPeriodicPayment": "${CREDIT_OFFERS_DS.formattedPeriodicPayment}",
"total_payments": "${CREDIT_OFFERS_DS.total_payments}",
"formattedMinAmount": "${CREDIT_OFFERS_DS.formattedMinAmount}",
"formattedMaxAmount": "${CREDIT_OFFERS_DS.formattedMaxAmount}",
"formattedTotalCost": "${CREDIT_OFFERS_DS.formattedTotalCost}",
"minAmount": "${CREDIT_OFFERS_DS.minAmount}",
"maxAmount": "${CREDIT_OFFERS_DS.maxAmount}",
"apr": "${CREDIT_OFFERS_DS.apr}",
"nominal_rate": "${CREDIT_OFFERS_DS.nominal_rate}"
}
},
"content": {
"headline": "Pay in 3 interest-free payments",
"subheadline": "Available for purchases of {formattedMinAmount} to {formattedMaxAmount}. No sign-up fees or late fees.",
"qualifyingSubheadline": "Split your purchase of {formattedTotalCost} into {total_payments} with no sign-up fees or late fees.",
"donutTimestamps": ["Today", "1 month", "2 months"],
"estimatedInstallments": {
"items": [
{ "total_payment:": "{formattedPeriodicPayment}", "payment_date": "Today" },
{ "total_payment:": "{formattedPeriodicPayment}", "payment_date": "1 month" },
{ "total_payment:": "{formattedPeriodicPayment}", "payment_date": "2 months" }
]
},
"instructions": {
"instructionsHeadline": "How to use Pay in 3",
"instructionsSubHeadline": "Confirm your info and apply, set up autopay, and review your purchase."
},
"preapproval": {
"preapprovalHeadline": "Pre-approved to Pay in 3 on this purchase ",
"preapprovalSubHeadline": "Pay {formattedTotalCost} in {total_payments} interest-free payments.",
"preapprovalDisclaimerHeadline": "What to know about pre-approval",
"preapprovalDisclaimerBody": "Pre-approval may not be valid if you make another Pay in 3 purchase before the session expires."
},
"cta": {
"buttonTextEligible": "Continue with Pay in 3",
"buttonTextIneligible": "Back to Checkout",
"link": "https://www.paypal.com/link/to/short-term-application"
},
"disclosure": "Pay in 3 is a form of credit, so carefully consider whether the purchase is affordable and how you will make the repayments. Be aware of the possible impact of using Pay in 3 and of missing payments, including making other borrowing more difficult or more expensive. Pay in 3 eligibility is subject to status and approval. 18+ UK residents only. Available for purchases of {formattedMinAmount} to {formattedMaxAmount}. Terms and conditions apply. PayPal Pay in 3 is a trading name of PayPal (Europe) S.à r.l. et Cie, S.C.A. 22-24 Boulevard Royal L-2449, Luxembourg.",
"learnMoreLink": [["Learn more about Pay in 3", ["https://www.paypal.com/uk/webapps/mpp/paypal-payin3/faq"]]]
}
}
3 changes: 1 addition & 2 deletions content/modals/US/v2_long_term_xo.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
"Pay Monthly is subject to consumer credit approval. Payments may change based on shipping, taxes, updates to your purchase, or missed payments. Offer availability depends on the merchant and may not be available for subscriptions or recurring payments. Pay Monthly is currently not available to residents of <span aria-hidden='true'>AK, CO, HI, MA, NV, NY, or TX</span><span class='sr-only'>Alaska, Colorado, Hawaii, Massachusetts, Nevada, New York, or Texas</span>. You must be of legal age in your U.S. state of residence. Missed payments may have an impact on your credit score. The lender for Pay Monthly is WebBank. PayPal, Inc. (NMLS #910457): <span aria-hidden='true'>CT</span><span class='sr-only'>Connecticut</span> Small Loan Licensee. <span aria-hidden='true'>RI</span><span class='sr-only'>Rhode Island</span> Loan Broker Licensee. <span aria-hidden='true'>VT</span><span class='sr-only'>Vermont</span> Loan Solicitation Licensee. <span aria-hidden='true'>VT</span><span class='sr-only'>Vermont</span> residents:",
["Find more disclosures ", "https://www.paypal.com/us/digital-wallet/ways-to-pay/buy-now-pay-later"],
"by going to PayPal's page on Pay Later."
],
"linkToProductList": "See other ways to pay over time"
]
}
}
60 changes: 60 additions & 0 deletions content/modals/US/v2_short_term_xo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"meta": {
"product": "PAY_LATER_SHORT_TERM",
"periodicPayment": "{formattedPeriodicPayment}",
"minAmount": "{minAmount}",
"maxAmount": "{maxAmount}",
"qualifying": "{qualifying_offer}",
"amount": "{transaction_amount}",
"apr": "{apr}",
"preapproved": "false",
"variables": {
"transaction_amount": "${eval(transaction_amount ? transaction_amount : '-')}",
"qualifying_offer": "${eval(CREDIT_OFFERS_DS.qualifying_offer ? CREDIT_OFFERS_DS.qualifying_offer : 'false')}",
"financing_code": "${CREDIT_OFFERS_DS.financing_code}",
"formattedPeriodicPayment": "${CREDIT_OFFERS_DS.formattedPeriodicPayment}",
"total_payments": "${CREDIT_OFFERS_DS.total_payments}",
"formattedMinAmount": "${CREDIT_OFFERS_DS.formattedMinAmount}",
"formattedMaxAmount": "${CREDIT_OFFERS_DS.formattedMaxAmount}",
"formattedTotalCost": "${CREDIT_OFFERS_DS.formattedTotalCost}",
"minAmount": "${CREDIT_OFFERS_DS.minAmount}",
"maxAmount": "${CREDIT_OFFERS_DS.maxAmount}",
"apr": "${CREDIT_OFFERS_DS.apr}",
"nominal_rate": "${CREDIT_OFFERS_DS.nominal_rate}"
}
},
"content": {
"headline": "Pay in 4 interest-free payments",
"subheadline": "No impact on credit score and no late fees. Available for purchases of {formattedMinAmount} to {formattedMaxAmount}.",
"qualifyingSubheadline": "Split your purchase of {formattedTotalCost} into {total_payments} with no impact on credit score and no late fees.",
"donutTimestamps": ["Today", "2 weeks", "4 weeks", "6 weeks"],
"instructions": {
"instructionsHeadline": "How to use Pay in 4",
"instructionsSubHeadline": "Confirm your info and apply, set up autopay, and review your purchase."
},
"preapproval": {
"preapprovalHeadline": "You’re pre-approved",
"preapprovalSubHeadline": "Pay {formattedTotalCost} in {total_payments} interest-free payments.",
"preapprovalDisclaimerHeadline": "What to know about pre-approval",
"preapprovalDisclaimerBody": [
"If you no longer meet the criteria used to select you for this offer, or give info we can’t match, pre-approval won’t apply and you may be declined for Pay in 4.",
"This offer starts on {current_date} and ends when you exit checkout, or when the session expires, or if you make another Pay in 4 purchase while this session is active.",
"We didn't use info from a credit bureau to make this offer."
]
},
"cta": {
"buttonTextEligible": "Continue with Pay in 4",
"buttonTextIneligible": "Back to Checkout",
"link": "https://www.paypal.com/link/to/short-term-application"
},
"disclosure": [
"Pay in 4 is available to consumers upon approval for purchases of {formattedMinAmount} to {formattedMaxAmount}. Pay in 4 is currently not available to residents of <span aria-hidden='true'>MO or NV</span><span class='sr-only'>Missouri or Nevada</span>. Offer availability depends on the merchant and also may not be available for certain recurring, subscription services. When applying, a soft credit check may be needed, but will not affect your credit score. You must be 18 years old or older to apply. PayPal, Inc.: Loans to <span aria-hidden='true'>CA</span><span class='sr-only'>California</span> residents are made or arranged pursuant to a <span aria-hidden='true'>CA</span><span class='sr-only'>California</span> Financing Law License. <span aria-hidden='true'>GA</span><span class='sr-only'>Georgia</span> Installment Lender Licensee, NMLS #910457. <span aria-hidden='true'>RI</span><span class='sr-only'>Rhode Island</span> Small Loan Lender Licensee. <span aria-hidden='true'>NM</span><span class='sr-only'>New Mexico</span> residents:",
[
"Find more disclosures ",
"https://www.paypal.com/us/webapps/mpp/campaigns/newmexicodisclosure",
"Find more disclosures, opens new tab"
],
"related to Pay in 4."
]
}
}
8 changes: 7 additions & 1 deletion src/components/modal/v2/parts/BodyContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ const BodyContent = () => {
const productMeta = useProductMeta(viewName);

const { headline, subheadline, qualifyingSubheadline = '', closeButtonLabel } = content;

const isQualifying = productMeta?.qualifying;
const isPreapproved = productMeta?.preapproved;
const preapprovalHeadline = content?.preapproval?.preapprovalHeadline;
const preapprovalSubHeadline = content?.preapproval?.preapprovalSubHeadline;

const openProductList = () => setViewName(VIEW_IDS.PRODUCT_LIST);

Expand Down Expand Up @@ -89,7 +93,6 @@ const BodyContent = () => {
),
[VIEW_IDS.PRODUCT_LIST]: <ProductList content={content} setViewName={setViewName} />
};

// IMPORTANT: These elements cannot be nested inside of other elements.
// They are using very precise CSS position sticky rules that require this
// specific adjacent DOM structure
Expand All @@ -103,6 +106,9 @@ const BodyContent = () => {
qualifyingSubheadline={qualifyingSubheadline}
closeButtonLabel={closeButtonLabel}
viewName={viewName}
preapprovalHeadline={preapprovalHeadline}
preapprovalSubHeadline={preapprovalSubHeadline}
isPreapproved={isPreapproved ?? 'false'}
/>
<div className="content__container">
<main className="main">
Expand Down
22 changes: 17 additions & 5 deletions src/components/modal/v2/parts/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ const Header = ({
isQualifying = 'false',
qualifyingSubheadline,
closeButtonLabel = 'Close',
viewName
viewName,
preapprovalHeadline,
preapprovalSubHeadline,
isPreapproved = 'false'
}) => {
const { country } = useServerData();
const [, handleClose] = useTransitionState();
Expand Down Expand Up @@ -73,19 +76,28 @@ const Header = ({
<h2
// id used for aria-labelleby on modal container element
id="header__headline"
className={`headline-${countryClassName}`}
className={
isPreapproved === 'true'
? `headline-${countryClassName}-preapproved`
: `headline-${countryClassName}`
}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: headline }}
dangerouslySetInnerHTML={{ __html: isPreapproved === 'true' ? preapprovalHeadline : headline }}
/>
{isQualifying === 'true' && qualifyingSubheadline !== '' ? (
<p className={`subheadline_p subheadline-${countryClassName} qualifying`}>
{qualifyingSubheadline.replace(/(\s?EUR)/g, ' €')}
{isPreapproved === 'true'
? preapprovalSubHeadline
: qualifyingSubheadline.replace(/(\s?EUR)/g, ' €')}
</p>
) : (
<p
className={`subheadline_p subheadline-${countryClassName}`}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: currencyFormat(subheadline) ?? '' }}
dangerouslySetInnerHTML={{
__html:
currencyFormat(isPreapproved === 'true' ? preapprovalSubHeadline : subheadline) ?? ''
}}
/>
)}
</div>
Expand Down
39 changes: 27 additions & 12 deletions src/components/modal/v2/parts/Instructions.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @jsx h */
import { h } from 'preact';
import { Fragment, h } from 'preact';
import { currencyFormat } from '../lib';

const Instructions = ({ instructions, expandedState = false, className = '' }) => {
Expand All @@ -13,17 +13,32 @@ const Instructions = ({ instructions, expandedState = false, className = '' }) =

return (
<div className="content__row instructions">
<ol className={(`${expandedState ? '' : 'collapsed'}`, className)}>
{instructions.map((instruction, index) => {
return (
<li className="instructions__item-wrapper">
{renderBullet(index + 1)}
{/* eslint-disable-next-line react/no-danger */}
<div dangerouslySetInnerHTML={{ __html: currencyFormat(instruction) }} />
</li>
);
})}
</ol>
{Array.isArray(instructions) ? (
<ol className={(`${expandedState ? '' : 'collapsed'}`, className)}>
{instructions.map((instruction, index) => {
return (
<li className="instructions__item-wrapper">
{renderBullet(index + 1)}
{/* eslint-disable-next-line react/no-danger */}
<div dangerouslySetInnerHTML={{ __html: currencyFormat(instruction) }} />
</li>
);
})}
</ol>
) : (
<Fragment>
<h2
className="instructions__item-wrapper"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: instructions.instructionsHeadline }}
/>
<p
className="subheadline_p"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: instructions.instructionsSubHeadline }}
/>
</Fragment>
)}
</div>
);
};
Expand Down
37 changes: 37 additions & 0 deletions src/components/modal/v2/parts/PreapprovalDisclaimer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/** @jsx h */
import { h } from 'preact';
import { currencyFormat, formatDateByCountry } from '../lib';

const PreapprovalDisclaimer = ({ preapprovalDisclaimerHeadline, preapprovalDisclaimerBody, country }) => {
return (
<div className="content__row preapproval-disclaimer">
<h2
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: preapprovalDisclaimerHeadline }}
/>
{Array.isArray(preapprovalDisclaimerBody) ? (
<ul>
{preapprovalDisclaimerBody.map(disclaimer => {
const disclaimerByLocale = disclaimer.replace(/{current_date}/, formatDateByCountry(country));
return (
<li className="preapproval-disclaimer__item-wrapper">
{/* eslint-disable-next-line react/no-danger */}
<div dangerouslySetInnerHTML={{ __html: currencyFormat(disclaimerByLocale) }} />
</li>
);
})}
</ul>
) : (
<div>
<p
className="subheadline_p"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: preapprovalDisclaimerBody }}
/>
</div>
)}
</div>
);
};

export default PreapprovalDisclaimer;
Loading

0 comments on commit fa0bca8

Please sign in to comment.