@designcrowd/library.brand-page 5.17.2 → 5.17.4

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.
Files changed (120) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-DVbX019x.js → CreatedOnBrandCrowd-de-de-C_NzyXvG.js} +3 -3
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-U7ZUILmi.js → CreatedOnBrandCrowd-en-us-DSmpdByg.js} +3 -3
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-D97zjmv_.js → CreatedOnBrandCrowd-es-es-4O9ttd4y.js} +3 -3
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-BuOAG7-D.js → CreatedOnBrandCrowd-fr-ca-DDr8rQHb.js} +3 -3
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-BuOAG7-D.js → CreatedOnBrandCrowd-fr-fr-DDr8rQHb.js} +3 -3
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-DMTRsNBz.js → CreatedOnBrandCrowd-pt-br-BUTVQ17i.js} +3 -3
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-DMTRsNBz.js → CreatedOnBrandCrowd-pt-pt-BUTVQ17i.js} +3 -3
  8. package/lib/src/{CreatedOnDcom-de-de-B_jbp2ga.js → CreatedOnDcom-de-de-thkGl7gg.js} +3 -3
  9. package/lib/src/{CreatedOnDcom-en-us-DQQQhn-z.js → CreatedOnDcom-en-us-DOgnHkVR.js} +3 -3
  10. package/lib/src/{CreatedOnDcom-es-es-q3MzWO6e.js → CreatedOnDcom-es-es-NyEB16vO.js} +3 -3
  11. package/lib/src/{CreatedOnDcom-fr-ca-Bep30mu7.js → CreatedOnDcom-fr-ca-Cd6WjWcu.js} +3 -3
  12. package/lib/src/{CreatedOnDcom-fr-fr-DTF8Zzzc.js → CreatedOnDcom-fr-fr-CDKX35U7.js} +3 -3
  13. package/lib/src/{CreatedOnDcom-pt-br-ByR1GU2L.js → CreatedOnDcom-pt-br-PbJzyRNp.js} +3 -3
  14. package/lib/src/{CreatedOnDcom-pt-pt-A0L4zTr0.js → CreatedOnDcom-pt-pt-tja7jglY.js} +3 -3
  15. package/lib/src/brand-page/clients/brand-page.client.d.ts +2 -1
  16. package/lib/src/brand-page/clients/brand-page.client.js +1 -0
  17. package/lib/src/brand-page/models/payment.model.d.ts +42 -0
  18. package/lib/src/brand-page/models/payment.model.js +9 -0
  19. package/lib/src/brand-page/utils/view-model.util.js +1 -0
  20. package/lib/src/brand-page/view-models.d.ts +1 -0
  21. package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +1 -1
  22. package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +1 -0
  23. package/lib/src/brand-page-maker/composables/useEventTracker.d.ts +2 -0
  24. package/lib/src/brand-page-maker/composables/useEventTracker.js +6 -0
  25. package/lib/src/brand-page-maker/constants/config-settings-constant.d.ts +1 -0
  26. package/lib/src/brand-page-maker/constants/config-settings-constant.js +7 -0
  27. package/lib/src/brand-page-maker/models/content-settings.js +1 -0
  28. package/lib/src/brand-page-maker/validators/section-button.validator.js +4 -1
  29. package/lib/src/bundled-translations-D5A4swr0.js +173 -0
  30. package/lib/src/bundled-translations.de-DE-Bq6H28Hz.js +173 -0
  31. package/lib/src/bundled-translations.es-ES-Bo-UGy51.js +173 -0
  32. package/lib/src/bundled-translations.fr-CA-7GXawEcN.js +173 -0
  33. package/lib/src/bundled-translations.fr-FR-DzVwt2U-.js +173 -0
  34. package/lib/src/bundled-translations.pt-BR-DSZZ-i-B.js +173 -0
  35. package/lib/src/bundled-translations.pt-PT-SNbEX0GM.js +173 -0
  36. package/lib/src/bundles/bundled-translations.de-DE.json +965 -1
  37. package/lib/src/bundles/bundled-translations.es-ES.json +965 -1
  38. package/lib/src/bundles/bundled-translations.fr-CA.json +965 -1
  39. package/lib/src/bundles/bundled-translations.fr-FR.json +965 -1
  40. package/lib/src/bundles/bundled-translations.json +965 -1
  41. package/lib/src/bundles/bundled-translations.pt-BR.json +965 -1
  42. package/lib/src/bundles/bundled-translations.pt-PT.json +965 -1
  43. package/lib/src/composables/useTranslate.d.ts +7 -1
  44. package/lib/src/composables/useTranslate.js +9 -1
  45. package/lib/src/css/library.brand-page-brandCrowd.min.css +76 -55
  46. package/lib/src/css/library.brand-page-brandPage.min.css +77 -57
  47. package/lib/src/css/library.brand-page-designCom.min.css +76 -55
  48. package/lib/src/css/library.brand-page-preview.min.css +76 -55
  49. package/lib/src/index.mjs +88 -87
  50. package/lib/src/{lib-CvEpWvWA.js → lib-DL-13itP.js} +24124 -23832
  51. package/lib/src/mockServiceWorker.js +1 -1
  52. package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +1 -0
  53. package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +1 -0
  54. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +1 -0
  55. package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.js +14 -0
  56. package/lib/src/shared/content-settings/components/payment-config-field/payment-toggle-field/PaymentToggleField.mixin.d.ts +13 -1
  57. package/lib/src/shared/content-settings/components/payment-config-field/payment-toggle-field/PaymentToggleField.mixin.js +10 -0
  58. package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +2 -1
  59. package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +1 -0
  60. package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +1 -0
  61. package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +1 -0
  62. package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +1 -0
  63. package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.d.ts +2 -1
  64. package/package.json +1 -1
  65. package/src/brand-page/clients/brand-page.client.ts +3 -0
  66. package/src/brand-page/components/about-section/AboutSection.vue +7 -1
  67. package/src/brand-page/components/payment/RequestPaymentStripe.vue +381 -44
  68. package/src/brand-page/components/shop/PaymentModal.vue +7 -1
  69. package/src/brand-page/components/shop/PaymentShippingAddress.vue +297 -0
  70. package/src/brand-page/components/shop/Shop.vue +1 -0
  71. package/src/brand-page/components/shop/i18n/countries.de-DE.json +240 -0
  72. package/src/brand-page/components/shop/i18n/countries.es-ES.json +240 -0
  73. package/src/brand-page/components/shop/i18n/countries.fr-CA.json +240 -0
  74. package/src/brand-page/components/shop/i18n/countries.fr-FR.json +240 -0
  75. package/src/brand-page/components/shop/i18n/countries.json +240 -0
  76. package/src/brand-page/components/shop/i18n/countries.pt-BR.json +240 -0
  77. package/src/brand-page/components/shop/i18n/countries.pt-PT.json +240 -0
  78. package/src/brand-page/components/shop/i18n/payment-shipping-address.de-DE.json +18 -0
  79. package/src/brand-page/components/shop/i18n/payment-shipping-address.es-ES.json +18 -0
  80. package/src/brand-page/components/shop/i18n/payment-shipping-address.fr-CA.json +18 -0
  81. package/src/brand-page/components/shop/i18n/payment-shipping-address.fr-FR.json +18 -0
  82. package/src/brand-page/components/shop/i18n/payment-shipping-address.json +18 -0
  83. package/src/brand-page/components/shop/i18n/payment-shipping-address.pt-BR.json +18 -0
  84. package/src/brand-page/components/shop/i18n/payment-shipping-address.pt-PT.json +18 -0
  85. package/src/brand-page/models/payment.model.ts +24 -0
  86. package/src/brand-page/utils/view-model.util.ts +1 -0
  87. package/src/brand-page/view-models.ts +1 -0
  88. package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.vue +1 -1
  89. package/src/brand-page-maker/composables/useEventTracker.ts +6 -0
  90. package/src/brand-page-maker/constants/config-settings-constant.ts +8 -0
  91. package/src/brand-page-maker/models/content-settings.ts +1 -0
  92. package/src/brand-page-maker/validators/section-button.validator.ts +5 -1
  93. package/src/bundles/bundled-translations.de-DE.json +965 -1
  94. package/src/bundles/bundled-translations.es-ES.json +965 -1
  95. package/src/bundles/bundled-translations.fr-CA.json +965 -1
  96. package/src/bundles/bundled-translations.fr-FR.json +965 -1
  97. package/src/bundles/bundled-translations.json +965 -1
  98. package/src/bundles/bundled-translations.pt-BR.json +965 -1
  99. package/src/bundles/bundled-translations.pt-PT.json +965 -1
  100. package/src/composables/useTranslate.ts +15 -0
  101. package/src/shared/content-settings/components/content-settings/i18n/content-settings.de-DE.json +3 -1
  102. package/src/shared/content-settings/components/content-settings/i18n/content-settings.es-ES.json +3 -1
  103. package/src/shared/content-settings/components/content-settings/i18n/content-settings.fr-CA.json +3 -1
  104. package/src/shared/content-settings/components/content-settings/i18n/content-settings.fr-FR.json +3 -1
  105. package/src/shared/content-settings/components/content-settings/i18n/content-settings.json +3 -1
  106. package/src/shared/content-settings/components/content-settings/i18n/content-settings.pt-BR.json +3 -1
  107. package/src/shared/content-settings/components/content-settings/i18n/content-settings.pt-PT.json +3 -1
  108. package/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.ts +17 -0
  109. package/src/shared/content-settings/components/payment-config-field/payment-toggle-field/PaymentToggleField.mixin.ts +12 -0
  110. package/src/shared/content-settings/components/payment-config-field/payment-toggle-field/PaymentToggleField.vue +9 -1
  111. package/lib/src/brand-page/components/payment/RequestPaymentStripe.mixin.d.ts +0 -106
  112. package/lib/src/brand-page/components/payment/RequestPaymentStripe.mixin.js +0 -253
  113. package/lib/src/bundled-translations-B6qZE8LU.js +0 -169
  114. package/lib/src/bundled-translations.de-DE-CsU6YsZb.js +0 -169
  115. package/lib/src/bundled-translations.es-ES-unPBdcJx.js +0 -169
  116. package/lib/src/bundled-translations.fr-CA-Dpa2wEtC.js +0 -169
  117. package/lib/src/bundled-translations.fr-FR-BPloaUjN.js +0 -169
  118. package/lib/src/bundled-translations.pt-BR-CFRGdaDO.js +0 -169
  119. package/lib/src/bundled-translations.pt-PT-BHVYCE0K.js +0 -169
  120. package/src/brand-page/components/payment/RequestPaymentStripe.mixin.ts +0 -364
