@bikdotai/bik-widgets 1.0.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.
Files changed (206) hide show
  1. package/.eslintrc +22 -0
  2. package/.eslintrc.js +19 -0
  3. package/.github/workflows/main.yml +293 -0
  4. package/.prettierignore +13 -0
  5. package/.prettierrc +10 -0
  6. package/README.md +128 -0
  7. package/cypress/apiHelper/endpoints.ts +21 -0
  8. package/cypress/apiHelper/executor.ts +42 -0
  9. package/cypress/e2e/bottomDrawer.cy.ts +49 -0
  10. package/cypress/e2e/directReward.cy.ts +67 -0
  11. package/cypress/e2e/scratchTheCard.cy.ts +68 -0
  12. package/cypress/e2e/stw.cy.ts +82 -0
  13. package/cypress/e2e/waRedirection.cy.ts +46 -0
  14. package/cypress/fixtures/payloads.ts +330 -0
  15. package/cypress/support/commands.ts +37 -0
  16. package/cypress/support/e2e.ts +20 -0
  17. package/cypress.staging.config.ts +23 -0
  18. package/jsconfig.json +6 -0
  19. package/localtest.sh +10 -0
  20. package/log-server.js +86 -0
  21. package/package.json +79 -0
  22. package/postcss.config.js +8 -0
  23. package/src/Globals.d.ts +2 -0
  24. package/src/assets/lottie/santa.json +11722 -0
  25. package/src/assets/svg/CalendarClockIcon.tsx +30 -0
  26. package/src/assets/svg/CalendarIcon.tsx +24 -0
  27. package/src/assets/svg/CheckIcon.tsx +17 -0
  28. package/src/assets/svg/ChevronIcon.tsx +21 -0
  29. package/src/assets/svg/Close.tsx +39 -0
  30. package/src/assets/svg/Confetti.tsx +140 -0
  31. package/src/assets/svg/Copy.tsx +26 -0
  32. package/src/assets/svg/DropdownCheckIcon.tsx +35 -0
  33. package/src/assets/svg/ErrorIcon.tsx +27 -0
  34. package/src/assets/svg/RadioIcon.tsx +25 -0
  35. package/src/assets/svg/UncheckedCheckboxIcon.tsx +28 -0
  36. package/src/assets/svg/UncheckedRadioIcon.tsx +26 -0
  37. package/src/assets/svg/info.tsx +30 -0
  38. package/src/assets/svg/qrcode.svg +14 -0
  39. package/src/bootstrap.tsx +8 -0
  40. package/src/components/CtaCard/index.tsx +37 -0
  41. package/src/components/CtaCard/preview.module.css +32 -0
  42. package/src/components/CtaCard/style.module.css +32 -0
  43. package/src/components/EmailInput/emailInputBox.tsx +95 -0
  44. package/src/components/Fab/index.tsx +224 -0
  45. package/src/components/Fab/preview.module.css +28 -0
  46. package/src/components/Fab/style.module.css +37 -0
  47. package/src/components/Icons/Call.tsx +26 -0
  48. package/src/components/Icons/Cross.tsx +24 -0
  49. package/src/components/Icons/Gmail.tsx +61 -0
  50. package/src/components/Icons/Instagram.tsx +60 -0
  51. package/src/components/Icons/LiveChat.tsx +43 -0
  52. package/src/components/Icons/Messenger.tsx +57 -0
  53. package/src/components/Icons/Send.tsx +22 -0
  54. package/src/components/Icons/Whatsapp.tsx +24 -0
  55. package/src/components/Shimmer/index.tsx +12 -0
  56. package/src/components/Shimmer/style.module.css +37 -0
  57. package/src/components/SmsInput/smsInputBox.tsx +135 -0
  58. package/src/components/UserDetailsV2/userDetailsV2.desktop.module.css +52 -0
  59. package/src/components/UserDetailsV2/userDetailsV2.mobile.module.css +52 -0
  60. package/src/components/UserDetailsV2/userDetailsV2.module.css +81 -0
  61. package/src/components/UserDetailsV2/userDetailsV2.tsx +527 -0
  62. package/src/components/WhatsappInput/Spinner.tsx +26 -0
  63. package/src/components/WhatsappInput/whatsappInput.module.css +106 -0
  64. package/src/components/WhatsappInput/whatsappInputBox.tsx +155 -0
  65. package/src/components/WhatsappInput/whatsappInputPreviewDesktop.module.css +71 -0
  66. package/src/components/WhatsappInput/whatsappInputPreviewMobile.module.css +65 -0
  67. package/src/components/checkbox/checkbox.module.css +19 -0
  68. package/src/components/checkbox/checkbox.tsx +88 -0
  69. package/src/components/countryCodePicker/countriesDropdown.module.css +77 -0
  70. package/src/components/countryCodePicker/countriesDropdown.tsx +81 -0
  71. package/src/components/couponDetails/coupon.module.css +208 -0
  72. package/src/components/couponDetails/coupon.tsx +210 -0
  73. package/src/components/couponDetails/couponPreviewDesktop.module.css +158 -0
  74. package/src/components/couponDetails/couponPreviewMobile.module.css +164 -0
  75. package/src/components/index.ts +3 -0
  76. package/src/components/inputComponents/Checkbox.module.css +197 -0
  77. package/src/components/inputComponents/Checkbox.tsx +85 -0
  78. package/src/components/inputComponents/DatePicker.module.css +565 -0
  79. package/src/components/inputComponents/DatePicker.tsx +278 -0
  80. package/src/components/inputComponents/Dropdown.module.css +796 -0
  81. package/src/components/inputComponents/Dropdown.tsx +630 -0
  82. package/src/components/inputComponents/InputBox.module.css +401 -0
  83. package/src/components/inputComponents/InputBox.tsx +209 -0
  84. package/src/components/selectedCountry/selectedCountry.module.css +76 -0
  85. package/src/components/selectedCountry/selectedCountry.tsx +76 -0
  86. package/src/components/selectedCountry/selectedCountryPreviewDesktop.module.css +56 -0
  87. package/src/components/selectedCountry/selectedCountryPreviewMobile.module.css +57 -0
  88. package/src/components/userDetailsForm/RenderCustomFields.tsx +333 -0
  89. package/src/components/userDetailsForm/userDetailsForm.tsx +675 -0
  90. package/src/hooks/index.ts +4 -0
  91. package/src/hooks/useExitIntent.ts +452 -0
  92. package/src/hooks/useIsMobile.tsx +21 -0
  93. package/src/hooks/useMessageEvent.ts +8 -0
  94. package/src/hooks/useTriggeredIntentDetails.ts +43 -0
  95. package/src/hooks/useUrlListerner.ts +30 -0
  96. package/src/hooks/useWebSocketLogger.ts +59 -0
  97. package/src/hooks/useWindowEvent.ts +8 -0
  98. package/src/icons/copyIcon.tsx +26 -0
  99. package/src/icons/crossIconDesktop.tsx +20 -0
  100. package/src/icons/crossIconMobile.tsx +20 -0
  101. package/src/index.html +30 -0
  102. package/src/index.ts +32 -0
  103. package/src/index.tsx +1 -0
  104. package/src/repo/widgetRepo.ts +21 -0
  105. package/src/types/customFields.ts +73 -0
  106. package/src/utilities/cookie.ts +70 -0
  107. package/src/utilities/customFieldTypeMapping.ts +67 -0
  108. package/src/utilities/customFieldValidation.ts +201 -0
  109. package/src/utilities/encryption.ts +21 -0
  110. package/src/utilities/exitIntentUtils.ts +31 -0
  111. package/src/utilities/global.css +11 -0
  112. package/src/utilities/languageUtilities.ts +235 -0
  113. package/src/utilities/localRunner.js +26 -0
  114. package/src/utilities/localRunner.ts +27 -0
  115. package/src/utilities/localStorage.ts +40 -0
  116. package/src/utilities/script.tsx +15 -0
  117. package/src/utilities/stringUtils.ts +5 -0
  118. package/src/utilities/styleUtils.ts +134 -0
  119. package/src/utilities/variables.ts +11 -0
  120. package/src/utilities/widgetUtils.js +342 -0
  121. package/src/utilities/widgetUtils.ts +313 -0
  122. package/src/widgets/BottomDrawer/config.ts +41 -0
  123. package/src/widgets/BottomDrawer/index.tsx +116 -0
  124. package/src/widgets/BottomDrawer/modal.tsx +286 -0
  125. package/src/widgets/BottomDrawer/preview.module.css +122 -0
  126. package/src/widgets/BottomDrawer/previewMobile.module.css +124 -0
  127. package/src/widgets/BottomDrawer/style.module.css +279 -0
  128. package/src/widgets/CaptivateBanner/captivateBanner.tsx +200 -0
  129. package/src/widgets/CaptivateBanner/config.ts +72 -0
  130. package/src/widgets/CaptivateBanner/index.tsx +204 -0
  131. package/src/widgets/CaptivateBanner/previewDesktop.module.css +51 -0
  132. package/src/widgets/CaptivateBanner/previewMobile.module.css +51 -0
  133. package/src/widgets/CaptivateBanner/style.module.css +77 -0
  134. package/src/widgets/CaptivateBanner/utils.ts +104 -0
  135. package/src/widgets/CentrallyAlignedPopup/config.ts +42 -0
  136. package/src/widgets/CentrallyAlignedPopup/index.tsx +109 -0
  137. package/src/widgets/CentrallyAlignedPopup/modal.tsx +269 -0
  138. package/src/widgets/CentrallyAlignedPopup/preview.module.css +153 -0
  139. package/src/widgets/CentrallyAlignedPopup/previewMobile.module.css +153 -0
  140. package/src/widgets/CentrallyAlignedPopup/style.module.css +283 -0
  141. package/src/widgets/DirectReward/components/couponDetails.tsx +265 -0
  142. package/src/widgets/DirectReward/components/userDetails.tsx +117 -0
  143. package/src/widgets/DirectReward/config.ts +186 -0
  144. package/src/widgets/DirectReward/directReward.tsx +350 -0
  145. package/src/widgets/DirectReward/index.tsx +579 -0
  146. package/src/widgets/DirectReward/previewStyles/thankYouPreviewDesktop.module.css +276 -0
  147. package/src/widgets/DirectReward/previewStyles/thankYouPreviewMobile.module.css +303 -0
  148. package/src/widgets/DirectReward/previewStyles/userDetailsPreviewDesktop.module.css +511 -0
  149. package/src/widgets/DirectReward/previewStyles/userDetailsPreviewMobile.module.css +462 -0
  150. package/src/widgets/DirectReward/style.module.css +836 -0
  151. package/src/widgets/ExitIntentHook.tsx +28 -0
  152. package/src/widgets/STW/api.ts +70 -0
  153. package/src/widgets/STW/components/svgFactory.tsx +44 -0
  154. package/src/widgets/STW/config.ts +193 -0
  155. package/src/widgets/STW/context.ts +7 -0
  156. package/src/widgets/STW/couponDetails.tsx +121 -0
  157. package/src/widgets/STW/index.tsx +733 -0
  158. package/src/widgets/STW/previewStyles/thankyouPreviewDesktop.module.css +215 -0
  159. package/src/widgets/STW/previewStyles/thankyouPreviewMobile.module.css +205 -0
  160. package/src/widgets/STW/previewStyles/userInputsPreviewDesktop.module.css +732 -0
  161. package/src/widgets/STW/previewStyles/userInputsPreviewMobile.module.css +661 -0
  162. package/src/widgets/STW/previewStyles/wheelPreviewDesktop.module.css +498 -0
  163. package/src/widgets/STW/previewStyles/wheelPreviewMobile.module.css +497 -0
  164. package/src/widgets/STW/stw1.tsx +119 -0
  165. package/src/widgets/STW/stw2Components/wheelDesign.tsx +183 -0
  166. package/src/widgets/STW/stw2Pages/couponDetails.tsx +72 -0
  167. package/src/widgets/STW/stw2Pages/stw2.tsx +212 -0
  168. package/src/widgets/STW/stw2Pages/style.module.css +1226 -0
  169. package/src/widgets/STW/stw2Pages/userDetails.tsx +86 -0
  170. package/src/widgets/STW/stw2Pages/wheel.tsx +117 -0
  171. package/src/widgets/STW/stw2PreviewStyles/thankyouPreviewDesktop.module.css +835 -0
  172. package/src/widgets/STW/stw2PreviewStyles/thankyouPreviewMobile.module.css +787 -0
  173. package/src/widgets/STW/stw2PreviewStyles/userInputsPreviewDesktop.module.css +867 -0
  174. package/src/widgets/STW/stw2PreviewStyles/userInputsPreviewMobile.module.css +798 -0
  175. package/src/widgets/STW/stw2PreviewStyles/wheelPreviewDesktop.module.css +572 -0
  176. package/src/widgets/STW/stw2PreviewStyles/wheelPreviewMobile.module.css +559 -0
  177. package/src/widgets/STW/style.module.css +901 -0
  178. package/src/widgets/STW/userDetails.tsx +150 -0
  179. package/src/widgets/STW/utility.ts +664 -0
  180. package/src/widgets/STW/wheel.tsx +304 -0
  181. package/src/widgets/ScratchCard/ScratchOff/scratchOff.tsx +157 -0
  182. package/src/widgets/ScratchCard/config.ts +152 -0
  183. package/src/widgets/ScratchCard/globalStyle.module.css +931 -0
  184. package/src/widgets/ScratchCard/index.tsx +546 -0
  185. package/src/widgets/ScratchCard/modal.tsx +225 -0
  186. package/src/widgets/ScratchCard/preview.module.css +250 -0
  187. package/src/widgets/ScratchCard/previewMobile.module.css +247 -0
  188. package/src/widgets/ScratchCard/previewStyles/userDetailsPreviewDesktop.module.css +537 -0
  189. package/src/widgets/ScratchCard/previewStyles/userDetailsPreviewMobile.module.css +463 -0
  190. package/src/widgets/ScratchCard/style.module.css +220 -0
  191. package/src/widgets/ShopifyForm/config.ts +168 -0
  192. package/src/widgets/ShopifyForm/index.tsx +214 -0
  193. package/src/widgets/ShopifyForm/previewDesktop.module.css +117 -0
  194. package/src/widgets/ShopifyForm/previewMobile.module.css +131 -0
  195. package/src/widgets/ShopifyForm/shopifyForm.tsx +445 -0
  196. package/src/widgets/ShopifyForm/style.module.css +161 -0
  197. package/src/widgets/SingleButtonRedirection/config.ts +47 -0
  198. package/src/widgets/SingleButtonRedirection/index.tsx +121 -0
  199. package/src/widgets/WebStories/config.ts +105 -0
  200. package/src/widgets/WebStories/index.css +3 -0
  201. package/src/widgets/WebStories/index.tsx +282 -0
  202. package/src/widgets/WebStories/style.module.css +26 -0
  203. package/src/widgets/index.tsx +3 -0
  204. package/src/widgets/utility.ts +31 -0
  205. package/tsconfig.json +12 -0
  206. package/webpack.config.js +239 -0
