@alexsab-ru/scripts 0.16.1 → 0.16.2

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 (2) hide show
  1. package/lib/form.js +91 -19
  2. package/package.json +1 -1
package/lib/form.js CHANGED
@@ -79,6 +79,47 @@ const stateBtn = (btn, value, disable = false) => {
79
79
  }
80
80
  };
81
81
 
82
+ const hasFileUploadField = (form, selector) => {
83
+ if (!selector) {
84
+ return false;
85
+ }
86
+ return !!form.querySelector(selector);
87
+ };
88
+
89
+ const appendDropzoneFiles = (formData, { filesToUploadKey, fileFieldName }) => {
90
+ if (!filesToUploadKey || !fileFieldName) {
91
+ return;
92
+ }
93
+
94
+ const files = window[filesToUploadKey];
95
+ if (!Array.isArray(files)) {
96
+ return;
97
+ }
98
+
99
+ files.forEach((file) => {
100
+ formData.append(fileFieldName, file);
101
+ });
102
+ };
103
+
104
+ const resetDropzones = ({ dropzonesKey, filesToUploadKey }) => {
105
+ if (!dropzonesKey || !filesToUploadKey) {
106
+ return;
107
+ }
108
+
109
+ const dropzones = window[dropzonesKey];
110
+ if (Array.isArray(dropzones)) {
111
+ dropzones.forEach((dropzone) => {
112
+ if (dropzone && typeof dropzone.removeAllFiles === 'function') {
113
+ dropzone.removeAllFiles();
114
+ }
115
+ });
116
+ }
117
+
118
+ if (Array.isArray(window[filesToUploadKey])) {
119
+ window[filesToUploadKey] = [];
120
+ }
121
+ };
122
+
82
123
  // Показ сообщения об ошибке
