@financial-times/n-conversion-forms 39.0.0 → 39.2.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "branch": "",
3
3
  "repo": "n-conversion-forms",
4
- "version": "78ce79e3d5055df8040fdc1e567d8b873a2b42fb",
5
- "tag": "v39.0.0"
4
+ "version": "6b38e46e4b26d1c996751c0fe4a2ffcd8b6fecb6",
5
+ "tag": "v39.2.0"
6
6
  }
@@ -1,5 +1,35 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
+ exports[`DeliveryOption renders a print offer HD for LUX country 1`] = `
4
+ <div id="deliveryOptionField"
5
+ class="o-forms-field ncf__delivery-option"
6
+ role="group"
7
+ aria-label="Delivery options"
8
+ >
9
+ <span class="o-forms-input o-forms-input--radio-round">
10
+ <label class="ncf__delivery-option__item"
11
+ for="HD"
12
+ >
13
+ <input type="radio"
14
+ id="HD"
15
+ name="deliveryOption"
16
+ value="HD"
17
+ class="ncf__delivery-option__input"
18
+ checked
19
+ >
20
+ <span class="o-forms-input__label ncf__delivery-option__label">
21
+ <span class="ncf__delivery-option__title o-forms-title__main">
22
+ Hand delivery
23
+ </span>
24
+ <div class="ncf__delivery-option__description">
25
+ Enjoy delivery of the newspaper daily to your home or office address.
26
+ </div>
27
+ </span>
28
+ </label>
29
+ </span>
30
+ </div>
31
+ `;
32
+
3
33
  exports[`DeliveryOption renders with USA print offer 1`] = `
4
34
  <div id="deliveryOptionField"
5
35
  class="o-forms-field ncf__delivery-option"
@@ -249,3 +249,161 @@ exports[`RegistrationConfirmation renders with default props 1`] = `
249
249
  </a>
250
250
  </div>