@@ -1,17 +1,17 @@
1
1
  <template>
2
2
  <div data-component="request-payment-stripe" :style="containerStyle">
3
- <div class="tw-relative tw-my-2 tw-justify-center">
3
+ <div class="tw-relative tw-my-2">
4
4
  <button
5
- class="tw-bg-transparent tw-border-none tw-top-0 tw-left-0 hover:tw-cursor-pointer"
5
+ class="tw-bg-transparent tw-border-none tw-absolute tw-left-0 tw-top-1/2 -tw-translate-y-1/2 hover:tw-cursor-pointer"
6
6
  @click="onBackClick"
7
7
  >
8
8
  <Icon name="chevron-left" size="sm" :style="arrowStyle" />
9
9
  </button>
10
- <div v-if="!isShop" class="tw-w-full tw-flex tw-justify-center">
10
+ <div class="tw-w-full tw-flex tw-justify-center">
11
11
  <span class="tw-text-center">
12
12
  {{ currencySymbol }}{{ amount }} ({{ currencyCode }})
13
13
  {{
14
- productName
14
+ !isShop && productName
15
15
  ? requestPaymentStripeTr('forProduct', {
16
16
  PRODUCT_NAME: productName,
17
17
  })
@@ -27,14 +27,35 @@
27
27
  <Loader />
28
28
  </div>
29
29
  <div v-show="isInitialised">
30
+ <PaymentShippingAddress
31
+ v-if="props.isShippingEnabled"
32
+ v-model="shippingDetails"
33
+ @validation-change="onShippingValidationChange"
34
+ />
35
+ <p class="tw-font-bold tw-mt-2">
36
+ {{ requestPaymentStripeTr('emailAddress') }}
37
+ </p>
38
+ <!-- Start Email Address -->
39
+ <TextInput
40
+ v-model="emailAddress"
41
+ class="tw-mt-3 tw-mb-2"
42
+ :placeholder="requestPaymentStripeTr('emailAddressPlaceholder')"
43
+ :error="Boolean(emailAddressError)"
44
+ @blur="onEmailAddressEvent"
45
+ @input="onEmailAddressEvent"
46
+ />
47
+ <p v-if="emailAddressError" class="form-error">
48
+ {{ emailAddressError.message }}
49
+ </p>
50
+ <!-- End Email Address -->
30
51
  <p class="tw-font-bold">{{ requestPaymentStripeTr('cardNumber') }}</p>
31
52
  <!-- Start Card Number -->
32
53
  <div
33
- ref="cardNumber"
34
- class="tw-border tw-border-solid tw-mb-2 tw-px-4 tw-py-1 tw-mt-3 tw-rounded tw-bg-white"
54
+ ref="cardNumberRef"
55
+ class="tw-w-full tw-border tw-border-solid tw-rounded tw-px-4 tw-py-3 tw-text-base tw-bg-white tw-mt-3 tw-mb-2"
35
56
  :class="{
36
57
  'tw-border-error-500': cardNumberElementError,
37
- 'tw-border-grayscale-500': !cardNumberElementError,
58
+ 'tw-border-grayscale-300': !cardNumberElementError,
38
59
  }"
39
60
  />
40
61
  <div v-if="cardNumberElementError" class="form-error tw-pb-2">
@@ -45,19 +66,19 @@
45
66
  <!-- Start Card CVC Expiry -->
46
67
  <div class="tw-flex tw-flex-row tw-mt-3">
47
68
  <div
48
- ref="cardExpiry"
49
- class="tw-border tw-border-solid tw-border-grayscale-500 tw-grow tw-mb-3 tw-px-4 tw-py-1 tw-rounded tw-bg-white"
69
+ ref="cardExpiryRef"
70
+ class="tw-border tw-border-solid tw-rounded tw-px-4 tw-py-3 tw-text-base tw-bg-white tw-grow tw-mb-3"
50
71
  :class="{
51
72
  'tw-border-error-500': cardExpiryElementError,
52
- 'tw-border-grayscale-500': !cardExpiryElementError,
73
+ 'tw-border-grayscale-300': !cardExpiryElementError,
53
74
  }"
