{"version":3,"sources":["webpack:///./app/react/packages/payment/services/recurly.js","webpack:///./app/react/packages/payment/services/recurlySavings.js","webpack:///./app/react/packages/payment/utils/currency.js","webpack:///./app/react/packages/payment/constants/plans.js","webpack:///./app/react/packages/payment/utils/formatCurrencyAmount.js","webpack:///./app/react/packages/payment/constants/creditCardFormInfo.js","webpack:///./app/react/packages/payment/utils/licenses.js","webpack:///./app/react/packages/payment/propShapes/currency.js","webpack:///./app/react/packages/payment/propShapes/discount.js","webpack:///./app/react/packages/payment/components/DefaultPaymentAlert.js","webpack:///./app/react/packages/payment/utils/getPlanTitle.js","webpack:///./app/react/packages/payment/utils/lang.js","webpack:///./app/react/packages/payment/hooks/recurly.js","webpack:///./app/react/packages/payment/utils/getPlanContent.js","webpack:///./app/react/packages/payment/context/Recurly.js","webpack:///./app/react/packages/payment/utils/getPlanPrice.js","webpack:///./app/react/packages/payment/components/forms/CountryField.js","webpack:///./app/react/packages/payment/components/forms/ProvinceField.js","webpack:///./app/react/packages/payment/propShapes/plan.js","webpack:///./app/react/packages/payment/components/forms/CreditCard.js","webpack:///./app/react/packages/payment/constants/addons.js","webpack:///./app/react/packages/payment/components/DiscountAlert.js","webpack:///./app/react/packages/payment/constants/payment.js"],"names":["isValidationError","err","includes","code","fields","planAmount","plan","currency","amountInCents","unit_amount_in_cents","centsToAmount","findPlanAddon","addonCode","add_ons","find","addonAmount","addon","isZeroDecimal","addonForFree","licenses","unlimitedTreshold","unlimited_treshold","Boolean","isDiscountApplicableTo","discount","applies_to_all_plans","plan_codes","plan_code","isDiscountApplicableToPlan","discount_type","DISCOUNT_TYPES","PERCENT","amount","DOLLAR_VALUE","DOLLARS","isDiscountApplicableToCurrency","amountDiscountInCents","discount_amount_in_cents","getDiscountedAmount","teachers","totalValue","discountPercentage","discountedAmount","Math","round","discountValue","Error","planToCurrencies","RECURLY_ABORT_ERROR_CODE","abortError","isAbortError","getPlanGroup","planCode","replace","names","EUR","USD","AUD","CAD","GBP","CZK","DKK","HUF","NOK","NZD","PLN","SGD","SEK","CHF","ZAR","JPY","MXN","ILS","INR","HKD","BRL","TRL","TRY","group1","group2","group3","group4","group5","group6","group7","decimalSeparator","indexOf","thousandSeparator","zeroDecimal","checkZeroDecimal","stateConfig","globalConfig","getInitialState","zero_decimal_currencies","window","zeroDecimalCurrencies","split","map","c","trim","Currency","this","symbol","currenciesSymbols","name","value","addCents","n","thousand","decimal","re","num","toFixed","max","noDecimalRegex","RegExp","formatted","planForCurrencies","LEGACY_PLAN_CODES","PLAN_FOR_ORGANIZATION","PLAN_FOR_SITE","CHANGE_ONLY_ON_RENEWAL_PLANS","TITLES","standard","lite","plus","fiveplan","tenplan","twentyplan","onehundredplan","formatCurrencyAmount","format","initialCreditCardValues","card","number","empty","valid","expiry","cvv","first_name","last_name","country","state","initialCreditCardWithTermsValues","terms","errorMessages","month","year","creditCardSchema","Yup","test","required","when","is","REQUIRE_CREDIT_CARD_STATE_COUNTRIES","then","creditCardTemrsSchema","oneOf","creditCardWithTermsSchema","concat","transformCardFieldAliases","fieldName","isUnlimitedTeachers","treshold","planConfig","UNLIMITED_TEACHERS_THRESHOLD","isUnlimitedStudents","UNLIMITED_STUDENTS_THRESHOLD","formatStudentLicenses","String","currencyPropShape","PropTypes","bool","isRequired","string","discountPropShape","oneOfType","object","discountType","currencies","arrayOf","recurlyDiscount","AlertLink","styled","Link","attrs","color","hover","fontWeight","DefaultPaymentAlert","href","getPlanTitle","type","months","pluralize","word","quantity","suffix","endsWith","substring","length","useCreateCreditCardToken","recurly","useRecurly","useCallback","form","Promise","resolve","reject","token","asyncCreditCardToken","useCreatePayPalToken","description","payPal","useMemo","PayPal","display","displayName","useEffect","destroy","off","on","error","start","useCreateApplePayToken","label","total","applePay","ApplePay","CANADA","ready","begin","getPlanContent","planContent","PAYMENT_PLANS","MONTHLY","SEMI_ANNUALLY","MONTHS","QUARTERLY","YEARLY","RecurlyProvider","children","publicKey","propTypes","node","getPlanPrice","planIntervalInMonths","paymentInterval","PRICING_INTERVAL","paymentTerm","PAYMENT_TERM","amountPerMonth","paymentIntervalMonths","CountryField","stateFieldName","props","useFormikContext","setFieldValue","setFieldTouched","clearState","getOptionText","getOptionValue","onChange","ProvinceField","stateLabel","planPropShape","plan_interval_length","plan_interval_unit","best_value","getPadding","theme","p","Number","isInteger","space","StyledElement","div","inputStyles","border","colors","blue500","basicStyles","fontFamily","fontSize","lineHeight","padding","basicPlaceholder","cardStyles","placeholder","content","CardIndividualElement","as","onBlur","icon","iconRight","formik","style","handleChange","e","repeat","event","target","handleBlur","outerHTML","_container","pt","pl","inputIconWidth","pr","pb","Card","CardElement","displayIcon","defaultProps","elementType","func","ADDONS","ELLII_PLUS","ADDONS_DATA","SELF_STUDY_PRODUCT_TITLE","link","formatDollarDiscount","currencyCode","isMoneyDiscount","DiscountAlert","justifyContent","px","mb","alignItems","bold","join","shape","discountShape","currencyShape","TITLE","SUBTITLE","BILLING_INTERVAL","PAYMENT_INTERVAL","PAYMENT_SUMMARY","PAYMENT_FORMS","CREDIT_CARD","PAY_PAL","APPLE_PAY","PAYMENT_METHODS","id","iconWeight"],"mappings":"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","file":"package-payment.c1d9c94675340946d3b7.chunk.js","sourcesContent":["import R from 'ramda'\n\nimport { DISCOUNT_TYPES } from '../constants/payment'\n\nexport function isValidationError(err) {\n const validationCode = ['validation', 'invalid-parameter'].includes(err.code)\n\n return validationCode && !!err.fields\n}\n\nexport function planAmount(plan, currency) {\n const amountInCents = plan.unit_amount_in_cents[currency.code] || 0\n\n return currency.centsToAmount(amountInCents)\n}\n\nexport function findPlanAddon(plan, addonCode) {\n return plan.add_ons?.find(R.propEq('add_on_code', addonCode))\n}\n\nexport function addonAmount(addon, currency) {\n if (!addon) {\n return 0\n }\n\n const amountInCents = addon.unit_amount_in_cents[currency.code] || 0\n\n return currency.isZeroDecimal ? amountInCents : amountInCents / 100\n}\n\n/**\n * Check if we should give addons for free.\n * This happens when user quote enough licenses to reach \"unlimited\" teachers.\n */\nexport function addonForFree({ plan, licenses }) {\n const { unlimited_treshold: unlimitedTreshold } = plan\n\n return Boolean(unlimitedTreshold) && licenses >= unlimitedTreshold\n}\n\nfunction isDiscountApplicableToPlan({ discount, plan }) {\n return (\n discount.applies_to_all_plans ||\n discount.plan_codes.includes(plan.code ?? plan.plan_code)\n )\n}\n\nfunction isDiscountApplicableToCurrency({ discount, currency }) {\n if (discount.discount_type === DISCOUNT_TYPES.PERCENT) {\n // Percent must be positive\n return Boolean(discount.amount)\n }\n\n if (\n discount.discount_type === DISCOUNT_TYPES.DOLLAR_VALUE ||\n discount.discount_type === DISCOUNT_TYPES.DOLLARS\n ) {\n // Money value must be positive\n return Boolean(discount.amount[currency.code])\n }\n\n // Unknown discount type\n return true\n}\n\nexport function isDiscountApplicableTo({ discount, plan, currency }) {\n return (\n discount &&\n isDiscountApplicableToPlan({ discount, plan }) &&\n isDiscountApplicableToCurrency({ discount, currency })\n )\n}\n\n/**\n * Return discount amount in cents for the given currency\n *\n * Deals with two problems:\n * 1) Discount may not have `discount_amount_in_cents` when user reaches payment/new page without a pre-selected plan.\n * 2) Discount.discount_amount_in_cents is not in cents.\n */\nfunction amountDiscountInCents({ discount, currency }) {\n if (discount.discount_amount_in_cents == null) {\n return discount.amount[currency.code] ?? 0\n }\n\n // FIXME: this property is in cents BUT the value is not\n const amount = discount.discount_amount_in_cents[currency.code]\n return currency.isZeroDecimal ? amount : amount * 100\n}\n\nexport function getDiscountedAmount({\n plan,\n discount,\n currency,\n teachers = 1,\n} = {}) {\n if (!isDiscountApplicableTo({ discount, plan, currency })) {\n return 0\n }\n\n if (discount.discount_type === DISCOUNT_TYPES.PERCENT) {\n const totalValue = plan.unit_amount_in_cents[currency.code] * teachers\n const discountPercentage = 1 - discount.amount / 100\n\n const discountedAmount = Math.round(totalValue * discountPercentage)\n\n return currency.centsToAmount(discountedAmount)\n }\n\n if (\n discount.discount_type === DISCOUNT_TYPES.DOLLAR_VALUE ||\n discount.discount_type === DISCOUNT_TYPES.DOLLARS\n ) {\n const totalValue = plan.unit_amount_in_cents[currency.code] * teachers\n const discountValue = amountDiscountInCents({ discount, currency })\n\n const discountedAmount = R.max(totalValue - discountValue, 0)\n\n return currency.centsToAmount(discountedAmount)\n }\n\n throw new Error('Unexpected discount configuration')\n}\n\n/**\n * Extract available currencies from a recurly plan. Ignore values with amount 0\n *\n * Plans have the following structure:\n *\n * {\n * unit_amount_in_cents: {\n * USD: 1200,\n * CAD: 1150,\n * AUD: 0,\n * }\n * }\n *\n * This means that the prices is 12 USD and 11.50 CAD.\n */\nexport function planToCurrencies(plan) {\n return R.compose(\n R.filter(currency => plan.unit_amount_in_cents[currency] !== 0),\n R.keys,\n R.prop('unit_amount_in_cents')\n )(plan)\n}\n\nconst RECURLY_ABORT_ERROR_CODE = 'recurly:aborte-error'\n\nexport function abortError() {\n const err = new Error('abort')\n err.code = RECURLY_ABORT_ERROR_CODE\n\n return err\n}\n\nexport function isAbortError(err) {\n return err.code === RECURLY_ABORT_ERROR_CODE\n}\n","import Currency from '../utils/currency'\nimport pluralize from '../utils/lang'\nimport { planAmount } from './recurly'\n\n/**\n * A simple way to normalize recurly plan interval and unit into \"month\" or \"year\"\n */\nexport function billInterval(plan) {\n const {\n plan_interval_length: intervalLength,\n plan_interval_unit: intervalUnit,\n } = plan || {}\n\n if (!intervalUnit) {\n return ''\n }\n\n // Convert 12 months into \"year\"\n if (intervalLength === 12 && intervalUnit === 'months') {\n return 'year'\n }\n\n // Convert 3 months into \"quarter\"\n if (intervalLength === 3 && intervalUnit === 'months') {\n return 'quarter'\n }\n\n return pluralize(intervalUnit, 1)\n}\n\nexport const getSavingsInPercentage = ({\n normalPrice = 0,\n discountedPrice = 0,\n} = {}) => {\n const costSavings = normalPrice - discountedPrice\n // const savingsValue = costSavings / normalPrice\n const savingsValue = costSavings / discountedPrice\n\n return savingsValue * 100\n}\n\nexport const calculatePlanSavings = ({\n shortTermPlanPrice = 0,\n yearlyPlanPrice = 0,\n quarterly = false,\n} = {}) => {\n const multiplier = quarterly ? 4 : 12\n const shortTermPricePerYear = shortTermPlanPrice * multiplier\n\n return Math.round(\n getSavingsInPercentage({\n normalPrice: shortTermPricePerYear,\n discountedPrice: yearlyPlanPrice,\n })\n )\n}\n\nexport const getSavingsFromRecurlyPlans = ({\n plans,\n currencyCode,\n quarterly = false,\n}) => {\n const shortTermPlan = plans.find(plan =>\n quarterly\n ? billInterval(plan) === 'quarter'\n : billInterval(plan) === 'month'\n )\n const annualPlan = plans.find(plan => billInterval(plan) === 'year')\n\n if (!shortTermPlan || !annualPlan) {\n return 0\n }\n\n const currency = new Currency(currencyCode)\n\n const shortTermAmount = planAmount(shortTermPlan, currency)\n const annualAmount = planAmount(annualPlan, currency)\n\n return calculatePlanSavings({\n shortTermPlanPrice: shortTermAmount,\n yearlyPlanPrice: annualAmount,\n quarterly,\n })\n}\n\nexport function getPlanGroup(planCode) {\n // strip interval from plan: plus3 -> plus\n return planCode.replace(/\\d+/, '')\n}\n\n/**\n * Given a plan code, return all plans that are logically the same plan but with different billing intervals.\n *\n * Usefull to build the array of plans to call `getSavingsFromRecurlyPlans` with.\n *\n * Example: getPlansForSaving(recurlyPlans, 'plus3') -> [plus1, plus3, plus12]\n *\n * @param {*} plans - Recurly Plans\n * @param {*} planCode - Target planCode\n * @returns Array of recurly plans\n */\nexport function getPlansForSaving(plans, planCode) {\n return plans.filter(p => p.plan_code.includes(getPlanGroup(planCode)))\n}\n\nexport function isQuarterlyPlan(planCode) {\n return planCode.includes('3')\n}\n","/**\n * Currency class deals with currency name and formatting.\n *\n * Inspired on app/assets/javascripts/payments/currency.js.coffee\n */\n\nimport getInitialState from 'Common/utils/getInitialState'\n\nconst names = {\n EUR: 'Euros',\n USD: 'United States Dollars',\n AUD: 'Australian Dollars',\n CAD: 'Canadian Dollars',\n GBP: 'British Pounds',\n CZK: 'Czech Korunas',\n DKK: 'Danish Krones',\n HUF: 'Hungarian Forints',\n NOK: 'Norwegian Krones',\n NZD: 'New Zealand Dollars',\n PLN: 'Polish Złoty',\n SGD: 'Singapore Dollars',\n SEK: 'Swedish Kronas',\n CHF: 'Swiss Francs',\n ZAR: 'South African Rand',\n JPY: 'Japanese Yen',\n MXN: 'Mexican Peso',\n ILS: 'Israeli New Shekel',\n INR: 'Indian Rupee',\n HKD: 'Hong Kong Dollars',\n BRL: 'Brazilian Real',\n TRL: 'Turkish Lira',\n TRY: 'Turkish Lira',\n}\n\n// format groups\nconst group1 = ['AUD'] // x xxx.xx (no comma separator, 2 decimal places)\nconst group2 = ['USD', 'CAD', 'GBP', 'NZD', 'ILS', 'MXN', 'SGD', 'EUR'] // x,xxx.xx (comma separator, 2 decimal places)\nconst group3 = ['BRL', 'CZK', 'DKK', 'NOK'] // x.xxx,xx (dot separator, comma for decimals, 2 decimal places)\nconst group4 = ['PLN', 'SEK'] // x xxx,xx (no comma separator, comma to mark decimals, 2 decimal places)\nconst group5 = ['CHF'] // x'xxx.xx (apostrophe separator, 2 decimal places)\nconst group6 = ['JPY'] // x,xxx (comma separator, NO decimals)\nconst group7 = ['HUF'] // x.xxx (dot separator, NO decimals)\n\nconst decimalSeparator = code => {\n if (\n group1.indexOf(code) >= 0 ||\n group2.indexOf(code) >= 0 ||\n group5.indexOf(code) >= 0\n ) {\n return '.'\n }\n\n if (group3.indexOf(code) >= 0 || group4.indexOf(code) >= 0) {\n return ','\n }\n}\n\nconst thousandSeparator = code => {\n if (group1.indexOf(code) >= 0 || group4.indexOf(code) >= 0) {\n // Use non-breaking space for thousands separator\n return '\\u00A0'\n }\n\n if (group2.indexOf(code) >= 0 || group6.indexOf(code) >= 0) {\n return ','\n }\n\n if (group3.indexOf(code) >= 0 || group7.indexOf(code) >= 0) {\n return '.'\n }\n\n if (group5.indexOf(code) >= 0) {\n return \"'\"\n }\n}\n\nfunction getZeroDecimalConfig() {\n const stateConfig = (getInitialState() || {}).zero_decimal_currencies\n const globalConfig = window.zeroDecimalCurrencies\n\n const config = stateConfig || globalConfig || ''\n\n return config.split(',').map(c => c.trim())\n}\n\nlet zeroDecimal = null\nfunction checkZeroDecimal(code) {\n if (zeroDecimal == null) {\n zeroDecimal = getZeroDecimalConfig()\n }\n\n return zeroDecimal.indexOf(code) >= 0\n}\n\nexport function resetZeroDecimalConfig() {\n zeroDecimal = null\n}\n\nclass Currency {\n constructor(code) {\n this.code = code\n this.symbol = code !== 'CHF' ? (window.currenciesSymbols || {})[code] : 'F'\n this.name = names[code] || code\n this.isZeroDecimal = checkZeroDecimal(code)\n }\n\n format(value, addCents = false) {\n const n = this.isZeroDecimal ? 0 : 2\n const thousand = thousandSeparator(this.code)\n const decimal = decimalSeparator(this.code)\n const re = `\\\\d(?=(\\\\d{3})+${n > 0 ? '\\\\D' : '$'})`\n // eslint-disable-next-line no-bitwise\n const num = value.toFixed(Math.max(0, ~~n))\n const noDecimalRegex = new RegExp(`[${decimal}]00$`)\n\n const formatted = (decimal ? num.replace('.', decimal) : num).replace(\n new RegExp(re, 'g'),\n `$&${thousand || ','}`\n )\n\n return addCents ? formatted : formatted.replace(noDecimalRegex, '')\n }\n\n centsToAmount(amountInCents) {\n return this.isZeroDecimal ? amountInCents : amountInCents / 100\n }\n}\n\nexport default Currency\n","// Plan from which currencies should be extracted to use as currency picker options\nexport const planForCurrencies = 'individualplan12'\n\nexport const LEGACY_PLAN_CODES = [\n 'esl3',\n 'esl6',\n 'esl12',\n 'esl3-b',\n 'esl6-b',\n 'esl12-b',\n 'esl1-c',\n 'esl12-c',\n 'standard1',\n 'standard12',\n]\n\n// Plan used for quote organizations\nexport const PLAN_FOR_ORGANIZATION = 'unlimited-yr-orgs'\n// Plan used for quote sites\nexport const PLAN_FOR_SITE = 'siteplan-volume12'\n\nexport const CHANGE_ONLY_ON_RENEWAL_PLANS = ['plus12', 'onehundredplan12']\n\nexport const TITLES = {\n standard: 'Standard',\n lite: 'Personal Lite',\n plus: 'Personal Plus',\n fiveplan: 'The Lite Plan',\n tenplan: 'The Flex Plan',\n twentyplan: 'The TWENTY Plan',\n onehundredplan: 'The Unlimited Plan',\n}\n","const formatCurrencyAmount = (amount, currency) => {\n return amount ? currency.format(amount) : '-'\n}\n\nexport default formatCurrencyAmount\n","import * as Yup from 'yup'\n\nimport { REQUIRE_CREDIT_CARD_STATE_COUNTRIES } from 'Common/constants/country'\n\nexport const initialCreditCardValues = {\n card: {\n number: { empty: true, valid: false },\n expiry: { empty: true, valid: false },\n cvv: { empty: true, valid: false },\n },\n first_name: '',\n last_name: '',\n country: '',\n state: '',\n}\n\nexport const initialCreditCardWithTermsValues = {\n ...initialCreditCardValues,\n terms: false,\n}\n\nexport const errorMessages = {\n number: 'Please enter a valid card number',\n first_name: \"Please enter the cardholder's first name\",\n last_name: \"Please enter the cardholder's last name\",\n month: 'Please enter a valid date',\n year: 'Please enter a valid date',\n expiry: 'Please enter a valid expiry date',\n cvv: 'Please enter a valid code',\n country: \"Please select the country from the card's billing address\",\n state: \"Please select the province/state from the card's billing address\",\n}\n\nexport const creditCardSchema = Yup.object({\n card: Yup.object()\n .test('valid-number', errorMessages.number, value => {\n return value.number.valid\n })\n .test('valid-expiry', errorMessages.expiry, value => {\n // Only check expiry if number is valid\n return value.expiry.valid || !value.number.valid\n })\n .test('valid-cvv', errorMessages.cvv, value => {\n // Only check cvv if expiry and number are valid\n return value.cvv.valid || !value.expiry.valid || !value.number.valid\n }),\n first_name: Yup.string().required(errorMessages.first_name),\n last_name: Yup.string().required(errorMessages.last_name),\n country: Yup.string().required(errorMessages.country),\n state: Yup.string().when('country', {\n is: code => REQUIRE_CREDIT_CARD_STATE_COUNTRIES.includes(code),\n then: Yup.string().required(errorMessages.state),\n }),\n})\n\nexport const creditCardTemrsSchema = Yup.object({\n terms: Yup.boolean().oneOf(\n [true],\n 'You must agree to the subscription\\xa0terms'\n ),\n})\n\nexport const creditCardWithTermsSchema = creditCardSchema.concat(\n creditCardTemrsSchema\n)\n\n// Definition used to clear another field remote errores when a field changes.\n// When expiry date is invalid, recurly flag month and year field as invalid.\n// This definitio allows us to clear both fields when one of them changes\nexport const cardDependentFields = {\n month: 'year',\n year: 'month',\n}\n\nexport const transformCardFieldAliases = fieldName => {\n return ['year', 'month', 'expiry', 'cvv'].includes(fieldName)\n ? 'card'\n : fieldName\n}\n","export const isUnlimitedTeachers = amount => {\n const treshold = window.planConfig?.UNLIMITED_TEACHERS_THRESHOLD\n\n return treshold && amount && amount >= treshold\n}\n\nexport const isUnlimitedStudents = amount => {\n const treshold = window.planConfig?.UNLIMITED_STUDENTS_THRESHOLD\n\n return treshold && amount && amount >= treshold\n}\n\nexport const formatStudentLicenses = amount => {\n return isUnlimitedStudents(amount) ? 'unlimited' : String(amount)\n}\n\nexport const formatStudentLicensesLimit = amount => {\n return isUnlimitedStudents(amount)\n ? 'unlimited students'\n : `up to ${amount} students`\n}\n","import PropTypes from 'prop-types'\n\nconst currencyPropShape = {\n isZeroDecimal: PropTypes.bool.isRequired,\n code: PropTypes.string.isRequired,\n}\n\nexport default currencyPropShape\n","import PropTypes from 'prop-types'\n\nconst discountPropShape = {\n amount: PropTypes.oneOfType([PropTypes.object, PropTypes.number]).isRequired,\n discountType: PropTypes.string.isRequired,\n currencies: PropTypes.arrayOf(PropTypes.string).isRequired,\n recurlyDiscount: PropTypes.bool,\n}\n\nexport default discountPropShape\n","import { Fragment } from 'react'\nimport styled from 'styled-components'\n\nimport { Link } from '@redriverpress/system'\n\nconst AlertLink = styled(Link).attrs(() => ({\n color: 'red900',\n hover: 'red700',\n fontWeight: 600,\n}))`\n background-image: none;\n text-decoration: underline;\n`\n// ToDo centralize this default messages in a single isolated file\nconst DefaultPaymentAlert = () => {\n return (\n \n We are having difficulty processing your payment. Please try again or{' '}\n contact us for further assistance.\n \n )\n}\n\nexport default DefaultPaymentAlert\n","import { TITLES } from '../constants/plans'\n\nexport default function getPlanTitle(planCode) {\n const type = planCode.replace(/\\d+/g, '')\n\n if (type === 'individual') {\n const months = planCode.replace(type, '')\n return `${months} month term`\n }\n\n return TITLES[type] || 'legacy'\n}\n","/* PLEASE AVOID USING THIS FUNCTION AND HANDLE PLURALIZING INLINE WHERE NEEDED */\n/* This is being kept around for legacy support only. */\n\n// A very dummy way of doing this. Only works with words that end is 's'.\n// Right now we only need to support: month, day, year, teacher\nconst pluralize = (word, quantity) => {\n const suffix = 's'\n\n if (quantity === 1) {\n if (word.endsWith(suffix)) {\n return word.substring(0, word.length - suffix.length)\n }\n\n return word\n }\n // Nothing to do if word is already plural\n if (word.endsWith(suffix)) {\n return word\n }\n\n return `${word}${suffix}`\n}\n\nexport default pluralize\n","import { useCallback, useMemo, useEffect } from 'react'\nimport { useRecurly } from '@recurly/react-recurly'\nimport { CANADA } from 'Common/constants/country'\nimport { abortError } from '../services/recurly'\n\nconst asyncCreditCardToken = (recurly, form) =>\n new Promise((resolve, reject) => {\n recurly.token(form, (err, token) => {\n if (err) {\n return reject(err)\n }\n\n resolve(token)\n })\n })\n\nexport function useCreateCreditCardToken() {\n const recurly = useRecurly()\n\n const createCreditCardToken = useCallback(\n form => {\n return asyncCreditCardToken(recurly, form)\n },\n [recurly]\n )\n\n return createCreditCardToken\n}\n\nexport function useCreatePayPalToken({ description }) {\n const recurly = useRecurly()\n const payPal = useMemo(() => {\n return recurly.PayPal({ display: { displayName: description } })\n }, [description])\n\n // Destroy the PayPal instance when the component unmounts\n useEffect(() => {\n return () => {\n payPal.destroy()\n }\n }, [payPal])\n\n const createPayPalToken = useCallback(() => {\n return new Promise((resolve, reject) => {\n // Discad any previous event listeners\n payPal.off()\n\n payPal.on('token', token => {\n resolve(token)\n })\n\n payPal.on('error', error => {\n reject(error)\n })\n\n payPal.on('cancel', () => {\n reject(abortError())\n })\n\n payPal.start()\n })\n }, [payPal])\n\n return createPayPalToken\n}\n\nexport function useCreateApplePayToken({ label, total, currency }) {\n const recurly = useRecurly()\n\n const createApplePayToken = useCallback(() => {\n return new Promise((resolve, reject) => {\n const applePay = recurly.ApplePay({\n country: CANADA,\n currency,\n label,\n total,\n })\n\n // Discad any previous event listeners\n applePay.off()\n\n applePay.on('token', token => {\n resolve(token)\n })\n\n applePay.on('error', error => {\n reject(error)\n })\n\n applePay.ready(() => {\n applePay.begin()\n })\n })\n }, [recurly, currency, label, total])\n\n return createApplePayToken\n}\n","import { PAYMENT_PLANS } from '../constants/payment'\nimport { PLAN_FOR_ORGANIZATION } from '../constants/plans'\n\nexport default function getPlanContent(planCode) {\n // Warning: This method depends on the order of the conditions to work,\n // have that in mind if you plan on changing it.\n let planContent = PAYMENT_PLANS.MONTHLY\n if (planCode.includes(String(PAYMENT_PLANS.SEMI_ANNUALLY.MONTHS))) {\n planContent = PAYMENT_PLANS.SEMI_ANNUALLY\n }\n if (planCode.includes(String(PAYMENT_PLANS.QUARTERLY.MONTHS))) {\n planContent = PAYMENT_PLANS.QUARTERLY\n }\n if (\n planCode.includes(String(PAYMENT_PLANS.YEARLY.MONTHS)) ||\n planCode === PLAN_FOR_ORGANIZATION\n ) {\n planContent = PAYMENT_PLANS.YEARLY\n }\n return planContent\n}\n","import PropTypes from 'prop-types'\nimport { RecurlyProvider as BaseProvider } from '@recurly/react-recurly'\n\nimport getInitialState from 'Common/utils/getInitialState'\n\nexport function RecurlyProvider({ children }) {\n const { publicKey } = getInitialState().recurly || {}\n\n return {children}\n}\n\nRecurlyProvider.propTypes = {\n children: PropTypes.node.isRequired,\n}\n\nexport default RecurlyProvider\n","import getPlanContent from 'Packages/payment/utils/getPlanContent'\nimport { planAmount } from 'Packages/payment/services/recurly'\n\nexport default function getPlanPrice({ plan, currency, teachers }) {\n const {\n MONTHS: planIntervalInMonths,\n PRICING_INTERVAL: paymentInterval,\n PAYMENT_TERM: paymentTerm,\n } = getPlanContent(plan.plan_code)\n\n const amount = planAmount(plan, currency) * teachers\n const amountPerMonth = Math.round((amount / planIntervalInMonths) * 100) / 100\n\n return {\n currency,\n amount,\n amountPerMonth,\n paymentInterval,\n paymentIntervalMonths: planIntervalInMonths,\n paymentTerm,\n }\n}\n","import { useCallback } from 'react'\nimport { useFormikContext } from 'formik'\nimport { prop } from 'ramda'\n\nimport SelectField from 'Packages/common/components/forms/SelectField'\n\n/**\n * Wrapper around SelectField for Countries.\n *\n * It's required to clear state/province formik field value when country changes.\n * It must be country and not state/province field because we remove state from the DOM when\n * country is different from Canada and United States. It won't listen to all country changes.\n */\nexport default function CountryField({ stateFieldName = 'state', ...props }) {\n const { setFieldValue, setFieldTouched } = useFormikContext()\n\n const clearState = useCallback(() => {\n setFieldValue(stateFieldName, '')\n setFieldTouched(stateFieldName, false)\n }, [stateFieldName])\n\n return (\n \n )\n}\n","import PropTypes from 'prop-types'\nimport { prop } from 'ramda'\n\nimport SelectField from 'Common/components/forms/SelectField'\nimport { stateLabel } from 'Common/services/country'\n\n/**\n * Wrapper around SelectField to share customizations required by province/state SelectField.\n * Let's hide, for exmaple, the fact that we need a key to clear selected value when country changes.\n */\nexport default function ProvinceField({ country, ...props }) {\n return (\n \n )\n}\n\nProvinceField.propTypes = {\n country: PropTypes.string.isRequired,\n}\n","import PropTypes from 'prop-types'\n\nconst planPropShape = {\n plan_code: PropTypes.string.isRequired,\n name: PropTypes.string.isRequired,\n description: PropTypes.string.isRequired,\n plan_interval_length: PropTypes.number.isRequired,\n plan_interval_unit: PropTypes.string.isRequired,\n best_value: PropTypes.bool,\n}\n\nexport default planPropShape\n","import { useCallback, useMemo } from 'react'\nimport PropTypes from 'prop-types'\nimport styled from 'styled-components'\nimport { border } from 'styled-system'\nimport { useFormikContext } from 'formik'\nimport {\n CardElement,\n CardNumberElement,\n CardMonthElement,\n CardYearElement,\n CardCvvElement,\n} from '@recurly/react-recurly'\nimport {\n InputWrapper,\n inputIconWidth,\n inputStyles,\n} from '@redriverpress/system'\n\nconst getPadding = name => props => {\n const { theme } = props\n const p = props[name]\n\n return Number.isInteger(p) ? theme.space[p] : p\n}\n\nconst StyledElement = styled.div`\n .recurly-element {\n ${inputStyles}\n ${border}\n\n height: calc(1.4em + ${getPadding('pt')} + ${getPadding('pb')});\n\n &.recurly-element-card {\n padding-left: calc(${getPadding('pl')} - 12px);\n padding-right: calc(${getPadding('pr')} - 8px);\n }\n\n &.recurly-element-focus {\n box-shadow: 0 0 0 2px ${props => props.theme.colors.blue500};\n outline: none;\n }\n }\n`\n\nconst basicStyles = {\n fontFamily:\n \"'Open Sans', BlinkMacSystemFont, -apple-system, Roboto, 'Segoe UI', sans-serif\",\n // Input fontSize is 1rem (theme.fontSize[1]). Body has 112.5%. Hardcode 112.5% because Elements\n // renders inside an iframe (use 1rem is not an option).\n fontSize: '112.5%',\n lineHeight: '1.4',\n padding: 0,\n}\n\nconst basicPlaceholder = {\n color: 'rgba(35, 31, 32, 0.5)',\n}\n\nconst cardStyles = {\n ...basicStyles,\n placeholder: {\n ...basicPlaceholder,\n content: { number: '0000 0000 0000 0000' },\n },\n}\n\n/**\n * Bridge between formik Field and recurly Elements.\n * is a component that can be used as formik Field component prop\n *\n * CardIndividualElement is responsible of apply styles to the Element. Also implements onChange and onBlur callbacks\n * in a way that formik is able to validate field presence (required).\n */\nfunction CardIndividualElement({\n as,\n onChange,\n onBlur,\n placeholder,\n icon,\n error,\n iconRight,\n label,\n ...props\n}) {\n const formik = useFormikContext()\n const { name } = props\n\n const style = useMemo(\n () => ({\n ...basicStyles,\n placeholder: {\n ...basicPlaceholder,\n content: placeholder,\n },\n }),\n [placeholder]\n )\n\n const handleChange = useCallback(\n e => {\n // Just a way to check \"required\" but make sure we return a different value when user add/removes a character\n const char = e.valid ? '*' : '?'\n const value = char.repeat(e.length)\n\n const event = { target: { name, value } }\n\n // Let formik know that the field changed\n formik.handleChange(event)\n // Now call onChange prop only if it's a user provided callback (formik injects onChange by default)\n if (onChange !== formik.handleChange) {\n onChange(event)\n }\n },\n [name, onChange, formik.handleChange]\n )\n\n const handleBlur = useCallback(\n e => {\n const event = { target: { name, outerHTML: e._container?.outerHTML } }\n\n // Let formik know that the field blur\n formik.handleBlur(event)\n // Now call onBlur prop only if it's a user provided callback (formik injects onBlur by default)\n if (onBlur !== formik.handleBlur) {\n onBlur(event)\n }\n },\n [name, onBlur, formik.handleBlur]\n )\n\n return (\n \n \n \n )\n}\n\nCardIndividualElement.defaultProps = {\n error: false,\n icon: null,\n label: null,\n iconRight: null,\n placeholder: null,\n}\n\nCardIndividualElement.propTypes = {\n as: PropTypes.elementType.isRequired,\n name: PropTypes.string.isRequired,\n label: PropTypes.string,\n placeholder: PropTypes.string,\n error: PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.bool,\n PropTypes.node,\n ]),\n icon: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),\n iconRight: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),\n onChange: PropTypes.func.isRequired,\n onBlur: PropTypes.func.isRequired,\n}\n\nexport function CardMonth(props) {\n return \n}\n\nexport function CardYear(props) {\n return \n}\n\nexport function CardCvv(props) {\n return \n}\n\nexport function CardNumber(props) {\n return \n}\n\nexport function Card({ icon, label, error, onChange, onBlur, ...props }) {\n const formik = useFormikContext()\n const { name } = props\n\n const handleChange = useCallback(\n e => {\n const event = { target: { name, value: e } }\n\n // Let formik know that the field changed\n formik.handleChange(event)\n // Now call onChange prop only if it's a user provided callback (formik injects onChange by default)\n if (onChange !== formik.handleChange) {\n onChange(event)\n }\n },\n [name, onChange, formik.handleChange]\n )\n\n const handleBlur = useCallback(() => {\n const event = { target: { name } }\n\n // Let formik know that the field blur\n formik.handleBlur(event)\n // Now call onBlur prop only if it's a user provided callback (formik injects onBlur by default)\n if (onBlur !== formik.handleBlur) {\n onBlur(event)\n }\n }, [name, onBlur, formik.handleBlur])\n\n return (\n \n \n \n )\n}\n\nCard.defaultProps = {\n error: false,\n icon: null,\n label: null,\n placeholder: null,\n}\n\nCard.propTypes = {\n name: PropTypes.string.isRequired,\n label: PropTypes.string,\n placeholder: PropTypes.string,\n error: PropTypes.oneOfType([\n PropTypes.string,\n PropTypes.bool,\n PropTypes.node,\n ]),\n icon: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),\n onChange: PropTypes.func.isRequired,\n onBlur: PropTypes.func.isRequired,\n}\n","import { SELF_STUDY_PRODUCT_TITLE } from 'Common/constants/brand'\n\nexport const ADDONS = {\n ELLII_PLUS: 'englishapp-for-schools',\n}\n\nexport const ADDONS_DATA = {\n [ADDONS.ELLII_PLUS]: {\n name: `${SELF_STUDY_PRODUCT_TITLE} Access`,\n description: `${SELF_STUDY_PRODUCT_TITLE} is a self-study library that lets your students study on their own without a teacher. It\\u0027s ideal for schools with computer lab programs or pre-enrollment\\u00A0courses.`,\n link: 'https://ellii.com/solo',\n },\n}\n","import { Box, Text, BR } from '@redriverpress/system'\nimport PropTypes from 'prop-types'\n\nimport Alert from 'Common/components/alert/Alert'\nimport { DISCOUNT_TYPES } from 'Packages/payment/constants/payment'\nimport { currencyShape, discountShape } from '../propShapes'\n\nconst formatDollarDiscount = (amount, currency, recurlyDiscount) => {\n const suffix = recurlyDiscount ? ` ${currency.code}` : ''\n const currencyCode = recurlyDiscount ? currency.code : 'USD'\n\n let value\n if (Number.isInteger(amount)) {\n value = amount\n } else {\n value = currency.centsToAmount(amount[currencyCode])\n }\n\n return `$${value}${suffix}`\n}\n\nfunction isMoneyDiscount(discountType) {\n return (\n discountType === DISCOUNT_TYPES.DOLLAR_VALUE ||\n discountType === DISCOUNT_TYPES.DOLLARS\n )\n}\n\nexport default function DiscountAlert({ discount, currency }) {\n const { amount, discountType, currencies, recurlyDiscount } = discount\n\n return (\n \n \n \n {discountType === DISCOUNT_TYPES.PERCENT\n ? `${amount}%`\n : formatDollarDiscount(amount, currency, recurlyDiscount)}\n {' '}\n discount will be automatically applied during checkout.\n {isMoneyDiscount(discountType) && !recurlyDiscount && (\n \n
\n Your discount will be applied only under{' '}\n \n {currencies.join(' and ')}\n {' '}\n currencies.\n
\n )}\n
\n \n )\n}\n\nDiscountAlert.propTypes = {\n discount: PropTypes.shape(discountShape).isRequired,\n currency: PropTypes.shape(currencyShape).isRequired,\n}\n","export const DISCOUNT_TYPES = {\n PERCENT: 'percent',\n DOLLAR_VALUE: 'dollar_value',\n DOLLARS: 'dollars',\n}\n\nexport const PAYMENT_PLANS = {\n MONTHLY: {\n TITLE: 'Monthly Plan',\n SUBTITLE: 'pay monthly',\n PAYMENT_TERM: 'monthly',\n BILLING_INTERVAL: '',\n PAYMENT_INTERVAL: 'per month',\n PAYMENT_SUMMARY: 'for 1 month',\n PRICING_INTERVAL: '/ mo',\n MONTHS: 1,\n },\n QUARTERLY: {\n TITLE: 'Quarterly Plan',\n SUBTITLE: 'pay quarterly',\n PAYMENT_TERM: 'quarterly',\n BILLING_INTERVAL: 'billed every 3 months at',\n PAYMENT_INTERVAL: 'every 3 months',\n PAYMENT_SUMMARY: 'for 3 months',\n PRICING_INTERVAL: '/ 3 mo',\n MONTHS: 3,\n },\n SEMI_ANNUALLY: {\n TITLE: 'Bi-annually Plan',\n SUBTITLE: 'pay semi\\u2011annually',\n PAYMENT_TERM: 'bi\\u2011annually',\n BILLING_INTERVAL: 'billed every 6 months at',\n PAYMENT_INTERVAL: 'every 6 months',\n PAYMENT_SUMMARY: 'for 6 months',\n PRICING_INTERVAL: '/ 6 mo',\n MONTHS: 6,\n },\n YEARLY: {\n TITLE: 'Annual Plan',\n SUBTITLE: 'pay for the full year',\n PAYMENT_TERM: 'annually',\n BILLING_INTERVAL: 'billed yearly at',\n PAYMENT_INTERVAL: 'per year',\n PAYMENT_SUMMARY: 'for 1 year',\n PRICING_INTERVAL: '/ yr',\n MONTHS: 12,\n },\n}\n\nexport const PAYMENT_FORMS = {\n CREDIT_CARD: 'creditCard',\n PAY_PAL: 'payPal',\n APPLE_PAY: 'applePay',\n}\n\nexport const PAYMENT_METHODS = [\n {\n id: PAYMENT_FORMS.CREDIT_CARD,\n name: 'Visa / Mastercard / Amex',\n icon: 'credit-card',\n },\n {\n id: PAYMENT_FORMS.PAY_PAL,\n name: 'PayPal',\n icon: 'paypal',\n iconWeight: 'brands',\n },\n {\n id: PAYMENT_FORMS.APPLE_PAY,\n name: 'Apple Pay',\n icon: 'apple',\n iconWeight: 'brands',\n },\n]\n"],"sourceRoot":""}