@hhgtech/hhg-components
Version:
Hello Health Group common components
1,142 lines (1,123 loc) • 237 kB
JavaScript
import { _ as __rest, a as __awaiter } from './tslib.es6-ea4dfe68.js';
import React__default, { createContext, useMemo, useEffect, useRef, useState, useContext, useCallback, forwardRef, useImperativeHandle, memo } from 'react';
import { createStyles, Box, Button as Button$1, Input as Input$1, clsx, Autocomplete, Checkbox as Checkbox$1, Radio as Radio$1, Select as Select$1, TextInput, NumberInput as NumberInput$1, Portal, Transition, Overlay } from '@mantine/core';
import dayjs from 'dayjs';
import debounce from 'lodash/debounce';
import { createFormContext, useForm } from '@mantine/form';
import { B as BEARER_TOKEN_COOKIE } from './index-235eabf2.js';
import { getCookie, setCookie } from './miscCookieHelper.js';
import { u as useTranslations } from './index-9d21b711.js';
import { T as TranslationsContext } from './translationsContext-3a9e3453.js';
import { M as MediaQueries, b as getWrapperDomWithSelector, a as getPopupWrapperDom } from './utils-cb7242c7.js';
import { T as Text } from './index-9f5659e8.js';
import { S as Select, d as Checkbox, I as Input, R as Radio, P as Phone, N as NumberInput, O as OTP } from './index-5d405c0d.js';
import { D as DatePicker } from './index-afb403a9.js';
import { B as Button } from './index-c68a0fa7.js';
import './index.styles-770020ac.js';
import { useClickOutside } from '@mantine/hooks';
import './useMantineLocale-0c6bea99.js';
import { C as COMMON_DATE_TRANSLATE_KEY } from './index-90813715.js';
import './index-ebe66e27.js';
import { Z as ZINDEX_SSO, I as ISO_FORMAT } from './index-5e947517.js';
import './other-4ccb5568.js';
import './index-c2190f6e.js';
import { M as MAPPED_LOCALE } from './utils-9b07a6ba.js';
import { DateInput } from '@mantine/dates';
import { u as usePlacesAutocomplete, G as GOOGLE_API_KEY } from './usePlacesAutocomplete-b017462a.js';
import { H as Heading$1 } from './index-dcc517ff.js';
import { t as translationsMap$1 } from './translationsProvider-03c8b1ac.js';
import { L as LOCALE } from './Locale-f270bd9d.js';
import { v1 } from 'uuid';
import { parsePhoneNumber } from 'react-phone-number-input';
import styled from '@emotion/styled';
import { theme } from './miscTheme.js';
import { css } from '@emotion/react';
import { T as TogetherComponentGlobalContext } from './utils-40e61585.js';
import { i as isVideo } from './index-a7fca99f.js';
import { D as DrawerComponent } from './index-aebc10a7.js';
import { u as useScreenSize } from './useScreenSize-981e5b51.js';
import { createPortal } from 'react-dom';
import { B as Button$2 } from './index-6351bdee.js';
import { I as InputDate } from './InputDate-13f91afd.js';
import { C as Close } from './Close-ee386937.js';
import './constantsIsProduction.js';
import './normalizeLink-593b397a.js';
import './constantsDomainLocales.js';
import '@hhgtech/icons/other';
import '@mantine/carousel';
import 'classnames';
import './useUniqueId-4305c9aa.js';
import './constantsSite.js';
import '@hhgtech/icons/core';
import '@mantine/notifications';
import 'date-fns/locale';
import './constantsRiskScreener.js';
import './i18n-values/en-PH.js';
import './i18n-values/hi-IN.js';
import './i18n-values/id-ID.js';
import './i18n-values/km-KH.js';
import './i18n-values/ms-MY.js';
import './i18n-values/my-MM.js';
import './i18n-values/th-TH.js';
import './i18n-values/tl-PH.js';
import './i18n-values/vi-VN.js';
import './i18n-values/vi-VN_MB.js';
import './i18n-values/zh-TW.js';
import './index-963a1701.js';
import 'slugify';
import 'string-format';
import './togetherApiPaths.js';
import './constants-f4091ce6.js';
import 'vaul';
const LeadGenComponentContext = createContext({});
const CAMPAIGN_TARGET_TYPE = { LINKS: 1, TAGS: 2 };
let LEAD_API = 'https://dev.leadgen.hellobacsi.com/';
const LEAD_DEVICE_TYPE = {
MOBILE: 1,
DESKTOP: 2,
};
let LEAD_CLASS = '';
if (LEAD_API.includes('localhost')) {
LEAD_API = 'https://dev.leadgen.hellobacsi.com/';
}
if (location.hostname.includes('marrybaby.vn')) {
LEAD_CLASS = 'pink';
}
// var LEAD_CURRENT_URL = location.href.toLowerCase();
let LEAD_CURRENT_URL = 'https://' + location.hostname + location.pathname + location.search;
LEAD_CURRENT_URL = LEAD_CURRENT_URL.toLowerCase();
// TODO: set inital object if exists
if (sessionStorage.getItem('insider_object')) {
window.insider_object = JSON.parse(sessionStorage.getItem('insider_object'));
}
const docLang = document.documentElement.lang;
// TODO: country code
const LEAD_LOCALE_DATA$1 = {
'vi-VN': {
popupLang: 'vi',
countryCode: 'vn',
countryCodeNumber: 84,
},
'id-ID': {
popupLang: 'id',
countryCode: 'id',
countryCodeNumber: 62,
},
'th-TH': {
popupLang: 'th',
countryCode: 'th',
countryCodeNumber: 66,
},
'ms-MY': {
popupLang: 'ms',
countryCode: 'my',
countryCodeNumber: 60,
},
'zh-TW': {
popupLang: 'zh',
countryCode: 'tw',
countryCodeNumber: 886,
},
'km-KH': {
popupLang: 'km',
countryCode: 'kh',
countryCodeNumber: 855,
},
'my-MM': {
popupLang: 'my',
countryCode: 'mm',
countryCodeNumber: 95,
},
'hi-IN': {
popupLang: 'hi',
countryCode: 'in',
countryCodeNumber: 91,
},
};
const LEAD_LOCALE = LEAD_LOCALE_DATA$1[docLang] || LEAD_LOCALE_DATA$1['vi-VN'];
function LEAD_RESET_VAR() {
// LEAD_CURRENT_URL = location.href.toLowerCase();
LEAD_CURRENT_URL =
'https://' + location.hostname + location.pathname + location.search;
}
const LEAD_TIMEZONE_DATA = {
1: 'Asia/Ho_Chi_Minh',
10: 'Asia/Ho_Chi_Minh',
11: 'Asia/Ho_Chi_Minh',
12: 'Asia/Ho_Chi_Minh',
2: 'Asia/Jakarta',
3: 'Asia/Bangkok',
4: 'Asia/Phnom_Penh',
5: 'Asia/Kuala_Lumpur',
6: 'Asia/Taipei',
7: 'Asia/Yangon',
8: 'Asia/Kolkata',
9: 'Asia/Manila', // Philippines / Filipinos Site
};
const LEADGEN_ACTIONS = {
SHOW: 'SHOW',
SCROLL: 'SCROLL',
TIME: 'TIME',
};
const LEADGEN_LAYOUT = {
LightBoxA: 'LightBoxA',
LightBoxB: 'LightBoxB',
SkinA: 'SkinA',
SkinB: 'SkinB',
Floating: 'Floating',
Tab: 'Tab',
InlineA: 'InlineA',
InlineB: 'InlineB',
CenterTab: 'CenterTab',
Sidebar: 'Sidebar',
Fullscreen: 'Fullscreen',
Slider: 'Slider',
};
const LEADGEN_BLOCK = {
TextBlock: 'TextBlock',
NumberBlock: 'NumberBlock',
DateBlock: 'DateBlock',
EmailBlock: 'EmailBlock',
PhoneBlock: 'PhoneBlock',
PhoneOtpBlock: 'PhoneOtpBlock',
WhatsappOtpBlock: 'WhatsappOtpBlock',
ZaloOtpBlock: 'ZaloOtpBlock',
LocationBlock: 'LocationBlock',
LinkButtonBlock: 'LinkButtonBlock',
RadioBlock: 'RadioBlock',
DropdownBlock: 'DropdownBlock',
CheckboxBlock: 'CheckboxBlock',
TncBlock: 'TncBlock',
TitleBlock: 'TitleBlock',
SubtitleBlock: 'SubtitleBlock',
};
const LEADGEN_BLOCK_INPUT = [
LEADGEN_BLOCK.TextBlock,
LEADGEN_BLOCK.NumberBlock,
LEADGEN_BLOCK.DateBlock,
LEADGEN_BLOCK.EmailBlock,
LEADGEN_BLOCK.PhoneBlock,
LEADGEN_BLOCK.PhoneOtpBlock,
LEADGEN_BLOCK.WhatsappOtpBlock,
LEADGEN_BLOCK.ZaloOtpBlock,
LEADGEN_BLOCK.LocationBlock,
LEADGEN_BLOCK.RadioBlock,
LEADGEN_BLOCK.DropdownBlock,
LEADGEN_BLOCK.CheckboxBlock,
LEADGEN_BLOCK.TncBlock,
];
const leadGenFieldNamePhone = (listBlockAdded) => {
return listBlockAdded
.filter(({ name }) => [
LEADGEN_BLOCK.PhoneBlock,
LEADGEN_BLOCK.PhoneOtpBlock,
LEADGEN_BLOCK.WhatsappOtpBlock,
LEADGEN_BLOCK.ZaloOtpBlock,
].includes(name))
.map(({ data }) => data.value);
};
const SSO_MAP_LEAD = ['name', 'email', 'birthday', 'phone', 'gender'];
const LEAD_LOCALE_DATA = {
'vi-VN': {
popupLang: 'vi',
countryCode: 'vn',
countryCodeNumber: 84,
},
'id-ID': {
popupLang: 'id',
countryCode: 'id',
countryCodeNumber: 62,
},
'th-TH': {
popupLang: 'th',
countryCode: 'th',
countryCodeNumber: 66,
},
'ms-MY': {
popupLang: 'ms',
countryCode: 'my',
countryCodeNumber: 60,
},
'zh-TW': {
popupLang: 'zh',
countryCode: 'tw',
countryCodeNumber: 886,
},
'km-KH': {
popupLang: 'km',
countryCode: 'kh',
countryCodeNumber: 855,
},
'my-MM': {
popupLang: 'my',
countryCode: 'mm',
countryCodeNumber: 95,
},
'hi-IN': {
popupLang: 'hi',
countryCode: 'in',
countryCodeNumber: 91,
},
};
const mappingSSOToLead = (userInfoProps) => {
var _a, _b;
try {
const { id, area_code } = userInfoProps;
if (!userInfoProps || !id) {
return;
}
const user = {};
for (const ssoKey of SSO_MAP_LEAD) {
if (ssoKey in userInfoProps &&
typeof (userInfoProps === null || userInfoProps === void 0 ? void 0 : userInfoProps[ssoKey]) !== 'undefined') {
const initValue = userInfoProps[ssoKey];
if (ssoKey === 'birthday') {
const dob = dayjs(initValue, 'YYYY-MM-DD', true);
if (dob.isValid()) {
user.birthday = dob.toDate();
}
}
else if (ssoKey === 'gender') {
user.gender = initValue.toString();
}
else if (ssoKey === 'phone' && typeof area_code !== 'undefined') {
user.phone = area_code + initValue;
}
else {
user[ssoKey] = initValue;
}
}
}
if (((_a = user === null || user === void 0 ? void 0 : user.email) === null || _a === void 0 ? void 0 : _a.includes('@hhg.com')) ||
((_b = user === null || user === void 0 ? void 0 : user.email) === null || _b === void 0 ? void 0 : _b.includes('@facebook.com'))) {
delete user.email;
}
return Object.values(user).length ? user : undefined;
}
catch (error) {
return;
}
};
const formatCampaignDetail = (campaign) => {
if (!campaign) {
return {};
}
try {
const { extra_fields, thank_you_image } = campaign || {};
const { textBlocks: exTextBlocks, imageBlocks: exImageBlocks, listBlockAdded: exListBlockAdded, listBlockThankyou: exListBlockThankyou, actionBlocks: exActionBlocks, } = extra_fields;
const textBlocks = JSON.parse(exTextBlocks);
const imageBlocks = JSON.parse(exImageBlocks);
const listBlockAdded = JSON.parse(exListBlockAdded);
const listBlockThankyou = JSON.parse(exListBlockThankyou);
const actionBlocks = JSON.parse(exActionBlocks);
const ThankYouBlock = {
image: { src: thank_you_image },
};
listBlockThankyou.forEach((block) => {
const { name, data } = block || {};
const { value: htmlText, align, newtab, url } = data || {};
switch (name) {
case LEADGEN_BLOCK.TitleBlock: {
ThankYouBlock.title = { htmlText, align };
}
case LEADGEN_BLOCK.SubtitleBlock: {
ThankYouBlock.description = { htmlText, align };
}
case LEADGEN_BLOCK.LinkButtonBlock: {
ThankYouBlock.button = { htmlText, newtab, url };
}
}
});
return Object.assign(Object.assign({}, campaign), { extra_fields: Object.assign(Object.assign({}, extra_fields), { textBlocks,
imageBlocks,
listBlockAdded,
listBlockThankyou,
actionBlocks }), ThankYouBlock });
}
catch (error) {
return {};
}
};
class Store {
constructor() {
this.apiSsoUrl = 'https://staging-id.hellobacsi.com/';
this.apiLeadUrl = 'https://dev.leadgen.hellobacsi.com/';
this.apiSubotUrl = 'https://staging-service-subot.hellohealthgroup.com/';
}
}
const leadStore = new Store();
const METHOD = {
GET: 'get',
POST: 'POST',
};
const LEADGEN_ERROR_CODE = {
UNAUTHORIZED: 'UNAUTHORIZED',
};
const LEADGEN_API_PATH = {
V2_CAMPAIGN: 'api/v2/campaign',
V2_SUBSCRIPTION_LEAD: 'api/v2/subscription-box',
V2_SUBSCRIPTION_INFO: 'api/campaign/get-title',
};
const SSO_API_PATH = {
USER_UPDATE: 'api/user/update',
};
const ssoApi = {
call(_a) {
var { url, data } = _a, config = __rest(_a, ["url", "data"]);
const token = getCookie(BEARER_TOKEN_COOKIE);
config.body = JSON.stringify(data);
config.headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
};
if (!token) {
return Promise.reject({
code: LEADGEN_ERROR_CODE.UNAUTHORIZED,
_data: '',
});
}
return fetch(`${leadStore.apiSsoUrl}${url}`, config)
.then((res) => res.json())
.catch(() => ({}));
},
};
const leadApi = {
call(_a) {
var { url, data = undefined } = _a, config = __rest(_a, ["url", "data"]);
config.body = JSON.stringify(data);
config.headers = {
'Content-Type': 'application/json',
};
return fetch(`${leadStore.apiLeadUrl}${url}`, config)
.then((res) => res.json())
.catch(() => ({}));
},
};
const subotApi = {
call(_a) {
var { url, data } = _a, config = __rest(_a, ["url", "data"]);
config.body = JSON.stringify(data);
config.headers = {
'Content-Type': 'application/json',
};
return fetch(`${leadStore.apiSubotUrl}${url}`, config)
.then((res) => res.json())
.catch(() => ({}));
},
};
const campaignGetById = (id) => {
return leadApi.call({
url: `api/internal/campaign/${id}`,
method: 'get',
});
};
const validateEmailOrPhoneOnLeadGen = ({ campaign_id, email, phone, }) => {
let phoneToSend = phone;
// Remove the '0' part. Logic from Back to check between Subot and Lead with different format
if (phoneToSend && phoneToSend.startsWith('0')) {
phoneToSend = phoneToSend.substring(1);
}
return leadApi.call({
url: 'api/subot-campaign/check',
method: 'post',
data: {
campaign_id,
email,
phone: phoneToSend,
},
});
};
const validateEmailOrPhoneOnSubot = ({ bot_id, email, phone, }) => {
let phoneToSend = phone;
// Remove the '0' part. Logic from Back to check between Subot and Lead with different format
if (phoneToSend && phoneToSend.startsWith('0')) {
phoneToSend = phoneToSend.substring(1);
}
return subotApi.call({
url: 'frontend/api/subot-campaign/check',
method: 'post',
data: {
bot_id,
email,
phone: phoneToSend,
},
});
};
const validatePhoneNumberOnLeadGen = ({ campaign_id, phone, }) => {
return leadApi.call({
url: 'api/collection/log/check-phone-with-campaign',
method: 'post',
data: {
campaign_id,
phone,
},
});
};
const LEAD_OTP_API = {
whatsapp: 'api/sms/whatsapp_otp',
phone: 'api/sms/otp',
zalo: 'api/sms/zalo_otp',
};
const sendSMSOtpLead = ({ phone, type, }) => {
return leadApi.call({
url: LEAD_OTP_API[type],
method: 'post',
data: {
// The type Whatsapp/Zalo do not remove the '+'
phone_number: type === 'phone' ? phone.replace('+', '') : phone,
},
});
};
const LEAD_VERIFY_OTP_API = {
whatsapp: 'api/sms/whatsapp_verify',
phone: 'api/sms/verify',
zalo: 'api/sms/zalo_verify',
};
const verifyOtpLead = ({ phone, otp, type, }) => {
return leadApi.call({
url: LEAD_VERIFY_OTP_API[type],
method: 'post',
data: {
// The type Whatsapp/Zalo do not remove the '+'
otp_code: otp,
phone_number: type === 'phone' ? phone.replace('+', '') : phone,
},
});
};
const getCampaignByCode = (campaign_code) => {
return leadApi.call({
url: `${LEADGEN_API_PATH.V2_CAMPAIGN}/${campaign_code}`,
method: METHOD.GET,
});
};
const getSubscriptionBoxInfo = ({ category, site, }) => {
return leadApi.call({
url: `${LEADGEN_API_PATH.V2_SUBSCRIPTION_INFO}?category=${category}&site=${site}`,
method: METHOD.GET,
});
};
const postSubscriptionBoxLead = ({ data }) => {
return leadApi.call({
url: LEADGEN_API_PATH.V2_SUBSCRIPTION_LEAD,
method: METHOD.POST,
data,
});
};
const postUserInfoFromLeadGen = ({ name }) => {
return ssoApi.call({
url: SSO_API_PATH.USER_UPDATE,
method: METHOD.POST,
data: { name },
});
};
const campaignPostImpression = ({ code, action, title_article, ga_client_id, cookie_id, extra, url, referrer, }) => {
return leadApi.call({
url: `api/campaign/${code}/impression`,
method: METHOD.POST,
data: {
action,
title_article,
cookie_id,
ga_client_id,
url,
extra,
referrer,
},
});
};
const Service = {
campaignGetById,
getCampaignByCode,
getSubscriptionBoxInfo,
postSubscriptionBoxLead,
postUserInfoFromLeadGen,
campaignPostImpression,
validateEmailOrPhoneOnSubot,
validateEmailOrPhoneOnLeadGen,
validatePhoneNumberOnLeadGen,
sendSMSOtpLead,
verifyOtpLead,
};
const checkUsedEmailOrPhone = (campaignId, campaign_subot_id, data) => __awaiter(void 0, void 0, void 0, function* () {
const key = 'email' in data ? 'email' : 'phone';
const value = 'email' in data ? data.email : data.phone;
const errorMsg = 'email' in data ? 'validator.emailUsed' : 'validator.phoneUsed';
/** Check on Leadgen Tool */
const resLeadGen = yield Service.validateEmailOrPhoneOnLeadGen({
campaign_id: [campaignId],
[key]: value, // Can be email or phone
});
if (resLeadGen._errorCode === 'SubmitLeadWithBotId_ERR_001' ||
resLeadGen._errorCode === 'SubmitLeadWithBotId_ERR_002') {
return errorMsg;
}
/** Check on Subot */
if (campaign_subot_id.length) {
const resSubot = yield Service.validateEmailOrPhoneOnSubot({
bot_id: campaign_subot_id,
[key]: value, // Can be email or phone
});
if (resSubot._errorCode === 'CheckSuBotLeadTool_ERR_001') {
return errorMsg;
}
}
});
const checkUsedPhoneOnly = (campaignId, phone) => __awaiter(void 0, void 0, void 0, function* () {
var _a;
const resLeadGen = yield Service.validatePhoneNumberOnLeadGen({
campaign_id: campaignId,
phone,
});
if (((_a = resLeadGen === null || resLeadGen === void 0 ? void 0 : resLeadGen._messages) === null || _a === void 0 ? void 0 : _a[0]) === 'Phone was exist') {
return 'validator.phoneUsed';
}
});
const validatedCache = {
email: {},
phone: {},
phoneOnly: {},
};
const checkUsedEmailOrPhoneWithCache = (campaignId, campaign_subot_id, data) => __awaiter(void 0, void 0, void 0, function* () {
const key = 'email' in data ? 'email' : 'phone';
const value = 'email' in data ? data.email : data.phone;
const errorMsg = 'email' in data ? 'validator.emailUsed' : 'validator.phoneUsed';
if (validatedCache[key][value]) {
if (validatedCache[key][value].value) {
return errorMsg;
}
else if (!validatedCache[key][value].value &&
validatedCache[key][value].expire > Date.now()) {
return '';
}
}
const res = yield checkUsedEmailOrPhone(campaignId, campaign_subot_id, data);
if (res) {
validatedCache[key][value] = {
value: true,
};
}
else {
validatedCache[key][value] = {
value: false,
expire: Date.now() + 1000 * 60,
};
}
return res;
});
const checkUsedPhoneOnlyWithCache = (campaignId, phone) => __awaiter(void 0, void 0, void 0, function* () {
if (validatedCache.phoneOnly[phone]) {
if (validatedCache.phoneOnly[phone].value) {
return 'validator.phoneUsed';
}
else if (!validatedCache.phoneOnly[phone].value &&
validatedCache.phoneOnly[phone].expire > Date.now()) {
return '';
}
}
const res = yield checkUsedPhoneOnly(campaignId, phone);
if (res) {
validatedCache.phoneOnly[phone] = {
value: true,
};
}
else {
validatedCache.phoneOnly[phone] = {
value: false,
expire: Date.now() + 1000 * 60,
};
}
return res;
});
const clearCacheUsedEmailOrPhone = () => {
validatedCache.email = {};
validatedCache.phone = {};
validatedCache.phoneOnly = {};
};
// You can give context variables any name
const [LeadFormProvider$1, useLeadFormContext$1, useLeadForm$1] = createFormContext();
const useLeadFormConfig$1 = ({ listBlockAdded = [], validatingPhoneRef, validatingEmailRef, campaignId, campaign_subot_id = [], userInfo, }) => {
const { t } = useTranslations();
const initialValues = useMemo(() => mappingSSOToLead(userInfo), [userInfo === null || userInfo === void 0 ? void 0 : userInfo.id]);
useEffect(() => {
if (!window.intlTelInputUtils) {
require('intl-tel-input/build/js/utils');
}
}, []);
const validateObj = useMemo(() => {
const InputBlocks = [
'TextBlock',
'NumberBlock',
'EmailBlock',
'PhoneBlock',
'DateBlock',
'CheckboxBlock',
'RadioBlock',
'DropdownBlock',
'PhoneOtpBlock',
'WhatsappOtpBlock',
'ZaloOtpBlock',
'LocationBlock',
'TncBlock',
];
// ALL are required and can skip if not touched yet
const withSharedCheck = (name, cb,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
block) => {
return (value) => {
var _a;
const isBLockRequired = (_a = block === null || block === void 0 ? void 0 : block.data) === null || _a === void 0 ? void 0 : _a.required;
if (!formRef.current.isTouched(name))
return;
if (typeof value === 'undefined' ||
value === '' ||
(Array.isArray(value) && value.length === 0)) {
return isBLockRequired
? t('validator.required')
: cb === null || cb === void 0 ? void 0 : cb(value);
}
return cb === null || cb === void 0 ? void 0 : cb(value);
};
};
return listBlockAdded
.filter((b) => InputBlocks.includes(b.name))
.reduce((r, b) => {
var _a;
const isRequired = (_a = b.data.required) !== null && _a !== void 0 ? _a : true;
if (b.name === 'NumberBlock') {
return Object.assign(Object.assign({}, r), { [b.data.value]: withSharedCheck(b.data.value, (value) => {
if (value && isNaN(Number(value))) {
return t('validator.number');
}
}, b) });
}
else if (b.name === 'EmailBlock') {
return Object.assign(Object.assign({}, r), { [b.data.value]: withSharedCheck(b.data.value, (value) => {
if (value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
return t('validator.email');
}
if (!value)
return;
validatingEmailRef.current = true;
setTimeout(() => {
formRef.current.setFieldError(b.data.value, 'Validating...');
checkUsedEmailOrPhoneWithCache(campaignId, campaign_subot_id, {
email: value,
})
.then((tKey) => {
if (tKey) {
formRef.current.setFieldError(b.data.value, t(tKey));
}
else {
formRef.current.clearFieldError(b.data.value);
}
validatingEmailRef.current = false;
})
.catch((e) => {
console.error(e);
formRef.current.setFieldError(b.data.value, e.message || 'Something went wrong');
validatingEmailRef.current = false;
});
}, 200);
}, b) });
}
else if (b.name === 'PhoneBlock' ||
b.name === 'PhoneOtpBlock' ||
b.name === 'ZaloOtpBlock' ||
b.name === 'WhatsappOtpBlock') {
return Object.assign(Object.assign({}, r), { [b.data.value]: withSharedCheck(b.data.value, (value) => {
if (value &&
window.intlTelInputUtils &&
!window.intlTelInputUtils.isValidNumber(String(value), LEAD_LOCALE.countryCode)) {
return t('validator.phone');
}
if (!value)
return;
validatingPhoneRef.current = true;
setTimeout(() => {
formRef.current.setFieldError(b.data.value, 'Validating...');
if (b.data.singleSubmission) {
checkUsedPhoneOnlyWithCache(campaignId, value)
.then((tKey) => {
if (tKey) {
formRef.current.setFieldError(b.data.value, t(tKey));
}
else {
formRef.current.clearFieldError(b.data.value);
}
validatingPhoneRef.current = false;
})
.catch((err) => {
console.error(err);
formRef.current.setFieldError(b.data.value, err.message || 'Something went wrong');
validatingPhoneRef.current = false;
});
}
else {
checkUsedEmailOrPhoneWithCache(campaignId, campaign_subot_id, {
phone: value,
})
.then((tKey) => {
if (tKey) {
formRef.current.setFieldError(b.data.value, t(tKey));
}
else {
formRef.current.clearFieldError(b.data.value);
}
validatingPhoneRef.current = false;
})
.catch((e) => {
console.error(e);
formRef.current.setFieldError(b.data.value, e.message || 'Something went wrong');
validatingPhoneRef.current = false;
});
}
}, 200);
}, b) });
}
else if (b.name === 'DateBlock') {
return Object.assign(Object.assign({}, r), { [b.data.value]: withSharedCheck(b.data.value, (value) => {
if (value && isNaN(Date.parse(value))) {
return t('validator.date');
}
}, b) });
}
else if (b.name === 'TncBlock') {
return Object.assign(Object.assign({}, r), { [`TNC-` + b.id]: withSharedCheck('TNC-' + b.id, (value) => {
if (isRequired && !value) {
return t('validator.required');
}
}, b) });
}
else {
return Object.assign(Object.assign({}, r), { [b.data.value]: withSharedCheck(b.data.value, undefined, b) });
}
}, {});
}, [listBlockAdded.map((b) => b.name).join(',')]);
const form = useLeadForm$1({
validateInputOnChange: true,
clearInputErrorOnChange: true,
validate: validateObj,
initialValues,
});
const formRef = useRef(form);
formRef.current = form;
return { form, validateObj };
};
const Component = ({ campaign, onClose: onCloseProp, onOtherSubmit, onSubmit, showThankyou, setShowThankyou, locale, children, showEmpty, setShowEmpty, userInfo, }) => {
var _a, _b;
const extraFields = campaign.extra_fields;
const campaignId = campaign.id;
const campaign_subot_id = campaign.bot_id || [];
const listBlockAdded = JSON.parse(extraFields.listBlockAdded);
const actionBlocks = JSON.parse(extraFields.actionBlocks);
const textBlocks = JSON.parse(extraFields.textBlocks);
const heading = ((_b = (_a = textBlocks === null || textBlocks === void 0 ? void 0 : textBlocks.titleBlock) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.value) || '';
const description = textBlocks.subtitleBlock.data.value;
const validatingPhoneRef = useRef(false);
const validatingEmailRef = useRef(false);
const leadFormConfig = useLeadFormConfig$1({
listBlockAdded,
validatingPhoneRef,
validatingEmailRef,
campaignId,
campaign_subot_id,
userInfo,
});
const [showOtpPhone, setShowOtpPhone] = useState(null);
const [formRef, setFormRef] = useState(null);
const onClose = () => {
if (showOtpPhone) {
setShowOtpPhone(null);
}
else {
onCloseProp === null || onCloseProp === void 0 ? void 0 : onCloseProp();
}
};
useEffect(() => {
clearCacheUsedEmailOrPhone();
}, []);
return campaign ? (React__default.createElement(LeadGenComponentContext.Provider, { value: {
campaignId,
campaign_subot_id,
heading,
description,
listBlockAdded,
textBlocks,
actionBlocks,
leadFormConfig,
validatingEmailRef,
validatingPhoneRef,
formRef: { current: formRef },
setFormRef,
locale,
onClose,
onOtherSubmit,
showOtpPhone,
setShowOtpPhone,
onSubmit,
showThankyou,
setShowThankyou,
showEmpty,
setShowEmpty,
} }, children)) : null;
};
const Description = (_a) => {
var rest = __rest(_a, []);
const { description } = useContext(LeadGenComponentContext);
return description ? (React__default.createElement(Text, Object.assign({ size: "p3" }, rest), description)) : null;
};
const LeadGenContext$1 = createContext({});
var useStyles$2 = createStyles(() => {
return {
control: {},
};
});
const libraries$1 = ['places'];
const LocationBlock = ({ name, placeholder, locale, required = true, }) => {
var _a;
const form = useLeadFormContext$1();
const [searchValue, setSearchValue] = useState('');
const [address, setAddress] = useState('');
const { predictions } = usePlacesAutocomplete(searchValue, '', locale === 'tl-PH' ? 'en' : (_a = locale === null || locale === void 0 ? void 0 : locale.split('-')) === null || _a === void 0 ? void 0 : _a[0]);
const [LoadScript, setLoadScript] = useState(null);
const [ready, setReady] = useState(false);
const randRef = useRef(Math.random().toString(36).substring(7));
const options = useMemo(() => {
const _opts = predictions.map((p) => {
return {
value: p.description,
label: p.description,
};
});
const isExist = _opts.find((o) => o.value === address);
if (!address || isExist) {
return _opts;
}
return [{ value: address, label: address }].concat(_opts);
}, [predictions, address]);
useEffect(() => {
var _a, _b, _c;
// only load extra google script when not yet loaded
if (!((_c = (_b = (_a = window === null || window === void 0 ? void 0 : window.google) === null || _a === void 0 ? void 0 : _a.maps) === null || _b === void 0 ? void 0 : _b.places) === null || _c === void 0 ? void 0 : _c.AutocompleteService)) {
import('@react-google-maps/api').then((m) => {
setLoadScript(() => m.LoadScript);
setTimeout(() => {
setReady(true);
}, 200);
});
}
else {
setReady(true);
}
}, []);
if (!ready)
return (React__default.createElement("div", { style: {
height: 73,
} }));
return (React__default.createElement(React__default.Fragment, null,
LoadScript && (React__default.createElement(LoadScript, { googleMapsApiKey: GOOGLE_API_KEY, libraries: libraries$1, loadingElement: React__default.createElement(React__default.Fragment, null) })),
React__default.createElement("div", { style: { display: 'none' }, "data-extra": true, "data-name": name, "data-control": 'text' }),
React__default.createElement(Select, Object.assign({ className: "lead-modal__form-control", label: placeholder, placeholder: placeholder, withAsterisk: required, name: name, data: options, searchValue: searchValue, onSearchChange: (query) => {
setSearchValue(query);
}, filter: () => true, clearable: true, searchable: true, onChange: (val) => setAddress(val || ''), icon: React__default.createElement("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none" },
React__default.createElement("path", { d: "M10 9.792q.605 0 1.032-.427.426-.428.426-1.032 0-.603-.426-1.031A1.4 1.4 0 0 0 10 6.875q-.604 0-1.032.427a1.4 1.4 0 0 0-.426 1.031q0 .604.426 1.032.428.426 1.032.427m0 8.083q-.145 0-.292-.042a.7.7 0 0 1-.27-.145Q6.478 15 5.01 12.708 3.54 10.418 3.54 8.5q0-3.021 1.949-4.823T10 1.875t4.51 1.802q1.95 1.802 1.949 4.823 0 1.917-1.468 4.208-1.47 2.292-4.427 4.98a.7.7 0 0 1-.271.145 1 1 0 0 1-.292.042", fill: "#8C8C8C" })), autoComplete: 'no-auto-complete-' + randRef.current, rightSection: React__default.createElement(React__default.Fragment, null) }, form.getInputProps(name)))));
};
const SubtitleBlock$1 = ({ children, align, }) => (React__default.createElement("p", { className: `lead-modal__description ${'le-text-align-' + (align || '')} ${LEAD_CLASS}` }, children));
const TitleBlock$1 = ({ children, align, }) => (React__default.createElement("h2", { className: `lead-modal__title ${'le-text-align-' + (align || '')} ${LEAD_CLASS}` }, children));
const Fields = ({ listBlockAdded, popupId, locale, onClose, onOtherSubmit, styles, classNames, popoverProps, }) => {
const { primaryColor } = useContext(LeadGenContext$1);
const { classes, cx } = useStyles$2(undefined, {
name: 'LeadGen__Field',
styles,
classNames,
});
const form = useLeadFormContext$1();
return (React__default.createElement(React__default.Fragment, null, listBlockAdded.map((b, index) => {
var _a;
const { name = '', data = {} } = b || {};
const { placeholder, value, align, listQuestion, isSendMailChimp = false, newtab, url, } = data;
const required = (_a = data.required) !== null && _a !== void 0 ? _a : true;
switch (name) {
case 'TitleBlock':
return (React__default.createElement(TitleBlock$1, { key: index, align: align }, value));
case 'SubtitleBlock':
return (React__default.createElement(SubtitleBlock$1, { key: index, align: align }, value));
case 'TextBlock':
return (React__default.createElement(Input, Object.assign({ key: index, withAsterisk: required, spellCheck: false, type: "text", placeholder: placeholder, className: cx('leadgen-control', classes.control),
// onChangeRaw={(e) => inputOnChange('text', e)}
label: placeholder, "data-control": "text", name: value }, form.getInputProps(value))));
case 'NumberBlock':
return (React__default.createElement(NumberInput, Object.assign({ key: index, withAsterisk: required, spellCheck: false, type: "number", placeholder: placeholder, className: cx('leadgen-control', classes.control),
// onChange={(e) => inputOnChange('number', e)}
label: placeholder, "data-control": "number", name: value }, form.getInputProps(value))));
case 'EmailBlock':
return (React__default.createElement(Input, Object.assign({ key: index, withAsterisk: required, spellCheck: false,
// type="email"
placeholder: placeholder, className: cx('leadgen-control', classes.control), label: placeholder, "data-control": "email", name: value }, form.getInputProps(value))));
case 'PhoneOtpBlock':
case 'WhatsappOtpBlock':
case 'ZaloOtpBlock':
case 'PhoneBlock': {
const id = popupId + '-' + value + '-' + index;
return (React__default.createElement(Input.Wrapper, Object.assign({ size: "md", withAsterisk: required, key: index, label: placeholder,
// error={errorField.phone}
className: cx('leadgen-control', classes.control), labelProps: {
htmlFor: id,
} }, form.getInputProps(value)),
React__default.createElement(Phone, { name: value, spellCheck: false, type: "tel", placeholder: placeholder, value: form.getInputProps(value).value, onChange: (v) => {
form.setFieldValue(value, v);
},
// onBlur={(e) => inputOnBlur('tel', e)}
id: id, defaultCountry: (locale ? MAPPED_LOCALE[locale] || 'VN' : 'VN'), "data-control": "tel" })));
}
case 'LocationBlock': {
return (React__default.createElement(LocationBlock, { key: index, name: value, placeholder: placeholder, locale: locale, required: required }));
}
case 'DateBlock':
return (React__default.createElement(React__default.Fragment, null,
React__default.createElement(DatePicker, Object.assign({ withAsterisk: required, key: index, type: "default", name: value, placeholder: placeholder, className: cx('leadgen-control', classes.control), label: placeholder, "data-control": "date", popoverProps: popoverProps }, form.getInputProps(value))),
React__default.createElement("input", { type: "hidden", name: value, "data-control": "date" })));
case 'LinkButtonBlock':
return (React__default.createElement("div", { key: index },
React__default.createElement("a", { target: newtab ? 'blank' : 'parrent', href: url, style: { textDecoration: 'none' } },
React__default.createElement(Button, { type: "button", size: "md", color: primaryColor, className: `lead-modal__btn ${LEAD_CLASS}`, onClick: () => {
onClose === null || onClose === void 0 ? void 0 : onClose();
onOtherSubmit === null || onOtherSubmit === void 0 ? void 0 : onOtherSubmit();
} }, value))));
case 'CheckboxBlock':
return (React__default.createElement(React__default.Fragment, null,
isSendMailChimp && (React__default.createElement("div", { style: {
display: 'none',
}, "data-name": value + '-mailchimp' })),
React__default.createElement(Checkbox.Group, Object.assign({ withAsterisk: required, className: cx('leadgen-control', classes.control), key: index, label: placeholder, size: "md", sx: {
display: 'flex',
flexDirection: 'column',
gap: 8,
} }, form.getInputProps(value)), listQuestion.map((l, _index) => (React__default.createElement(Checkbox, { name: value, key: _index, value: l.value, label: l.placeholder, "data-control": "checkbox" }))))));
case 'RadioBlock':
return (React__default.createElement(React__default.Fragment, null,
isSendMailChimp && (React__default.createElement(Input, { type: "hidden", name: value + '-mailchimp', value: isSendMailChimp })),
React__default.createElement(Radio.Group, Object.assign({ withAsterisk: required, className: cx('leadgen-control', classes.control), key: index, label: placeholder, size: "md" }, form.getInputProps(value)), listQuestion.map((l, _index) => (React__default.createElement(Radio, { name: value, key: _index, value: l.value, label: l.placeholder, "data-control": "radio" }))))));
case 'DropdownBlock':
return (React__default.createElement(React__default.Fragment, null,
React__default.createElement("div", { style: { display: 'none' }, "data-extra": true, "data-name": value, "data-control": 'dropdown' }),
React__default.createElement(Select, Object.assign({ key: index, className: cx('leadgen-control', classes.control), label: placeholder, withAsterisk: required, name: value, data: listQuestion.map((l) => ({
value: l.value,
label: l.placeholder,
})) }, form.getInputProps(value)))));
case 'TncBlock':
const tncInputProps = form.getInputProps('TNC-' + b.id);
return (React__default.createElement(React__default.Fragment, null,
React__default.createElement(Checkbox, Object.assign({ name: 'TNC-' + b.id, key: b.id, label: React__default.createElement("p", { className: "lead-modal__tnc-link", dangerouslySetInnerHTML: { __html: data.valueHTML } }), className: "tnc-block", "data-control": "checkbox" }, tncInputProps, { error: tncInputProps.error ? tncInputProps.error : undefined }))));
}
return null;
})));
};
var useStyles$1 = createStyles((theme) => {
return {
root: {},
header: {},
heading: {},
description: {},
term: {
a: {
color: theme.fn.primaryColor(),
},
},
controlList: {},
control: {},
submitBtn: {},
submitBtnWrapper: {},
};
});
const Heading = (_a) => {
var rest = __rest(_a, []);
const { heading } = useContext(LeadGenComponentContext);
return heading ? (React__default.createElement(Text, Object.assign({ size: "h3" }, rest), heading)) : null;
};
const FormComponent = ({ styles, className, classNames, fillInfo, popoverProps, submitProps, }) => {
var _a;
const { primaryColor } = useContext(LeadGenContext$1);
const { listBlockAdded, leadFormConfig: { form, validateObj }, validatingEmailRef, validatingPhoneRef, formRef, setFormRef, onClose, onOtherSubmit, actionBlocks, locale, setShowOtpPhone, onSubmit, } = useContext(LeadGenComponentContext);
const { classes, cx } = useStyles$1(undefined, {
name: 'LeadGen__FormComponent',
styles,
classNames,
});
const [isSubmitLoading, setIsSubmitLoading] = useState(false);
const popUpSubmitText = actionBlocks.submitBlock.data.value;
const middlewareOnSubmit = (e) => {
e.preventDefault();
// mark all as touched to allow validation
form.setTouched(Object.keys(validateObj).reduce((acc, cur) => {
acc[cur] = true;
return acc;
}, {}));
if (validatingEmailRef.current || validatingPhoneRef.current) {
return;
}
setTimeout(() => {
form.onSubmit((v) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
if (Object.keys(form.errors).length)
return;
let newShowOtpPhone = null;
if (listBlockAdded.findIndex((x) => x.name === 'PhoneOtpBlock') > -1) {
// not submit yet, open otp
const fieldName = (_b = (_a = listBlockAdded.find((x) => x.name === 'PhoneOtpBlock')) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.value;
if ((_c = v[fieldName]) === null || _c === void 0 ? void 0 : _c.startsWith('+')) {
newShowOtpPhone = {
phone: v[fieldName],
type: 'phone',
};
}
}
if (listBlockAdded.findIndex((x) => x.name === 'WhatsappOtpBlock') > -1) {
// not submit yet, open otp
const fieldName = (_e = (_d = listBlockAdded.find((x) => x.name === 'WhatsappOtpBlock')) === null || _d === void 0 ? void 0 : _d.data) === null || _e === void 0 ? void 0 : _e.value;
if ((_f = v[fieldName]) === null || _f === void 0 ? void 0 : _f.startsWith('+')) {
newShowOtpPhone = {
phone: v[fieldName],
type: 'whatsapp',
};
}
}
if (listBlockAdded.findIndex((x) => x.name === 'ZaloOtpBlock') > -1) {
// not submit yet, open otp
const fieldName = (_h = (_g = listBlockAdded.find((x) => x.name === 'ZaloOtpBlock')) === null || _g === void 0 ? void 0 : _g.data) === null || _h === void 0 ? void 0 : _h.value;
if ((_j = v[fieldName]) === null || _j === void 0 ? void 0 : _j.startsWith('+')) {
newShowOtpPhone = {
phone: v[fieldName],
type: 'zalo',
};
}
}
if (newShowOtpPhone) {
setIsSubmitLoading(true);
Service.sendSMSOtpLead(newShowOtpPhone)
.then((res) => {
var _a;
const respMessage = (_a = res === null || res === void 0 ? void 0 : res._messages) === null || _a === void 0 ? void 0 : _a[0];
if (respMessage === 'This phone number was verified') {
onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit(formRef.current, v);
return;
}
setShowOtpPhone(newShowOtpPhone);
})
.finally(() => {
setIsSubmitLoading(false);
});
return;
}
onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit(formRef.current, v);
})(e);
}, 100);
};
useEffect(() => {
form === null || form === void 0 ? void 0 : form.setValues(fillInfo);
}, [fillInfo]);
return (React__default.createElement(LeadFormProvider$1, { form: form },
React__default.createElement(Box, { component: "form", ref: (el) => el && setFormRef(el), className: cx(className, classes.root), onSubmit: middlewareOnSubmit, styles: styles },
React__default.createElement("div", { className: classes.header },
React__default.createElement(Heading, { className: classes.heading }),
React__default.createElement(Description, { className: classes.description })),