@financial-times/n-conversion-forms 32.2.0 → 32.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.toolkitrc.yml +1 -3
- package/.toolkitstate/ci.json +2 -2
- package/components/__snapshots__/package-change.spec.js.snap +15 -0
- package/components/accept-terms-subscription.jsx +100 -0
- package/components/accept-terms-subscription.spec.js +22 -0
- package/components/accept-terms-subscription.stories.js +8 -0
- package/components/index.js +1 -0
- package/components/package-change.jsx +13 -9
- package/components/package-change.spec.js +17 -0
- package/components/package-change.stories.js +8 -0
- package/components/payment-term.jsx +62 -18
- package/components/payment-term.spec.js +73 -0
- package/components/payment-term.stories.js +39 -0
- package/components/seven-day-pass-experiment-confirmation.jsx +110 -0
- package/components/seven-day-pass-experiment-confirmation.stories.js +33 -0
- package/dist/accept-terms-subscription.jsx +52 -0
- package/dist/index.js +7 -0
- package/dist/package-change.jsx +5 -3
- package/dist/payment-term.jsx +45 -12
- package/dist/seven-day-pass-experiment-confirmation.jsx +93 -0
- package/package.json +3 -2
package/.toolkitrc.yml
CHANGED
|
@@ -5,11 +5,9 @@ plugins:
|
|
|
5
5
|
- "@dotcom-tool-kit/eslint"
|
|
6
6
|
- "@dotcom-tool-kit/prettier"
|
|
7
7
|
- "@dotcom-tool-kit/lint-staged"
|
|
8
|
+
- "@dotcom-tool-kit/husky-npm"
|
|
8
9
|
- './toolkit/run-storybook'
|
|
9
10
|
hooks:
|
|
10
|
-
git:precommit:
|
|
11
|
-
- SecretSquirrel
|
|
12
|
-
- LintStaged
|
|
13
11
|
test:local:
|
|
14
12
|
- Eslint
|
|
15
13
|
- JestLocal
|
package/.toolkitstate/ci.json
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
+
exports[`PackageChange annual render when is7DayPassExperiment is true 1`] = `
|
|
4
|
+
<div class="ncf__package-change">
|
|
5
|
+
<div class="ncf__package-change__package">
|
|
6
|
+
<div class="ncf__package-change__content">
|
|
7
|
+
<p>
|
|
8
|
+
You have chosen
|
|
9
|
+
<span class="ncf__strong">
|
|
10
|
+
Trial
|
|
11
|
+
</span>
|
|
12
|
+
</p>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
`;
|
|
17
|
+
|
|
3
18
|
exports[`PackageChange annual render with defaults 1`] = `
|
|
4
19
|
<div class="ncf__package-change">
|
|
5
20
|
<div class="ncf__package-change__package">
|
|
@@ -9,6 +9,8 @@ export function AcceptTermsSubscription({
|
|
|
9
9
|
isTrial = false,
|
|
10
10
|
isPrintProduct = false,
|
|
11
11
|
isSingleTerm = false,
|
|
12
|
+
is7DayPassExperiment = false,
|
|
13
|
+
isTermedSubscriptionTermType = false,
|
|
12
14
|
isTransition = false,
|
|
13
15
|
transitionType = null,
|
|
14
16
|
isDeferredBilling = false,
|
|
@@ -37,6 +39,102 @@ export function AcceptTermsSubscription({
|
|
|
37
39
|
required: true,
|
|
38
40
|
};
|
|
39
41
|
|
|
42
|
+
if (is7DayPassExperiment) {
|
|
43
|
+
return (
|
|
44
|
+
<div {...divProps}>
|
|
45
|
+
<ul className="o-typography-list ncf__accept-terms-list">
|
|
46
|
+
<li>
|
|
47
|
+
<span className="terms-transition terms-transition--immediate">
|
|
48
|
+
I give consent for my chosen payment method to be charged
|
|
49
|
+
automatically.
|
|
50
|
+
</span>
|
|
51
|
+
</li>
|
|
52
|
+
<li>
|
|
53
|
+
<span className="terms-transition terms-transition--immediate">
|
|
54
|
+
By placing your order subject to the Terms & Conditions (save for
|
|
55
|
+
section 2) referred to below, you agree that we may start your
|
|
56
|
+
7-day pass immediately upon our acceptance of your order and that
|
|
57
|
+
you are waiving your statutory right to cancel our contract within
|
|
58
|
+
14 days of confirmation. Your payment is a one-time payment
|
|
59
|
+
collected at the time of checkout, and cancelling at any point
|
|
60
|
+
(whether before or after the 14-day period) will not entitle you
|
|
61
|
+
to a refund.
|
|
62
|
+
</span>
|
|
63
|
+
</li>
|
|
64
|
+
<li>
|
|
65
|
+
<span className="terms-transition">
|
|
66
|
+
Please see here for the complete{' '}
|
|
67
|
+
<a
|
|
68
|
+
className="ncf__link--external"
|
|
69
|
+
href="http://help.ft.com/help/legal-privacy/terms-conditions/"
|
|
70
|
+
target="_blank"
|
|
71
|
+
rel="noopener noreferrer"
|
|
72
|
+
>
|
|
73
|
+
Terms & Conditions
|
|
74
|
+
</a>
|
|
75
|
+
.
|
|
76
|
+
</span>
|
|
77
|
+
</li>
|
|
78
|
+
</ul>
|
|
79
|
+
<label className={labelClassName} htmlFor="termsAcceptance">
|
|
80
|
+
<input {...inputProps} />
|
|
81
|
+
<span className="o-forms-input__label">
|
|
82
|
+
I agree to the above terms & conditions.
|
|
83
|
+
</span>
|
|
84
|
+
<p className="o-forms-input__error">
|
|
85
|
+
Please accept our terms & conditions
|
|
86
|
+
</p>
|
|
87
|
+
</label>
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (isTermedSubscriptionTermType) {
|
|
93
|
+
return (
|
|
94
|
+
<div {...divProps}>
|
|
95
|
+
<ul className="o-typography-list ncf__accept-terms-list">
|
|
96
|
+
<li>
|
|
97
|
+
<span className="terms-transition terms-transition--immediate">
|
|
98
|
+
I give consent for the chosen payment method to be charged automatically.
|
|
99
|
+
</span>
|
|
100
|
+
</li>
|
|
101
|
+
<li>
|
|
102
|
+
<span className="terms-transition terms-transition--immediate">
|
|
103
|
+
By placing your order subject to the Terms & Conditions (save for section 2) referred to
|
|
104
|
+
below, you are waiving your statutory right to cancel our contract within 14 days of
|
|
105
|
+
payment. Your payment is a one-time payment collected at the time of checkout, and
|
|
106
|
+
unsubscribing or cancelling at any point (whether before or after the 14-day period)
|
|
107
|
+
will not entitle you to a refund.
|
|
108
|
+
</span>
|
|
109
|
+
</li>
|
|
110
|
+
<li>
|
|
111
|
+
<span className="terms-transition">
|
|
112
|
+
Please see here for the complete{' '}
|
|
113
|
+
<a
|
|
114
|
+
className="ncf__link--external"
|
|
115
|
+
href="http://help.ft.com/help/legal-privacy/terms-conditions/"
|
|
116
|
+
target="_blank"
|
|
117
|
+
rel="noopener noreferrer"
|
|
118
|
+
>
|
|
119
|
+
Terms & Conditions
|
|
120
|
+
</a>
|
|
121
|
+
.
|
|
122
|
+
</span>
|
|
123
|
+
</li>
|
|
124
|
+
</ul>
|
|
125
|
+
<label className={labelClassName} htmlFor="termsAcceptance">
|
|
126
|
+
<input {...inputProps} />
|
|
127
|
+
<span className="o-forms-input__label">
|
|
128
|
+
I agree to the above terms & conditions.
|
|
129
|
+
</span>
|
|
130
|
+
<p className="o-forms-input__error">
|
|
131
|
+
Please accept our terms & conditions
|
|
132
|
+
</p>
|
|
133
|
+
</label>
|
|
134
|
+
</div>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
40
138
|
const transitionTerms = isTransition && (
|
|
41
139
|
<>
|
|
42
140
|
{!isSingleTerm && (
|
|
@@ -209,6 +307,8 @@ AcceptTermsSubscription.propTypes = {
|
|
|
209
307
|
isTrial: PropTypes.bool,
|
|
210
308
|
isPrintProduct: PropTypes.bool,
|
|
211
309
|
isSingleTerm: PropTypes.bool,
|
|
310
|
+
is7DayPassExperiment: PropTypes.bool,
|
|
311
|
+
isTermedSubscriptionTermType: PropTypes.bool,
|
|
212
312
|
isTransition: PropTypes.bool,
|
|
213
313
|
transitionType: PropTypes.string,
|
|
214
314
|
isDeferredBilling: PropTypes.bool,
|
|
@@ -70,6 +70,28 @@ describe('AcceptTermsSubscription', () => {
|
|
|
70
70
|
expect(transitionTerms.exists()).toBe(true);
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
+
it('renders the transition terms when isTermedSubscriptionTermType prop is true', () => {
|
|
74
|
+
const props = {
|
|
75
|
+
isTermedSubscriptionTermType: true,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const component = mount(<AcceptTermsSubscription {...props} />);
|
|
79
|
+
|
|
80
|
+
const transitionTerms1 = component.find('.terms-transition').at(0);
|
|
81
|
+
const transitionTerms2 = component.find('.terms-transition').at(1);
|
|
82
|
+
const transitionTerms3 = component.find('.terms-transition').at(2);
|
|
83
|
+
|
|
84
|
+
expect(transitionTerms1.text()).toEqual(
|
|
85
|
+
'I give consent for the chosen payment method to be charged automatically.'
|
|
86
|
+
);
|
|
87
|
+
expect(transitionTerms2.text()).toEqual(
|
|
88
|
+
'By placing your order subject to the Terms & Conditions (save for section 2) referred to below, you are waiving your statutory right to cancel our contract within 14 days of payment. Your payment is a one-time payment collected at the time of checkout, and unsubscribing or cancelling at any point (whether before or after the 14-day period) will not entitle you to a refund.'
|
|
89
|
+
);
|
|
90
|
+
expect(transitionTerms3.text()).toEqual(
|
|
91
|
+
'Please see here for the complete Terms & Conditions.'
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
|
|
73
95
|
it('does not render the transition terms when transitionType prop is null', () => {
|
|
74
96
|
const props = {
|
|
75
97
|
transitionType: null,
|
|
@@ -30,6 +30,14 @@ IsSingleTerm.args = {
|
|
|
30
30
|
isSingleTerm: true,
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
export const TermedSubscriptionTermType = (args) => (
|
|
34
|
+
<AcceptTermsSubscription {...args} />
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
TermedSubscriptionTermType.args = {
|
|
38
|
+
isTermedSubscriptionTermType: true,
|
|
39
|
+
};
|
|
40
|
+
|
|
33
41
|
export const IsTransition = (args) => <AcceptTermsSubscription {...args} />;
|
|
34
42
|
|
|
35
43
|
IsTransition.args = {
|
package/components/index.js
CHANGED
|
@@ -49,6 +49,7 @@ export { Province } from './province';
|
|
|
49
49
|
export { RegistrationConfirmation } from './registration-confirmation';
|
|
50
50
|
export { Responsibility } from './responsibility';
|
|
51
51
|
export { Section } from './section';
|
|
52
|
+
export { SevenDayPassExperimentConfirmation } from './seven-day-pass-experiment-confirmation';
|
|
52
53
|
export { State } from './state';
|
|
53
54
|
export { Submit } from './submit';
|
|
54
55
|
export { TrialBanner } from './trial-banner';
|
|
@@ -5,6 +5,7 @@ export function PackageChange({
|
|
|
5
5
|
changePackageUrl,
|
|
6
6
|
currentPackage,
|
|
7
7
|
packageDescription,
|
|
8
|
+
is7DayPassExperiment,
|
|
8
9
|
}) {
|
|
9
10
|
return (
|
|
10
11
|
<div className="ncf__package-change">
|
|
@@ -20,15 +21,17 @@ export function PackageChange({
|
|
|
20
21
|
</p>
|
|
21
22
|
)}
|
|
22
23
|
</div>
|
|
23
|
-
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
{!is7DayPassExperiment && (
|
|
25
|
+
<div className="ncf__package-change__actions">
|
|
26
|
+
<a
|
|
27
|
+
href={changePackageUrl}
|
|
28
|
+
className="ncf__button ncf__button--mono ncf__button--baseline"
|
|
29
|
+
data-trackable="change"
|
|
30
|
+
>
|
|
31
|
+
Change
|
|
32
|
+
</a>
|
|
33
|
+
</div>
|
|
34
|
+
)}
|
|
32
35
|
</div>
|
|
33
36
|
</div>
|
|
34
37
|
);
|
|
@@ -38,4 +41,5 @@ PackageChange.propTypes = {
|
|
|
38
41
|
changePackageUrl: PropTypes.string.isRequired,
|
|
39
42
|
currentPackage: PropTypes.string.isRequired,
|
|
40
43
|
packageDescription: PropTypes.string,
|
|
44
|
+
is7DayPassExperiment: PropTypes.bool,
|
|
41
45
|
};
|
|
@@ -74,6 +74,23 @@ describe('PackageChange', () => {
|
|
|
74
74
|
|
|
75
75
|
expect(PackageChange).toRenderCorrectly(props);
|
|
76
76
|
});
|
|
77
|
+
|
|
78
|
+
it('render when is7DayPassExperiment is true', () => {
|
|
79
|
+
const props = {
|
|
80
|
+
changePackageUrl: 'https://www.ft.com',
|
|
81
|
+
currentPackage: 'Trial',
|
|
82
|
+
is7DayPassExperiment: true,
|
|
83
|
+
terms: [
|
|
84
|
+
{
|
|
85
|
+
name: term,
|
|
86
|
+
price: '£4.99',
|
|
87
|
+
weeklyPrice: '£4.99',
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
expect(PackageChange).toRenderCorrectly(props);
|
|
93
|
+
});
|
|
77
94
|
});
|
|
78
95
|
});
|
|
79
96
|
});
|
|
@@ -18,3 +18,11 @@ WithPackageDescription.args = {
|
|
|
18
18
|
changePackageUrl: 'https://ft.com/products',
|
|
19
19
|
packageDescription: 'Personalised email briefings and alerts',
|
|
20
20
|
};
|
|
21
|
+
|
|
22
|
+
export const SevenDayPassExperiment = (args) => <PackageChange {...args} />;
|
|
23
|
+
SevenDayPassExperiment.args = {
|
|
24
|
+
currentPackage: 'Premium Digital',
|
|
25
|
+
changePackageUrl: 'https://ft.com/products',
|
|
26
|
+
packageDescription: 'Personalised email briefings and alerts',
|
|
27
|
+
is7DayPassExperiment: true,
|
|
28
|
+
};
|
|
@@ -15,12 +15,14 @@ export function PaymentTerm({
|
|
|
15
15
|
largePrice = false,
|
|
16
16
|
optionsInARow = false,
|
|
17
17
|
billingCountry = '',
|
|
18
|
+
is7DayPassExperiment = false,
|
|
19
|
+
isTermedSubscriptionTermType = false,
|
|
18
20
|
}) {
|
|
19
21
|
/**
|
|
20
22
|
* Compute monthly price for given term name
|
|
21
23
|
* @param {number} amount price in number format
|
|
22
24
|
* @param {string} currency country id of the currency
|
|
23
|
-
* @param {string} period PxY (yearly) or PxM (montly) where x is the amount of years/months
|
|
25
|
+
* @param {string} period (expressed in IS0 8601 duration format): e.g. PxY (yearly) or PxM (montly) where x is the amount of years/months
|
|
24
26
|
* @returns {string}
|
|
25
27
|
*/
|
|
26
28
|
const getMontlyPriceFromPeriod = (amount, currency, period) => {
|
|
@@ -32,13 +34,22 @@ export function PaymentTerm({
|
|
|
32
34
|
/**
|
|
33
35
|
* returns period converted to time if found
|
|
34
36
|
* otherwise returns empty string to avoid show information not mapped
|
|
35
|
-
* @param {string} period PxY (yearly)
|
|
37
|
+
* @param {string} period (expressed in IS0 8601 duration format): PxY (yearly), PxM (montly), or PxW, where x is the amount of years/months/weeks
|
|
36
38
|
* @returns {string}
|
|
37
39
|
*/
|
|
38
40
|
const getTimeFromPeriod = (period) => {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
+
const periodUnitCodeToWordMap = {
|
|
42
|
+
Y: 'years',
|
|
43
|
+
M: 'months',
|
|
44
|
+
W: 'weeks',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const periodUnitCode = period.substring(period.length - 1);
|
|
48
|
+
|
|
49
|
+
const freq = periodUnitCodeToWordMap[periodUnitCode] || '';
|
|
50
|
+
|
|
41
51
|
const amount = period.substring(1, period.length - 1);
|
|
52
|
+
|
|
42
53
|
return period ? `${amount} ${freq}` : '';
|
|
43
54
|
};
|
|
44
55
|
|
|
@@ -107,11 +118,22 @@ export function PaymentTerm({
|
|
|
107
118
|
},
|
|
108
119
|
monthly: {
|
|
109
120
|
title: 'Monthly',
|
|
110
|
-
price: (price) =>
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
121
|
+
price: (price, is7DayPassExperiment) => {
|
|
122
|
+
const paymentIntervalTextToDisplay = (() => {
|
|
123
|
+
if (is7DayPassExperiment) {
|
|
124
|
+
return ' one-time payment';
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return ' per month';
|
|
128
|
+
})();
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<React.Fragment>
|
|
132
|
+
<span className="ncf__payment-term__price">{price}</span>
|
|
133
|
+
{paymentIntervalTextToDisplay}
|
|
134
|
+
</React.Fragment>
|
|
135
|
+
);
|
|
136
|
+
},
|
|
115
137
|
trialPrice: (price) => (
|
|
116
138
|
<React.Fragment>
|
|
117
139
|
Unless you cancel during your trial you will be billed{' '}
|
|
@@ -121,9 +143,17 @@ export function PaymentTerm({
|
|
|
121
143
|
),
|
|
122
144
|
monthlyPrice: () => {},
|
|
123
145
|
renewsText: (isFixedTermOffer) => {
|
|
124
|
-
const textToDisplay =
|
|
125
|
-
|
|
126
|
-
|
|
146
|
+
const textToDisplay = (() => {
|
|
147
|
+
if (is7DayPassExperiment) {
|
|
148
|
+
return 'This subscription is for 7 days, charged at the outset.';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (isFixedTermOffer) {
|
|
152
|
+
return 'This subscription is for 3 months, charged monthly. You can cancel at anytime';
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return 'Renews monthly unless cancelled';
|
|
156
|
+
})();
|
|
127
157
|
|
|
128
158
|
return (
|
|
129
159
|
<p className="ncf__payment-term__renews-text">{textToDisplay}</p>
|
|
@@ -157,6 +187,7 @@ export function PaymentTerm({
|
|
|
157
187
|
</span>
|
|
158
188
|
),
|
|
159
189
|
renewsText: (renewalPeriod) =>
|
|
190
|
+
!isTermedSubscriptionTermType &&
|
|
160
191
|
Boolean(renewalPeriod) && (
|
|
161
192
|
<p className="ncf__payment-term__renews-text">
|
|
162
193
|
Renews every {renewalPeriod} unless cancelled
|
|
@@ -219,9 +250,12 @@ export function PaymentTerm({
|
|
|
219
250
|
<React.Fragment>
|
|
220
251
|
{nameMap[option.name] ? (
|
|
221
252
|
<div className="ncf__payment-term__description">
|
|
222
|
-
{nameMap[option.name].price(option.price)}
|
|
253
|
+
{nameMap[option.name].price(option.price, is7DayPassExperiment)}
|
|
223
254
|
{nameMap[option.name].monthlyPrice(option.monthlyPrice)}
|
|
224
|
-
{nameMap[option.name].renewsText(
|
|
255
|
+
{nameMap[option.name].renewsText(
|
|
256
|
+
isFixedTermOffer,
|
|
257
|
+
is7DayPassExperiment
|
|
258
|
+
)}
|
|
225
259
|
{/* Remove this discount text temporarily in favour of monthly price */}
|
|
226
260
|
{/* <br />Save up to 25% when you pay annually */}
|
|
227
261
|
</div>
|
|
@@ -263,11 +297,20 @@ export function PaymentTerm({
|
|
|
263
297
|
const showTrialCopyInTitle =
|
|
264
298
|
option.isTrial && !isPrintOrBundle && !isEpaper;
|
|
265
299
|
|
|
266
|
-
const defaultTitle =
|
|
267
|
-
|
|
300
|
+
const defaultTitle = (() => {
|
|
301
|
+
if (is7DayPassExperiment) {
|
|
302
|
+
return '';
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (Boolean(option.name && nameMap[option.name])) {
|
|
306
|
+
return nameMap[option.name].title;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return '';
|
|
310
|
+
})();
|
|
268
311
|
|
|
269
312
|
const title = isFixedTermOffer
|
|
270
|
-
?
|
|
313
|
+
? [offerDisplayName, defaultTitle].filter(Boolean).join(' - ')
|
|
271
314
|
: defaultTitle;
|
|
272
315
|
|
|
273
316
|
let termDisplayName = '';
|
|
@@ -339,7 +382,7 @@ export function PaymentTerm({
|
|
|
339
382
|
|
|
340
383
|
{showLegal && (
|
|
341
384
|
<div className="ncf__payment-term__legal">
|
|
342
|
-
{isFixedTermOffer ? (
|
|
385
|
+
{isTermedSubscriptionTermType || isFixedTermOffer ? (
|
|
343
386
|
<p>
|
|
344
387
|
Find out more about our cancellation policy in our{' '}
|
|
345
388
|
<a
|
|
@@ -411,6 +454,7 @@ PaymentTerm.propTypes = {
|
|
|
411
454
|
})
|
|
412
455
|
),
|
|
413
456
|
isFixedTermOffer: PropTypes.bool,
|
|
457
|
+
isTermedSubscriptionTermType: PropTypes.bool,
|
|
414
458
|
offerDisplayName: PropTypes.string,
|
|
415
459
|
showLegal: PropTypes.bool,
|
|
416
460
|
largePrice: PropTypes.bool,
|
|
@@ -153,6 +153,63 @@ describe('PaymentTerm', () => {
|
|
|
153
153
|
});
|
|
154
154
|
});
|
|
155
155
|
|
|
156
|
+
describe('given is7DayPassExperiment is true', () => {
|
|
157
|
+
const options = [
|
|
158
|
+
{
|
|
159
|
+
name: 'monthly',
|
|
160
|
+
price: '$5.00',
|
|
161
|
+
value: 'monthly',
|
|
162
|
+
monthlyPrice: '$5.00',
|
|
163
|
+
},
|
|
164
|
+
];
|
|
165
|
+
const wrapper = shallow(
|
|
166
|
+
<PaymentTerm
|
|
167
|
+
isFixedTermOffer={true}
|
|
168
|
+
options={options}
|
|
169
|
+
offerDisplayName="7-day pass"
|
|
170
|
+
is7DayPassExperiment={true}
|
|
171
|
+
/>
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
it('renders renewal text that actually reflects how the 7-day pass is a fixed term subscription with a one-off payment made at the outset', () => {
|
|
175
|
+
expect(wrapper.find('.ncf__payment-term__renews-text').text()).toMatch(
|
|
176
|
+
/This subscription is for 7 days, charged at the outset./
|
|
177
|
+
);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('renders offer name and omits payment term title', () => {
|
|
181
|
+
expect(wrapper.find('.ncf__payment-term__title').text()).toMatch(
|
|
182
|
+
'7-day pass'
|
|
183
|
+
);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe('given isTermedSubscriptionTermType is true', () => {
|
|
188
|
+
const options = [
|
|
189
|
+
{
|
|
190
|
+
name: '8 weeks',
|
|
191
|
+
price: '£19.00',
|
|
192
|
+
amount: '19.00',
|
|
193
|
+
value: 'P8W',
|
|
194
|
+
},
|
|
195
|
+
];
|
|
196
|
+
const wrapper = shallow(
|
|
197
|
+
<PaymentTerm options={options} isTermedSubscriptionTermType={true} />
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
it('renders subscription term as title', () => {
|
|
201
|
+
expect(wrapper.find('.ncf__payment-term__title').text()).toMatch(
|
|
202
|
+
'8 weeks'
|
|
203
|
+
);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('renders description text that reflects that the termed subscription requires a single payment that expresses the per duration cost for shorter durations', () => {
|
|
207
|
+
expect(wrapper.find('.ncf__payment-term__description').text()).toContain(
|
|
208
|
+
'Single £19.00 paymentThat’s equivalent to GBP9.50 per month'
|
|
209
|
+
);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
156
213
|
describe('getDisplayName', () => {
|
|
157
214
|
const baseOptions = {
|
|
158
215
|
name: 'monthly',
|
|
@@ -199,6 +256,22 @@ describe('PaymentTerm', () => {
|
|
|
199
256
|
);
|
|
200
257
|
});
|
|
201
258
|
});
|
|
259
|
+
describe('7-day pass experiment', () => {
|
|
260
|
+
const options = [
|
|
261
|
+
{
|
|
262
|
+
...baseOptions,
|
|
263
|
+
isTrial: false,
|
|
264
|
+
},
|
|
265
|
+
];
|
|
266
|
+
it('renders with time period only if trial.option == false', () => {
|
|
267
|
+
const wrapper = shallow(
|
|
268
|
+
<PaymentTerm options={options} is7DayPassExperiment={true} />
|
|
269
|
+
);
|
|
270
|
+
expect(wrapper.find('.ncf__payment-term__label').text().trim()).toMatch(
|
|
271
|
+
'£20.00 one-time paymentThis subscription is for 7 days, charged at the outset.'
|
|
272
|
+
);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
202
275
|
});
|
|
203
276
|
|
|
204
277
|
describe('[data-base-amount]', () => {
|
|
@@ -109,6 +109,45 @@ FixedTermOffer.args = {
|
|
|
109
109
|
offerDisplayName: 'Mix & Match',
|
|
110
110
|
};
|
|
111
111
|
|
|
112
|
+
export const SevenDayPassExperimentOffer = (args) => (
|
|
113
|
+
<div className="ncf">
|
|
114
|
+
<Fieldset>
|
|
115
|
+
<PaymentTerm {...args} />
|
|
116
|
+
</Fieldset>
|
|
117
|
+
</div>
|
|
118
|
+
);
|
|
119
|
+
SevenDayPassExperimentOffer.args = {
|
|
120
|
+
options: [
|
|
121
|
+
{
|
|
122
|
+
name: 'monthly',
|
|
123
|
+
price: '$5.00',
|
|
124
|
+
value: 5.0,
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
isFixedTermOffer: true,
|
|
128
|
+
is7DayPassExperiment: true,
|
|
129
|
+
offerDisplayName: '7-day pass',
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export const TermedSubscriptionTermType = (args) => (
|
|
133
|
+
<div className="ncf">
|
|
134
|
+
<Fieldset>
|
|
135
|
+
<PaymentTerm {...args} />
|
|
136
|
+
</Fieldset>
|
|
137
|
+
</div>
|
|
138
|
+
);
|
|
139
|
+
TermedSubscriptionTermType.args = {
|
|
140
|
+
options: [
|
|
141
|
+
{
|
|
142
|
+
name: '8 weeks',
|
|
143
|
+
price: '£19.00',
|
|
144
|
+
amount: '19.00',
|
|
145
|
+
value: 'P8W',
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
isTermedSubscriptionTermType: true,
|
|
149
|
+
};
|
|
150
|
+
|
|
112
151
|
export const RenewOffers = (args) => (
|
|
113
152
|
<div className="ncf">
|
|
114
153
|
<Fieldset>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
const DetailsMobileView = ({ details }) => (
|
|
5
|
+
<dl className="ncf__list ncf__lite-sub__details ncf__lite-sub-confirmation--hidden-md ncf__lite-sub-confirmation--hidden-lg">
|
|
6
|
+
{details.map((detail, index) => (
|
|
7
|
+
<React.Fragment key={index}>
|
|
8
|
+
<dt className="ncf__list-title">{detail.title}</dt>
|
|
9
|
+
<dd className="ncf__list-data">{detail.data}</dd>
|
|
10
|
+
</React.Fragment>
|
|
11
|
+
))}
|
|
12
|
+
</dl>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export function SevenDayPassExperimentConfirmation({
|
|
16
|
+
offerName = '',
|
|
17
|
+
details = [],
|
|
18
|
+
}) {
|
|
19
|
+
const detailElements = details && (
|
|
20
|
+
<React.Fragment>
|
|
21
|
+
<h2 className="ncf__header2--afterline">Your billing details</h2>
|
|
22
|
+
<dl className="ncf__list ncf__lite-sub-confirmation--hidden-sm">
|
|
23
|
+
{details.map((detail, index) => (
|
|
24
|
+
<React.Fragment key={index}>
|
|
25
|
+
<dt className="ncf__list-title">{detail.title}</dt>
|
|
26
|
+
<dd className="ncf__list-data">{detail.data}</dd>
|
|
27
|
+
</React.Fragment>
|
|
28
|
+
))}
|
|
29
|
+
</dl>
|
|
30
|
+
<DetailsMobileView details={details} />
|
|
31
|
+
</React.Fragment>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<div className="ncf ncf__wrapper">
|
|
36
|
+
<div className="ncf__center">
|
|
37
|
+
<div className="ncf__icon ncf__icon--tick ncf__icon--large"></div>
|
|
38
|
+
<p className="ncf__paragraph--reduced-padding ncf__paragraph--subscription-confirmation">
|
|
39
|
+
You are now subscribed to:
|
|
40
|
+
</p>
|
|
41
|
+
<h1 className="ncf__header ncf__header--confirmation">
|
|
42
|
+
{'Premium Digital'}
|
|
43
|
+
</h1>
|
|
44
|
+
</div>
|
|
45
|
+
<p className="ncf__paragraph">
|
|
46
|
+
Exciting news! You are one of the first to try a{' '}
|
|
47
|
+
<strong>{offerName}</strong>. As a thank you, we are pleased to extend
|
|
48
|
+
your subscription to one month at no additional cost.
|
|
49
|
+
</p>
|
|
50
|
+
<p className="ncf__center">
|
|
51
|
+
<a
|
|
52
|
+
href="/"
|
|
53
|
+
className="ncf__button ncf__button--submit ncf__button--margin ncf__lite-sub-confirmation--lite-sub-cta"
|
|
54
|
+
>
|
|
55
|
+
Go to FT.com
|
|
56
|
+
</a>
|
|
57
|
+
</p>
|
|
58
|
+
<p className="ncf__paragraph">
|
|
59
|
+
Please save or print this page for your records as your purchase
|
|
60
|
+
confirmation.
|
|
61
|
+
</p>
|
|
62
|
+
|
|
63
|
+
<p className="ncf__paragraph">
|
|
64
|
+
Here's a summary of your Premium Digital subscription:
|
|
65
|
+
</p>
|
|
66
|
+
|
|
67
|
+
{detailElements}
|
|
68
|
+
|
|
69
|
+
<div className="ncf__headed-paragraph">
|
|
70
|
+
<h3 className="ncf__header">Something not right?</h3>
|
|
71
|
+
<p className="ncf__paragraph">
|
|
72
|
+
Go to your{' '}
|
|
73
|
+
<a
|
|
74
|
+
className="ncf__link ncf__link--external"
|
|
75
|
+
href="https://www.ft.com/myaccount/personal-details"
|
|
76
|
+
target="_blank"
|
|
77
|
+
rel="noopener noreferrer"
|
|
78
|
+
data-trackable="yourAccount"
|
|
79
|
+
>
|
|
80
|
+
account settings
|
|
81
|
+
</a>{' '}
|
|
82
|
+
to view or edit your account. If you need to get in touch call us on{' '}
|
|
83
|
+
<a href="tel:+442077556248" className="ncf__link ncf__link--external">
|
|
84
|
+
+44 20 7755 6248
|
|
85
|
+
</a>
|
|
86
|
+
. Or{' '}
|
|
87
|
+
<a
|
|
88
|
+
className="ncf__link ncf__link--external"
|
|
89
|
+
href="https://help.ft.com/contact/"
|
|
90
|
+
target="_blank"
|
|
91
|
+
rel="noopener noreferrer"
|
|
92
|
+
>
|
|
93
|
+
contact us
|
|
94
|
+
</a>{' '}
|
|
95
|
+
for additional support.
|
|
96
|
+
</p>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
SevenDayPassExperimentConfirmation.propTypes = {
|
|
103
|
+
offerName: PropTypes.string.isRequired,
|
|
104
|
+
details: PropTypes.arrayOf(
|
|
105
|
+
PropTypes.shape({
|
|
106
|
+
title: PropTypes.string.isRequired,
|
|
107
|
+
data: PropTypes.string.isRequired,
|
|
108
|
+
})
|
|
109
|
+
),
|
|
110
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SevenDayPassExperimentConfirmation } from './seven-day-pass-experiment-confirmation';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: '7-day pass experiment confirmation',
|
|
6
|
+
component: SevenDayPassExperimentConfirmation,
|
|
7
|
+
argTypes: {
|
|
8
|
+
details: { control: 'array' },
|
|
9
|
+
offerType: { control: 'string' },
|
|
10
|
+
offerName: { control: 'string' },
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const Basic = (args) => <SevenDayPassExperimentConfirmation {...args} />;
|
|
15
|
+
Basic.args = {
|
|
16
|
+
offerType: 'Premium',
|
|
17
|
+
details: [
|
|
18
|
+
{
|
|
19
|
+
title: 'End Date',
|
|
20
|
+
data: 'September 18, 2023',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
title: 'One-time payment',
|
|
24
|
+
data: '£4.99',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
title: 'Payment method',
|
|
28
|
+
data: 'Credit / Debit Card',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
offerName: '7-day pass',
|
|
32
|
+
subscriptionAmount: '£4.99',
|
|
33
|
+
};
|
|
@@ -24,6 +24,10 @@ function AcceptTermsSubscription(_ref) {
|
|
|
24
24
|
isPrintProduct = _ref$isPrintProduct === void 0 ? false : _ref$isPrintProduct,
|
|
25
25
|
_ref$isSingleTerm = _ref.isSingleTerm,
|
|
26
26
|
isSingleTerm = _ref$isSingleTerm === void 0 ? false : _ref$isSingleTerm,
|
|
27
|
+
_ref$is7DayPassExperi = _ref.is7DayPassExperiment,
|
|
28
|
+
is7DayPassExperiment = _ref$is7DayPassExperi === void 0 ? false : _ref$is7DayPassExperi,
|
|
29
|
+
_ref$isTermedSubscrip = _ref.isTermedSubscriptionTermType,
|
|
30
|
+
isTermedSubscriptionTermType = _ref$isTermedSubscrip === void 0 ? false : _ref$isTermedSubscrip,
|
|
27
31
|
_ref$isTransition = _ref.isTransition,
|
|
28
32
|
isTransition = _ref$isTransition === void 0 ? false : _ref$isTransition,
|
|
29
33
|
_ref$transitionType = _ref.transitionType,
|
|
@@ -49,6 +53,52 @@ function AcceptTermsSubscription(_ref) {
|
|
|
49
53
|
'aria-required': 'true',
|
|
50
54
|
required: true
|
|
51
55
|
};
|
|
56
|
+
if (is7DayPassExperiment) {
|
|
57
|
+
return /*#__PURE__*/_react["default"].createElement("div", divProps, /*#__PURE__*/_react["default"].createElement("ul", {
|
|
58
|
+
className: "o-typography-list ncf__accept-terms-list"
|
|
59
|
+
}, /*#__PURE__*/_react["default"].createElement("li", null, /*#__PURE__*/_react["default"].createElement("span", {
|
|
60
|
+
className: "terms-transition terms-transition--immediate"
|
|
61
|
+
}, "I give consent for my chosen payment method to be charged automatically.")), /*#__PURE__*/_react["default"].createElement("li", null, /*#__PURE__*/_react["default"].createElement("span", {
|
|
62
|
+
className: "terms-transition terms-transition--immediate"
|
|
63
|
+
}, "By placing your order subject to the Terms & Conditions (save for section 2) referred to below, you agree that we may start your 7-day pass immediately upon our acceptance of your order and that you are waiving your statutory right to cancel our contract within 14 days of confirmation. Your payment is a one-time payment collected at the time of checkout, and cancelling at any point (whether before or after the 14-day period) will not entitle you to a refund.")), /*#__PURE__*/_react["default"].createElement("li", null, /*#__PURE__*/_react["default"].createElement("span", {
|
|
64
|
+
className: "terms-transition"
|
|
65
|
+
}, "Please see here for the complete", ' ', /*#__PURE__*/_react["default"].createElement("a", {
|
|
66
|
+
className: "ncf__link--external",
|
|
67
|
+
href: "http://help.ft.com/help/legal-privacy/terms-conditions/",
|
|
68
|
+
target: "_blank",
|
|
69
|
+
rel: "noopener noreferrer"
|
|
70
|
+
}, "Terms & Conditions"), "."))), /*#__PURE__*/_react["default"].createElement("label", {
|
|
71
|
+
className: labelClassName,
|
|
72
|
+
htmlFor: "termsAcceptance"
|
|
73
|
+
}, /*#__PURE__*/_react["default"].createElement("input", inputProps), /*#__PURE__*/_react["default"].createElement("span", {
|
|
74
|
+
className: "o-forms-input__label"
|
|
75
|
+
}, "I agree to the above terms & conditions."), /*#__PURE__*/_react["default"].createElement("p", {
|
|
76
|
+
className: "o-forms-input__error"
|
|
77
|
+
}, "Please accept our terms & conditions")));
|
|
78
|
+
}
|
|
79
|
+
if (isTermedSubscriptionTermType) {
|
|
80
|
+
return /*#__PURE__*/_react["default"].createElement("div", divProps, /*#__PURE__*/_react["default"].createElement("ul", {
|
|
81
|
+
className: "o-typography-list ncf__accept-terms-list"
|
|
82
|
+
}, /*#__PURE__*/_react["default"].createElement("li", null, /*#__PURE__*/_react["default"].createElement("span", {
|
|
83
|
+
className: "terms-transition terms-transition--immediate"
|
|
84
|
+
}, "I give consent for the chosen payment method to be charged automatically.")), /*#__PURE__*/_react["default"].createElement("li", null, /*#__PURE__*/_react["default"].createElement("span", {
|
|
85
|
+
className: "terms-transition terms-transition--immediate"
|
|
86
|
+
}, "By placing your order subject to the Terms & Conditions (save for section 2) referred to below, you are waiving your statutory right to cancel our contract within 14 days of payment. Your payment is a one-time payment collected at the time of checkout, and unsubscribing or cancelling at any point (whether before or after the 14-day period) will not entitle you to a refund.")), /*#__PURE__*/_react["default"].createElement("li", null, /*#__PURE__*/_react["default"].createElement("span", {
|
|
87
|
+
className: "terms-transition"
|
|
88
|
+
}, "Please see here for the complete", ' ', /*#__PURE__*/_react["default"].createElement("a", {
|
|
89
|
+
className: "ncf__link--external",
|
|
90
|
+
href: "http://help.ft.com/help/legal-privacy/terms-conditions/",
|
|
91
|
+
target: "_blank",
|
|
92
|
+
rel: "noopener noreferrer"
|
|
93
|
+
}, "Terms & Conditions"), "."))), /*#__PURE__*/_react["default"].createElement("label", {
|
|
94
|
+
className: labelClassName,
|
|
95
|
+
htmlFor: "termsAcceptance"
|
|
96
|
+
}, /*#__PURE__*/_react["default"].createElement("input", inputProps), /*#__PURE__*/_react["default"].createElement("span", {
|
|
97
|
+
className: "o-forms-input__label"
|
|
98
|
+
}, "I agree to the above terms & conditions."), /*#__PURE__*/_react["default"].createElement("p", {
|
|
99
|
+
className: "o-forms-input__error"
|
|
100
|
+
}, "Please accept our terms & conditions")));
|
|
101
|
+
}
|
|
52
102
|
var transitionTerms = isTransition && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, !isSingleTerm && /*#__PURE__*/_react["default"].createElement("li", null, /*#__PURE__*/_react["default"].createElement("span", {
|
|
53
103
|
className: "terms-transition"
|
|
54
104
|
}, "I give consent for my chosen payment method to be charged automatically at the end of each subscription term until I cancel it by contacting", ' ', /*#__PURE__*/_react["default"].createElement("a", {
|
|
@@ -118,6 +168,8 @@ AcceptTermsSubscription.propTypes = {
|
|
|
118
168
|
isTrial: _propTypes["default"].bool,
|
|
119
169
|
isPrintProduct: _propTypes["default"].bool,
|
|
120
170
|
isSingleTerm: _propTypes["default"].bool,
|
|
171
|
+
is7DayPassExperiment: _propTypes["default"].bool,
|
|
172
|
+
isTermedSubscriptionTermType: _propTypes["default"].bool,
|
|
121
173
|
isTransition: _propTypes["default"].bool,
|
|
122
174
|
transitionType: _propTypes["default"].string,
|
|
123
175
|
isDeferredBilling: _propTypes["default"].bool
|
package/dist/index.js
CHANGED
|
@@ -339,6 +339,12 @@ Object.defineProperty(exports, "Section", {
|
|
|
339
339
|
return _section.Section;
|
|
340
340
|
}
|
|
341
341
|
});
|
|
342
|
+
Object.defineProperty(exports, "SevenDayPassExperimentConfirmation", {
|
|
343
|
+
enumerable: true,
|
|
344
|
+
get: function get() {
|
|
345
|
+
return _sevenDayPassExperimentConfirmation.SevenDayPassExperimentConfirmation;
|
|
346
|
+
}
|
|
347
|
+
});
|
|
342
348
|
Object.defineProperty(exports, "State", {
|
|
343
349
|
enumerable: true,
|
|
344
350
|
get: function get() {
|
|
@@ -414,6 +420,7 @@ var _province = require("./province");
|
|
|
414
420
|
var _registrationConfirmation = require("./registration-confirmation");
|
|
415
421
|
var _responsibility = require("./responsibility");
|
|
416
422
|
var _section = require("./section");
|
|
423
|
+
var _sevenDayPassExperimentConfirmation = require("./seven-day-pass-experiment-confirmation");
|
|
417
424
|
var _state = require("./state");
|
|
418
425
|
var _submit = require("./submit");
|
|
419
426
|
var _trialBanner = require("./trial-banner");
|
package/dist/package-change.jsx
CHANGED
|
@@ -10,7 +10,8 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
|
10
10
|
function PackageChange(_ref) {
|
|
11
11
|
var changePackageUrl = _ref.changePackageUrl,
|
|
12
12
|
currentPackage = _ref.currentPackage,
|
|
13
|
-
packageDescription = _ref.packageDescription
|
|
13
|
+
packageDescription = _ref.packageDescription,
|
|
14
|
+
is7DayPassExperiment = _ref.is7DayPassExperiment;
|
|
14
15
|
return /*#__PURE__*/_react["default"].createElement("div", {
|
|
15
16
|
className: "ncf__package-change"
|
|
16
17
|
}, /*#__PURE__*/_react["default"].createElement("div", {
|
|
@@ -21,7 +22,7 @@ function PackageChange(_ref) {
|
|
|
21
22
|
className: "ncf__strong"
|
|
22
23
|
}, currentPackage)), packageDescription && /*#__PURE__*/_react["default"].createElement("p", {
|
|
23
24
|
className: "ncf__package-change__content__description"
|
|
24
|
-
}, packageDescription)), /*#__PURE__*/_react["default"].createElement("div", {
|
|
25
|
+
}, packageDescription)), !is7DayPassExperiment && /*#__PURE__*/_react["default"].createElement("div", {
|
|
25
26
|
className: "ncf__package-change__actions"
|
|
26
27
|
}, /*#__PURE__*/_react["default"].createElement("a", {
|
|
27
28
|
href: changePackageUrl,
|
|
@@ -32,5 +33,6 @@ function PackageChange(_ref) {
|
|
|
32
33
|
PackageChange.propTypes = {
|
|
33
34
|
changePackageUrl: _propTypes["default"].string.isRequired,
|
|
34
35
|
currentPackage: _propTypes["default"].string.isRequired,
|
|
35
|
-
packageDescription: _propTypes["default"].string
|
|
36
|
+
packageDescription: _propTypes["default"].string,
|
|
37
|
+
is7DayPassExperiment: _propTypes["default"].bool
|
|
36
38
|
};
|
package/dist/payment-term.jsx
CHANGED
|
@@ -33,12 +33,16 @@ function PaymentTerm(_ref) {
|
|
|
33
33
|
_ref$optionsInARow = _ref.optionsInARow,
|
|
34
34
|
optionsInARow = _ref$optionsInARow === void 0 ? false : _ref$optionsInARow,
|
|
35
35
|
_ref$billingCountry = _ref.billingCountry,
|
|
36
|
-
billingCountry = _ref$billingCountry === void 0 ? '' : _ref$billingCountry
|
|
36
|
+
billingCountry = _ref$billingCountry === void 0 ? '' : _ref$billingCountry,
|
|
37
|
+
_ref$is7DayPassExperi = _ref.is7DayPassExperiment,
|
|
38
|
+
is7DayPassExperiment = _ref$is7DayPassExperi === void 0 ? false : _ref$is7DayPassExperi,
|
|
39
|
+
_ref$isTermedSubscrip = _ref.isTermedSubscriptionTermType,
|
|
40
|
+
isTermedSubscriptionTermType = _ref$isTermedSubscrip === void 0 ? false : _ref$isTermedSubscrip;
|
|
37
41
|
/**
|
|
38
42
|
* Compute monthly price for given term name
|
|
39
43
|
* @param {number} amount price in number format
|
|
40
44
|
* @param {string} currency country id of the currency
|
|
41
|
-
* @param {string} period PxY (yearly) or PxM (montly) where x is the amount of years/months
|
|
45
|
+
* @param {string} period (expressed in IS0 8601 duration format): e.g. PxY (yearly) or PxM (montly) where x is the amount of years/months
|
|
42
46
|
* @returns {string}
|
|
43
47
|
*/
|
|
44
48
|
var getMontlyPriceFromPeriod = function getMontlyPriceFromPeriod(amount, currency, period) {
|
|
@@ -53,11 +57,17 @@ function PaymentTerm(_ref) {
|
|
|
53
57
|
/**
|
|
54
58
|
* returns period converted to time if found
|
|
55
59
|
* otherwise returns empty string to avoid show information not mapped
|
|
56
|
-
* @param {string} period PxY (yearly)
|
|
60
|
+
* @param {string} period (expressed in IS0 8601 duration format): PxY (yearly), PxM (montly), or PxW, where x is the amount of years/months/weeks
|
|
57
61
|
* @returns {string}
|
|
58
62
|
*/
|
|
59
63
|
var getTimeFromPeriod = function getTimeFromPeriod(period) {
|
|
60
|
-
var
|
|
64
|
+
var periodUnitCodeToWordMap = {
|
|
65
|
+
Y: 'years',
|
|
66
|
+
M: 'months',
|
|
67
|
+
W: 'weeks'
|
|
68
|
+
};
|
|
69
|
+
var periodUnitCode = period.substring(period.length - 1);
|
|
70
|
+
var freq = periodUnitCodeToWordMap[periodUnitCode] || '';
|
|
61
71
|
var amount = period.substring(1, period.length - 1);
|
|
62
72
|
return period ? "".concat(amount, " ").concat(freq) : '';
|
|
63
73
|
};
|
|
@@ -118,10 +128,16 @@ function PaymentTerm(_ref) {
|
|
|
118
128
|
},
|
|
119
129
|
monthly: {
|
|
120
130
|
title: 'Monthly',
|
|
121
|
-
price: function price(_price3) {
|
|
131
|
+
price: function price(_price3, is7DayPassExperiment) {
|
|
132
|
+
var paymentIntervalTextToDisplay = function () {
|
|
133
|
+
if (is7DayPassExperiment) {
|
|
134
|
+
return ' one-time payment';
|
|
135
|
+
}
|
|
136
|
+
return ' per month';
|
|
137
|
+
}();
|
|
122
138
|
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("span", {
|
|
123
139
|
className: "ncf__payment-term__price"
|
|
124
|
-
}, _price3),
|
|
140
|
+
}, _price3), paymentIntervalTextToDisplay);
|
|
125
141
|
},
|
|
126
142
|
trialPrice: function trialPrice(price) {
|
|
127
143
|
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, "Unless you cancel during your trial you will be billed", ' ', /*#__PURE__*/_react["default"].createElement("span", {
|
|
@@ -130,7 +146,15 @@ function PaymentTerm(_ref) {
|
|
|
130
146
|
},
|
|
131
147
|
monthlyPrice: function monthlyPrice() {},
|
|
132
148
|
renewsText: function renewsText(isFixedTermOffer) {
|
|
133
|
-
var textToDisplay =
|
|
149
|
+
var textToDisplay = function () {
|
|
150
|
+
if (is7DayPassExperiment) {
|
|
151
|
+
return 'This subscription is for 7 days, charged at the outset.';
|
|
152
|
+
}
|
|
153
|
+
if (isFixedTermOffer) {
|
|
154
|
+
return 'This subscription is for 3 months, charged monthly. You can cancel at anytime';
|
|
155
|
+
}
|
|
156
|
+
return 'Renews monthly unless cancelled';
|
|
157
|
+
}();
|
|
134
158
|
return /*#__PURE__*/_react["default"].createElement("p", {
|
|
135
159
|
className: "ncf__payment-term__renews-text"
|
|
136
160
|
}, textToDisplay);
|
|
@@ -155,7 +179,7 @@ function PaymentTerm(_ref) {
|
|
|
155
179
|
}, _monthlyPrice), ' ', "per month");
|
|
156
180
|
},
|
|
157
181
|
renewsText: function renewsText(renewalPeriod) {
|
|
158
|
-
return Boolean(renewalPeriod) && /*#__PURE__*/_react["default"].createElement("p", {
|
|
182
|
+
return !isTermedSubscriptionTermType && Boolean(renewalPeriod) && /*#__PURE__*/_react["default"].createElement("p", {
|
|
159
183
|
className: "ncf__payment-term__renews-text"
|
|
160
184
|
}, "Renews every ", renewalPeriod, " unless cancelled");
|
|
161
185
|
}
|
|
@@ -192,7 +216,7 @@ function PaymentTerm(_ref) {
|
|
|
192
216
|
className: "ncf__payment-term__trial-price"
|
|
193
217
|
}, option.trialPrice), /*#__PURE__*/_react["default"].createElement("br", null), nameMap[option.name] && nameMap[option.name].trialPrice(option.price)) : /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, nameMap[option.name] ? /*#__PURE__*/_react["default"].createElement("div", {
|
|
194
218
|
className: "ncf__payment-term__description"
|
|
195
|
-
}, nameMap[option.name].price(option.price), nameMap[option.name].monthlyPrice(option.monthlyPrice), nameMap[option.name].renewsText(isFixedTermOffer)) :
|
|
219
|
+
}, nameMap[option.name].price(option.price, is7DayPassExperiment), nameMap[option.name].monthlyPrice(option.monthlyPrice), nameMap[option.name].renewsText(isFixedTermOffer, is7DayPassExperiment)) :
|
|
196
220
|
// this should cover the cases different than annual, quarterly and monthly
|
|
197
221
|
// for those containing period on option.value, render custom template, for the rest keep legacy render
|
|
198
222
|
isValidPeriod(option.value) ? /*#__PURE__*/_react["default"].createElement("div", {
|
|
@@ -205,8 +229,16 @@ function PaymentTerm(_ref) {
|
|
|
205
229
|
};
|
|
206
230
|
var getTermDisplayName = function getTermDisplayName() {
|
|
207
231
|
var showTrialCopyInTitle = option.isTrial && !isPrintOrBundle && !isEpaper;
|
|
208
|
-
var defaultTitle =
|
|
209
|
-
|
|
232
|
+
var defaultTitle = function () {
|
|
233
|
+
if (is7DayPassExperiment) {
|
|
234
|
+
return '';
|
|
235
|
+
}
|
|
236
|
+
if (Boolean(option.name && nameMap[option.name])) {
|
|
237
|
+
return nameMap[option.name].title;
|
|
238
|
+
}
|
|
239
|
+
return '';
|
|
240
|
+
}();
|
|
241
|
+
var title = isFixedTermOffer ? [offerDisplayName, defaultTitle].filter(Boolean).join(' - ') : defaultTitle;
|
|
210
242
|
var termDisplayName = '';
|
|
211
243
|
if (showTrialCopyInTitle) {
|
|
212
244
|
var termName = option.displayName ? option.displayName : 'Premium Digital';
|
|
@@ -252,7 +284,7 @@ function PaymentTerm(_ref) {
|
|
|
252
284
|
return createPaymentTerm(option);
|
|
253
285
|
})), showLegal && /*#__PURE__*/_react["default"].createElement("div", {
|
|
254
286
|
className: "ncf__payment-term__legal"
|
|
255
|
-
}, isFixedTermOffer ? /*#__PURE__*/_react["default"].createElement("p", null, "Find out more about our cancellation policy in our", ' ', /*#__PURE__*/_react["default"].createElement("a", {
|
|
287
|
+
}, isTermedSubscriptionTermType || isFixedTermOffer ? /*#__PURE__*/_react["default"].createElement("p", null, "Find out more about our cancellation policy in our", ' ', /*#__PURE__*/_react["default"].createElement("a", {
|
|
256
288
|
className: "ncf__link--external",
|
|
257
289
|
href: "https://help.ft.com/legal-privacy/terms-and-conditions/",
|
|
258
290
|
title: "FT Legal Terms and Conditions help page",
|
|
@@ -292,6 +324,7 @@ PaymentTerm.propTypes = {
|
|
|
292
324
|
fulfilmentOption: _propTypes["default"].string
|
|
293
325
|
})),
|
|
294
326
|
isFixedTermOffer: _propTypes["default"].bool,
|
|
327
|
+
isTermedSubscriptionTermType: _propTypes["default"].bool,
|
|
295
328
|
offerDisplayName: _propTypes["default"].string,
|
|
296
329
|
showLegal: _propTypes["default"].bool,
|
|
297
330
|
largePrice: _propTypes["default"].bool,
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.SevenDayPassExperimentConfirmation = SevenDayPassExperimentConfirmation;
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
10
|
+
var DetailsMobileView = function DetailsMobileView(_ref) {
|
|
11
|
+
var details = _ref.details;
|
|
12
|
+
return /*#__PURE__*/_react["default"].createElement("dl", {
|
|
13
|
+
className: "ncf__list ncf__lite-sub__details ncf__lite-sub-confirmation--hidden-md ncf__lite-sub-confirmation--hidden-lg"
|
|
14
|
+
}, details.map(function (detail, index) {
|
|
15
|
+
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, {
|
|
16
|
+
key: index
|
|
17
|
+
}, /*#__PURE__*/_react["default"].createElement("dt", {
|
|
18
|
+
className: "ncf__list-title"
|
|
19
|
+
}, detail.title), /*#__PURE__*/_react["default"].createElement("dd", {
|
|
20
|
+
className: "ncf__list-data"
|
|
21
|
+
}, detail.data));
|
|
22
|
+
}));
|
|
23
|
+
};
|
|
24
|
+
function SevenDayPassExperimentConfirmation(_ref2) {
|
|
25
|
+
var _ref2$offerName = _ref2.offerName,
|
|
26
|
+
offerName = _ref2$offerName === void 0 ? '' : _ref2$offerName,
|
|
27
|
+
_ref2$details = _ref2.details,
|
|
28
|
+
details = _ref2$details === void 0 ? [] : _ref2$details;
|
|
29
|
+
var detailElements = details && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("h2", {
|
|
30
|
+
className: "ncf__header2--afterline"
|
|
31
|
+
}, "Your billing details"), /*#__PURE__*/_react["default"].createElement("dl", {
|
|
32
|
+
className: "ncf__list ncf__lite-sub-confirmation--hidden-sm"
|
|
33
|
+
}, details.map(function (detail, index) {
|
|
34
|
+
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, {
|
|
35
|
+
key: index
|
|
36
|
+
}, /*#__PURE__*/_react["default"].createElement("dt", {
|
|
37
|
+
className: "ncf__list-title"
|
|
38
|
+
}, detail.title), /*#__PURE__*/_react["default"].createElement("dd", {
|
|
39
|
+
className: "ncf__list-data"
|
|
40
|
+
}, detail.data));
|
|
41
|
+
})), /*#__PURE__*/_react["default"].createElement(DetailsMobileView, {
|
|
42
|
+
details: details
|
|
43
|
+
}));
|
|
44
|
+
return /*#__PURE__*/_react["default"].createElement("div", {
|
|
45
|
+
className: "ncf ncf__wrapper"
|
|
46
|
+
}, /*#__PURE__*/_react["default"].createElement("div", {
|
|
47
|
+
className: "ncf__center"
|
|
48
|
+
}, /*#__PURE__*/_react["default"].createElement("div", {
|
|
49
|
+
className: "ncf__icon ncf__icon--tick ncf__icon--large"
|
|
50
|
+
}), /*#__PURE__*/_react["default"].createElement("p", {
|
|
51
|
+
className: "ncf__paragraph--reduced-padding ncf__paragraph--subscription-confirmation"
|
|
52
|
+
}, "You are now subscribed to:"), /*#__PURE__*/_react["default"].createElement("h1", {
|
|
53
|
+
className: "ncf__header ncf__header--confirmation"
|
|
54
|
+
}, 'Premium Digital')), /*#__PURE__*/_react["default"].createElement("p", {
|
|
55
|
+
className: "ncf__paragraph"
|
|
56
|
+
}, "Exciting news! You are one of the first to try a", ' ', /*#__PURE__*/_react["default"].createElement("strong", null, offerName), ". As a thank you, we are pleased to extend your subscription to one month at no additional cost."), /*#__PURE__*/_react["default"].createElement("p", {
|
|
57
|
+
className: "ncf__center"
|
|
58
|
+
}, /*#__PURE__*/_react["default"].createElement("a", {
|
|
59
|
+
href: "/",
|
|
60
|
+
className: "ncf__button ncf__button--submit ncf__button--margin ncf__lite-sub-confirmation--lite-sub-cta"
|
|
61
|
+
}, "Go to FT.com")), /*#__PURE__*/_react["default"].createElement("p", {
|
|
62
|
+
className: "ncf__paragraph"
|
|
63
|
+
}, "Please save or print this page for your records as your purchase confirmation."), /*#__PURE__*/_react["default"].createElement("p", {
|
|
64
|
+
className: "ncf__paragraph"
|
|
65
|
+
}, "Here's a summary of your Premium Digital subscription:"), detailElements, /*#__PURE__*/_react["default"].createElement("div", {
|
|
66
|
+
className: "ncf__headed-paragraph"
|
|
67
|
+
}, /*#__PURE__*/_react["default"].createElement("h3", {
|
|
68
|
+
className: "ncf__header"
|
|
69
|
+
}, "Something not right?"), /*#__PURE__*/_react["default"].createElement("p", {
|
|
70
|
+
className: "ncf__paragraph"
|
|
71
|
+
}, "Go to your", ' ', /*#__PURE__*/_react["default"].createElement("a", {
|
|
72
|
+
className: "ncf__link ncf__link--external",
|
|
73
|
+
href: "https://www.ft.com/myaccount/personal-details",
|
|
74
|
+
target: "_blank",
|
|
75
|
+
rel: "noopener noreferrer",
|
|
76
|
+
"data-trackable": "yourAccount"
|
|
77
|
+
}, "account settings"), ' ', "to view or edit your account. If you need to get in touch call us on", ' ', /*#__PURE__*/_react["default"].createElement("a", {
|
|
78
|
+
href: "tel:+442077556248",
|
|
79
|
+
className: "ncf__link ncf__link--external"
|
|
80
|
+
}, "+44 20 7755 6248"), ". Or", ' ', /*#__PURE__*/_react["default"].createElement("a", {
|
|
81
|
+
className: "ncf__link ncf__link--external",
|
|
82
|
+
href: "https://help.ft.com/contact/",
|
|
83
|
+
target: "_blank",
|
|
84
|
+
rel: "noopener noreferrer"
|
|
85
|
+
}, "contact us"), ' ', "for additional support.")));
|
|
86
|
+
}
|
|
87
|
+
SevenDayPassExperimentConfirmation.propTypes = {
|
|
88
|
+
offerName: _propTypes["default"].string.isRequired,
|
|
89
|
+
details: _propTypes["default"].arrayOf(_propTypes["default"].shape({
|
|
90
|
+
title: _propTypes["default"].string.isRequired,
|
|
91
|
+
data: _propTypes["default"].string.isRequired
|
|
92
|
+
}))
|
|
93
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@financial-times/n-conversion-forms",
|
|
3
|
-
"version": "32.
|
|
3
|
+
"version": "32.4.0",
|
|
4
4
|
"description": "Containing jsx components and styles for forms included on Accounts and Acqusition apps (next-signup, next-profile, next-retention, etc).",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -37,9 +37,10 @@
|
|
|
37
37
|
"@babel/preset-env": "^7.22.15",
|
|
38
38
|
"@babel/preset-react": "^7.22.15",
|
|
39
39
|
"@dotcom-tool-kit/babel": "^3.1.3",
|
|
40
|
-
"@dotcom-tool-kit/component": "^
|
|
40
|
+
"@dotcom-tool-kit/component": "^4.0.4",
|
|
41
41
|
"@dotcom-tool-kit/eslint": "^3.1.3",
|
|
42
42
|
"@dotcom-tool-kit/frontend-app": "^3.1.9",
|
|
43
|
+
"@dotcom-tool-kit/husky-npm": "^4.1.0",
|
|
43
44
|
"@dotcom-tool-kit/jest": "^3.2.0",
|
|
44
45
|
"@dotcom-tool-kit/lint-staged": "^4.1.3",
|
|
45
46
|
"@dotcom-tool-kit/logger": "^3.1.1",
|