@alexsab-ru/scripts 0.15.2 → 0.16.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.
- package/lib/calltouch/create-request.js +76 -53
- package/lib/form.js +72 -12
- package/package.json +1 -1
|
@@ -1,8 +1,75 @@
|
|
|
1
|
-
export const createRequest = (routeKey, phoneValue, nameValue, verbose = false) => {
|
|
2
|
-
return new Promise((resolve, reject) => {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
export const createRequest = (routeKey, phoneValue, nameValue, verbose = false, modId = '') => {
|
|
2
|
+
return new Promise((resolve, reject) => {
|
|
3
|
+
let errorText = '';
|
|
4
|
+
|
|
5
|
+
// Если mod_id передан явно, пытаемся взять выделенный инстанс multi-project:
|
|
6
|
+
// window["ctw_<mod_id>"].
|
|
7
|
+
const scopedKey = modId ? `ctw_${modId}` : '';
|
|
8
|
+
const scopedCtw = scopedKey && window[scopedKey] ? window[scopedKey] : null;
|
|
9
|
+
// Fallback для старого сценария, где есть только один глобальный инстанс.
|
|
10
|
+
const fallbackCtw = window.ctw || null;
|
|
11
|
+
const ctwInstance = scopedCtw || fallbackCtw;
|
|
12
|
+
|
|
13
|
+
if (!ctwInstance || typeof ctwInstance.createRequest !== 'function') {
|
|
14
|
+
reject('window.ctw is not defined');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const executeCreateRequest = () => {
|
|
19
|
+
let phone_ct = phoneValue.replace(/[^0-9]/gim, '');
|
|
20
|
+
if (phone_ct[0] == '8') { phone_ct = phone_ct.substring(1); }
|
|
21
|
+
if (phone_ct[0] == '7') { phone_ct = phone_ct.substring(1); }
|
|
22
|
+
phone_ct = '7' + phone_ct;
|
|
23
|
+
|
|
24
|
+
ctwInstance.createRequest(
|
|
25
|
+
routeKey,
|
|
26
|
+
phone_ct,
|
|
27
|
+
(nameValue.length > 0 ? [{ "name": "Name", "value": nameValue }] : []),
|
|
28
|
+
function(success, data) {
|
|
29
|
+
verbose && console.log(success, data);
|
|
30
|
+
if (success) {
|
|
31
|
+
verbose && console.log('Создана заявка на колбек, идентификатор: ' + data.callbackRequestId);
|
|
32
|
+
resolve(data);
|
|
33
|
+
} else {
|
|
34
|
+
errorText = 'Error in createRequest';
|
|
35
|
+
switch (data.type) {
|
|
36
|
+
case 'request_throttle_timeout':
|
|
37
|
+
case 'request_throttle_count':
|
|
38
|
+
errorText = 'Достигнут лимит создания заявок, попробуйте позже';
|
|
39
|
+
verbose && console.log(errorText);
|
|
40
|
+
break;
|
|
41
|
+
case 'request_phone_blacklisted':
|
|
42
|
+
errorText = 'номер телефона находится в черном списке';
|
|
43
|
+
verbose && console.log(errorText);
|
|
44
|
+
break;
|
|
45
|
+
case 'validation_error':
|
|
46
|
+
errorText = 'были переданы некорректные данные';
|
|
47
|
+
verbose && console.log(errorText);
|
|
48
|
+
break;
|
|
49
|
+
default:
|
|
50
|
+
errorText = 'Во время выполнения запроса произошла ошибка: ' + data.type;
|
|
51
|
+
verbose && console.log(errorText);
|
|
52
|
+
}
|
|
53
|
+
reject(errorText);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Multi-project: если нашли window["ctw_<mod_id>"], сразу создаём заявку.
|
|
60
|
+
// Здесь намеренно пропускаем getRouteKeyData.
|
|
61
|
+
if (scopedCtw) {
|
|
62
|
+
executeCreateRequest();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Legacy-ветка: без mod_id сохраняем исходную проверку routeKey через getRouteKeyData.
|
|
67
|
+
if (typeof ctwInstance.getRouteKeyData !== 'function') {
|
|
68
|
+
reject('window.ctw.getRouteKeyData is not defined');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
ctwInstance.getRouteKeyData(routeKey, function(success, data) {
|
|
6
73
|
verbose && console.log(success, data);
|
|
7
74
|
if (success) {
|
|
8
75
|
if (data.widgetFound) {
|
|
@@ -15,62 +82,18 @@ return new Promise((resolve, reject) => {
|
|
|
15
82
|
verbose && console.log('колл-центр не работает, заявки в нерабочее время не собираем');
|
|
16
83
|
}
|
|
17
84
|
}
|
|
18
|
-
|
|
19
|
-
var phone_ct = phoneValue.replace(/[^0-9]/gim, '');
|
|
20
|
-
if (phone_ct[0] == '8') { phone_ct = phone_ct.substring(1); }
|
|
21
|
-
if (phone_ct[0] == '7') { phone_ct = phone_ct.substring(1); }
|
|
22
|
-
phone_ct = '7' + phone_ct;
|
|
23
|
-
|
|
24
|
-
window.ctw.createRequest(
|
|
25
|
-
routeKey,
|
|
26
|
-
phone_ct,
|
|
27
|
-
( nameValue.length > 0 ? [
|
|
28
|
-
{"name": "Name", "value": nameValue}
|
|
29
|
-
] : []),
|
|
30
|
-
function (success, data) {
|
|
31
|
-
verbose && console.log(success, data)
|
|
32
|
-
if (success) {
|
|
33
|
-
verbose && console.log('Создана заявка на колбек, идентификатор: ' + data.callbackRequestId);
|
|
34
|
-
resolve(data); // Разрешаем Promise данными от createRequest
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
errorText = 'Error in createRequest';
|
|
38
|
-
switch (data.type) {
|
|
39
|
-
case "request_throttle_timeout":
|
|
40
|
-
case "request_throttle_count":
|
|
41
|
-
errorText = 'Достигнут лимит создания заявок, попробуйте позже';
|
|
42
|
-
verbose && console.log(errorText);
|
|
43
|
-
break;
|
|
44
|
-
case "request_phone_blacklisted":
|
|
45
|
-
errorText = 'номер телефона находится в черном списке';
|
|
46
|
-
verbose && console.log(errorText);
|
|
47
|
-
break;
|
|
48
|
-
case "validation_error":
|
|
49
|
-
errorText = 'были переданы некорректные данные';
|
|
50
|
-
verbose && console.log(errorText);
|
|
51
|
-
break;
|
|
52
|
-
default:
|
|
53
|
-
errorText = 'Во время выполнения запроса произошла ошибка: ' + data.type;
|
|
54
|
-
verbose && console.log(errorText);
|
|
55
|
-
}
|
|
56
|
-
reject(errorText); // Отклоняем Promise в случае ошибки
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
);
|
|
85
|
+
executeCreateRequest();
|
|
60
86
|
} else {
|
|
61
|
-
errorText = 'не найден включенный виджет '+routeKey+', либо услуга обратного звонка не активна';
|
|
87
|
+
errorText = 'не найден включенный виджет ' + routeKey + ', либо услуга обратного звонка не активна';
|
|
62
88
|
verbose && console.log(errorText);
|
|
63
89
|
reject(errorText);
|
|
64
90
|
}
|
|
65
91
|
} else {
|
|
66
92
|
errorText = 'во время обработки произошла ошибка';
|
|
67
93
|
verbose && console.log(errorText);
|
|
68
|
-
verbose && console.log(data)
|
|
94
|
+
verbose && console.log(data);
|
|
69
95
|
reject(errorText);
|
|
70
96
|
}
|
|
71
97
|
});
|
|
72
|
-
}
|
|
73
|
-
reject("window.ctw is not defined");
|
|
74
|
-
}
|
|
75
|
-
});
|
|
98
|
+
});
|
|
76
99
|
};
|
package/lib/form.js
CHANGED
|
@@ -22,19 +22,35 @@ export const maskphone = (e) => {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
export const phoneChecker = (phone) => {
|
|
25
|
+
export const phoneChecker = (phone, options = {}) => {
|
|
26
|
+
// Опция silent:
|
|
27
|
+
// - true => функция работает в "тихом" режиме (НЕ показывает сообщения), возвращает только true|false
|
|
28
|
+
// - false => ведёт себя как раньше: показывает разные сообщения об ошибках
|
|
29
|
+
const { silent = false } = options;
|
|
30
|
+
|
|
26
31
|
let form = phone.closest("form");
|
|
32
|
+
|
|
33
|
+
// Пустое значение
|
|
27
34
|
if (!phone.value.length) {
|
|
28
|
-
|
|
35
|
+
if (!silent && form) {
|
|
36
|
+
showErrorMes(form, ".phone", "Телефон является обязательным полем");
|
|
37
|
+
}
|
|
29
38
|
return false;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Формат и анти-флуд (одинаковые цифры)
|
|
42
|
+
const phoneRe = new RegExp(/^\+7 [0-9]{3} [0-9]{3}-[0-9]{2}-[0-9]{2}$/);
|
|
43
|
+
if (!phoneRe.test(phone.value) || noValidPhone(phone.value)) {
|
|
44
|
+
if (!silent && form) {
|
|
33
45
|
showErrorMes(form, ".phone", "Введен некорректный номер телефона");
|
|
34
|
-
return false;
|
|
35
46
|
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Валидно — в шумном режиме прячем текст ошибки
|
|
51
|
+
if (!silent && form) {
|
|
52
|
+
showErrorMes(form, ".phone", "");
|
|
36
53
|
}
|
|
37
|
-
showErrorMes(form, ".phone", "");
|
|
38
54
|
return true;
|
|
39
55
|
};
|
|
40
56
|
|
|
@@ -106,6 +122,8 @@ export const messageModal = document.getElementById("message-modal");
|
|
|
106
122
|
export const connectForms = (url, props = propsParams) => {
|
|
107
123
|
props = {...propsParams, ...props};
|
|
108
124
|
|
|
125
|
+
console.log("url: ", url);
|
|
126
|
+
console.log("props: ", props);
|
|
109
127
|
|
|
110
128
|
document.querySelectorAll("input[name=phone]").forEach(function (element) {
|
|
111
129
|
// element.addEventListener("focus", maskphone);
|
|
@@ -274,20 +292,62 @@ const submitForm = async (form) => {
|
|
|
274
292
|
});
|
|
275
293
|
|
|
276
294
|
let formDataObj = {};
|
|
295
|
+
// Считаем значения один раз, чтобы одинаково использовать их в try/catch и логах.
|
|
296
|
+
const dealerRouteKey = dealer && dealer.dataset ? (dealer.dataset.ctRouteKey || '').trim() : '';
|
|
297
|
+
const dealerModId = dealer && dealer.dataset ? (dealer.dataset.ctModId || '').trim() : '';
|
|
298
|
+
const calltouchRouteKey = dealerRouteKey || props.ct_routeKey;
|
|
299
|
+
const scopedCtwName = dealerModId ? `ctw_${dealerModId}` : '';
|
|
300
|
+
const hasScopedCtw = scopedCtwName ? typeof window[scopedCtwName] !== 'undefined' : false;
|
|
301
|
+
const hasGlobalCtw = typeof window.ctw !== 'undefined';
|
|
302
|
+
|
|
277
303
|
try {
|
|
278
|
-
//
|
|
279
|
-
|
|
280
|
-
|
|
304
|
+
// Для multi-project берём routeKey/mod_id у выбранного дилера (data-атрибуты select).
|
|
305
|
+
// Если дилерские значения отсутствуют, используем старый глобальный props.ct_routeKey.
|
|
306
|
+
props.verbose && console.log('Calltouch submit debug:', {
|
|
307
|
+
formId: form.id || '',
|
|
308
|
+
phone: phone && phone.value ? phone.value : '',
|
|
309
|
+
name: name && name.value ? name.value : '',
|
|
310
|
+
dealerValue: dealer && dealer.value ? dealer.value : '',
|
|
311
|
+
dealerRouteKey,
|
|
312
|
+
dealerModId,
|
|
313
|
+
fallbackRouteKey: props.ct_routeKey,
|
|
314
|
+
calltouchRouteKey,
|
|
315
|
+
scopedCtwName,
|
|
316
|
+
hasScopedCtw,
|
|
317
|
+
hasGlobalCtw
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// Отправка заявки на обратный вызов в CallTouch.
|
|
321
|
+
if(calltouchRouteKey != '') {
|
|
322
|
+
const requestData = await createRequest(calltouchRouteKey, phone.value, name.value, props.verbose, dealerModId);
|
|
281
323
|
formData.append("ct_callback", true);
|
|
282
324
|
formData.append("ctw_createRequest", JSON.stringify(requestData));
|
|
325
|
+
if (dealerModId !== '') {
|
|
326
|
+
// Храним mod_id в payload для отладки и серверных логов.
|
|
327
|
+
formData.append("ct_mod_id", dealerModId);
|
|
328
|
+
}
|
|
283
329
|
} else {
|
|
284
330
|
throw new Error('Empty ct_routeKey');
|
|
285
331
|
}
|
|
286
332
|
} catch (error) {
|
|
287
|
-
if(
|
|
333
|
+
if(calltouchRouteKey != '') {
|
|
288
334
|
formData.append("ctw_createRequest", error);
|
|
289
335
|
}
|
|
290
|
-
|
|
336
|
+
const normalizedError = error instanceof Error ? {
|
|
337
|
+
name: error.name,
|
|
338
|
+
message: error.message,
|
|
339
|
+
stack: error.stack
|
|
340
|
+
} : error;
|
|
341
|
+
console.error("Error during request Calltouch callback:", normalizedError, {
|
|
342
|
+
formId: form.id || '',
|
|
343
|
+
dealerRouteKey,
|
|
344
|
+
dealerModId,
|
|
345
|
+
fallbackRouteKey: props.ct_routeKey,
|
|
346
|
+
calltouchRouteKey,
|
|
347
|
+
scopedCtwName,
|
|
348
|
+
hasScopedCtw,
|
|
349
|
+
hasGlobalCtw
|
|
350
|
+
});
|
|
291
351
|
formDataObj = getFormDataObject(formData, form.id);
|
|
292
352
|
}
|
|
293
353
|
|