@@ -0,0 +1,675 @@
1
+ import React, { useContext, useEffect, useState } from 'react';
2
+ import {
3
+ IDRWidgetCustomisation,
4
+ ISTWWidgetCustomisation,
5
+ ISTWWidgetLeadGeneration,
6
+ IUserInputs,
7
+ WIDGET_NAME,
8
+ LANGUAGE_VALUES,
9
+ } from '@bikdotai/bik-models/dm';
10
+ import { CountriesData } from '../../widgets/STW/utility';
11
+ import { STWContext } from '../../widgets/STW/context';
12
+ import useIsMobile from '../../hooks/useIsMobile';
13
+ import { ComponentStyleMap } from '../../utilities/styleUtils';
14
+ import parse from 'html-react-parser';
15
+ import { decodeTextHelper } from '../../widgets/utility';
16
+ import EmailInputBox from '../EmailInput/emailInputBox';
17
+ import SMSInputBox from '../SmsInput/smsInputBox';
18
+ import WhatsappInputBox from '../WhatsappInput/whatsappInputBox';
19
+ import SVGFactory, { SVGName } from '../../widgets/STW/components/svgFactory';
20
+ import { phone } from 'phone';
21
+ import { tlds } from '@hapi/tlds';
22
+ import { LanguageUtils } from '../../utilities/languageUtilities';
23
+ import RenderCustomFields from './RenderCustomFields';
24
+ import {
25
+ UserFields,
26
+ UserFieldDetails,
27
+ CustomFieldError,
28
+ } from '../../types/customFields';
29
+ import { validateCustomFields } from '../../utilities/customFieldValidation';
30
+ import {
31
+ CUSTOM_FIELDS,
32
+ mapCustomFields,
33
+ } from '../../utilities/customFieldTypeMapping';
34
+
35
+ const UserDetailsForm: React.FC<{
36
+ claimPrizeHandle?: (userInputs: UserFields) => Promise<void>;
37
+ widgetCustomisation: ISTWWidgetCustomisation | IDRWidgetCustomisation;
38
+ leadGeneration: ISTWWidgetLeadGeneration;
39
+ error: string;
40
+ isLoading: boolean;
41
+ templateName: WIDGET_NAME;
42
+ showTitle?: boolean;
43
+ skipSubtitle?: boolean;
44
+ widgetName: string;
45
+ countryCode: string;
46
+ id?: string;
47
+ hideCreatorLabel?: boolean;
48
+ widgetLanguage?: LANGUAGE_VALUES;
49
+ }> = ({
50
+ widgetCustomisation,
51
+ leadGeneration,
52
+ hideCreatorLabel,
53
+ error,
54
+ isLoading,
55
+ claimPrizeHandle,
56
+ templateName,
57
+ showTitle = true,
58
+ skipSubtitle = false,
59
+ widgetName,
60
+ countryCode,
61
+ id,
62
+ widgetLanguage,
63
+ }) => {
64
+ const languageUtilities = new LanguageUtils();
65
+ const skipCountryPicker: boolean =
66
+ widgetCustomisation.skipCountryPicker ?? false;
67
+ const selectedCountry = CountriesData.filter(
68
+ country => country.code3 === countryCode,
69
+ );
70
+ const { preview, isMobile } = useContext(STWContext);
71
+ const { fontFamily, fontColour } =
72
+ widgetCustomisation as ISTWWidgetCustomisation;
73
+ const {
74
+ mandatoryOption,
75
+ optionalOptions,
76
+ enableConsentPolicies,
77
+ privacyPolicyURL,
78
+ } = leadGeneration as ISTWWidgetLeadGeneration;
79
+ const isMobileDevice = useIsMobile();
80
+ let userDetailsTitleSize: string;
81
+ let userDetailsSubTitleSize: string;
82
+
83
+ if (preview) {
84
+ userDetailsTitleSize = isMobile ? '16px' : '12px';
85
+ userDetailsSubTitleSize = isMobile ? '13px' : '10px';
86
+ } else {
87
+ userDetailsTitleSize = isMobileDevice ? '18px' : `24px`;
88
+ userDetailsSubTitleSize = isMobileDevice ? '14px' : `16px`;
89
+ }
90
+
91
+ const [userInputs, setUserInputs] = useState<UserFields>({
92
+ isWhatsapp: {
93
+ value: null,
94
+ countryCodeData: selectedCountry.length
95
+ ? selectedCountry[0]
96
+ : {
97
+ dial: '+91',
98
+ code: 'IN',
99
+ code3: 'IND',
100
+ },
101
+ showComponent: true,
102
+ error: null,
103
+ },
104
+ isSms: {
105
+ value: null,
106
+ countryCodeData: selectedCountry.length
107
+ ? selectedCountry[0]
108
+ : {
109
+ dial: '+91',
110
+ code: 'IN',
111
+ code3: 'IND',
112
+ },
113
+ showComponent: true,
114
+ error: null,
115
+ },
116
+ isEmail: {
117
+ value: null,
118
+ error: null,
119
+ },
120
+ isPolicyChecked: {
121
+ value: null,
122
+ error: null,
123
+ },
124
+ customFields: {},
125
+ });
126
+ const [optionlOptionsRevised, setOptionalOptionsRevised] =
127
+ useState<IUserInputs>();
128
+ const [isPrivacyPolicyChecked, setIsPrivacyPolicyChecked] =
129
+ useState<boolean>(false);
130
+ const [currentStyle, setCurrentStyle] = useState<Record<
131
+ string,
132
+ string
133
+ > | null>(null);
134
+ const [customFieldErrors, setCustomFieldErrors] = useState<CustomFieldError>(
135
+ {},
136
+ );
137
+ const multiLingualData =
138
+ widgetCustomisation?.multiLingualConfigurations?.[widgetLanguage];
139
+
140
+ useEffect(() => {
141
+ const mandatoryOptionTemp = Object.keys(mandatoryOption).filter(key => {
142
+ return key === 'isWhatsapp' || key === 'isSms';
143
+ });
144
+ if (mandatoryOptionTemp.length) {
145
+ let optionalOptionsTemp = { ...optionalOptions };
146
+ Object.keys(optionalOptions).filter(key => {
147
+ if ((key === 'isWhatsapp' || key === 'isSms') && optionalOptions[key]) {
148
+ optionalOptionsTemp = {
149
+ [key]: optionalOptions[key],
150
+ ...optionalOptionsTemp,
151
+ };
152
+ }
153
+ });
154
+ setOptionalOptionsRevised(optionalOptionsTemp);
155
+ }
156
+ }, [mandatoryOption, optionalOptions]);
157
+
158
+ const onChangeHandle = (
159
+ value: string,
160
+ key: 'isWhatsapp' | 'isSms' | 'isEmail',
161
+ ) => {
162
+ setUserInputs(prevInputs => ({
163
+ ...prevInputs,
164
+ [key]: { ...prevInputs[key], error: null, value: value },
165
+ }));
166
+ };
167
+
168
+ const validateEmail = email => {
169
+ const emailRegex =
170
+ /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
171
+ const match = email.match(emailRegex);
172
+ if (!match) return false;
173
+
174
+ const domain = email.split('@')[1];
175
+ const tld = domain.split('.').pop();
176
+ return tlds.has(tld);
177
+ };
178
+
179
+ const claimPrize = () => {
180
+ let hasError = false;
181
+ let updatedUserInput = JSON.parse(JSON.stringify(userInputs));
182
+ const customFieldsError: CustomFieldError = {};
183
+
184
+ Object.keys(mandatoryOption).forEach(key => {
185
+ if (
186
+ key !== CUSTOM_FIELDS &&
187
+ mandatoryOption[key] &&
188
+ userInputs[key] &&
189
+ !(userInputs[key] as UserFieldDetails).value
190
+ ) {
191
+ updatedUserInput = {
192
+ ...updatedUserInput,
193
+ [key]: {
194
+ ...updatedUserInput[key],
195
+ error: languageUtilities.getRequiredFieldMessage(widgetLanguage),
196
+ },
197
+ };
198
+ hasError = true;
199
+ } else if (
200
+ key === CUSTOM_FIELDS &&
201
+ mandatoryOption[key] &&
202
+ mandatoryOption.customFields?.length > 0
203
+ ) {
204
+ const mandatoryFields = mapCustomFields(mandatoryOption.customFields);
205
+ const validationResult = validateCustomFields(
206
+ mandatoryFields,
207
+ [],
208
+ updatedUserInput.customFields || {},
209
+ );
210
+
211
+ if (!validationResult.isValid) {
212
+ Object.assign(customFieldsError, validationResult.errors);
213
+ hasError = true;
214
+ }
215
+ }
216
+ });
217
+
218
+ Object.keys(optionalOptions).forEach(key => {
219
+ const otherKey = key === 'isWhatsapp' ? 'isSms' : 'isWhatsapp';
220
+ if (
221
+ optionalOptions[key] &&
222
+ key !== 'isEmail' &&
223
+ key !== CUSTOM_FIELDS &&
224
+ !userInputs[key].showComponent
225
+ ) {
226
+ updatedUserInput = {
227
+ ...updatedUserInput,
228
+ [key]: {
229
+ ...updatedUserInput[key],
230
+ value: updatedUserInput[otherKey].value,
231
+ },
232
+ };
233
+ } else if (
234
+ key === CUSTOM_FIELDS &&
235
+ optionalOptions[key] &&
236
+ optionalOptions.customFields?.length > 0
237
+ ) {
238
+ const optionalFields = mapCustomFields(optionalOptions.customFields);
239
+ const validationResult = validateCustomFields(
240
+ [],
241
+ optionalFields,
242
+ updatedUserInput.customFields || {},
243
+ );
244
+
245
+ if (!validationResult.isValid) {
246
+ Object.assign(customFieldsError, validationResult.errors);
247
+ hasError = true;
248
+ }
249
+ }
250
+ });
251
+
252
+ if (enableConsentPolicies && !isPrivacyPolicyChecked) {
253
+ hasError = true;
254
+ updatedUserInput = {
255
+ ...updatedUserInput,
256
+ isPolicyChecked: {
257
+ ...updatedUserInput.isPolicyChecked,
258
+ error:
259
+ languageUtilities.getPrivacyPolicyAcceptanceMessage(widgetLanguage),
260
+ },
261
+ };
262
+ }
263
+ if (userInputs.isEmail.value && !validateEmail(userInputs.isEmail.value)) {
264
+ updatedUserInput = {
265
+ ...updatedUserInput,
266
+ isEmail: {
267
+ ...updatedUserInput.isEmail,
268
+ error: languageUtilities.getEmailValidationMessage(widgetLanguage),
269
+ },
270
+ };
271
+ hasError = true;
272
+ }
273
+ if (
274
+ userInputs.isWhatsapp.value &&
275
+ !phone(
276
+ (userInputs.isWhatsapp.countryCodeData.dial +
277
+ userInputs.isWhatsapp.value) as string,
278
+ { strictDetection: true },
279
+ ).isValid
280
+ ) {
281
+ updatedUserInput = {
282
+ ...updatedUserInput,
283
+ isWhatsapp: {
284
+ ...updatedUserInput.isWhatsapp,
285
+ error:
286
+ languageUtilities.getPhoneNumberValidationMessage(widgetLanguage),
287
+ },
288
+ };
289
+ hasError = true;
290
+ }
291
+ if (
292
+ userInputs.isSms.value &&
293
+ !phone(
294
+ (userInputs.isSms.countryCodeData.dial +
295
+ userInputs.isSms.value) as string,
296
+ { strictDetection: true },
297
+ ).isValid
298
+ ) {
299
+ updatedUserInput = {
300
+ ...updatedUserInput,
301
+ isSms: {
302
+ ...updatedUserInput.isSms,
303
+ error:
304
+ languageUtilities.getPhoneNumberValidationMessage(widgetLanguage),
305
+ },
306
+ };
307
+ hasError = true;
308
+ }
309
+ setCustomFieldErrors(customFieldsError);
310
+ setUserInputs(updatedUserInput);
311
+ if (hasError) {
312
+ return;
313
+ }
314
+
315
+ claimPrizeHandle?.(updatedUserInput);
316
+ };
317
+
318
+ const onPrivacyPolicyChangeHandle = (value: boolean) => {
319
+ setIsPrivacyPolicyChecked(value);
320
+ setUserInputs(prevInputs => ({
321
+ ...prevInputs,
322
+ isPolicyChecked: { value: value, error: null },
323
+ }));
324
+ };
325
+
326
+ useEffect(() => {
327
+ if (preview) {
328
+ if (isMobile) {
329
+ ComponentStyleMap[templateName]?.userInputPreviewMobile.then(
330
+ async style => {
331
+ setCurrentStyle((await style()).default);
332
+ },
333
+ );
334
+ } else {
335
+ ComponentStyleMap[templateName]?.userInputPreviewDesktop.then(
336
+ async style => {
337
+ setCurrentStyle((await style()).default);
338
+ },
339
+ );
340
+ }
341
+ } else {
342
+ ComponentStyleMap[templateName]?.globalStyle.then(async style => {
343
+ setCurrentStyle((await style()).default);
344
+ });
345
+ }
346
+ }, [preview, isMobile]);
347
+
348
+ useEffect(() => {
349
+ if (currentStyle) {
350
+ document
351
+ .getElementById(currentStyle.bikFooter2)
352
+ .setAttribute(
353
+ 'dir',
354
+ languageUtilities.getLanguageDirection(widgetLanguage),
355
+ );
356
+ }
357
+ }, [widgetLanguage, currentStyle]);
358
+
359
+ const screenTitle =
360
+ (multiLingualData?.postPlayScreenTitle ??
361
+ widgetCustomisation?.postPlayScreenTitle) ? (
362
+ parse(
363
+ decodeTextHelper(
364
+ multiLingualData?.postPlayScreenTitle ??
365
+ widgetCustomisation.postPlayScreenTitle,
366
+ ),
367
+ )
368
+ ) : (
369
+ <p>
370
+ <strong>Special prize only for you!</strong>
371
+ </p>
372
+ );
373
+ const screenSubTitle =
374
+ (multiLingualData?.postPlayScreenSubTitle ??
375
+ widgetCustomisation?.postPlayScreenSubTitle) ? (
376
+ parse(
377
+ decodeTextHelper(
378
+ multiLingualData?.postPlayScreenSubTitle ??
379
+ widgetCustomisation.postPlayScreenSubTitle,
380
+ ),
381
+ )
382
+ ) : (
383
+ <></>
384
+ );
385
+ const screenButtonText =
386
+ templateName === WIDGET_NAME.DIRECT_REWARD ||
387
+ templateName === WIDGET_NAME.LEAD_GENERATOR
388
+ ? (multiLingualData?.playScreenButtonText ??
389
+ widgetCustomisation?.playScreenButtonText)
390
+ : (multiLingualData?.postPlayScreenButtonText ??
391
+ widgetCustomisation.postPlayScreenButtonText ??
392
+ 'Claim the prize');
393
+ const screenButtonTextColour =
394
+ templateName === WIDGET_NAME.DIRECT_REWARD ||
395
+ templateName === WIDGET_NAME.LEAD_GENERATOR
396
+ ? (widgetCustomisation as IDRWidgetCustomisation)
397
+ .playScreenButtonTextColour
398
+ : (widgetCustomisation.postPlayScreenButtonTextColour ?? '#fff');
399
+ const screenButtonColour =
400
+ templateName === WIDGET_NAME.DIRECT_REWARD ||
401
+ templateName === WIDGET_NAME.LEAD_GENERATOR
402
+ ? (widgetCustomisation as IDRWidgetCustomisation).playScreenButtonColour
403
+ : (widgetCustomisation.postPlayScreenButtonColour ?? '#731dcf');
404
+
405
+ if (!currentStyle) {
406
+ return <></>;
407
+ }
408
+
409
+ return (
410
+ <>
411
+ <div
412
+ id={currentStyle.bikFooter2}
413
+ style={{
414
+ fontFamily: fontFamily?.name,
415
+ display: 'flex',
416
+ flexDirection: 'column',
417
+ }}
418
+ >
419
+ {showTitle && (
420
+ <div
421
+ style={{ fontSize: userDetailsTitleSize, color: fontColour }}
422
+ className={currentStyle.userDetailsTitleWrapper}
423
+ >
424
+ {screenTitle}
425
+ </div>
426
+ )}
427
+ {!skipSubtitle && (
428
+ <div
429
+ style={{
430
+ marginTop: preview ? 4 : 8,
431
+ fontSize: userDetailsSubTitleSize,
432
+ color: fontColour,
433
+ opacity: 0.8,
434
+ }}
435
+ className={currentStyle.userDetailsTitleWrapper}
436
+ >
437
+ {screenSubTitle}
438
+ </div>
439
+ )}
440
+ {Object.keys(mandatoryOption).map(key => {
441
+ return (
442
+ <>
443
+ {key === 'isEmail' && mandatoryOption[key] && (
444
+ <EmailInputBox
445
+ id={`bik-${id}-input-email`}
446
+ onChangeHandle={onChangeHandle}
447
+ value={userInputs.isEmail.value as string}
448
+ error={userInputs.isEmail.error}
449
+ fontColour={fontColour}
450
+ widgetLanguage={widgetLanguage}
451
+ />
452
+ )}
453
+ {key === 'isSms' && mandatoryOption[key] && (
454
+ <SMSInputBox
455
+ id={`bik-${id}-input-sms`}
456
+ selectedCountryData={userInputs.isSms.countryCodeData}
457
+ setUserInputs={setUserInputs}
458
+ onChangeHandle={onChangeHandle}
459
+ value={userInputs.isSms.value as string}
460
+ error={userInputs.isSms.error}
461
+ skipCountryPicker={skipCountryPicker ?? false}
462
+ fontColour={fontColour}
463
+ widgetLanguage={widgetLanguage}
464
+ />
465
+ )}
466
+ {key === 'isWhatsapp' && mandatoryOption[key] && (
467
+ <WhatsappInputBox
468
+ id={`bik-${id}-input-whatsapp`}
469
+ selectedCountryData={userInputs.isWhatsapp.countryCodeData}
470
+ setUserInputs={setUserInputs}
471
+ onChangeHandle={onChangeHandle}
472
+ value={userInputs.isWhatsapp.value as string}
473
+ error={userInputs.isWhatsapp.error}
474
+ skipCountryPicker={skipCountryPicker ?? false}
475
+ fontColour={fontColour}
476
+ screenButtonColour={screenButtonColour}
477
+ widgetLanguage={widgetLanguage}
478
+ />
479
+ )}
480
+ {key === CUSTOM_FIELDS && mandatoryOption[key]?.length > 0 && (
481
+ <RenderCustomFields
482
+ id={id}
483
+ customFields={mapCustomFields(mandatoryOption[key])}
484
+ userInputs={userInputs}
485
+ setUserInputs={setUserInputs}
486
+ isRequired={true}
487
+ customFieldErrors={customFieldErrors}
488
+ setCustomFieldErrors={setCustomFieldErrors}
489
+ fontColour={fontColour}
490
+ onFocusColour={screenButtonColour}
491
+ backgroundColor={widgetCustomisation?.backgroundColour}
492
+ />
493
+ )}
494
+ </>
495
+ );
496
+ })}
497
+ {optionlOptionsRevised &&
498
+ Object.keys(optionlOptionsRevised)?.map(key => {
499
+ return (
500
+ <>
501
+ {key === 'isEmail' && optionlOptionsRevised[key] && (
502
+ <EmailInputBox
503
+ fontColour={fontColour}
504
+ id={`bik-${id}-input-email-op`}
505
+ onChangeHandle={onChangeHandle}
506
+ value={userInputs.isEmail.value as string}
507
+ title={languageUtilities.getOptionalEmailTitle(
508
+ widgetLanguage,
509
+ )}
510
+ error={userInputs.isEmail.error}
511
+ widgetLanguage={widgetLanguage}
512
+ />
513
+ )}
514
+ {key === 'isSms' &&
515
+ optionlOptionsRevised[key] &&
516
+ userInputs.isSms.showComponent && (
517
+ <SMSInputBox
518
+ fontColour={fontColour}
519
+ id={`bik-${id}-input-sms-op`}
520
+ selectedCountryData={userInputs.isSms.countryCodeData}
521
+ setUserInputs={setUserInputs}
522
+ onChangeHandle={onChangeHandle}
523
+ value={userInputs.isSms.value as string}
524
+ title={languageUtilities.getOptionalPhoneNumberTitle(
525
+ widgetLanguage,
526
+ )}
527
+ error={userInputs.isSms.error}
528
+ skipCountryPicker={skipCountryPicker ?? false}
529
+ widgetLanguage={widgetLanguage}
530
+ />
531
+ )}
532
+ {key === 'isWhatsapp' &&
533
+ optionlOptionsRevised[key] &&
534
+ userInputs.isWhatsapp.showComponent && (
535
+ <WhatsappInputBox
536
+ fontColour={fontColour}
537
+ id={`bik-${id}-input-whatsapp-op`}
538
+ selectedCountryData={
539
+ userInputs.isWhatsapp.countryCodeData
540
+ }
541
+ setUserInputs={setUserInputs}
542
+ onChangeHandle={onChangeHandle}
543
+ value={userInputs.isWhatsapp.value as string}
544
+ title={languageUtilities.getOptionalWhatsappNumberTitle(
545
+ widgetLanguage,
546
+ )}
547
+ error={userInputs.isWhatsapp.error}
548
+ skipCountryPicker={skipCountryPicker ?? false}
549
+ widgetLanguage={widgetLanguage}
550
+ screenButtonColour={screenButtonColour}
551
+ />
552
+ )}
553
+
554
+ {key === CUSTOM_FIELDS && optionalOptions[key]?.length > 0 && (
555
+ <RenderCustomFields
556
+ id={id}
557
+ customFields={mapCustomFields(optionalOptions[key])}
558
+ userInputs={userInputs}
559
+ setUserInputs={setUserInputs}
560
+ isRequired={false}
561
+ customFieldErrors={customFieldErrors}
562
+ setCustomFieldErrors={setCustomFieldErrors}
563
+ fontColour={fontColour}
564
+ onFocusColour={screenButtonColour}
565
+ backgroundColor={widgetCustomisation?.backgroundColour}
566
+ />
567
+ )}
568
+ </>
569
+ );
570
+ })}
571
+ {enableConsentPolicies && (
572
+ <>
573
+ {/* Style override for bikStwH2 font size */}
574
+ <style>{`.bikStwH2Override { font-size: ${preview ? '8px' : '12px'} !important; }`}</style>
575
+ <div
576
+ className={currentStyle.bikStwWaCheckboxContainer}
577
+ style={preview ? { gap: '4px', marginTop: '4px' } : {}}
578
+ >
579
+ <input
580
+ type="checkbox"
581
+ id={currentStyle.bikStwPolicyCheckbox}
582
+ name="bik-wa"
583
+ checked={isPrivacyPolicyChecked}
584
+ onChange={e => onPrivacyPolicyChangeHandle(e.target.checked)}
585
+ style={{
586
+ display: 'block',
587
+ margin: 0,
588
+ appearance: 'auto',
589
+ ...(preview
590
+ ? { width: '10px' }
591
+ : {
592
+ width: '12px',
593
+ height: '12px',
594
+ clip: 'unset',
595
+ position: 'relative',
596
+ }),
597
+ }}
598
+ />
599
+ <h2
600
+ className={`${currentStyle.bikStwH2} bikStwH2Override`}
601
+ style={{ color: fontColour }}
602
+ >
603
+ {languageUtilities.getPrivacyPolicyText(widgetLanguage)}{' '}
604
+ <a
605
+ href={privacyPolicyURL}
606
+ style={{
607
+ color: fontColour,
608
+ fontSize: preview ? '8px' : '12px',
609
+ display: 'inline-block',
610
+ }}
611
+ target="_blank"
612
+ rel="noreferrer"
613
+ >
614
+ {languageUtilities.getPrivacyPolicyLabel(widgetLanguage)}
615
+ </a>
616
+ </h2>
617
+ </div>
618
+ {userInputs.isPolicyChecked.error?.length ? (
619
+ <p id={currentStyle.bikErrorWrapper}>
620
+ {userInputs.isPolicyChecked.error}
621
+ </p>
622
+ ) : (
623
+ <></>
624
+ )}
625
+ </>
626
+ )}
627
+ {error?.length ? (
628
+ <p id={currentStyle.bikErrorWrapper} style={{ color: fontColour }}>
629
+ {error}
630
+ </p>
631
+ ) : (
632
+ <></>
633
+ )}
634
+ <button
635
+ id={currentStyle.bikayiBtn}
636
+ className={currentStyle.bikCliamBtn}
637
+ onClick={() => claimPrize()}
638
+ style={{
639
+ backgroundColor: screenButtonColour,
640
+ color: screenButtonTextColour,
641
+ fontFamily: fontFamily?.name ?? 'inherit',
642
+ }}
643
+ >
644
+ {isLoading ? (
645
+ <div className={currentStyle.loader}></div>
646
+ ) : (
647
+ screenButtonText
648
+ )}
649
+ </button>
650
+ </div>
651
+ {!widgetCustomisation.hidePoweredBy && !hideCreatorLabel && (
652
+ <p
653
+ className={currentStyle.poweredBy}
654
+ style={{ opacity: 0.4 }}
655
+ onClick={() =>
656
+ window.open(
657
+ `https://bik.ai/?utm_campaign=${widgetName}&utm_medium=Widgets&utm_source=Powered_by_bik`,
658
+ )
659
+ }
660
+ >
661
+ <a
662
+ href={`https://bik.ai/?utm_campaign=${widgetName}&utm_medium=Widgets&utm_source=Powered_by_bik`}
663
+ target="_blank"
664
+ rel="noreferrer"
665
+ style={{ color: fontColour }}
666
+ >
667
+ {languageUtilities.getPoweredByMessage(widgetLanguage)}
668
+ </a>
669
+ <SVGFactory name={SVGName.BIK} color={fontColour} />
670
+ </p>
671
+ )}
672
+ </>
673
+ );
674
+ };
675
+ export default UserDetailsForm;
@@ -0,0 +1,4 @@
1
+ import { useWindowEvent } from './useWindowEvent';
2
+ import { useMessageEvent } from './useMessageEvent';
3
+
4
+ export { useWindowEvent, useMessageEvent };