251
251
  `;
252
+
253
+ exports[`RegistrationConfirmation renders with subscription finder banner 1`] = `
254
+ <div class="ncf">
255
+ <div class="ncf__center ncf__margin">
256
+ <div class="ncf__icon ncf__icon--tick ncf__icon--large">
257
+ </div>
258
+ <h1 class="ncf__header ncf__header--confirmation">
259
+ Success
260
+ </h1>
261
+ <p class="ncf__confirmation--message">
262
+ We’ve sent confirmation to your email.
263
+ </p>
264
+ </div>
265
+ <div class="ncf__confirmation__professional-subscription-check-banner"
266
+ data-trackable="professional-subscription-check-banner"
267
+ >
268
+ <div class="ncf__confirmation__professional-subscription-check-banner-header">
269
+ <h2 class="ncf__confirmation__professional-subscription-check-banner-title">
270
+ See if you can join the FT through your organisation
271
+ </h2>
272
+ <p class="ncf__confirmation__professional-subscription-check-banner-text">
273
+ Your email address matches the domain we have for an FT Professional subscription. This means your organisation may have an FT subscription you can join for free.
274
+ </p>
275
+ </div>
276
+ <ul class="ncf__confirmation__professional-subscription-check-banner-checklist">
277
+ <li class="ncf__confirmation__professional-subscription-check-banner-checklist-item">
278
+ Get the
279
+ <b class="ncf__confirmation__professional-subscription-check-banner-text--bold">
280
+ FT for free
281
+ </b>
282
+ through your organisation
283
+ </li>
284
+ <li class="ncf__confirmation__professional-subscription-check-banner-checklist-item">
285
+ Full access to Standard FT content
286
+ </li>
287
+ <li class="ncf__confirmation__professional-subscription-check-banner-checklist-item">
288
+ Unlimited access to Premium content and newsletters
289
+ </li>
290
+ </ul>
291
+ <a href="https://example.com"
292
+ class="ncf__button ncf__button--professional-inverse"
293
+ data-trackable="professional-subscription-check-banner-request"
294
+ >
295
+ Check if your organisation subscribes
296
+ </a>
297
+ </div>
298
+ <div class="ncf__divider-horizontal">
299
+ </div>
300
+ <div class="ncf__confirmation--links ncf__margin">
301
+ <div class="ncf__confirmation--socials">
302
+ <b>
303
+ Breaking news alerts, direct to your lock screen
304
+ </b>
305
+ <p class="ncf__confirmation--mobile">
306
+ Download our apps or follow us on our socials
307
+ </p>
308
+ <p class="ncf__confirmation--desktop">
309
+ Find us in the app and google play stores or follow us on our socials
310
+ </p>
311
+ <div class="ncf__confirmation--badges">
312
+ <div class="o-social-follow"
313
+ aria-label="Follow on social media"
314
+ >
315
+ <a href="https://www.instagram.com/financialtimes"
316
+ class="o-social-follow-icon o-social-follow-icon--instagram"
317
+ target="_blank"
318
+ rel="noopener noreferrer"
319
+ data-trackable="register-social-instagram"
320
+ >
321
+ <span class="o-social-follow-icon__label">
322
+ on instagram
323
+ </span>
324
+ </a>
325
+ <a href="https://www.linkedin.com/company/financial-times"
326
+ class="o-social-follow-icon o-social-follow-icon--linkedin"
327
+ target="_blank"
328
+ rel="noopener noreferrer"
329
+ data-trackable="register-social-linkedin"
330
+ >
331
+ <span class="o-social-follow-icon__label">
332
+ on linkedin
333
+ </span>
334
+ </a>
335
+ <a href="https://twitter.com/FT"
336
+ class="o-social-follow-icon o-social-follow-icon--twitter"
337
+ target="_blank"
338
+ rel="noopener noreferrer"
339
+ data-trackable="register-social-twitter"
340
+ >
341
+ <span class="o-social-follow-icon__label">
342
+ on twitter
343
+ </span>
344
+ </a>
345
+ <a href="https://www.facebook.com/financialtimes"
346
+ class="o-social-follow-icon o-social-follow-icon--facebook"
347
+ target="_blank"
348
+ rel="noopener noreferrer"
349
+ data-trackable="register-social-facebook"
350
+ >
351
+ <span class="o-social-follow-icon__label">
352
+ on facebook
353
+ </span>
354
+ </a>
355
+ </div>
356
+ <div class="ncf__confirmation--mobile ncf__confirmation--app-badges"
357
+ aria-label="Download the app"
358
+ >
359
+ <a href="https://apps.apple.com/app/apple-store/id1200842933"
360
+ class="ncf-icon ncf-icon--apple"
361
+ target="_blank"
362
+ rel="noopener noreferrer"
363
+ data-trackable="register-app-apple"
364
+ >
365
+ <span class="o-social-follow-icon__label">
366
+ on apple
367
+ </span>
368
+ </a>
369
+ <a href="https://play.google.com/store/apps/details?id=com.ft.news"
370
+ class="ncf-icon ncf-icon--android"
371
+ target="_blank"
372
+ rel="noopener noreferrer"
373
+ data-trackable="register-app-android"
374
+ >
375
+ <span class="o-social-follow-icon__label">
376
+ on android
377
+ </span>
378
+ </a>
379
+ </div>
380
+ </div>
381
+ </div>
382
+ <div class="ncf__confirmation--alerts">
383
+ <b>
384
+ Set up email alerts in
385
+ <span aria-label="myFT"
386
+ class="ncf-icon ncf-icon--myft"
387
+ >
388
+ </span>
389
+ </b>
390
+ <p>
391
+ Choose the content you want to follow by personalising your alerts for the most important topics and additional newsletters
392
+ </p>
393
+ <a href="/myft"
394
+ class="margin-top-x4 ncf__button ncf__button--secondary"
395
+ data-trackable="register-personalise-my-alerts"
396
+ >
397
+ Personalise my alerts
398
+ </a>
399
+ </div>
400
+ </div>
401
+ <a href="/"
402
+ target="_parent"
403
+ class="ncf__confirmation--finish ncf__button ncf__button--submit"
404
+ data-trackable="register-finish"
405
+ >
406
+ Start reading
407
+ </a>
408
+ </div>
409
+ `;
@@ -7,10 +7,7 @@ import {
7
7
  addressLine2AutoComplete,
8
8
  addressLine3AutoComplete,
9
9
  } from '../helpers/constants';
10
- import {
11
- identifyFTShippingZone,
12
- countriesSupportedISO,
13
- } from '../helpers/supportedCountries';
10
+ import { identifyShippingZone } from '../helpers/supportedCountries';
14
11
 
15
12
  export function DeliveryAddress({
16
13
  fieldId = 'deliveryAddressFields',
@@ -29,7 +26,7 @@ export function DeliveryAddress({
29
26
  'o-forms-input--text',
30
27
  { 'o-forms-input--invalid': hasError },
31
28
  ]);
32
- const FTShippingZone = identifyFTShippingZone(country);
29
+ const shippingZone = identifyShippingZone(country);
33
30
 
34
31
  const addressLine1 = (
35
32
  <label
@@ -38,7 +35,7 @@ export function DeliveryAddress({
38
35
  >
39
36
  <span className="o-forms-title">
40
37
  <span className="o-forms-title__main">
41
- {deliveryAddressMap[addressType].addressLine1Title[FTShippingZone] ||
38
+ {deliveryAddressMap[addressType].addressLine1Title[shippingZone] ||
42
39
  'Address line 1'}
43
40
  </span>
44
41
  </span>
@@ -51,8 +48,8 @@ export function DeliveryAddress({
51
48
  autoComplete={addressLine1AutoComplete}
52
49
  placeholder={
53
50
  deliveryAddressMap[addressType].addressLine1Placeholder[
54
- FTShippingZone
55
- ]
51
+ shippingZone
52
+ ] || ''
56
53
  }
57
54
  maxLength={50}
58
55
  aria-required="true"
@@ -83,12 +80,12 @@ export function DeliveryAddress({
83
80
  data-trackable="field-deliveryAddressLine2"
84
81
  autoComplete={
85
82
  deliveryAddressMap[addressType].addressLine2AutoComplete[
86
- FTShippingZone
83
+ shippingZone
87
84
  ] || addressLine2AutoComplete
88
85
  }
89
86
  placeholder={
90
87
  deliveryAddressMap[addressType].addressLine2Placeholder[
91
- FTShippingZone
88
+ shippingZone
92
89
  ] || ''
93
90
  }
94
91
  maxLength={50}
@@ -106,10 +103,10 @@ export function DeliveryAddress({
106
103
  >
107
104
  <span className="o-forms-title">
108
105
  <span className="o-forms-title__main">
109
- {deliveryAddressMap[addressType].addressLine3Title[FTShippingZone]}
106
+ {deliveryAddressMap[addressType].addressLine3Title[shippingZone]}
110
107
  </span>
111
108
  <span className="o-forms-title__prompt">
112
- {deliveryAddressMap[addressType].addressLine3Prompt[FTShippingZone]}
109
+ {deliveryAddressMap[addressType].addressLine3Prompt[shippingZone]}
113
110
  </span>
114
111
  </span>
115
112
  <span className={inputWrapperClassNames}>
@@ -120,12 +117,12 @@ export function DeliveryAddress({
120
117
  data-trackable="field-deliveryAddressLine3"
121
118
  autoComplete={
122
119
  deliveryAddressMap[addressType].addressLine3AutoComplete[
123
- FTShippingZone
120
+ shippingZone
124
121
  ] || addressLine3AutoComplete
125
122
  }
126
123
  placeholder={
127
124
  deliveryAddressMap[addressType].addressLine3Placeholder[
128
- FTShippingZone
125
+ shippingZone
129
126
  ] || 'e.g. Apt. 1'
130
127
  }
131
128
  maxLength={
@@ -141,7 +138,7 @@ export function DeliveryAddress({
141
138
  addressLine1,
142
139
  addressLine2,
143
140
  addressLine3,
144
- FTShippingZone
141
+ shippingZone
145
142
  );
146
143
 
147
144
  return (
@@ -159,6 +156,6 @@ DeliveryAddress.propTypes = {
159
156
  line3: PropTypes.string,
160
157
  isDisabled: PropTypes.bool,
161
158
  isHidden: PropTypes.bool,
162
- country: PropTypes.oneOf(countriesSupportedISO),
159
+ country: PropTypes.string,
163
160
  addressType: PropTypes.oneOf(['home', 'company', 'pobox']),
164
161
  };
@@ -1,10 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import classNames from 'classnames';
4
- import {
5
- countriesSupportedISO,
6
- identifyFTShippingZone,
7
- } from '../helpers/supportedCountries';
4
+ import { identifyShippingZone } from '../helpers/supportedCountries';
8
5
 
9
6
  export function DeliveryCity({
10
7
  hasError = false,
@@ -24,15 +21,15 @@ export function DeliveryCity({
24
21
  CAN: 'e.g. Montreal',
25
22
  ARE: 'e.g. Dubai',
26
23
  };
27
- const FTShippingZone = identifyFTShippingZone(country);
24
+ const shippingZone = identifyShippingZone(country);
28
25
 
29
26
  const labelMapping = {
30
27
  ARE: 'Emirate or City',
31
28
  APAC: 'City/Prefecture',
32
29
  DEFAULT: 'City',
33
30
  };
34
- const inputLabel = labelMapping[FTShippingZone]
35
- ? labelMapping[FTShippingZone]
31
+ const inputLabel = labelMapping[shippingZone]
32
+ ? labelMapping[shippingZone]
36
33
  : labelMapping['DEFAULT'];
37
34
 
38
35
  return (
@@ -72,5 +69,5 @@ DeliveryCity.propTypes = {
72
69
  value: PropTypes.string,
73
70
  isDisabled: PropTypes.bool,
74
71
  maxlength: PropTypes.number,
75
- country: PropTypes.oneOf(countriesSupportedISO),
72
+ country: PropTypes.string,
76
73
  };
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import classNames from 'classnames';
4
- import { identifyFTShippingZone } from '../helpers/supportedCountries';
4
+ import { identifyShippingZone } from '../helpers/supportedCountries';
5
5
 
6
6
  const spanMessageByCountry = {
7
7
  GBR: (
@@ -99,7 +99,7 @@ export function DeliveryInstructions({
99
99
  fieldId = 'deliveryInstructionsField',
100
100
  hasError = false,
101
101
  inputId = 'deliveryInstructions',
102
- maxlength = null,
102
+ maxlength = '',
103
103
  rows = null,
104
104
  isDisabled = false,
105
105
  placeholder = '',
@@ -111,12 +111,12 @@ export function DeliveryInstructions({
111
111
  'o-forms-input--textarea',
112
112
  { 'o-forms-input--invalid': hasError },
113
113
  ]);
114
- const FTShippingZone = identifyFTShippingZone(country);
114
+ const shippingZone = identifyShippingZone(country);
115
115
  const extraInstruction =
116
116
  country === 'GBR'
117
117
  ? ''
118
118
  : '\u000a- Special handling, e.g. place in plastic bag, 24/7 security on reception';
119
- const defaultPlaceholder = {
119
+ const shippingZoneToPlaceholderMap = {
120
120
  CEMEA_V1: `Enter instructions ${
121
121
  maxlength && `(Max. ${maxlength} characters)`
122
122
  }:\u000a- Door colour, letterbox location\u000a- Door entry codes, etc.`,
@@ -134,13 +134,20 @@ export function DeliveryInstructions({
134
134
  }:\u000a- Door colour, driveway signage\u000a- Cross street${extraInstruction}`,
