@designcrowd/library.brand-page 5.17.3 → 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.
- package/lib/src/{CreatedOnBrandCrowd-de-de-yFg0wq_8.js → CreatedOnBrandCrowd-de-de-C_NzyXvG.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-D4sUyR-U.js → CreatedOnBrandCrowd-en-us-DSmpdByg.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-CjXHshc0.js → CreatedOnBrandCrowd-es-es-4O9ttd4y.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-CtsyncLl.js → CreatedOnBrandCrowd-fr-ca-DDr8rQHb.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-CtsyncLl.js → CreatedOnBrandCrowd-fr-fr-DDr8rQHb.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-D8Z-gS4q.js → CreatedOnBrandCrowd-pt-br-BUTVQ17i.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-D8Z-gS4q.js → CreatedOnBrandCrowd-pt-pt-BUTVQ17i.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-k7a8-Akd.js → CreatedOnDcom-de-de-thkGl7gg.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-Bh5mbVcr.js → CreatedOnDcom-en-us-DOgnHkVR.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-DkEBWtQn.js → CreatedOnDcom-es-es-NyEB16vO.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-DcarvQ1r.js → CreatedOnDcom-fr-ca-Cd6WjWcu.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-Cbe-yOPu.js → CreatedOnDcom-fr-fr-CDKX35U7.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-DlWu_Kwc.js → CreatedOnDcom-pt-br-PbJzyRNp.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-DZp9RWfH.js → CreatedOnDcom-pt-pt-tja7jglY.js} +1 -1
- package/lib/src/brand-page/clients/brand-page.client.d.ts +2 -1
- package/lib/src/brand-page/clients/brand-page.client.js +1 -0
- package/lib/src/brand-page/models/payment.model.d.ts +42 -0
- package/lib/src/brand-page/models/payment.model.js +9 -0
- package/lib/src/brand-page/utils/view-model.util.js +1 -0
- package/lib/src/brand-page/view-models.d.ts +1 -0
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +1 -0
- package/lib/src/brand-page-maker/composables/useEventTracker.d.ts +2 -0
- package/lib/src/brand-page-maker/composables/useEventTracker.js +6 -0
- package/lib/src/brand-page-maker/constants/config-settings-constant.d.ts +1 -0
- package/lib/src/brand-page-maker/constants/config-settings-constant.js +7 -0
- package/lib/src/brand-page-maker/models/content-settings.js +1 -0
- package/lib/src/bundled-translations-D5A4swr0.js +173 -0
- package/lib/src/bundled-translations.de-DE-Bq6H28Hz.js +173 -0
- package/lib/src/bundled-translations.es-ES-Bo-UGy51.js +173 -0
- package/lib/src/bundled-translations.fr-CA-7GXawEcN.js +173 -0
- package/lib/src/bundled-translations.fr-FR-DzVwt2U-.js +173 -0
- package/lib/src/bundled-translations.pt-BR-DSZZ-i-B.js +173 -0
- package/lib/src/bundled-translations.pt-PT-SNbEX0GM.js +173 -0
- package/lib/src/bundles/bundled-translations.de-DE.json +965 -1
- package/lib/src/bundles/bundled-translations.es-ES.json +965 -1
- package/lib/src/bundles/bundled-translations.fr-CA.json +965 -1
- package/lib/src/bundles/bundled-translations.fr-FR.json +965 -1
- package/lib/src/bundles/bundled-translations.json +965 -1
- package/lib/src/bundles/bundled-translations.pt-BR.json +965 -1
- package/lib/src/bundles/bundled-translations.pt-PT.json +965 -1
- package/lib/src/composables/useTranslate.d.ts +7 -1
- package/lib/src/composables/useTranslate.js +9 -1
- package/lib/src/css/library.brand-page-brandCrowd.min.css +33 -14
- package/lib/src/css/library.brand-page-brandPage.min.css +33 -14
- package/lib/src/css/library.brand-page-designCom.min.css +33 -14
- package/lib/src/css/library.brand-page-preview.min.css +33 -14
- package/lib/src/index.mjs +88 -87
- package/lib/src/{lib-DOfGX3z2.js → lib-DL-13itP.js} +21136 -20938
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +1 -0
- package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +1 -0
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +1 -0
- package/lib/src/shared/content-settings/components/payment-config-field/payment-toggle-field/PaymentToggleField.mixin.d.ts +13 -1
- package/lib/src/shared/content-settings/components/payment-config-field/payment-toggle-field/PaymentToggleField.mixin.js +10 -0
- package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +2 -1
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +1 -0
- package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +1 -0
- package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +1 -0
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +1 -0
- package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.d.ts +2 -1
- package/package.json +1 -1
- package/src/brand-page/clients/brand-page.client.ts +3 -0
- package/src/brand-page/components/payment/RequestPaymentStripe.vue +381 -44
- package/src/brand-page/components/shop/PaymentModal.vue +7 -1
- package/src/brand-page/components/shop/PaymentShippingAddress.vue +297 -0
- package/src/brand-page/components/shop/Shop.vue +1 -0
- package/src/brand-page/components/shop/i18n/countries.de-DE.json +240 -0
- package/src/brand-page/components/shop/i18n/countries.es-ES.json +240 -0
- package/src/brand-page/components/shop/i18n/countries.fr-CA.json +240 -0
- package/src/brand-page/components/shop/i18n/countries.fr-FR.json +240 -0
- package/src/brand-page/components/shop/i18n/countries.json +240 -0
- package/src/brand-page/components/shop/i18n/countries.pt-BR.json +240 -0
- package/src/brand-page/components/shop/i18n/countries.pt-PT.json +240 -0
- package/src/brand-page/components/shop/i18n/payment-shipping-address.de-DE.json +18 -0
- package/src/brand-page/components/shop/i18n/payment-shipping-address.es-ES.json +18 -0
- package/src/brand-page/components/shop/i18n/payment-shipping-address.fr-CA.json +18 -0
- package/src/brand-page/components/shop/i18n/payment-shipping-address.fr-FR.json +18 -0
- package/src/brand-page/components/shop/i18n/payment-shipping-address.json +18 -0
- package/src/brand-page/components/shop/i18n/payment-shipping-address.pt-BR.json +18 -0
- package/src/brand-page/components/shop/i18n/payment-shipping-address.pt-PT.json +18 -0
- package/src/brand-page/models/payment.model.ts +24 -0
- package/src/brand-page/utils/view-model.util.ts +1 -0
- package/src/brand-page/view-models.ts +1 -0
- package/src/brand-page-maker/composables/useEventTracker.ts +6 -0
- package/src/brand-page-maker/constants/config-settings-constant.ts +8 -0
- package/src/brand-page-maker/models/content-settings.ts +1 -0
- package/src/bundles/bundled-translations.de-DE.json +965 -1
- package/src/bundles/bundled-translations.es-ES.json +965 -1
- package/src/bundles/bundled-translations.fr-CA.json +965 -1
- package/src/bundles/bundled-translations.fr-FR.json +965 -1
- package/src/bundles/bundled-translations.json +965 -1
- package/src/bundles/bundled-translations.pt-BR.json +965 -1
- package/src/bundles/bundled-translations.pt-PT.json +965 -1
- package/src/composables/useTranslate.ts +15 -0
- package/src/shared/content-settings/components/content-settings/i18n/content-settings.de-DE.json +3 -1
- package/src/shared/content-settings/components/content-settings/i18n/content-settings.es-ES.json +3 -1
- package/src/shared/content-settings/components/content-settings/i18n/content-settings.fr-CA.json +3 -1
- package/src/shared/content-settings/components/content-settings/i18n/content-settings.fr-FR.json +3 -1
- package/src/shared/content-settings/components/content-settings/i18n/content-settings.json +3 -1
- package/src/shared/content-settings/components/content-settings/i18n/content-settings.pt-BR.json +3 -1
- package/src/shared/content-settings/components/content-settings/i18n/content-settings.pt-PT.json +3 -1
- package/src/shared/content-settings/components/payment-config-field/payment-toggle-field/PaymentToggleField.mixin.ts +12 -0
- package/src/shared/content-settings/components/payment-config-field/payment-toggle-field/PaymentToggleField.vue +9 -1
- package/lib/src/brand-page/components/payment/RequestPaymentStripe.mixin.d.ts +0 -106
- package/lib/src/brand-page/components/payment/RequestPaymentStripe.mixin.js +0 -253
- package/lib/src/bundled-translations-B6qZE8LU.js +0 -169
- package/lib/src/bundled-translations.de-DE-CsU6YsZb.js +0 -169
- package/lib/src/bundled-translations.es-ES-unPBdcJx.js +0 -169
- package/lib/src/bundled-translations.fr-CA-Dpa2wEtC.js +0 -169
- package/lib/src/bundled-translations.fr-FR-BPloaUjN.js +0 -169
- package/lib/src/bundled-translations.pt-BR-CFRGdaDO.js +0 -169
- package/lib/src/bundled-translations.pt-PT-BHVYCE0K.js +0 -169
- package/src/brand-page/components/payment/RequestPaymentStripe.mixin.ts +0 -364
package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts
CHANGED
|
@@ -783,6 +783,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
783
783
|
toggleLogoBackground(): Promise<any>;
|
|
784
784
|
}>;
|
|
785
785
|
eventTracker: {
|
|
786
|
+
sendShippingToggleEvent: (isEnabled: boolean) => void;
|
|
786
787
|
sendSaveContactEvent: () => void;
|
|
787
788
|
sendStartForFreeEvent: () => void;
|
|
788
789
|
sendFooterLinkClickEvent: (linkType: "watermark_logo" | "create_your_website") => void;
|
|
@@ -731,6 +731,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
731
731
|
toggleShouldPlayVideo(): void;
|
|
732
732
|
}>;
|
|
733
733
|
bpEventTracker: {
|
|
734
|
+
sendShippingToggleEvent: (isEnabled: boolean) => void;
|
|
734
735
|
sendSaveContactEvent: () => void;
|
|
735
736
|
sendStartForFreeEvent: () => void;
|
|
736
737
|
sendFooterLinkClickEvent: (linkType: "watermark_logo" | "create_your_website") => void;
|
|
@@ -475,6 +475,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
475
475
|
clearAiTextEditContext(): void;
|
|
476
476
|
}>;
|
|
477
477
|
eventTracker: {
|
|
478
|
+
sendShippingToggleEvent: (isEnabled: boolean) => void;
|
|
478
479
|
sendSaveContactEvent: () => void;
|
|
479
480
|
sendStartForFreeEvent: () => void;
|
|
480
481
|
sendFooterLinkClickEvent: (linkType: "watermark_logo" | "create_your_website") => void;
|
|
@@ -21,6 +21,11 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
21
21
|
type: PropType<RequestPaymentConfig>;
|
|
22
22
|
required: true;
|
|
23
23
|
};
|
|
24
|
+
placeholder: {
|
|
25
|
+
type: StringConstructor;
|
|
26
|
+
required: false;
|
|
27
|
+
default: string;
|
|
28
|
+
};
|
|
24
29
|
}>, {}, {}, {
|
|
25
30
|
toggleState: {
|
|
26
31
|
get(): boolean;
|
|
@@ -47,7 +52,14 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
47
52
|
type: PropType<RequestPaymentConfig>;
|
|
48
53
|
required: true;
|
|
49
54
|
};
|
|
55
|
+
placeholder: {
|
|
56
|
+
type: StringConstructor;
|
|
57
|
+
required: false;
|
|
58
|
+
default: string;
|
|
59
|
+
};
|
|
50
60
|
}>> & Readonly<{
|
|
51
61
|
"onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
|
|
52
|
-
}>, {
|
|
62
|
+
}>, {
|
|
63
|
+
placeholder: string;
|
|
64
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
53
65
|
export default _default;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineComponent } from 'vue';
|
|
2
|
+
import { useEventTracker } from '../../../../../brand-page-maker/composables/useEventTracker';
|
|
2
3
|
export default defineComponent({
|
|
3
4
|
props: {
|
|
4
5
|
id: {
|
|
@@ -21,6 +22,11 @@ export default defineComponent({
|
|
|
21
22
|
type: Object,
|
|
22
23
|
required: true,
|
|
23
24
|
},
|
|
25
|
+
placeholder: {
|
|
26
|
+
type: String,
|
|
27
|
+
required: false,
|
|
28
|
+
default: '',
|
|
29
|
+
},
|
|
24
30
|
},
|
|
25
31
|
emits: ['update:modelValue'],
|
|
26
32
|
computed: {
|
|
@@ -38,6 +44,10 @@ export default defineComponent({
|
|
|
38
44
|
name: this.name,
|
|
39
45
|
value,
|
|
40
46
|
};
|
|
47
|
+
if (this.settingsName === 'isShippingEnabled') {
|
|
48
|
+
const eventTracker = useEventTracker();
|
|
49
|
+
eventTracker.sendShippingToggleEvent(newVal);
|
|
50
|
+
}
|
|
41
51
|
this.$emit('update:modelValue', payload);
|
|
42
52
|
},
|
|
43
53
|
},
|
|
@@ -208,7 +208,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
208
208
|
searchTerm: string | undefined;
|
|
209
209
|
}): void;
|
|
210
210
|
_setSelectedTab({ tabName }: {
|
|
211
|
-
tabName: "
|
|
211
|
+
tabName: "AI" | "all" | "categories";
|
|
212
212
|
}): void;
|
|
213
213
|
_setSelectedCategory({ categoryName, }: {
|
|
214
214
|
categoryName: string | undefined;
|
|
@@ -242,6 +242,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
242
242
|
setupLogoChangeWatcher(): void;
|
|
243
243
|
}>;
|
|
244
244
|
eventTracker: {
|
|
245
|
+
sendShippingToggleEvent: (isEnabled: boolean) => void;
|
|
245
246
|
sendSaveContactEvent: () => void;
|
|
246
247
|
sendStartForFreeEvent: () => void;
|
|
247
248
|
sendFooterLinkClickEvent: (linkType: "watermark_logo" | "create_your_website") => void;
|
|
@@ -4725,6 +4725,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
4725
4725
|
onDraggingStart: () => void;
|
|
4726
4726
|
onDraggingEnd: (ev?: any, routeId?: string, previousParentRouteId?: string) => void;
|
|
4727
4727
|
eventTracker: {
|
|
4728
|
+
sendShippingToggleEvent: (isEnabled: boolean) => void;
|
|
4728
4729
|
sendSaveContactEvent: () => void;
|
|
4729
4730
|
sendStartForFreeEvent: () => void;
|
|
4730
4731
|
sendFooterLinkClickEvent: (linkType: "watermark_logo" | "create_your_website") => void;
|
package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts
CHANGED
|
@@ -431,6 +431,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
431
431
|
}): Promise<void>;
|
|
432
432
|
}>;
|
|
433
433
|
eventTracker: {
|
|
434
|
+
sendShippingToggleEvent: (isEnabled: boolean) => void;
|
|
434
435
|
sendSaveContactEvent: () => void;
|
|
435
436
|
sendStartForFreeEvent: () => void;
|
|
436
437
|
sendFooterLinkClickEvent: (linkType: "watermark_logo" | "create_your_website") => void;
|
|
@@ -18,6 +18,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
18
18
|
}>;
|
|
19
19
|
isDesignCom: import("vue").ComputedRef<boolean>;
|
|
20
20
|
eventTracker: {
|
|
21
|
+
sendShippingToggleEvent: (isEnabled: boolean) => void;
|
|
21
22
|
sendSaveContactEvent: () => void;
|
|
22
23
|
sendStartForFreeEvent: () => void;
|
|
23
24
|
sendFooterLinkClickEvent: (linkType: "watermark_logo" | "create_your_website") => void;
|
|
@@ -876,6 +876,7 @@ declare const _default: import("vue").DefineComponent<{}, {
|
|
|
876
876
|
removeBackgroundVideo(): void;
|
|
877
877
|
}>;
|
|
878
878
|
eventTracker: {
|
|
879
|
+
sendShippingToggleEvent: (isEnabled: boolean) => void;
|
|
879
880
|
sendSaveContactEvent: () => void;
|
|
880
881
|
sendStartForFreeEvent: () => void;
|
|
881
882
|
sendFooterLinkClickEvent: (linkType: "watermark_logo" | "create_your_website") => void;
|
|
@@ -489,7 +489,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
489
489
|
searchTerm: string | undefined;
|
|
490
490
|
}): void;
|
|
491
491
|
_setSelectedTab({ tabName }: {
|
|
492
|
-
tabName: "
|
|
492
|
+
tabName: "AI" | "all" | "categories";
|
|
493
493
|
}): void;
|
|
494
494
|
_setSelectedCategory({ categoryName, }: {
|
|
495
495
|
categoryName: string | undefined;
|
|
@@ -562,6 +562,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
562
562
|
}>;
|
|
563
563
|
isDesignCom: import("vue").ComputedRef<boolean>;
|
|
564
564
|
eventTracker: {
|
|
565
|
+
sendShippingToggleEvent: (isEnabled: boolean) => void;
|
|
565
566
|
sendSaveContactEvent: () => void;
|
|
566
567
|
sendStartForFreeEvent: () => void;
|
|
567
568
|
sendFooterLinkClickEvent: (linkType: "watermark_logo" | "create_your_website") => void;
|
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@ import * as constants from '../constants';
|
|
|
3
3
|
import type {
|
|
4
4
|
CreateCartResult,
|
|
5
5
|
CreateStripePaymentIntentResponse,
|
|
6
|
+
StripeShippingDetails,
|
|
6
7
|
} from '../models';
|
|
7
8
|
import * as csrfUtil from '../utils/csrf.util';
|
|
8
9
|
|
|
@@ -171,6 +172,7 @@ const createStripePaymentIntent = async (request: {
|
|
|
171
172
|
customerEmail: string;
|
|
172
173
|
customerRequestDetails?: string;
|
|
173
174
|
customerMessage?: string;
|
|
175
|
+
shippingDetails?: StripeShippingDetails;
|
|
174
176
|
}): Promise<CreateStripePaymentIntentResponse | null> => {
|
|
175
177
|
const csrfToken = csrfUtil.getCsrfTokenFromMetaHeader();
|
|
176
178
|
|
|
@@ -181,6 +183,7 @@ const createStripePaymentIntent = async (request: {
|
|
|
181
183
|
customerEmail: request.customerEmail,
|
|
182
184
|
customerRequestDetails: request.customerRequestDetails,
|
|
183
185
|
customerMessage: request.customerMessage,
|
|
186
|
+
shipping: request.shippingDetails,
|
|
184
187
|
},
|
|
185
188
|
{
|
|
186
189
|
headers: {
|
|
@@ -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
|
|
3
|
+
<div class="tw-relative tw-my-2">
|
|
4
4
|
<button
|
|
5
|
-
class="tw-bg-transparent tw-border-none tw-
|
|
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
|
|
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="
|
|
34
|
-
class="tw-border tw-border-solid tw-
|
|
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-
|
|
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="
|
|
49
|
-
class="tw-border tw-border-solid tw-
|
|
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-
|
|
73
|
+
'tw-border-grayscale-300': !cardExpiryElementError,
|
|
53
74
|
}"
|
|
54
75
|
/>
|
|
55
76
|
<div
|
|
56
|
-
ref="
|
|
57
|
-
class="tw-border tw-border-solid tw-
|
|
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-
|
|
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
|
|
141
|
-
import {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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-
|
|
495
|
+
@apply tw-text-xs;
|
|
159
496
|
color: #f21b3f;
|
|
160
497
|
}
|
|
161
498
|
</style>
|