54
75
  />
55
76
  <div
56
- ref="cardCvc"
57
- class="tw-border tw-border-solid tw-border-grayscale-500 tw-grow tw-mb-3 tw-ml-2 tw-px-4 tw-py-1 tw-rounded tw-w-1/4 tw-bg-white"
77
+ ref="cardCvcRef"
78
+ class="tw-border tw-border-solid tw-rounded tw-px-4 tw-py-3 tw-text-base tw-bg-white tw-grow tw-mb-3 tw-ml-2 tw-w-1/4"
58
79
  :class="{
59
80
  'tw-border-error-500': cardCvcElementError,
60
- 'tw-border-grayscale-500': !cardCvcElementError,
81
+ 'tw-border-grayscale-300': !cardCvcElementError,
61
82
  }"
62
83
  />
63
84
  </div>
@@ -69,21 +90,6 @@
69
90
  </div>
70
91
  <!-- End Card CVC Expiry -->
71
92
 
72
- <p class="tw-font-bold">{{ requestPaymentStripeTr('emailAddress') }}</p>
73
- <!-- Start Email Address -->
74
- <TextInput
75
- v-model="emailAddress"
76
- class="tw-mt-3 tw-mb-2"
77
- :placeholder="requestPaymentStripeTr('emailAddressPlaceholder')"
78
- :error="Boolean(emailAddressError)"
79
- @blur="onEmailAddressEvent"
80
- @input="onEmailAddressEvent"
81
- />
82
- <p v-if="emailAddressError" class="form-error">
83
- {{ emailAddressError.message }}
84
- </p>
85
- <!-- End Email Address -->
86
-
87
93
  <!-- Start Error Message -->