83
124
  export const showErrorMes = (form, el, text) => {
84
125
  let field = form.querySelector(el);
@@ -111,6 +152,11 @@ const propsParams = {
111
152
  verbose: false,
112
153
  agreeSelector: "agree",
113
154
  sendMailCookie: "SEND_MAIL",
155
+ fileUploadSelector: ".file-upload",
156
+ fileFieldName: "file[]",
157
+ filesToUploadKey: "filesToUpload",
158
+ dropzonesKey: "dropzones",
159
+ successOnAttentionPhone: "79000000000",
114
160
  }
115
161
 
116
162
  export const errorIcon = '<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52"><path fill="#ed1c24" d="M26,0A26,26,0,1,0,52,26,26,26,0,0,0,26,0Zm9.6,17.5a1.94,1.94,0,0,1,2,2,2,2,0,1,1-2-2Zm-19.2,0a1.94,1.94,0,0,1,2,2,2,2,0,1,1-2-2ZM39.65,40.69a.93.93,0,0,1-.45.11,1,1,0,0,1-.89-.55,13.81,13.81,0,0,0-24.62,0,1,1,0,1,1-1.78-.9,15.8,15.8,0,0,1,28.18,0A1,1,0,0,1,39.65,40.69Z"></path></svg>';
@@ -171,6 +217,9 @@ const submitForm = async (form) => {
171
217
  const phone = form.querySelector('[name="phone"]');
172
218
  const name = form.querySelector('[name="name"]');
173
219
  const dealer = form.querySelector('[name="dealer"]');
220
+ const hasFileUpload = hasFileUploadField(form, props.fileUploadSelector);
221
+ const ftaCookie = Boolean(getCookie('fta'));
222
+ const verbose = Boolean(props.verbose || ftaCookie);
174
223
 
175
224
  let validate;
176
225
 
@@ -256,11 +305,14 @@ const submitForm = async (form) => {
256
305
  reachGoal("form_submit");
257
306
 
258
307
  let formData = new FormData(form);
308
+ if (hasFileUpload) {
309
+ appendDropzoneFiles(formData, props);
310
+ }
259
311
  let sendMailCookie = props.sendMailCookie;
260
312
  if(formData.get('dealer')) {
261
313
  sendMailCookie += "_" + formData.get('dealer');
262
314
  }
263
- if(getCookie('fta')) {
315
+ if(ftaCookie) {
264
316
  formData.append("fta", true);
265
317
  }
266
318
  if(getCookie('__gtm_campaign_url')) {
@@ -284,6 +336,9 @@ const submitForm = async (form) => {
284
336
  .split("&")
285
337
  .forEach(function (pair) {
286
338
  let param = pair.split("=");
339
+ if(!param[0]){
340
+ return;
341
+ }
287
342
  if(formData.get(param[0])){
288
343
  formData.set(param[0], decodeURIComponent(param[1]));
289
344
  } else {
@@ -304,7 +359,7 @@ const submitForm = async (form) => {
304
359
  try {
305
360
  // Для multi-project берём routeKey/mod_id у выбранного дилера (data-атрибуты select).
306
361
  // Если дилерские значения отсутствуют, используем старый глобальный props.ct_routeKey.
307
- props.verbose && console.log('Calltouch submit debug:', {
362
+ verbose && console.log('Calltouch submit debug:', {
308
363
  formId: form.id || '',
309
364
  phone: phone && phone.value ? phone.value : '',
310
365
  name: name && name.value ? name.value : '',
@@ -321,7 +376,7 @@ const submitForm = async (form) => {
321
376
 
322
377
  // Отправка заявки на обратный вызов в CallTouch.
323
378
  if(calltouchRouteKey != '') {
324
- const requestData = await createRequest(calltouchRouteKey, phone.value, name.value, props.verbose, dealerModId);
379
+ const requestData = await createRequest(calltouchRouteKey, phone.value, name.value, verbose, dealerModId);
325
380
  formData.append("ct_callback", true);
326
381
  formData.append("ctw_createRequest", JSON.stringify(requestData));
327
382
  if (dealerModId !== '') {
@@ -359,21 +414,33 @@ const submitForm = async (form) => {
359
414
  }
360
415
  }
361
416
 
362
- const params = new URLSearchParams([...formData]);
363
-
364
- await fetch(url, {
365
- method: "POST",
366
- mode: "cors",
367
- cache: "no-cache",
368
- credentials: "same-origin",
369
- headers: {
370
- "Content-Type": "application/x-www-form-urlencoded",
371
- },
372
- body: params,
373
- })
374
- .then((res) => res.json())
417
+ const requestOptions = hasFileUpload
418
+ ? {
419
+ method: "POST",
420
+ body: formData,
421
+ }
422
+ : {
423
+ method: "POST",
424
+ mode: "cors",
425
+ cache: "no-cache",
426
+ credentials: "same-origin",
427
+ headers: {
428
+ "Content-Type": "application/x-www-form-urlencoded",
429
+ },
430
+ body: new URLSearchParams([...formData]),
431
+ };
432
+
433
+ await fetch(url, requestOptions)
434
+ .then(async (res) => {
435
+ const text = await res.text();
436
+ try {
437
+ return JSON.parse(text);
438
+ } catch (error) {
439
+ throw new Error("Ошибка обработки данных");
440
+ }
441
+ })
375
442
  .then((data) => {
376
- props.verbose && console.log(data);
443
+ verbose && console.log(data);
377
444
  stateBtn(btn, btnText);
378
445
  if (data.answer == "required") {
379
446
  reachGoal("form_required");
@@ -390,7 +457,9 @@ const submitForm = async (form) => {
390
457
  }
391
458
  return;
392
459
  } else {
393
- if(data.attention != true) {
460
+ const normalizedPhone = String(formData.get("phone") || (phone && phone.value ? phone.value : "")).replace(/\D/g, "");
461
+ const attentionPhone = String(props.successOnAttentionPhone || "").replace(/\D/g, "");
462
+ if(data.attention != true || (attentionPhone && normalizedPhone === attentionPhone)) {
394
463
  reachGoal("form_success", formDataObj);
395
464
  }
396
465
  setCookie(sendMailCookie, true, {'domain': window.location.hostname,'path':'/','expires':600});
@@ -402,6 +471,9 @@ const submitForm = async (form) => {
402
471
  }
403
472
  }
404
473
  form.reset();
474
+ if (hasFileUpload) {
475
+ resetDropzones(props);
476
+ }
405
477
  })
406
478
  .catch((error) => {
407
479
  reachGoal("form_error");
@@ -477,4 +549,4 @@ document.querySelectorAll("form:not(.vue-form)").forEach((form) => {
477
549
  await sendForm(form);
478
550
  })
479
551
  });
480
- }
552
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexsab-ru/scripts",
3
- "version": "0.16.1",
3
+ "version": "0.16.2",
4
4
  "description": "common libs for websites",
5
5
  "main": "index.js",
6
6
  "scripts": {