Skip to content

Commit

Permalink
Merge pull request #2430 from jcamposmk/DAT-1633-plan-selection-screen
Browse files Browse the repository at this point in the history
Dat 1633 plan selection screen
  • Loading branch information
jcamposmk authored Jan 23, 2024
2 parents b2a5ca7 + 2a4bf2c commit 88d22fd
Show file tree
Hide file tree
Showing 52 changed files with 2,784 additions and 294 deletions.
10 changes: 5 additions & 5 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"arrowParens": "always"
}
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"arrowParens": "always"
}
6 changes: 3 additions & 3 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import queryString from 'query-string';
import React, { useEffect, useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { Helmet } from 'react-helmet';
import { Navigate, Route, Routes, useLocation } from 'react-router-dom';
import './App.scss';
Expand All @@ -15,7 +15,6 @@ import InvoicesList from './components/InvoicesList/InvoicesList';
import NewFeatures from './components/NewFeatures/NewFeatures';
import Checkout from './components/Plans/Checkout/Checkout';
import { CheckoutSummary } from './components/Plans/Checkout/CheckoutSummary/CheckoutSummary';
import { GoToUpgrade } from './components/Plans/PlanCalculator/GoToUpgrade';
import PrivateRoute from './components/PrivateRoute';
import PublicRouteWithLegacyFallback from './components/PublicRouteWithLegacyFallback';
import RedirectWithQuery from './components/RedirectWithQuery';
Expand All @@ -36,6 +35,7 @@ import UpdatePaymentInformationSummary from './components/Plans/UpdatePaymentInf
import IntegrationsSection from './components/Integrations/index';
import smoothscroll from 'smoothscroll-polyfill';
import { PlanTypes } from './components/BuyProcess/PlanTypes';
import { PlanSelection } from './components/BuyProcess/PlanSelection';

// https://www.npmjs.com/package/smoothscroll-polyfill
smoothscroll.polyfill();
Expand Down Expand Up @@ -198,7 +198,7 @@ const App = ({ locale, window, dependencies: { appSessionRef, sessionManager } }
path="/plan-selection/premium/:planType"
element={
<PrivateRoute>
<GoToUpgrade />
<PlanSelection />
</PrivateRoute>
}
/>
Expand Down
20 changes: 11 additions & 9 deletions src/components/BuyProcess/NavigationTabs/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import { FormattedMessage, useIntl } from 'react-intl';
import { Link } from 'react-router-dom';
import { URL_PLAN_TYPE } from '../../../doppler-types';
import { PLAN_TYPE, URL_PLAN_TYPE } from '../../../doppler-types';
import { FieldGroup, FieldItemAccessible } from '../../form-helpers/form-helpers';
import { RadioBox, RadioInfo } from '../RadioBox';

Expand All @@ -12,32 +12,34 @@ export const NavigationTabs = ({ planTypes, selectedPlanType, searchQueryParams
const _ = (id, values) => intl.formatMessage({ id: id }, values);

const getTypePlanDescriptionWithTooltip = (planType) =>
_(`plan_calculator.plan_type_${planType.replace('-', '_')}`);
_(`buy_process.plan_selection.plan_type_${planType.replace('-', '_')}_label`);

return (
<nav>
<FieldGroup aria-label="navigator tabs">
{planTypes.map((planType) => (
<FieldItemAccessible
data-testid="tab-item--plan-calculator"
className="col-md-4 m-b-12"
className="col-md-4 m-b-12 p-l-0"
key={planType.type}
deleteFloat={true}
>
<Link
to={`/buy-process/primer-pantalla/${
URL_PLAN_TYPE[planType.type]
}${searchQueryParams}`}
to={`/plan-selection/premium/${URL_PLAN_TYPE[planType.type]}${searchQueryParams}`}
>
<RadioBox
value={planType.type}
label={getTypePlanDescriptionWithTooltip(planType.type)}
checked={planType.type === selectedPlanType}
disabled={planType.disabled}
footer={
<RadioFooter
text={
<FormattedMessage
id={`buy_process.min_monthly_plan_price`}
id={
planType.type === PLAN_TYPE.byCredit
? `buy_process.min_single_plan_price`
: `buy_process.min_monthly_plan_price`
}
values={{
P: (chunk) => <p>{chunk}</p>,
Strong: (chunk) => <strong>{chunk}</strong>,
Expand All @@ -47,7 +49,7 @@ export const NavigationTabs = ({ planTypes, selectedPlanType, searchQueryParams
}
/>
}
info={<RadioInfo info={planType.info} />}
info={<RadioInfo info={_(planType.info)} />}
handleClick={null}
/>
</Link>
Expand Down
24 changes: 17 additions & 7 deletions src/components/BuyProcess/NavigationTabs/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,21 @@ import { PLAN_TYPE, URL_PLAN_TYPE } from '../../../doppler-types';
import { MemoryRouter as Router } from 'react-router-dom';

const planTypes = [
{ type: PLAN_TYPE.byContact, minPrice: 8 },
{ type: PLAN_TYPE.byEmail, minPrice: 134 },
{ type: PLAN_TYPE.byCredit, minPrice: 23 },
{
type: PLAN_TYPE.byContact,
minPrice: 8,
info: 'buy_process.plan_selection.plan_type_subscribers_info',
},
{
type: PLAN_TYPE.byEmail,
minPrice: 134,
info: 'buy_process.plan_selection.plan_type_monthly_deliveries_info',
},
{
type: PLAN_TYPE.byCredit,
minPrice: 23,
info: 'buy_process.plan_selection.plan_type_prepaid_info',
},
];
const searchQueryParams = '?promo-code=FAKE_VALUE';

Expand All @@ -22,9 +34,7 @@ describe('NavigationTabs component', () => {
<IntlProvider>
<Router
initialEntries={[
`/buy-process/primer-pantalla/${
URL_PLAN_TYPE[PLAN_TYPE.byContact]
}${searchQueryParams}`,
`/plan-selection/premium/${URL_PLAN_TYPE[PLAN_TYPE.byContact]}${searchQueryParams}`,
]}
>
<NavigationTabs
Expand All @@ -45,7 +55,7 @@ describe('NavigationTabs component', () => {
links.forEach((link, index) => {
expect(link).toHaveAttribute(
'href',
`/buy-process/primer-pantalla/${URL_PLAN_TYPE[planTypes[index].type]}${searchQueryParams}`,
`/plan-selection/premium/${URL_PLAN_TYPE[planTypes[index].type]}${searchQueryParams}`,
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,23 @@ import { FormattedMessageMarkdown } from '../../../../i18n/FormattedMessageMarkd

export const SubscriptionType = ({ period, discountPercentage }) => {
return (
<div className="dp-align--center p-t-30">
<div className="p-b-6">
<FormattedMessageMarkdown id="plan_calculator.current_subscription" values={{ period }} />
<section className="dp-align--center p-t-30">
<div className="dp-wrap-message dp-wrap-info">
<span class="dp-message-icon" />
<div class="dp-content-message">
<div className="p-b-6">
<FormattedMessageMarkdown
id="plan_calculator.current_subscription"
values={{ period }}
/>
</div>
<FormattedMessageMarkdown
id="plan_calculator.subscription_discount"
values={{ discountPercentage }}
/>
</div>
</div>
<FormattedMessageMarkdown
id="plan_calculator.subscription_discount"
values={{ discountPercentage }}
/>
</div>
</section>
);
};

Expand Down
6 changes: 3 additions & 3 deletions src/components/BuyProcess/PaymentFrequency/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const PaymentFrequency = ({
const query = useQueryParams();
const paymentFrequencyDefault = query.get('monthPlan');
const isMonthlySubscription = currentSubscriptionUser === 1;

const lang = intl.locale;
const [
{ paymentFrequencies, selectedPaymentFrequency, selectedPaymentFrequencyIndex },
dispatch,
Expand Down Expand Up @@ -75,8 +75,8 @@ export const PaymentFrequency = ({
if (paymentFrequencies.length > 0) {
return (
<section>
<h4>Frecuencia de pago</h4>
<nav className="dp-payment-frequency">
<h4>{_('buy_process.payment_frequency')}</h4>
<nav className={`dp-payment-frequency${lang === 'en' ? '-en' : ''}`}>
{paymentFrequencies.map((discount, index) => (
<button
key={`discount-${index}`}
Expand Down
96 changes: 96 additions & 0 deletions src/components/BuyProcess/PlanSelection/BannerUpgrade/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import { PLAN_TYPE, URL_PLAN_TYPE } from '../../../../doppler-types';

export const BannerUpgrade = ({ currentPlan, currentPlanList, planTypes, hightestPlan }) => {
const currentPlanSelected = currentPlan?.id === currentPlanList[currentPlanList.length - 1]?.id;

if (currentPlanSelected && currentPlan) {
const upgradeInfo = getUpgradeInfo(currentPlan?.type, planTypes);

if (hightestPlan) {
return (
<div
className="dp-message-upgrade-plan m-t-24 m-b-24"
data-testid="dp-message-upgrade-plan"
>
<p>
<FormattedMessage
id={upgradeInfo.suggestion.messageId}
values={{
Link: (chunk) => <Link to={upgradeInfo.suggestion.link}>{chunk}</Link>,
Bold: (chunk) => <strong>{chunk}</strong>,
}}
/>
</p>
</div>
);
}

return (
<div className="dp-calc-message" data-testid="dp-calc-message">
<p>
<FormattedMessage
id={upgradeInfo.banner.messageId}
values={{
Link: (chunk) => <Link to={upgradeInfo.banner.link}>{chunk}</Link>,
}}
/>
</p>
</div>
);
}

return null;
};

export const getUpgradeInfo = (type, planTypes) => {
const bannerInfo = {
messageId: `plan_calculator.banner_for_${type.replace('-', '_')}`,
link: `/plan-selection/premium/${URL_PLAN_TYPE[PLAN_TYPE.byEmail]}${window.location.search}`,
};
const suggestionInfo = {
messageId: `plan_calculator.suggestion_for_${type.replace('-', '_')}`,
link: `/upgrade-suggestion-form`,
};

switch (type) {
case PLAN_TYPE.byCredit:
case PLAN_TYPE.byContact:
if (planTypes?.includes(PLAN_TYPE.byEmail)) {
return { banner: bannerInfo, suggestion: suggestionInfo };
} else {
const subscriberMonthlyPlan = {
...suggestionInfo,
messageId: 'plan_calculator.advice_for_subscribers_large_plan',
};
return {
banner: subscriberMonthlyPlan,
suggestion: subscriberMonthlyPlan,
};
}

case PLAN_TYPE.byEmail:
return {
banner: {
...bannerInfo,
link: `/upgrade-suggestion-form`,
},
suggestion: {
...suggestionInfo,
link: `/plan-selection/premium/${URL_PLAN_TYPE[PLAN_TYPE.byEmail]}`,
},
};
default:
return {
banner: {
...bannerInfo,
messageId: `plan_calculator.banner_for_unknown`,
},
suggestion: {
...suggestionInfo,
messageId: `plan_calculator.suggestion_for_unknown`,
},
};
}
};
16 changes: 16 additions & 0 deletions src/components/BuyProcess/PlanSelection/GoBackButton/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useIntl } from 'react-intl';

export const GoBackButton = () => {
const intl = useIntl();
const _ = (id, values) => intl.formatMessage({ id: id }, values);

return (
<button
type="button"
className="dp-button button-medium ctaTertiary"
onClick={() => window.history.back()}
>
{_('plan_calculator.button_back')}
</button>
);
};
21 changes: 21 additions & 0 deletions src/components/BuyProcess/PlanSelection/SubscriptionType/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import PropTypes from 'prop-types';
import { FormattedMessageMarkdown } from '../../../../i18n/FormattedMessageMarkdown';

export const SubscriptionType = ({ period, discountPercentage }) => {
return (
<div className="dp-align--center p-t-30">
<div className="p-b-6">
<FormattedMessageMarkdown id="plan_calculator.current_subscription" values={{ period }} />
</div>
<FormattedMessageMarkdown
id="plan_calculator.subscription_discount"
values={{ discountPercentage }}
/>
</div>
);
};

SubscriptionType.propTypes = {
period: PropTypes.oneOf([1, 3, 6, 12]),
discountPercentage: PropTypes.number,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import '@testing-library/jest-dom/extend-expect';
import { render, screen } from '@testing-library/react';
import { SubscriptionType } from '.';
import IntlProvider from '../../../../i18n/DopplerIntlProvider.double-with-ids-as-values';

describe('SuscriptionType', () => {
it(`should render SuscriptionType`, async () => {
// Act
render(
<IntlProvider>
<SubscriptionType period={3} discountPercentage={5} />
</IntlProvider>,
);

// Assert
screen.getByText('plan_calculator.current_subscription');
screen.getByText('plan_calculator.subscription_discount');
});
});
Loading

0 comments on commit 88d22fd

Please sign in to comment.