88
94
  <p v-if="submitError" class="form-error tw-mt-2">
89
95
  {{ submitError.message }}
@@ -134,28 +140,359 @@
134
140
  </div>
135
141
  </div>
136
142
  </template>
137
- <script>
143
+ <script setup lang="ts">
144
+ import type { StyleValue } from 'vue';
145
+ import { computed, onMounted, ref } from 'vue';
138
146
  import { Icon, TextInput, Loader } from '@designcrowd/fe-shared-lib';
147
+ import validator from 'validator';
139
148
  import IconStripe from '../icon/IconStripe.vue';
140
- import CheckoutStripeMixin from './RequestPaymentStripe.mixin.ts';
141
- import { requestPaymentStripeTr } from '@src/composables/useTranslate';
142
-
143
- export default {
144
- components: {
145
- Icon,
146
- IconStripe,
147
- TextInput,
148
- Loader,
149
- },
150
- mixins: [CheckoutStripeMixin],
151
- methods: {
152
- requestPaymentStripeTr,
153
- },
149
+ import PaymentShippingAddress from '../shop/PaymentShippingAddress.vue';
150
+ import { debug, debugError } from '../../../utils/debug.util';
151
+ import * as constants from '../../constants';
152
+ import type {
153
+ BrandPagePaymentConfig,
154
+ ButtonStyles,
155
+ CheckoutInformation,
156
+ CreateCartResult,
157
+ StripePaymentIntent,
158
+ StripeShippingDetails,
159
+ } from '../../models';
160
+ import { requestPaymentStripeTr } from '../../../composables/useTranslate';
161
+ import brandPageClient from '../../clients/brand-page.client';
162
+
163
+ declare global {
164
+ interface Window {
165
+ Stripe?: stripe.StripeStatic;
166
+ }
167
+ }
168
+
169
+ const STRIPE_SCRIPT_URL = 'https://js.stripe.com/v3/';
170
+ const SCRIPT_TAG_NAME = 'SCRIPT';
171
+
172
+ interface Props {
173
+ cart: CreateCartResult<StripePaymentIntent>;
174
+ checkoutInformation: CheckoutInformation;
175
+ buttonStyles: ButtonStyles;
176
+ paymentConfig: BrandPagePaymentConfig;
177
+ stripePublishableKey: string;
178
+ productName?: string;
179
+ isShop?: boolean;
180
+ isShippingEnabled: boolean;
181
+ }
182
+
183
+ const props = withDefaults(defineProps<Props>(), {
184
+ productName: undefined,
185
+ isShop: false,
186
+ isShippingEnabled: false,
187
+ });
188
+
189
+ const emit = defineEmits<{
190
+ (e: 'go-to-payment-option-selection'): void;
191
+ (e: 'success', payload: { result: unknown }): void;
192
+ }>();
193
+
194
+ const cardNumberRef = ref<HTMLElement | null>(null);
195
+ const cardExpiryRef = ref<HTMLElement | null>(null);
196
+ const cardCvcRef = ref<HTMLElement | null>(null);
197
+
198
+ const cardCvcElement = ref<stripe.elements.Element | undefined>(undefined);
199
+ const cardCvcElementError = ref<stripe.Error | undefined>(undefined);
200
+ const cardExpiryElement = ref<stripe.elements.Element | undefined>(undefined);
201
+ const cardExpiryElementError = ref<stripe.Error | undefined>(undefined);
202
+ const cardNumberElement = ref<stripe.elements.Element | undefined>(undefined);
203
+ const cardNumberElementError = ref<stripe.Error | undefined>(undefined);
204
+ const emailAddress = ref<string | undefined>(undefined);
205
+ const emailAddressError = ref<Error | undefined>(undefined);
206
+ const isBusy = ref(false);
207
+ const isCardCvcValid = ref(false);
208
+ const isCardExpiryValid = ref(false);
209
+ const isCardNumberValid = ref(false);
210
+ const isInitialised = ref(false);
211
+ const stripeInstance = ref<stripe.Stripe | undefined>(undefined);
212
+ const submitButtonMessage = ref('Pay');
213
+ const submitError = ref<Error | stripe.Error | undefined>(undefined);
214
+
215
+ const shippingDetails = ref<StripeShippingDetails>({
216
+ name: '',
217
+ line1: '',
218
+ line2: '',
219
+ city: '',
220
+ state: '',
221
+ postalCode: '',
222
+ country: '',
223
+ });
224
+
225
+ const isShippingValid = ref(false);
226
+
227
+ const amount = computed((): string => {
228
+ return (props.cart.totalAmount / 100).toFixed(2) || '';
229
+ });
230
+
231
+ const currencyCode = computed((): string => {
232
+ return props.paymentConfig?.defaultCurrency || '';
233
+ });
234
+
235
+ const currencySymbol = computed((): string => {
236
+ return props.paymentConfig?.defaultCurrencySymbol || '$';
237
+ });
238
+
239
+ const isStripeElementFormComplete = computed((): boolean => {
240
+ return (
241
+ isCardCvcValid.value && isCardExpiryValid.value && isCardNumberValid.value
242
+ );
243
+ });
244
+
245
+ const isSubmitButtonEnabled = computed((): boolean => {
246
+ return (
247
+ isInitialised.value &&
248
+ isStripeElementFormComplete.value &&
249
+ Boolean(emailAddress.value) &&
250
+ !emailAddressError.value &&
251
+ !isBusy.value &&
252
+ (props.isShippingEnabled ? isShippingValid.value : true)
253
+ );
254
+ });
255
+
256
+ const arrowStyle = computed((): StyleValue => {
257
+ return {
258
+ color: props.buttonStyles.style?.color,
259
+ } as StyleValue;
260
+ });
261
+
262
+ const payButtonStyle = computed((): StyleValue => {
263
+ if (!props.buttonStyles || !props.buttonStyles.style) {
264
+ return { ...props.buttonStyles } as StyleValue;
265
+ }
266
+
267
+ return {
268
+ ...props.buttonStyles.style,
269
+ color: props.buttonStyles.style.backgroundColor,
270
+ backgroundColor: props.buttonStyles.style.color,
271
+ } as StyleValue;
272
+ });
273
+
274
+ const containerStyle = computed((): StyleValue => {
275
+ const buttonStyle = { ...props.buttonStyles?.style };
276
+
277
+ return {
278
+ color: buttonStyle.color,
279
+ } as StyleValue;
280
+ });
281
+
282
+ const initialiseStripeScript = (): void => {
283
+ debug('initialiseStripeScript: start');
284
+
285
+ const stripeScript = Array.from(document.head.children).find(
286
+ (child): child is HTMLScriptElement => {
287
+ return (
288
+ child.tagName.toUpperCase() === SCRIPT_TAG_NAME &&
289
+ child.hasAttribute('src') &&
290
+ child.getAttribute('src') === STRIPE_SCRIPT_URL
291
+ );
292
+ },
293
+ );
294
+
295
+ if (stripeScript) {
296
+ debug('initialiseStripeScript: script exists');
297
+
298
+ return;
299
+ }
300
+
301
+ const scriptElement = document.createElement(
302
+ SCRIPT_TAG_NAME,
303
+ ) as HTMLScriptElement;
304
+
305
+ scriptElement.setAttribute('src', STRIPE_SCRIPT_URL);
306
+ scriptElement.setAttribute('async', '');
307
+ scriptElement.setAttribute('defer', '');
308
+
309
+ document.head.appendChild(scriptElement);
310
+
311
+ debug('initialiseStripeScript: script injected');
312
+ };
313
+
314
+ const initStripeElements = (): void => {
315
+ if (!props.stripePublishableKey) {
316
+ debugError('initStripeElements: stripe publishable key undefined');
317
+
318
+ return;
319
+ }
320
+
321
+ if (typeof window.Stripe !== 'function') {
322
+ setTimeout(() => {
323
+ debug('initStripeElements: waiting for stripe script');
324
+ initStripeElements();
325
+ }, 250);
326
+
327
+ return;
328
+ }
329
+
330
+ debug('initStripeElements: start');
331
+
332
+ try {
333
+ stripeInstance.value = window.Stripe(props.stripePublishableKey, {
334
+ stripeAccount: props.cart.paymentProviderExternalId,
335
+ });
336
+
337
+ const stripeElements = stripeInstance.value.elements();
338
+
339
+ cardNumberElement.value = stripeElements.create('cardNumber', {
340
+ style: constants.stripeDefaultStyle,
341
+ placeholder: 'Credit Card Number',
342
+ });
343
+ if (cardNumberRef.value) {
344
+ cardNumberElement.value.mount(cardNumberRef.value);
345
+ }
346
+ cardNumberElement.value.addEventListener('change', onStripeElementChange);
347
+
348
+ cardExpiryElement.value = stripeElements.create('cardExpiry', {
349
+ style: constants.stripeDefaultStyle,
350
+ placeholder: 'Expiry',
351
+ });
352
+ if (cardExpiryRef.value) {
353
+ cardExpiryElement.value.mount(cardExpiryRef.value);
354
+ }
355
+ cardExpiryElement.value.addEventListener('change', onStripeElementChange);
356
+
357
+ cardCvcElement.value = stripeElements.create('cardCvc', {
358
+ style: constants.stripeDefaultStyle,
359
+ placeholder: 'CVV',
360
+ });
361
+ if (cardCvcRef.value) {
362
+ cardCvcElement.value.mount(cardCvcRef.value);
363
+ }
364
+ cardCvcElement.value.addEventListener('change', onStripeElementChange);
365
+
366
+ isInitialised.value = true;
367
+ } catch (err) {
368
+ console.error(err);
369
+ }
370
+
371
+ debug('initStripeElements: end');
372
+ };
373
+
374
+ const onBackClick = (): void => {
375
+ emit('go-to-payment-option-selection');
376
+ };
377
+
378
+ const onEmailAddressEvent = (): void => {
379
+ validateEmailAddress();
380
+ };
381
+
382
+ const onStripeElementChange = (
383
+ response?: stripe.elements.ElementChangeResponse,
384
+ ): void => {
385
+ if (!response) {
386
+ return;
387
+ }
388
+
389
+ switch (response.elementType) {
390
+ case 'cardCvc':
391
+ isCardCvcValid.value = response.complete;
392
+ cardCvcElementError.value = response.error;
393
+ break;
394
+ case 'cardExpiry':
395
+ isCardExpiryValid.value = response.complete;
396
+ cardExpiryElementError.value = response.error;
397
+ break;
398
+ case 'cardNumber':
399
+ isCardNumberValid.value = response.complete;
400
+ cardNumberElementError.value = response.error;
401
+ break;
402
+ }
403
+ };
404
+
405
+ const onSubmitPaymentClick = async (): Promise<void> => {
406
+ if (
407
+ !cardNumberElement.value ||
408
+ !isSubmitButtonEnabled.value ||
409
+ !stripeInstance.value ||
410
+ !props.stripePublishableKey ||
411
+ !emailAddress.value
412
+ ) {
413
+ debugError('onSubmitPaymentClick: invalid operation');
414
+
415
+ return;
416
+ }
417
+
418
+ isBusy.value = true;
419
+
420
+ try {
421
+ const paymentIntentResponse =
422
+ await brandPageClient.createStripePaymentIntent({
423
+ cartId: props.cart.cartId,
424
+ customerEmail: emailAddress.value,
425
+ customerRequestDetails:
426
+ props.checkoutInformation.customerRequestDetails,
427
+ customerMessage: props.checkoutInformation.customerMessage,
428
+ shippingDetails:
429
+ props.isShop && props.isShippingEnabled
430
+ ? shippingDetails.value
431
+ : undefined,
432
+ });
433
+
434
+ if (!paymentIntentResponse) {
435
+ submitError.value = new Error(
436
+ 'Unable to create payment intent. Please try again.',
437
+ );
438
+
439
+ return;
440
+ }
441
+
442
+ const confirmCardPaymentResult =
443
+ await stripeInstance.value.confirmCardPayment(
444
+ paymentIntentResponse.paymentIntent.client_secret,
445
+ {
446
+ payment_method: {
447
+ card: cardNumberElement.value,
448
+ },
449
+ },
450
+ );
451
+
452
+ if (confirmCardPaymentResult.error) {
453
+ debugError(confirmCardPaymentResult.error);
454
+ submitError.value = confirmCardPaymentResult.error;
455
+ } else {
456
+ debug('onSubmitPaymentClick: payment intent success');
457
+ emit('success', { result: confirmCardPaymentResult });
458
+ }
459
+ } finally {
460
+ isBusy.value = false;
461
+ }
462
+ };
463
+
464
+ const validateEmailAddress = (): void => {
465
+ if (!emailAddress.value) {
466
+ emailAddressError.value = new Error(
467
+ requestPaymentStripeTr('invalidEmailMessage'),
468
+ );
469
+
470
+ return;
471
+ }
472
+
473
+ if (!validator.isEmail(emailAddress.value)) {
474
+ emailAddressError.value = new Error(
475
+ requestPaymentStripeTr('invalidEmailMessage'),
476
+ );
477
+
478
+ return;
479
+ }
480
+
481
+ emailAddressError.value = undefined;
154
482
  };
483
+
484
+ const onShippingValidationChange = (isValid: boolean): void => {
485
+ isShippingValid.value = isValid;
486
+ };
487
+
488
+ onMounted(() => {
489
+ initialiseStripeScript();
490
+ initStripeElements();
491
+ });
155
492
  </script>
156
493
  <style scoped>
157
494
  .form-error {
158
- @apply tw-text-sm;
495
+ @apply tw-text-xs;
159
496
  color: #f21b3f;
160
497
  }
161
498
  </style>
@@ -35,6 +35,7 @@
35
35
  :stripe-publishable-key="context.stripePublishableKey!"
36
36
  :product-name="productName"
37
37
  :is-shop="true"
38
+ :is-shipping-enabled="props.isShippingEnabled"
38
39
  @go-to-payment-option-selection="onGoToCartSelection"
39
40
  @success="onRequestPaymentStripeSuccess"
40
41
  />
@@ -114,7 +115,7 @@
114
115
  <script setup lang="ts">
115
116
  import { Modal, Button, Loader } from '@designcrowd/fe-shared-lib';
116
117
  import { useCartStore } from '@shared/ecommerce-settings/store/cart-settings-store';
117
- import { computed, reactive, onMounted } from 'vue';
118
+ import { computed, reactive, ref, onMounted } from 'vue';
118
119
  import IconStripe from '../icon/IconStripe.vue';
119
120
  import RequestPaymentStripe from '../payment/RequestPaymentStripe.vue';
120
121
  import TextWrapper from '../text-wrapper/TextWrapper.vue';
@@ -127,6 +128,7 @@ import type {
127
128
  BrandPagePaymentConfig,
128
129
  TextStyleDeclaration,
129
130
  StripePaymentIntent,
131
+ StripeShippingDetails,
130
132
  } from '@brand-page/models';
131
133
  import { paymentProviders } from '@brand-page/constants';
132
134
  import raygunUtil from '@brand-page/utils/raygun.util';
@@ -150,10 +152,12 @@ interface Props {
150
152
  shopPaymentConfig: BrandPagePaymentConfig;
151
153
  descriptionStyle: TextStyleDeclaration | undefined;
152
154
  successMessage: string;
155
+ isShippingEnabled: boolean;
153
156
  }
154
157
 
155
158
  const props = withDefaults(defineProps<Props>(), {
156
159
  isVisible: true,
160
+ isShippingEnabled: false,
157
161
  });
158
162
 
159
163
  const uniformDescriptionStyle = computed<TextStyleDeclaration>(() => ({
@@ -169,6 +173,8 @@ const data = reactive({
169
173
  state: 'creating-cart' as State,
170
174
  });
171
175
 
176
+ const customerEmail = ref('');
177
+
172
178
  const emit = defineEmits(['on-close', 'on-back']);
173
179
 
174
180
  const onClose = () => {