135
135
  };
136
136
 
137
+ const defaultPlaceholder = `Enter instructions ${
138
+ maxlength && `(Max. ${maxlength} characters)`
139
+ }:\u000a- Door colour, letterbox location\u000a- Door entry codes, etc.`;
140
+
137
141
  const textAreaProps = {
138
142
  id: inputId,
139
143
  name: inputId,
140
144
  ...(maxlength && { maxLength: maxlength }),
141
145
  ...(rows && { rows }),
142
146
  'data-trackable': 'field-deliveryInstructions',
143
- placeholder: placeholder ? placeholder : defaultPlaceholder[FTShippingZone],
147
+ placeholder:
148
+ placeholder ||
149
+ shippingZoneToPlaceholderMap[shippingZone] ||
150
+ defaultPlaceholder,
144
151
  disabled: isDisabled,
145
152
  defaultValue: value,
146
153
  };
@@ -160,7 +167,7 @@ export function DeliveryInstructions({
160
167
  >
161
168
  <span className="o-forms-title">
162
169
  <span className="o-forms-title__main">Delivery instructions</span>
163
- {spanMessageByCountry[FTShippingZone]}
170
+ {spanMessageByCountry[shippingZone]}
164
171
  {country === 'GBR' && deliveryInstructionsMessage}
165
172
  </span>
166
173
 
@@ -177,5 +184,5 @@ DeliveryInstructions.propTypes = {
177
184
  rows: PropTypes.number,
178
185
  isDisabled: PropTypes.bool,
179
186
  value: PropTypes.string,
180
- country: PropTypes.oneOf(['GBR', 'USA', 'CAN']).isRequired,
187
+ country: PropTypes.string.isRequired,
181
188
  };
@@ -10,17 +10,38 @@ export default {
10
10
  },
11
11
  };
12
12
 
13
- export const Basic = (args) => <DeliveryInstructions {...args} />;
14
- Basic.args = {
13
+ export const GreatBritainDeliveryInstructions = (args) => (
14
+ <DeliveryInstructions {...args} />
15
+ );
16
+ GreatBritainDeliveryInstructions.args = {
15
17
  country: 'GBR',
18
+ maxlength: 50,
16
19
  };
17
20
 
18
- export const SpanMessageForUSA = (args) => <DeliveryInstructions {...args} />;
19
- SpanMessageForUSA.args = {
21
+ export const UnitedStatesDeliveryInstructions = (args) => (
22
+ <DeliveryInstructions {...args} />
23
+ );
24
+ UnitedStatesDeliveryInstructions.args = {
20
25
  country: 'USA',
21
26
  };
22
27
 
23
- export const SpanMessageForCAN = (args) => <DeliveryInstructions {...args} />;
24
- SpanMessageForCAN.args = {
28
+ export const CanadaDeliveryInstructions = (args) => (
29
+ <DeliveryInstructions {...args} />
30
+ );
31
+ CanadaDeliveryInstructions.args = {
25
32
  country: 'CAN',
26
33
  };
34
+
35
+ export const LuxembourgDeliveryInstructions = (args) => (
36
+ <DeliveryInstructions {...args} />
37
+ );
38
+ LuxembourgDeliveryInstructions.args = {
39
+ country: 'LUX',
40
+ };
41
+
42
+ export const BosniaDeliveryInstructions = (args) => (
43
+ <DeliveryInstructions {...args} />
44
+ );
45
+ BosniaDeliveryInstructions.args = {
46
+ country: 'BIH',
47
+ };
@@ -2,10 +2,7 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import classNames from 'classnames';
4
4
  import { getDeliveryOption } from '../utils/delivery-option-messages';
5
- import {
6
- identifyFTShippingZone,
7
- countriesSupportedISO,
8
- } from '../helpers/supportedCountries';
5
+ import { identifyShippingZone } from '../helpers/supportedCountries';
9
6
 
10
7
  export function DeliveryOption({
11
8
  fieldId = 'deliveryOptionField',
@@ -20,7 +17,7 @@ export function DeliveryOption({
20
17
  { 'ncf__delivery-option--single': isSingle },
21
18
  ]);
22
19
 
23
- const shippingZone = identifyFTShippingZone(countryCode);
20
+ const shippingZone = identifyShippingZone(countryCode);
24
21
 
25
22
  return (
26
23
  <div
@@ -87,7 +84,7 @@ export function DeliveryOption({
87
84
  }
88
85
 
89
86
  DeliveryOption.propTypes = {
90
- country: PropTypes.oneOf(countriesSupportedISO).isRequired,
87
+ country: PropTypes.string.isRequired,
91
88
  productCode: PropTypes.string,
92
89
  options: PropTypes.arrayOf(
93
90
  PropTypes.shape({
@@ -128,4 +128,23 @@ describe('DeliveryOption', () => {
128
128
 
129
129
  expect(DeliveryOption).toRenderCorrectly(props);
130
130
  });
131
+
132
+ it('renders a print offer HD for LUX country', () => {
133
+ const props = {
134
+ country: 'LUX',
135
+ productCode: 'EPNWE',
136
+ options: [
137
+ {
138
+ value: 'HD',
139
+ isSelected: true,
140
+ isValidDeliveryOption: true,
141
+ deliveryOnPublicationDate: false,
142
+ flightMarket: true,
143
+ mailDelivery: false,
144
+ },
145
+ ],
146
+ };
147
+
148
+ expect(DeliveryOption).toRenderCorrectly(props);
149
+ });
131
150
  });
@@ -104,3 +104,23 @@ JapanDeliveryOptions.args = {
104
104
  },
105
105
  ],
106
106
  };
107
+
108
+ export const LuxembourgDeliveryOptions = (args) => (
109
+ <div className="ncf">
110
+ <DeliveryOption {...args} />
111
+ </div>
112
+ );
113
+ LuxembourgDeliveryOptions.args = {
114
+ country: 'LUX',
115
+ productCode: 'EPNWE',
116
+ options: [
117
+ {
118
+ value: 'HD',
119
+ isSelected: true,
120
+ isValidDeliveryOption: true,
121
+ deliveryOnPublicationDate: false,
122
+ flightMarket: true,
123
+ mailDelivery: false,
124
+ },
125
+ ],
126
+ };
@@ -2,6 +2,8 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
 
4
4
  const EMAIL_DEFAULT_TEXT = 'your email';
5
+ const DEFAULT_PROFESSIONAL_SUBSCRIPTION_CHECK_REQUEST_URL =
6
+ 'https://find-your-subscription.ft.com/request';
5
7
 
6
8
  const SOCIALS = [
7
9
  {
@@ -35,6 +37,8 @@ const STORES = [
35
37
 
36
38
  export function RegistrationConfirmation({
37
39
  email = EMAIL_DEFAULT_TEXT,
40
+ showProfessionalSubscriptionCheckBanner = false,
41
+ professionalSubscriptionCheckRequestUrl = DEFAULT_PROFESSIONAL_SUBSCRIPTION_CHECK_REQUEST_URL,
38
42
  returnUrl = '/',
39
43
  }) {
40
44
  return (
@@ -47,6 +51,48 @@ export function RegistrationConfirmation({
47
51
  </p>
48
52
  </div>
49
53
 
54
+ {showProfessionalSubscriptionCheckBanner && (
55
+ <div
56
+ className="ncf__confirmation__professional-subscription-check-banner"
57
+ data-trackable="professional-subscription-check-banner"
58
+ >
59
+ <div className="ncf__confirmation__professional-subscription-check-banner-header">
60
+ <h2 className="ncf__confirmation__professional-subscription-check-banner-title">
61
+ See if you can join the FT through your organisation
62
+ </h2>
63
+ <p className="ncf__confirmation__professional-subscription-check-banner-text">
64
+ Your email address matches the domain we have for an FT
65
+ Professional subscription. This means your organisation may have
66
+ an FT subscription you can join for free.
67
+ </p>
68
+ </div>
69
+
70
+ <ul className="ncf__confirmation__professional-subscription-check-banner-checklist">
71
+ <li className="ncf__confirmation__professional-subscription-check-banner-checklist-item">
72
+ Get the{' '}
73
+ <b className="ncf__confirmation__professional-subscription-check-banner-text--bold">
74
+ FT for free
75
+ </b>{' '}
76
+ through your organisation
77
+ </li>
78
+ <li className="ncf__confirmation__professional-subscription-check-banner-checklist-item">
79
+ Full access to Standard FT content
80
+ </li>
81
+ <li className="ncf__confirmation__professional-subscription-check-banner-checklist-item">
82
+ Unlimited access to Premium content and newsletters
83
+ </li>
84
+ </ul>
85
+
86
+ <a
87
+ href={professionalSubscriptionCheckRequestUrl}
88
+ className="ncf__button ncf__button--professional-inverse"
89
+ data-trackable="professional-subscription-check-banner-request"
90
+ >
91
+ Check if your organisation subscribes
92
+ </a>
93
+ </div>
94
+ )}
95
+
50
96
  <div className="ncf__divider-horizontal" />
51
97
 
52
98
  <div className="ncf__confirmation--links ncf__margin">
@@ -130,4 +176,6 @@ export function RegistrationConfirmation({
130
176
 
131
177
  RegistrationConfirmation.propTypes = {
132
178
  email: PropTypes.string,
179
+ showProfessionalSubscriptionCheckBanner: PropTypes.bool,
180
+ professionalSubscriptionCheckRequestUrl: PropTypes.string,
133
181
  };
@@ -15,4 +15,13 @@ describe('RegistrationConfirmation', () => {
15
15
 
16
16
  expect(RegistrationConfirmation).toRenderCorrectly(props);
17
17
  });
18
+
19
+ it('renders with subscription finder banner', () => {
20
+ const props = {
21
+ showProfessionalSubscriptionCheckBanner: true,
22
+ professionalSubscriptionCheckRequestUrl: 'https://example.com',
23
+ };
24
+
25
+ expect(RegistrationConfirmation).toRenderCorrectly(props);
26
+ });
18
27
  });
@@ -8,3 +8,11 @@ export default {
8
8
 
9
9
  export const Basic = (args) => <RegistrationConfirmation {...args} />;
10
10
  Basic.args = {};
11
+
12
+ export const WithProfessionalSubscriptionCheckBanner = (args) => (
13
+ <RegistrationConfirmation {...args} />
14
+ );
15
+ WithProfessionalSubscriptionCheckBanner.args = {
16
+ ...Basic.args,
17
+ showProfessionalSubscriptionCheckBanner: true,
18
+ };
@@ -36,7 +36,7 @@ function DeliveryAddress(_ref) {
36
36
  var inputWrapperClassNames = (0, _classnames["default"])(['o-forms-input', 'o-forms-input--text', {
37
37
  'o-forms-input--invalid': hasError
38
38
  }]);
39
- var FTShippingZone = (0, _supportedCountries.identifyFTShippingZone)(country);
39
+ var shippingZone = (0, _supportedCountries.identifyShippingZone)(country);
40
40
  var addressLine1 = /*#__PURE__*/_react["default"].createElement("label", {
41
41
  className: "o-forms-field ncf__validation-error",
42
42
  htmlFor: "deliveryAddressLine1"
@@ -44,7 +44,7 @@ function DeliveryAddress(_ref) {
44
44
  className: "o-forms-title"
45
45
  }, /*#__PURE__*/_react["default"].createElement("span", {
46
46
  className: "o-forms-title__main"
47
- }, _deliveryAddressMap["default"][addressType].addressLine1Title[FTShippingZone] || 'Address line 1')), /*#__PURE__*/_react["default"].createElement("span", {
47
+ }, _deliveryAddressMap["default"][addressType].addressLine1Title[shippingZone] || 'Address line 1')), /*#__PURE__*/_react["default"].createElement("span", {
48
48
  className: inputWrapperClassNames
49
49
  }, /*#__PURE__*/_react["default"].createElement("input", {
50
50
  type: "text",
@@ -52,7 +52,7 @@ function DeliveryAddress(_ref) {
52
52
  name: "deliveryAddressLine1",
53
53
  "data-trackable": "field-deliveryAddressLine1",
54
54
  autoComplete: _constants.addressLine1AutoComplete,
55
- placeholder: _deliveryAddressMap["default"][addressType].addressLine1Placeholder[FTShippingZone],
55
+ placeholder: _deliveryAddressMap["default"][addressType].addressLine1Placeholder[shippingZone] || '',
56
56
  maxLength: 50,
57
57
  "aria-required": "true",
58
58
  required: true,
@@ -75,8 +75,8 @@ function DeliveryAddress(_ref) {
75
75
  id: "deliveryAddressLine2",
76
76
  name: "deliveryAddressLine2",
77
77
  "data-trackable": "field-deliveryAddressLine2",
78
- autoComplete: _deliveryAddressMap["default"][addressType].addressLine2AutoComplete[FTShippingZone] || _constants.addressLine2AutoComplete,
79
- placeholder: _deliveryAddressMap["default"][addressType].addressLine2Placeholder[FTShippingZone] || '',
78
+ autoComplete: _deliveryAddressMap["default"][addressType].addressLine2AutoComplete[shippingZone] || _constants.addressLine2AutoComplete,
79
+ placeholder: _deliveryAddressMap["default"][addressType].addressLine2Placeholder[shippingZone] || '',
80
80
  maxLength: 50,
81
81
  disabled: isDisabled,
82
82
  defaultValue: line2
@@ -88,22 +88,22 @@ function DeliveryAddress(_ref) {
88
88
  className: "o-forms-title"
89
89
  }, /*#__PURE__*/_react["default"].createElement("span", {
90
90
  className: "o-forms-title__main"
91
- }, _deliveryAddressMap["default"][addressType].addressLine3Title[FTShippingZone]), /*#__PURE__*/_react["default"].createElement("span", {
91
+ }, _deliveryAddressMap["default"][addressType].addressLine3Title[shippingZone]), /*#__PURE__*/_react["default"].createElement("span", {
92
92
  className: "o-forms-title__prompt"
93
- }, _deliveryAddressMap["default"][addressType].addressLine3Prompt[FTShippingZone])), /*#__PURE__*/_react["default"].createElement("span", {
93
+ }, _deliveryAddressMap["default"][addressType].addressLine3Prompt[shippingZone])), /*#__PURE__*/_react["default"].createElement("span", {
94
94
  className: inputWrapperClassNames
95
95
  }, /*#__PURE__*/_react["default"].createElement("input", {
96
96
  type: "text",
97
97
  id: "deliveryAddressLine3",
98
98
  name: "deliveryAddressLine3",
99
99
  "data-trackable": "field-deliveryAddressLine3",
100
- autoComplete: _deliveryAddressMap["default"][addressType].addressLine3AutoComplete[FTShippingZone] || _constants.addressLine3AutoComplete,
101
- placeholder: _deliveryAddressMap["default"][addressType].addressLine3Placeholder[FTShippingZone] || 'e.g. Apt. 1',
100
+ autoComplete: _deliveryAddressMap["default"][addressType].addressLine3AutoComplete[shippingZone] || _constants.addressLine3AutoComplete,
101
+ placeholder: _deliveryAddressMap["default"][addressType].addressLine3Placeholder[shippingZone] || 'e.g. Apt. 1',
102
102
  maxLength: _deliveryAddressMap["default"][addressType].addressLine3MaxLength[country] || 50,
103
103
  disabled: isDisabled,
104
104
  defaultValue: line3
105
105
  })));
106
- var addressLines = _deliveryAddressMap["default"][addressType].template(addressLine1, addressLine2, addressLine3, FTShippingZone);
106
+ var addressLines = _deliveryAddressMap["default"][addressType].template(addressLine1, addressLine2, addressLine3, shippingZone);
107
107
  return /*#__PURE__*/_react["default"].createElement("div", {
108
108
  id: fieldId,
109
109
  "data-validate": "required",
@@ -118,6 +118,6 @@ DeliveryAddress.propTypes = {
118
118
  line3: _propTypes["default"].string,
119
119
  isDisabled: _propTypes["default"].bool,
120
120
  isHidden: _propTypes["default"].bool,
121
- country: _propTypes["default"].oneOf(_supportedCountries.countriesSupportedISO),
121
+ country: _propTypes["default"].string,
122
122
  addressType: _propTypes["default"].oneOf(['home', 'company', 'pobox'])
123
123
  };
@@ -27,13 +27,13 @@ function DeliveryCity(_ref) {
27
27
  CAN: 'e.g. Montreal',
28
28
  ARE: 'e.g. Dubai'
29
29
  };
30
- var FTShippingZone = (0, _supportedCountries.identifyFTShippingZone)(country);
30
+ var shippingZone = (0, _supportedCountries.identifyShippingZone)(country);
31
31
  var labelMapping = {
32
32
  ARE: 'Emirate or City',
33
33
  APAC: 'City/Prefecture',
34
34
  DEFAULT: 'City'
35
35
  };
36
- var inputLabel = labelMapping[FTShippingZone] ? labelMapping[FTShippingZone] : labelMapping['DEFAULT'];
36
+ var inputLabel = labelMapping[shippingZone] ? labelMapping[shippingZone] : labelMapping['DEFAULT'];
37
37
  return /*#__PURE__*/_react["default"].createElement("label", {
38
38
  id: "deliveryCityField",
39
39
  className: "o-forms-field ncf__validation-error",
@@ -66,5 +66,5 @@ DeliveryCity.propTypes = {
66
66
  value: _propTypes["default"].string,
67
67
  isDisabled: _propTypes["default"].bool,
68
68
  maxlength: _propTypes["default"].number,
69
- country: _propTypes["default"].oneOf(_supportedCountries.countriesSupportedISO)
69
+ country: _propTypes["default"].string
70
70
  };
@@ -62,7 +62,7 @@ function DeliveryInstructions(_ref) {
62
62
  _ref$inputId = _ref.inputId,
63
63
  inputId = _ref$inputId === void 0 ? 'deliveryInstructions' : _ref$inputId,
64
64
  _ref$maxlength = _ref.maxlength,
65
- maxlength = _ref$maxlength === void 0 ? null : _ref$maxlength,
65
+ maxlength = _ref$maxlength === void 0 ? '' : _ref$maxlength,
66
66
  _ref$rows = _ref.rows,
67
67
  rows = _ref$rows === void 0 ? null : _ref$rows,
68
68
  _ref$isDisabled = _ref.isDisabled,
@@ -75,15 +75,16 @@ function DeliveryInstructions(_ref) {
75
75
  var textAreaWrapperClassNames = (0, _classnames["default"])(['o-forms-input', 'o-forms-input--textarea', {
76
76
  'o-forms-input--invalid': hasError
77
77
  }]);
78
- var FTShippingZone = (0, _supportedCountries.identifyFTShippingZone)(country);
78
+ var shippingZone = (0, _supportedCountries.identifyShippingZone)(country);
79
79
  var extraInstruction = country === 'GBR' ? '' : "\n- Special handling, e.g. place in plastic bag, 24/7 security on reception";
80
- var defaultPlaceholder = {
80
+ var shippingZoneToPlaceholderMap = {
81
81
  CEMEA_V1: "Enter instructions ".concat(maxlength && "(Max. ".concat(maxlength, " characters)"), ":\n- Door colour, letterbox location\n- Door entry codes, etc."),
82
82
  CEMEA_V2: "Enter instructions ".concat(maxlength && "(Max. ".concat(maxlength, " characters)"), ":\n- Door colour, letterbox location\n- Door entry codes, etc."),
83
83
  GBR: "Enter instructions ".concat(maxlength && "(Max. ".concat(maxlength, " characters)"), ":\n- Door colour, letterbox location\n- Placement i.e. letterbox delivery").concat(extraInstruction),
84
84
  USA: "Enter instructions ".concat(maxlength && "(Max. ".concat(maxlength, " characters)"), ":\n- Door colour, driveway signage\n- Cross street").concat(extraInstruction),
85
85
  CAN: "Enter instructions ".concat(maxlength && "(Max. ".concat(maxlength, " characters)"), ":\n- Door colour, driveway signage\n- Cross street").concat(extraInstruction)
86
86
  };
87
+ var defaultPlaceholder = "Enter instructions ".concat(maxlength && "(Max. ".concat(maxlength, " characters)"), ":\n- Door colour, letterbox location\n- Door entry codes, etc.");
87
88
  var textAreaProps = _objectSpread(_objectSpread(_objectSpread({
88
89
  id: inputId,
89
90
  name: inputId
@@ -93,7 +94,7 @@ function DeliveryInstructions(_ref) {
93
94
  rows: rows
94
95
  }), {}, {
95
96
  'data-trackable': 'field-deliveryInstructions',
96
- placeholder: placeholder ? placeholder : defaultPlaceholder[FTShippingZone],
97
+ placeholder: placeholder || shippingZoneToPlaceholderMap[shippingZone] || defaultPlaceholder,
97
98
  disabled: isDisabled,
98
99
  defaultValue: value
99
100
  });
@@ -109,7 +110,7 @@ function DeliveryInstructions(_ref) {
109
110
  className: "o-forms-title"
110
111
  }, /*#__PURE__*/_react["default"].createElement("span", {
111
112
  className: "o-forms-title__main"
112
- }, "Delivery instructions"), spanMessageByCountry[FTShippingZone], country === 'GBR' && deliveryInstructionsMessage), /*#__PURE__*/_react["default"].createElement("span", {
113
+ }, "Delivery instructions"), spanMessageByCountry[shippingZone], country === 'GBR' && deliveryInstructionsMessage), /*#__PURE__*/_react["default"].createElement("span", {
113
114
  className: textAreaWrapperClassNames
114
115
  }, /*#__PURE__*/_react["default"].createElement("textarea", textAreaProps)));
115
116
  }
@@ -119,5 +120,5 @@ DeliveryInstructions.propTypes = {
119
120
  rows: _propTypes["default"].number,
120
121
  isDisabled: _propTypes["default"].bool,
121
122
  value: _propTypes["default"].string,
122
- country: _propTypes["default"].oneOf(['GBR', 'USA', 'CAN']).isRequired
123
+ country: _propTypes["default"].string.isRequired
123
124
  };
@@ -23,7 +23,7 @@ function DeliveryOption(_ref) {
23
23
  var divClassName = (0, _classnames["default"])(['o-forms-field', 'ncf__delivery-option', {
24
24
  'ncf__delivery-option--single': isSingle
25
25
  }]);
26
- var shippingZone = (0, _supportedCountries.identifyFTShippingZone)(countryCode);
26
+ var shippingZone = (0, _supportedCountries.identifyShippingZone)(countryCode);
27
27
  return /*#__PURE__*/_react["default"].createElement("div", {
28
28
  id: fieldId,
29
29
  className: divClassName,
@@ -72,7 +72,7 @@ function DeliveryOption(_ref) {
72
72
  })));
73
73
  }
74
74
  DeliveryOption.propTypes = {
75
- country: _propTypes["default"].oneOf(_supportedCountries.countriesSupportedISO).isRequired,
75
+ country: _propTypes["default"].string.isRequired,
76
76
  productCode: _propTypes["default"].string,
77
77
  options: _propTypes["default"].arrayOf(_propTypes["default"].shape({
78
78
  value: _propTypes["default"].oneOf(['PV', 'HD', 'EV']),
@@ -8,6 +8,7 @@ exports.RegistrationConfirmation = RegistrationConfirmation;
8
8
  var _react = _interopRequireDefault(require("react"));
9
9
  var _propTypes = _interopRequireDefault(require("prop-types"));
10
10
  var EMAIL_DEFAULT_TEXT = 'your email';
11
+ var DEFAULT_PROFESSIONAL_SUBSCRIPTION_CHECK_REQUEST_URL = 'https://find-your-subscription.ft.com/request';
11
12
  var SOCIALS = [{
12
13
  name: 'instagram',
13
14
  link: 'https://www.instagram.com/financialtimes'
@@ -31,6 +32,10 @@ var STORES = [{
31
32
  function RegistrationConfirmation(_ref) {
32
33
  var _ref$email = _ref.email,
33
34
  email = _ref$email === void 0 ? EMAIL_DEFAULT_TEXT : _ref$email,
35
+ _ref$showProfessional = _ref.showProfessionalSubscriptionCheckBanner,
36
+ showProfessionalSubscriptionCheckBanner = _ref$showProfessional === void 0 ? false : _ref$showProfessional,
37
+ _ref$professionalSubs = _ref.professionalSubscriptionCheckRequestUrl,
38
+ professionalSubscriptionCheckRequestUrl = _ref$professionalSubs === void 0 ? DEFAULT_PROFESSIONAL_SUBSCRIPTION_CHECK_REQUEST_URL : _ref$professionalSubs,
34
39
  _ref$returnUrl = _ref.returnUrl,
35
40
  returnUrl = _ref$returnUrl === void 0 ? '/' : _ref$returnUrl;
36
41
  return /*#__PURE__*/_react["default"].createElement("div", {
@@ -43,7 +48,30 @@ function RegistrationConfirmation(_ref) {
43
48
  className: "ncf__header ncf__header--confirmation"
44
49
  }, "Success"), /*#__PURE__*/_react["default"].createElement("p", {
45
50
  className: "ncf__confirmation--message"
46
- }, "We\u2019ve sent confirmation to ", email, ".")), /*#__PURE__*/_react["default"].createElement("div", {
51
+ }, "We\u2019ve sent confirmation to ", email, ".")), showProfessionalSubscriptionCheckBanner && /*#__PURE__*/_react["default"].createElement("div", {
52
+ className: "ncf__confirmation__professional-subscription-check-banner",
53
+ "data-trackable": "professional-subscription-check-banner"
54
+ }, /*#__PURE__*/_react["default"].createElement("div", {
55
+ className: "ncf__confirmation__professional-subscription-check-banner-header"
56
+ }, /*#__PURE__*/_react["default"].createElement("h2", {
57
+ className: "ncf__confirmation__professional-subscription-check-banner-title"
58
+ }, "See if you can join the FT through your organisation"), /*#__PURE__*/_react["default"].createElement("p", {
59
+ className: "ncf__confirmation__professional-subscription-check-banner-text"
60
+ }, "Your email address matches the domain we have for an FT Professional subscription. This means your organisation may have an FT subscription you can join for free.")), /*#__PURE__*/_react["default"].createElement("ul", {
61
+ className: "ncf__confirmation__professional-subscription-check-banner-checklist"
62
+ }, /*#__PURE__*/_react["default"].createElement("li", {
63
+ className: "ncf__confirmation__professional-subscription-check-banner-checklist-item"
64
+ }, "Get the", ' ', /*#__PURE__*/_react["default"].createElement("b", {
65
+ className: "ncf__confirmation__professional-subscription-check-banner-text--bold"
66
+ }, "FT for free"), ' ', "through your organisation"), /*#__PURE__*/_react["default"].createElement("li", {
67
+ className: "ncf__confirmation__professional-subscription-check-banner-checklist-item"
68
+ }, "Full access to Standard FT content"), /*#__PURE__*/_react["default"].createElement("li", {
69
+ className: "ncf__confirmation__professional-subscription-check-banner-checklist-item"
70
+ }, "Unlimited access to Premium content and newsletters")), /*#__PURE__*/_react["default"].createElement("a", {
71
+ href: professionalSubscriptionCheckRequestUrl,
72
+ className: "ncf__button ncf__button--professional-inverse",
73
+ "data-trackable": "professional-subscription-check-banner-request"
74
+ }, "Check if your organisation subscribes")), /*#__PURE__*/_react["default"].createElement("div", {
47
75
  className: "ncf__divider-horizontal"
48
76
  }), /*#__PURE__*/_react["default"].createElement("div", {
49
77
  className: "ncf__confirmation--links ncf__margin"
@@ -104,5 +132,7 @@ function RegistrationConfirmation(_ref) {
104
132
  }, "Start reading"));
105
133
  }
106
134
  RegistrationConfirmation.propTypes = {
107
- email: _propTypes["default"].string
135
+ email: _propTypes["default"].string,
136
+ showProfessionalSubscriptionCheckBanner: _propTypes["default"].bool,
137
+ professionalSubscriptionCheckRequestUrl: _propTypes["default"].string
108
138
  };
package/helpers/index.js CHANGED
@@ -4,8 +4,7 @@ module.exports = {
4
4
  cemeaV1ISO: require('./supportedCountries').cemeaV1ISO,
5
5
  cemeaV2ISO: require('./supportedCountries').cemeaV2ISO,
6
6
  apacISO: require('./supportedCountries').apacISO,
7
- identifyFTShippingZone: require('./supportedCountries')
8
- .identifyFTShippingZone,
7
+ identifyShippingZone: require('./supportedCountries').identifyShippingZone,
9
8
  countriesSupported: require('./supportedCountries').countriesSupported,
10
9
  countriesSupportedISO: require('./supportedCountries').countriesSupportedISO,
11
10
  supportedPostcodeValidators: require('./supportedPostcodeValidators')
@@ -31,8 +31,8 @@ describe('helpers', () => {
31
31
  expect(helpers).toHaveProperty('apacISO');
32
32
  });
33
33
 
34
- it('export identifyFTShippingZone', () => {
35
- expect(helpers).toHaveProperty('identifyFTShippingZone');
34
+ it('export identifyShippingZone', () => {
35
+ expect(helpers).toHaveProperty('identifyShippingZone');
36
36
  });
37
37
 
38
38
  it('export countriesSupported', () => {
@@ -60,7 +60,7 @@ const apacISO = Object.keys(supportedCountriesMasterList.apac);
60
60
  const countriesSupported = flattenObj(supportedCountriesMasterList);
61
61
  const countriesSupportedISO = Object.keys(countriesSupported);
62
62
 
63
- const identifyFTShippingZone = (country) => {
63
+ const identifyShippingZone = (country) => {
64
64
  if (cemeaV1ISO.includes(country)) {
65
65
  return printRegions.cemeaV1;
66
66
  }
@@ -79,5 +79,5 @@ module.exports = {
79
79
  apacISO,
80
80
  countriesSupported,
81
81
  countriesSupportedISO,
82
- identifyFTShippingZone,
82
+ identifyShippingZone,
83
83
  };
package/main.scss CHANGED
@@ -256,6 +256,16 @@
256
256
  );
257
257
  }
258
258
 
259
+ &--professional-inverse {
260
+ @include oButtonsContent(
261
+ $opts: (
262
+ 'size': 'big',
263
+ 'theme': 'professional-inverse',
264
+ 'type': 'primary',
265
+ )
266
+ );
267
+ }
268
+
259
269
  &--secondary {
260
270
  @include oButtonsContent(
261
271
  $opts: (
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/n-conversion-forms",
3
- "version": "39.0.0",
3
+ "version": "39.2.0",
4
4
  "description": "Containing jsx components and styles for forms included on Accounts and Acquisition apps (next-signup, next-profile, next-retention, etc).",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -31,6 +31,114 @@
31
31
  }
32
32
  }
33
33
 
34
+ &__professional-subscription-check-banner {
35
+ display: flex;
36
+ flex-direction: column;
37
+ align-items: flex-start;
38
+ gap: oSpacingByName('s2');
39
+ padding: oSpacingByName('s6') oSpacingByName('s4');
40
+ padding-left: calc(oSpacingByName('m12') + oSpacingByName('s1'));
41
+ background-color: oColorsByName('slate');
42
+ color: oColorsByName('white');
43
+ margin: oSpacingByName('s8') calc((oSpacingByName('m12') + oSpacingByName('s1')));
44
+
45
+ @include oGridRespondTo($until: M) {
46
+ align-items: stretch;
47
+ padding: oSpacingByName('s4');
48
+ margin: oSpacingByName('s8') 0px;
49
+ }
50
+
51
+ &-header {
52
+ flex: 1;
53
+ }
54
+
55
+ &-title {
56
+ text-indent: calc(-1 * (oSpacingByName('m12') + oSpacingByName('s1')));
57
+ margin: 0px;
58
+
59
+ @include oTypographySans(
60
+ $scale: 1,
61
+ $weight: 'semibold',
62
+ $include-font-family: false
63
+ );
64
+
65
+ @include oGridRespondTo($until: M) {
66
+ display: flex;
67
+ align-items: center;
68
+ text-indent: 0px;
69
+
70
+ @include oTypographySans(
71
+ $scale: 0,
72
+ $weight: 'semibold',
73
+ $include-font-family: false
74
+ );
75
+ }
76
+
77
+ &::before {
78
+ @include oIconsContent(
79
+ $icon-name: 'info',
80
+ $color: oColorsByName('white'),
81
+ $size: 32
82
+ );
83
+ content: '';
84
+ color: oColorsByName('white');
85
+ vertical-align: middle;
86
+ margin-right: oSpacingByName('s2');
87
+ margin-left: oSpacingByName('s3');
88
+
89
+ @include oGridRespondTo($until: M) {
90
+ flex-shrink: 0;
91
+ margin: 0px;
92
+ }
93
+ }
94
+ }
95
+
96
+ &-text {
97
+ @include oTypographySans(
98
+ $scale: -1,
99
+ $weight: 'regular',
100
+ $include-font-family: false
101
+ );
102
+ margin: oSpacingByName('s2') 0px 0px;
103
+
104
+ &--bold {
105
+ font-weight: oFontsWeight('semibold');
106
+ }
107
+ }
108
+
109
+ &-checklist {
110
+ list-style-type: none;
111
+ list-style-position: outside;
112
+ padding: 0px;
113
+ margin: 0px;
114
+
115
+ @include oTypographySans(
116
+ $scale: -1,
117
+ $weight: 'regular',
118
+ $include-font-family: false
119
+ );
120
+
121
+ &-item {
122
+ margin: oSpacingByName('s1') 0px;
123
+ border-bottom: 1px solid oColorsMix('white-80', 'slate', 20);
124
+
125
+ &:last-child {
126
+ border-bottom: none;
127
+ }
128
+
129
+ &::before {
130
+ @include oIconsContent(
131
+ $icon-name: 'tick',
132
+ $color: oColorsByName('mint'),
133
+ $size: 32
134
+ );
135
+ content: '';
136
+ vertical-align: middle;
137
+ }
138
+ }
139
+ }
140
+ }
141
+
34
142
  &--links {
35
143
  display: grid;
36
144
  grid-template-rows: 1fr 1fr;
@@ -38,6 +38,114 @@
38
38
  }
39
39
  }
40
40
 
41
+ &__professional-subscription-check-banner {
42
+ display: flex;
43
+ flex-direction: column;
44
+ align-items: flex-start;
45
+ gap: oSpacingByName('s2');
46
+ padding: oSpacingByName('s6') oSpacingByName('s4');
47
+ padding-left: calc(oSpacingByName('m12') + oSpacingByName('s1'));
48
+ background-color: oColorsByName('slate');
49
+ color: oColorsByName('white');
50
+ margin: oSpacingByName('s8') calc((oSpacingByName('m12') + oSpacingByName('s1')));
51
+
52
+ @include oGridRespondTo($until: M) {
53
+ align-items: stretch;
54
+ padding: oSpacingByName('s4');
55
+ margin: oSpacingByName('s8') 0px;
56
+ }
57
+
58
+ &-header {
59
+ flex: 1;
60
+ }
61
+
62
+ &-title {
63
+ text-indent: calc(-1 * (oSpacingByName('m12') + oSpacingByName('s1')));
64
+ margin: 0px;
65
+
66
+ @include oTypographySans(
67
+ $scale: 1,
68
+ $weight: 'semibold',
69
+ $include-font-family: false
70
+ );
71
+
72
+ @include oGridRespondTo($until: M) {
73
+ display: flex;
74
+ align-items: center;
75
+ text-indent: 0px;
76
+
77
+ @include oTypographySans(
78
+ $scale: 0,
79
+ $weight: 'semibold',
80
+ $include-font-family: false
81
+ );
82
+ }
83
+
84
+ &::before {
85
+ @include oIconsContent(
86
+ $icon-name: 'info',
87
+ $color: oColorsByName('white'),
88
+ $size: 32
89
+ );
90
+ content: '';
91
+ color: oColorsByName('white');
92
+ vertical-align: middle;
93
+ margin-right: oSpacingByName('s2');
94
+ margin-left: oSpacingByName('s3');
95
+
96
+ @include oGridRespondTo($until: M) {
97
+ flex-shrink: 0;
98
+ margin: 0px;
99
+ }
100
+ }
101
+ }
102
+
103
+ &-text {
104
+ @include oTypographySans(
105
+ $scale: -1,
106
+ $weight: 'regular',
107
+ $include-font-family: false
108
+ );
109
+ margin: oSpacingByName('s2') 0px 0px;
110
+
111
+ &--bold {
112
+ font-weight: oFontsWeight('semibold');
113
+ }
114
+ }
115
+
116
+ &-checklist {
117
+ list-style-type: none;
118
+ list-style-position: outside;
119
+ padding: 0px;
120
+ margin: 0px;
121
+
122
+ @include oTypographySans(
123
+ $scale: -1,
124
+ $weight: 'regular',
125
+ $include-font-family: false
126
+ );
127
+
128
+ &-item {
129
+ margin: oSpacingByName('s1') 0px;
130
+ border-bottom: 1px solid oColorsMix('white-80', 'slate', 20);
131
+
132
+ &:last-child {
133
+ border-bottom: none;
134
+ }
135
+
136
+ &::before {
137
+ @include oIconsContent(
138
+ $icon-name: 'tick',
139
+ $color: oColorsByName('mint'),
140
+ $size: 32
141
+ );
142
+ content: '';
143
+ vertical-align: middle;
144
+ }
145
+ }
146
+ }
147
+ }
148
+
41
149
  &--links {
42
150
  display: grid;
43
151
  grid-template-rows: 1fr 1fr;
@@ -250,6 +250,15 @@ const deliveryOptionMessages = [
250
250
  },
251
251
  ];
252
252
 
253
+ // Default delivery options based on delivery type
254
+ const defaultDeliveryOptionsMap = {
255
+ HD: {
256
+ title: 'Hand delivery',
257
+ description:
258
+ 'Enjoy delivery of the newspaper daily to your home or office address.',
259
+ },
260
+ };
261
+
253
262
  function includesDeliveryFrequency(productCode = '', item) {
254
263
  return item.deliveryFrequency.find((freq) => {
255
264
  const productCodePattern = deliveryFrequencyProductsMapping[freq];
@@ -308,7 +317,10 @@ function getDeliveryOption({ productCode, option, shippingZone, countryCode }) {
308
317
  return countryCodeToCustomDeliveryOptionsMap[countryCode][option.value];
309
318
  }
310
319
 
311
- return findCustomDeliveryOption(productCode, option, shippingZone);
320
+ return (
321
+ findCustomDeliveryOption(productCode, option, shippingZone) ||
322
+ defaultDeliveryOptionsMap[option.value]
323
+ );
312
324
  }
313
325
 
314
326
  module.exports = {
@@ -1,5 +1,11 @@
1
1
  const { getDeliveryOption } = require('./delivery-option-messages');
2
2
 
3
+ const defaultHandDeliveryOption = {
4
+ title: 'Hand delivery',
5
+ description:
6
+ 'Enjoy delivery of the newspaper daily to your home or office address.',
7
+ };
8
+
3
9
  describe('Find Custom Delivery Option', () => {
4
10
  const stubOption = { value: 'HD' };
5
11
  const sixDaysProductCode = 'P2N6D';
@@ -20,7 +26,7 @@ describe('Find Custom Delivery Option', () => {
20
26
  shippingZone: 'AAA',
21
27
  countryCode: 'AAA',
22
28
  })
23
- ).toBeUndefined();
29
+ ).toEqual(defaultHandDeliveryOption);
24
30
  });
25
31
 
26
32
  it('returns undefined when invalid distributor type code', () => {
@@ -45,7 +51,7 @@ describe('Find Custom Delivery Option', () => {
45
51
  shippingZone: 'AAA',
46
52
  countryCode: 'AAA',
47
53
  })
48
- ).toBeUndefined();
54
+ ).toEqual(defaultHandDeliveryOption);
49
55
  });
50
56
  });
51
57