@redneckz/wildless-cms-uni-blocks 0.14.1022 → 0.14.1024
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/bin/migration-scripts/0.14.1013.js +3 -1
- package/bundle/api/sendUserSurvey.d.ts +1 -0
- package/bundle/blocks.schema.json +1 -1
- package/bundle/bundle.umd.js +792 -751
- package/bundle/bundle.umd.min.js +1 -1
- package/bundle/components/ApplicationForm/handlers.d.ts +4 -3
- package/bundle/components/ApplicationLeadForm/getLeadFormTaskData.d.ts +7 -1
- package/bundle/model/AspectsProps.d.ts +7 -1
- package/bundle/ui-kit/UserSurveyDialog/Star.d.ts +4 -5
- package/bundle/ui-kit/UserSurveyDialog/UserSurveyDialogContent.d.ts +4 -2
- package/bundle/ui-kit/UserSurveyDialog/useUserSurveyDialog.d.ts +1 -1
- package/dist/api/sendUserSurvey.d.ts +1 -0
- package/dist/api/sendUserSurvey.js +1 -1
- package/dist/api/sendUserSurvey.js.map +1 -1
- package/dist/components/ApplicationForm/ApplicationForm.js +3 -0
- package/dist/components/ApplicationForm/ApplicationForm.js.map +1 -1
- package/dist/components/ApplicationForm/handlers.d.ts +4 -3
- package/dist/components/ApplicationForm/handlers.js +9 -3
- package/dist/components/ApplicationForm/handlers.js.map +1 -1
- package/dist/components/ApplicationLeadForm/getLeadFormTaskData.d.ts +7 -1
- package/dist/components/ApplicationLeadForm/getLeadFormTaskData.js.map +1 -1
- package/dist/components/Header/HeaderQuickActionsMenu.js +1 -3
- package/dist/components/Header/HeaderQuickActionsMenu.js.map +1 -1
- package/dist/model/AspectsProps.d.ts +7 -1
- package/dist/ui-kit/UserSurveyDialog/FirstStep.js +3 -3
- package/dist/ui-kit/UserSurveyDialog/FirstStep.js.map +1 -1
- package/dist/ui-kit/UserSurveyDialog/SecondStep.js +2 -2
- package/dist/ui-kit/UserSurveyDialog/SecondStep.js.map +1 -1
- package/dist/ui-kit/UserSurveyDialog/Star.d.ts +4 -5
- package/dist/ui-kit/UserSurveyDialog/Star.js +12 -4
- package/dist/ui-kit/UserSurveyDialog/Star.js.map +1 -1
- package/dist/ui-kit/UserSurveyDialog/UserSurveyDialog.js +17 -2
- package/dist/ui-kit/UserSurveyDialog/UserSurveyDialog.js.map +1 -1
- package/dist/ui-kit/UserSurveyDialog/UserSurveyDialogContent.d.ts +4 -2
- package/dist/ui-kit/UserSurveyDialog/useUserSurveyDialog.d.ts +1 -1
- package/dist/ui-kit/UserSurveyDialog/useUserSurveyDialog.js +23 -11
- package/dist/ui-kit/UserSurveyDialog/useUserSurveyDialog.js.map +1 -1
- package/lib/api/sendUserSurvey.d.ts +1 -0
- package/lib/api/sendUserSurvey.js +1 -1
- package/lib/api/sendUserSurvey.js.map +1 -1
- package/lib/components/ApplicationForm/ApplicationForm.js +3 -0
- package/lib/components/ApplicationForm/ApplicationForm.js.map +1 -1
- package/lib/components/ApplicationForm/handlers.d.ts +4 -3
- package/lib/components/ApplicationForm/handlers.js +9 -3
- package/lib/components/ApplicationForm/handlers.js.map +1 -1
- package/lib/components/ApplicationLeadForm/getLeadFormTaskData.d.ts +7 -1
- package/lib/components/ApplicationLeadForm/getLeadFormTaskData.js.map +1 -1
- package/lib/components/Header/HeaderQuickActionsMenu.js +1 -3
- package/lib/components/Header/HeaderQuickActionsMenu.js.map +1 -1
- package/lib/model/AspectsProps.d.ts +7 -1
- package/lib/ui-kit/UserSurveyDialog/FirstStep.js +3 -3
- package/lib/ui-kit/UserSurveyDialog/FirstStep.js.map +1 -1
- package/lib/ui-kit/UserSurveyDialog/SecondStep.js +2 -2
- package/lib/ui-kit/UserSurveyDialog/SecondStep.js.map +1 -1
- package/lib/ui-kit/UserSurveyDialog/Star.d.ts +4 -5
- package/lib/ui-kit/UserSurveyDialog/Star.js +12 -4
- package/lib/ui-kit/UserSurveyDialog/Star.js.map +1 -1
- package/lib/ui-kit/UserSurveyDialog/UserSurveyDialog.js +17 -2
- package/lib/ui-kit/UserSurveyDialog/UserSurveyDialog.js.map +1 -1
- package/lib/ui-kit/UserSurveyDialog/UserSurveyDialogContent.d.ts +4 -2
- package/lib/ui-kit/UserSurveyDialog/useUserSurveyDialog.d.ts +1 -1
- package/lib/ui-kit/UserSurveyDialog/useUserSurveyDialog.js +24 -12
- package/lib/ui-kit/UserSurveyDialog/useUserSurveyDialog.js.map +1 -1
- package/mobile/bundle/api/sendUserSurvey.d.ts +1 -0
- package/mobile/bundle/bundle.umd.js +792 -751
- package/mobile/bundle/bundle.umd.min.js +1 -1
- package/mobile/bundle/components/ApplicationForm/handlers.d.ts +4 -3
- package/mobile/bundle/components/ApplicationLeadForm/getLeadFormTaskData.d.ts +7 -1
- package/mobile/bundle/model/AspectsProps.d.ts +7 -1
- package/mobile/bundle/ui-kit/UserSurveyDialog/Star.d.ts +4 -5
- package/mobile/bundle/ui-kit/UserSurveyDialog/UserSurveyDialogContent.d.ts +4 -2
- package/mobile/bundle/ui-kit/UserSurveyDialog/useUserSurveyDialog.d.ts +1 -1
- package/mobile/dist/api/sendUserSurvey.d.ts +1 -0
- package/mobile/dist/api/sendUserSurvey.js +1 -1
- package/mobile/dist/api/sendUserSurvey.js.map +1 -1
- package/mobile/dist/components/ApplicationForm/ApplicationForm.js +3 -0
- package/mobile/dist/components/ApplicationForm/ApplicationForm.js.map +1 -1
- package/mobile/dist/components/ApplicationForm/handlers.d.ts +4 -3
- package/mobile/dist/components/ApplicationForm/handlers.js +9 -3
- package/mobile/dist/components/ApplicationForm/handlers.js.map +1 -1
- package/mobile/dist/components/ApplicationLeadForm/getLeadFormTaskData.d.ts +7 -1
- package/mobile/dist/components/ApplicationLeadForm/getLeadFormTaskData.js.map +1 -1
- package/mobile/dist/components/Header/HeaderQuickActionsMenu.js +1 -3
- package/mobile/dist/components/Header/HeaderQuickActionsMenu.js.map +1 -1
- package/mobile/dist/model/AspectsProps.d.ts +7 -1
- package/mobile/dist/ui-kit/UserSurveyDialog/FirstStep.js +3 -3
- package/mobile/dist/ui-kit/UserSurveyDialog/FirstStep.js.map +1 -1
- package/mobile/dist/ui-kit/UserSurveyDialog/SecondStep.js +2 -2
- package/mobile/dist/ui-kit/UserSurveyDialog/SecondStep.js.map +1 -1
- package/mobile/dist/ui-kit/UserSurveyDialog/Star.d.ts +4 -5
- package/mobile/dist/ui-kit/UserSurveyDialog/Star.js +12 -4
- package/mobile/dist/ui-kit/UserSurveyDialog/Star.js.map +1 -1
- package/mobile/dist/ui-kit/UserSurveyDialog/UserSurveyDialog.js +17 -2
- package/mobile/dist/ui-kit/UserSurveyDialog/UserSurveyDialog.js.map +1 -1
- package/mobile/dist/ui-kit/UserSurveyDialog/UserSurveyDialogContent.d.ts +4 -2
- package/mobile/dist/ui-kit/UserSurveyDialog/useUserSurveyDialog.d.ts +1 -1
- package/mobile/dist/ui-kit/UserSurveyDialog/useUserSurveyDialog.js +23 -11
- package/mobile/dist/ui-kit/UserSurveyDialog/useUserSurveyDialog.js.map +1 -1
- package/mobile/lib/api/sendUserSurvey.d.ts +1 -0
- package/mobile/lib/api/sendUserSurvey.js +1 -1
- package/mobile/lib/api/sendUserSurvey.js.map +1 -1
- package/mobile/lib/components/ApplicationForm/ApplicationForm.js +3 -0
- package/mobile/lib/components/ApplicationForm/ApplicationForm.js.map +1 -1
- package/mobile/lib/components/ApplicationForm/handlers.d.ts +4 -3
- package/mobile/lib/components/ApplicationForm/handlers.js +9 -3
- package/mobile/lib/components/ApplicationForm/handlers.js.map +1 -1
- package/mobile/lib/components/ApplicationLeadForm/getLeadFormTaskData.d.ts +7 -1
- package/mobile/lib/components/ApplicationLeadForm/getLeadFormTaskData.js.map +1 -1
- package/mobile/lib/components/Header/HeaderQuickActionsMenu.js +1 -3
- package/mobile/lib/components/Header/HeaderQuickActionsMenu.js.map +1 -1
- package/mobile/lib/model/AspectsProps.d.ts +7 -1
- package/mobile/lib/ui-kit/UserSurveyDialog/FirstStep.js +3 -3
- package/mobile/lib/ui-kit/UserSurveyDialog/FirstStep.js.map +1 -1
- package/mobile/lib/ui-kit/UserSurveyDialog/SecondStep.js +2 -2
- package/mobile/lib/ui-kit/UserSurveyDialog/SecondStep.js.map +1 -1
- package/mobile/lib/ui-kit/UserSurveyDialog/Star.d.ts +4 -5
- package/mobile/lib/ui-kit/UserSurveyDialog/Star.js +12 -4
- package/mobile/lib/ui-kit/UserSurveyDialog/Star.js.map +1 -1
- package/mobile/lib/ui-kit/UserSurveyDialog/UserSurveyDialog.js +17 -2
- package/mobile/lib/ui-kit/UserSurveyDialog/UserSurveyDialog.js.map +1 -1
- package/mobile/lib/ui-kit/UserSurveyDialog/UserSurveyDialogContent.d.ts +4 -2
- package/mobile/lib/ui-kit/UserSurveyDialog/useUserSurveyDialog.d.ts +1 -1
- package/mobile/lib/ui-kit/UserSurveyDialog/useUserSurveyDialog.js +24 -12
- package/mobile/lib/ui-kit/UserSurveyDialog/useUserSurveyDialog.js.map +1 -1
- package/mobile/src/api/sendUserSurvey.ts +2 -1
- package/mobile/src/components/ApplicationForm/ApplicationForm.tsx +3 -0
- package/mobile/src/components/ApplicationForm/handlers.ts +11 -0
- package/mobile/src/components/ApplicationLeadForm/getLeadFormTaskData.ts +8 -4
- package/mobile/src/components/Header/HeaderQuickActionsMenu.tsx +1 -3
- package/mobile/src/model/AspectsProps.ts +9 -1
- package/mobile/src/ui-kit/UserSurveyDialog/FirstStep.tsx +9 -6
- package/mobile/src/ui-kit/UserSurveyDialog/SecondStep.tsx +2 -2
- package/mobile/src/ui-kit/UserSurveyDialog/Star.tsx +33 -18
- package/mobile/src/ui-kit/UserSurveyDialog/UserSurveyDialog.tsx +21 -2
- package/mobile/src/ui-kit/UserSurveyDialog/UserSurveyDialogContent.ts +5 -2
- package/mobile/src/ui-kit/UserSurveyDialog/useUserSurveyDialog.ts +30 -13
- package/package.json +1 -1
- package/src/api/sendUserSurvey.ts +2 -1
- package/src/components/ApplicationForm/ApplicationForm.tsx +3 -0
- package/src/components/ApplicationForm/handlers.ts +11 -0
- package/src/components/ApplicationLeadForm/getLeadFormTaskData.ts +8 -4
- package/src/components/Header/HeaderQuickActionsMenu.tsx +1 -3
- package/src/model/AspectsProps.ts +9 -1
- package/src/ui-kit/UserSurveyDialog/FirstStep.tsx +9 -6
- package/src/ui-kit/UserSurveyDialog/SecondStep.tsx +2 -2
- package/src/ui-kit/UserSurveyDialog/Star.tsx +33 -18
- package/src/ui-kit/UserSurveyDialog/UserSurveyDialog.tsx +21 -2
- package/src/ui-kit/UserSurveyDialog/UserSurveyDialogContent.ts +5 -2
- package/src/ui-kit/UserSurveyDialog/useUserSurveyDialog.ts +30 -13
package/bundle/bundle.umd.js
CHANGED
|
@@ -1376,6 +1376,652 @@
|
|
|
1376
1376
|
return (jsx(Dialog, { maxWidth: "lg", onClose: onClose, children: jsxs("div", { className: "flex flex-col gap-lg items-center rounded-md space-x-m", children: [jsx(Img, { image: { icon: statusIcon, iconVersion: 'normal' }, width: "136", height: "136" }), jsx(Headline, { className: "w-full", title: ok ? 'Ваша заявка отправлена' : 'Не удалось отправить заявку', description: ok ? responseOKDescription : responseFailDescription, headlineVersion: "XS", isEmbedded: true }), jsx(Button, { type: "button", onClick: onClose, children: "\u0425\u043E\u0440\u043E\u0448\u043E" })] }) }));
|
|
1377
1377
|
});
|
|
1378
1378
|
|
|
1379
|
+
function copy(source, target) {
|
|
1380
|
+
for (const [k, v] of source.entries()) {
|
|
1381
|
+
if (v !== null && v !== undefined) {
|
|
1382
|
+
target.setItem(k, v);
|
|
1383
|
+
}
|
|
1384
|
+
else {
|
|
1385
|
+
target.removeItem(k);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
function replicate(primary, secondary) {
|
|
1391
|
+
copy(primary, secondary);
|
|
1392
|
+
copy(secondary, primary);
|
|
1393
|
+
return primary.bus.watch(({ type, event }) => {
|
|
1394
|
+
if (event !== null && event !== undefined) {
|
|
1395
|
+
secondary.setItem(type, event);
|
|
1396
|
+
}
|
|
1397
|
+
else {
|
|
1398
|
+
secondary.removeItem(type);
|
|
1399
|
+
}
|
|
1400
|
+
});
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
class StorageAdapter {
|
|
1404
|
+
storage;
|
|
1405
|
+
bus;
|
|
1406
|
+
get size() {
|
|
1407
|
+
return this.storage?.length ?? 0;
|
|
1408
|
+
}
|
|
1409
|
+
constructor(storage, bus = new EventBus()) {
|
|
1410
|
+
this.storage = storage;
|
|
1411
|
+
this.bus = bus;
|
|
1412
|
+
}
|
|
1413
|
+
hasItem(key) {
|
|
1414
|
+
return Boolean(this.storage?.getItem(String(key)));
|
|
1415
|
+
}
|
|
1416
|
+
getItem(key) {
|
|
1417
|
+
const _ = this.storage?.getItem(String(key)) ?? null;
|
|
1418
|
+
try {
|
|
1419
|
+
return JSON.parse(String(_));
|
|
1420
|
+
}
|
|
1421
|
+
catch (ex) {
|
|
1422
|
+
return null;
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
entries() {
|
|
1426
|
+
return Array.from({ length: this.size }, (_, i) => {
|
|
1427
|
+
const k = String(this.storage?.key(i));
|
|
1428
|
+
return [k, this.getItem(k)];
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
setItem(key, value) {
|
|
1432
|
+
if (value !== null) {
|
|
1433
|
+
this.storage?.setItem(String(key), JSON.stringify(value));
|
|
1434
|
+
}
|
|
1435
|
+
else {
|
|
1436
|
+
this.storage?.removeItem(String(key));
|
|
1437
|
+
}
|
|
1438
|
+
this.bus?.subject(key, value);
|
|
1439
|
+
}
|
|
1440
|
+
removeItem(key) {
|
|
1441
|
+
this.storage?.removeItem(String(key));
|
|
1442
|
+
this.bus?.subject(key, null);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
class Store {
|
|
1447
|
+
bus;
|
|
1448
|
+
store = new Map();
|
|
1449
|
+
get size() {
|
|
1450
|
+
return this.store.size;
|
|
1451
|
+
}
|
|
1452
|
+
constructor(bus = new EventBus()) {
|
|
1453
|
+
this.bus = bus;
|
|
1454
|
+
}
|
|
1455
|
+
hasItem(key) {
|
|
1456
|
+
return this.store.has(key);
|
|
1457
|
+
}
|
|
1458
|
+
getItem(key) {
|
|
1459
|
+
return this.store.get(key);
|
|
1460
|
+
}
|
|
1461
|
+
entries() {
|
|
1462
|
+
return this.store.entries();
|
|
1463
|
+
}
|
|
1464
|
+
setItem(key, value) {
|
|
1465
|
+
this.store.set(key, value);
|
|
1466
|
+
this.bus.subject(key, value);
|
|
1467
|
+
}
|
|
1468
|
+
removeItem(key) {
|
|
1469
|
+
this.store.delete(key);
|
|
1470
|
+
this.bus.subject(key, null);
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
function useRerender() {
|
|
1475
|
+
const [, setCount] = useState(0);
|
|
1476
|
+
return useCallback(() => setCount(_ => (_ + 1) % (1 << 16)), []);
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
const DEFAULT_METHODS = {};
|
|
1480
|
+
/**
|
|
1481
|
+
* MobX like reactivity (simplified).
|
|
1482
|
+
* Can be used to migrate from Redux/MobX or something else
|
|
1483
|
+
*
|
|
1484
|
+
* @param store
|
|
1485
|
+
* @returns reactive proxy backed by store
|
|
1486
|
+
*/
|
|
1487
|
+
function useStore(store, methods = DEFAULT_METHODS) {
|
|
1488
|
+
const deps = useRef(null);
|
|
1489
|
+
const render = useRerender();
|
|
1490
|
+
useEffect(() => store.bus.watch(ev => {
|
|
1491
|
+
if (deps.current?.has(String(ev.type))) {
|
|
1492
|
+
render();
|
|
1493
|
+
}
|
|
1494
|
+
}), [store, render]);
|
|
1495
|
+
return useMemo(() => new Proxy(methods, {
|
|
1496
|
+
get(_, key) {
|
|
1497
|
+
deps.current ||= new Set();
|
|
1498
|
+
deps.current.add(key);
|
|
1499
|
+
return store.getItem(key);
|
|
1500
|
+
},
|
|
1501
|
+
has(_, key) {
|
|
1502
|
+
deps.current ||= new Set();
|
|
1503
|
+
deps.current.add(key);
|
|
1504
|
+
return store.hasItem(key);
|
|
1505
|
+
},
|
|
1506
|
+
set(_, key, value) {
|
|
1507
|
+
store.setItem(key, value);
|
|
1508
|
+
return true;
|
|
1509
|
+
},
|
|
1510
|
+
deleteProperty(_, key) {
|
|
1511
|
+
store.removeItem(key);
|
|
1512
|
+
return true;
|
|
1513
|
+
}
|
|
1514
|
+
}), [store]);
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
const localStore = new Store(); // localStorage cache
|
|
1518
|
+
replicate(localStore, new StorageAdapter(globalThis?.localStorage));
|
|
1519
|
+
function useLocalStore(methods) {
|
|
1520
|
+
return useStore(localStore, methods);
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
const sessionStore = new Store(); // sessionStorage cache
|
|
1524
|
+
replicate(sessionStore, new StorageAdapter(globalThis?.sessionStorage));
|
|
1525
|
+
function useSessionStore() {
|
|
1526
|
+
return useStore(sessionStore);
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
const API_BASE_URI = '/api/v1';
|
|
1530
|
+
|
|
1531
|
+
const getUserTimezoneOffset = () => {
|
|
1532
|
+
const offset = new Date().getTimezoneOffset();
|
|
1533
|
+
const absOffset = Math.abs(offset);
|
|
1534
|
+
const hours = Math.floor(absOffset / 60);
|
|
1535
|
+
const minutes = absOffset % 60;
|
|
1536
|
+
const sign = offset < 0 ? '+' : '-';
|
|
1537
|
+
return `GMT${sign}${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
|
1538
|
+
};
|
|
1539
|
+
|
|
1540
|
+
const ENDPOINT_MAPPING = {
|
|
1541
|
+
lead: {
|
|
1542
|
+
withTypeForm: true,
|
|
1543
|
+
isNaturalEndpoint: true,
|
|
1544
|
+
},
|
|
1545
|
+
sendcorporatelead: {
|
|
1546
|
+
withTypeForm: true,
|
|
1547
|
+
isNaturalEndpoint: false,
|
|
1548
|
+
},
|
|
1549
|
+
practice: {
|
|
1550
|
+
withTypeForm: false,
|
|
1551
|
+
isNaturalEndpoint: true,
|
|
1552
|
+
},
|
|
1553
|
+
internship: {
|
|
1554
|
+
withTypeForm: false,
|
|
1555
|
+
isNaturalEndpoint: true,
|
|
1556
|
+
},
|
|
1557
|
+
initcorporatelead: {
|
|
1558
|
+
withTypeForm: true,
|
|
1559
|
+
isNaturalEndpoint: false,
|
|
1560
|
+
},
|
|
1561
|
+
confirmCorporateLead: {
|
|
1562
|
+
withTypeForm: true,
|
|
1563
|
+
isNaturalEndpoint: false,
|
|
1564
|
+
},
|
|
1565
|
+
callback: {
|
|
1566
|
+
withTypeForm: false,
|
|
1567
|
+
isNaturalEndpoint: true,
|
|
1568
|
+
},
|
|
1569
|
+
};
|
|
1570
|
+
|
|
1571
|
+
const formatDate = (date, toTimeStamp = false) => {
|
|
1572
|
+
if (typeof date === 'string') {
|
|
1573
|
+
return date.split('-').reverse().join('.');
|
|
1574
|
+
}
|
|
1575
|
+
else {
|
|
1576
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
1577
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
1578
|
+
const year = String(date.getFullYear());
|
|
1579
|
+
return toTimeStamp ? `${year}-${month}-${day}` : `${day}.${month}.${year}`;
|
|
1580
|
+
}
|
|
1581
|
+
};
|
|
1582
|
+
|
|
1583
|
+
const formatPhone = (phone) => phone?.replace(/[^+\d]/g, '');
|
|
1584
|
+
|
|
1585
|
+
const getSubmitBody = ({ body, endpoint, router }) => {
|
|
1586
|
+
const isNaturalPerson = endpoint && ENDPOINT_MAPPING[endpoint].isNaturalEndpoint;
|
|
1587
|
+
const withTypeForm = endpoint && ENDPOINT_MAPPING[endpoint].withTypeForm;
|
|
1588
|
+
const { typeForm, region, phone = '', email, birthday, desiredMeetingDate, fullRegion, addressBranch, secondaryPhone = '', bankEmpolee, applicationDate, partnerName, russianPhone, partnerSymbolCode, internshipEndDate, internshipStartDate, ...staticBody } = body;
|
|
1589
|
+
return {
|
|
1590
|
+
...(withTypeForm ? { typeForm } : {}),
|
|
1591
|
+
...getRegion$1(region, isNaturalPerson),
|
|
1592
|
+
...getEmail(email, isNaturalPerson),
|
|
1593
|
+
...getPhone(phone),
|
|
1594
|
+
...getPhone(russianPhone),
|
|
1595
|
+
...(isNaturalPerson ? getFormatDate([[birthday, 'birthday']]) : { birthday }),
|
|
1596
|
+
...getFormatDate([
|
|
1597
|
+
[desiredMeetingDate, 'desiredMeetingDate'],
|
|
1598
|
+
[internshipEndDate, 'internshipEndDate'],
|
|
1599
|
+
[internshipStartDate, 'internshipStartDate'],
|
|
1600
|
+
]),
|
|
1601
|
+
...(typeForm === 'FEEDBACK'
|
|
1602
|
+
? {}
|
|
1603
|
+
: {
|
|
1604
|
+
addressBranch,
|
|
1605
|
+
bankEmpolee,
|
|
1606
|
+
applicationDate,
|
|
1607
|
+
...getSecondaryPhone(secondaryPhone),
|
|
1608
|
+
}),
|
|
1609
|
+
...addPageSlug(typeForm, router),
|
|
1610
|
+
...formatPFForm(typeForm, {
|
|
1611
|
+
fullRegion,
|
|
1612
|
+
partnerName,
|
|
1613
|
+
partnerSymbolCode,
|
|
1614
|
+
}),
|
|
1615
|
+
...getRkoTariffName(typeForm),
|
|
1616
|
+
...staticBody,
|
|
1617
|
+
};
|
|
1618
|
+
};
|
|
1619
|
+
const getPhoneBody = (phone) => {
|
|
1620
|
+
return {
|
|
1621
|
+
...getPhone(phone),
|
|
1622
|
+
};
|
|
1623
|
+
};
|
|
1624
|
+
const getPhone = (phone) => (phone ? { phone: formatPhone(phone) } : {});
|
|
1625
|
+
const getFormatDate = (dates) => Object.fromEntries(dates.filter(([value]) => value).map(([value, key]) => [key, formatDate(value)]));
|
|
1626
|
+
const getRegion$1 = (region, isNaturalPerson = true) => ({
|
|
1627
|
+
[isNaturalPerson ? 'regionBranch' : 'region']: region,
|
|
1628
|
+
});
|
|
1629
|
+
const getEmail = (email, isNaturalPerson = true) => ({
|
|
1630
|
+
[isNaturalPerson ? 'email' : 'mail']: email,
|
|
1631
|
+
});
|
|
1632
|
+
const getSecondaryPhone = (secondaryPhone = '') => !secondaryPhone || secondaryPhone === '+7 ('
|
|
1633
|
+
? {}
|
|
1634
|
+
: { secondaryPhoneNumber: formatPhone(secondaryPhone) };
|
|
1635
|
+
const formatPFForm = (typeForm, data) => typeForm === 'PF'
|
|
1636
|
+
? {
|
|
1637
|
+
region: data?.fullRegion,
|
|
1638
|
+
partner: data?.partnerName,
|
|
1639
|
+
partnerId: data?.partnerSymbolCode,
|
|
1640
|
+
}
|
|
1641
|
+
: {};
|
|
1642
|
+
const addPageSlug = (typeForm, router) => typeForm === 'UNIVERSAL'
|
|
1643
|
+
? {
|
|
1644
|
+
typeForm: router?.pathname?.split('/')?.at(-1) || '/',
|
|
1645
|
+
}
|
|
1646
|
+
: {};
|
|
1647
|
+
const getRkoTariffName = (typeForm) => typeForm === 'CALC'
|
|
1648
|
+
? {
|
|
1649
|
+
partnerComments: globalThis?.sessionStorage.getItem('rkoTariffName') ?? 'Неизвестный тариф',
|
|
1650
|
+
}
|
|
1651
|
+
: {};
|
|
1652
|
+
|
|
1653
|
+
// eslint-disable-next-line max-lines-per-function
|
|
1654
|
+
function LeadServiceAPI() {
|
|
1655
|
+
async function send({ body, router, endpoint }) {
|
|
1656
|
+
const calculatedEndpoint = endpoint && getEndpoint(endpoint, body);
|
|
1657
|
+
const url = `${API_BASE_URI}/${calculatedEndpoint}`;
|
|
1658
|
+
const submitBody = getSubmitBody({
|
|
1659
|
+
body,
|
|
1660
|
+
endpoint,
|
|
1661
|
+
router,
|
|
1662
|
+
});
|
|
1663
|
+
try {
|
|
1664
|
+
const response = await LeadServiceFetch(url, submitBody);
|
|
1665
|
+
if (!response?.ok) {
|
|
1666
|
+
return null;
|
|
1667
|
+
}
|
|
1668
|
+
return await response.json();
|
|
1669
|
+
}
|
|
1670
|
+
catch (e) {
|
|
1671
|
+
return null;
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
async function sendCode({ phone }) {
|
|
1675
|
+
const submitBody = getPhoneBody(phone);
|
|
1676
|
+
try {
|
|
1677
|
+
const response = LeadServiceFetch(`${API_BASE_URI}/initCorporateLead`, submitBody).then(async (res) => {
|
|
1678
|
+
if (!res.ok) {
|
|
1679
|
+
throw new Error(`Ошибка HTTP: ${res.status}`);
|
|
1680
|
+
}
|
|
1681
|
+
return await res.text();
|
|
1682
|
+
});
|
|
1683
|
+
return await response;
|
|
1684
|
+
}
|
|
1685
|
+
catch (e) {
|
|
1686
|
+
return null;
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
async function checkCode({ reqId, code, body, router, endpoint = 'confirmCorporateLead', }) {
|
|
1690
|
+
const submitBody = {
|
|
1691
|
+
requestId: reqId,
|
|
1692
|
+
confimationCode: code,
|
|
1693
|
+
leadRequest: getSubmitBody({ body, endpoint, router }),
|
|
1694
|
+
};
|
|
1695
|
+
try {
|
|
1696
|
+
const response = await LeadServiceFetch(`${API_BASE_URI}/${endpoint}`, submitBody);
|
|
1697
|
+
return await response.json();
|
|
1698
|
+
}
|
|
1699
|
+
catch (e) {
|
|
1700
|
+
return null;
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
async function sendPhoneCallRequest(body, endpoint) {
|
|
1704
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1705
|
+
const submitBody = getSubmitBody({ body, endpoint });
|
|
1706
|
+
const formatSubmitBody = getFormatCallbackSubmitBody(submitBody);
|
|
1707
|
+
try {
|
|
1708
|
+
const response = await LeadServiceFetch(`${API_BASE_URI}/callback`, formatSubmitBody);
|
|
1709
|
+
if (!response?.ok) {
|
|
1710
|
+
return null;
|
|
1711
|
+
}
|
|
1712
|
+
return await response.json();
|
|
1713
|
+
}
|
|
1714
|
+
catch (e) {
|
|
1715
|
+
return null;
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
return {
|
|
1719
|
+
send,
|
|
1720
|
+
sendCode,
|
|
1721
|
+
checkCode,
|
|
1722
|
+
sendPhoneCallRequest,
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
const LeadServiceFetch = (url, submitBody) => fetch(url, {
|
|
1726
|
+
method: 'POST',
|
|
1727
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1728
|
+
mode: 'cors',
|
|
1729
|
+
body: JSON.stringify(submitBody),
|
|
1730
|
+
});
|
|
1731
|
+
const getFormatCallbackSubmitBody = (submitBody) => {
|
|
1732
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1733
|
+
const { typeForm, consentDataProcessing, phone, ...rest } = submitBody;
|
|
1734
|
+
return {
|
|
1735
|
+
...rest,
|
|
1736
|
+
phone: phone?.startsWith('+') ? phone.slice(1) : phone,
|
|
1737
|
+
clientTimezone: getUserTimezoneOffset(),
|
|
1738
|
+
};
|
|
1739
|
+
};
|
|
1740
|
+
const getEndpoint = (endpoint, body) => {
|
|
1741
|
+
const { serviceDirection } = body;
|
|
1742
|
+
if (endpoint === 'lead' && serviceDirection !== 'Юридическое лицо / ИП') {
|
|
1743
|
+
return 'lead';
|
|
1744
|
+
}
|
|
1745
|
+
return endpoint;
|
|
1746
|
+
};
|
|
1747
|
+
|
|
1748
|
+
const sendUserSurvey = async (body) => {
|
|
1749
|
+
try {
|
|
1750
|
+
const response = await LeadServiceFetch(`${API_BASE_URI}/survey`, body);
|
|
1751
|
+
return response;
|
|
1752
|
+
}
|
|
1753
|
+
catch (e) {
|
|
1754
|
+
return null;
|
|
1755
|
+
}
|
|
1756
|
+
};
|
|
1757
|
+
|
|
1758
|
+
const FinalStep = JSX(() => {
|
|
1759
|
+
return (jsxs("div", { className: "flex flex-col items-center", children: [jsx(Heading, { className: "text-center", headingType: "h5", title: "\u0421\u043F\u0430\u0441\u0438\u0431\u043E \u0437\u0430 \u0443\u0447\u0430\u0441\u0442\u0438\u0435!" }), jsx(Paragraph, { children: "\u0412\u0430\u0448\u0435 \u043C\u043D\u0435\u043D\u0438\u0435 \u043E\u0447\u0435\u043D\u044C \u0432\u0430\u0436\u043D\u043E \u0434\u043B\u044F \u043D\u0430\u0441" })] }));
|
|
1760
|
+
});
|
|
1761
|
+
|
|
1762
|
+
const Loader = JSX(({ color = 'text-primary-main', position = 'absolute', blur = true, size = 'big' }) => (jsx("div", { className: style('flex justify-center items-center h-full w-full z-50', position, {
|
|
1763
|
+
'backdrop-blur': blur,
|
|
1764
|
+
}), children: jsx("div", { className: style('inline-block', 'animate-spin rounded-full', 'border-solid border-current', 'border-r-transparent', size === 'extraSmall' && 'border-2 h-4 w-4', size === 'small' && 'border-4 h-8 w-8', size === 'big' && 'border-8 h-28 w-28', color), role: "status" }) })));
|
|
1765
|
+
|
|
1766
|
+
const SubmitButton$1 = JSX(({ isLoading, disabled, children, className, ...rest }) => (jsxs(Button, { type: "submit", className: style('relative', className), disabled: isLoading || disabled, ...rest, children: [isLoading ? jsx(Loader, { blur: true, size: "small" }) : null, children] })));
|
|
1767
|
+
|
|
1768
|
+
const GREY_COLOR = '#C9CACC';
|
|
1769
|
+
const GREEN_COLOR = '#42AB44';
|
|
1770
|
+
const Star = JSX(({ value, hover, rating, setHover, setRating }) => (jsx("div", { onClick: () => value && setRating?.(value), onMouseEnter: () => value && setHover?.(value), onMouseLeave: () => setHover?.(null), children: jsx("svg", { "data-rating": value, fill: getColor({ value, hover, rating }), width: "57", height: "57", viewBox: "0 0 57 57", children: jsx("path", { d: "M47.7803 18.2879L47.7836 18.2884C50.566 18.7521 53.0867 20.1374 53.9176 22.7226C54.7498 25.3116 53.5025 27.9027 51.4977 29.8954L51.4942 29.8989L45.7132 35.6799C45.5729 35.8202 45.3591 36.1532 45.2186 36.6438C45.0796 37.1295 45.0808 37.5314 45.1257 37.7381L45.1268 37.743L46.78 44.8909C47.4787 47.9228 47.3175 51.2217 44.8924 52.9896C42.4714 54.7546 39.2808 53.9093 36.5999 52.3257L29.6214 48.1946C29.4392 48.0866 29.0426 47.96 28.5087 47.96C27.9816 47.96 27.5736 48.0831 27.3687 48.2004L27.3634 48.2035L20.4041 52.3232L20.4019 52.3246C17.7218 53.9145 14.5351 54.7459 12.1155 52.9803C9.69339 51.213 9.51826 47.9236 10.22 44.8909L11.8731 37.743L11.8743 37.7379C11.9191 37.5311 11.9203 37.1293 11.7813 36.6438C11.6409 36.1532 11.4271 35.8202 11.2867 35.6799L5.50006 29.8932C3.50738 27.9006 2.26429 25.3118 3.08972 22.7269C3.91586 20.1398 6.43161 18.7525 9.21638 18.2884L16.6527 17.0529L16.6552 17.0525C16.8169 17.0243 17.1619 16.8935 17.5523 16.604C17.945 16.3128 18.1668 16.022 18.2378 15.877L18.2462 15.8598L22.3508 7.65087L22.352 7.6485C23.629 5.08222 25.7146 3.01416 28.4796 3.01416C31.2412 3.01416 33.3328 5.07832 34.6215 7.64213L34.6236 7.64649L38.7303 15.8598L38.75 15.9001C38.7884 15.9807 38.8225 16.0591 38.8511 16.1283C38.9197 16.1891 39.0148 16.2702 39.1464 16.3781C39.1829 16.394 39.242 16.4185 39.3288 16.4505C39.5779 16.5424 39.9286 16.6512 40.3732 16.7719C41.2573 17.0121 42.3688 17.2611 43.4823 17.4894C44.5886 17.7163 45.6648 17.9163 46.4667 18.0598C46.8669 18.1315 47.1972 18.1888 47.4266 18.2281L47.6909 18.2729L47.7589 18.2843L47.7803 18.2879Z" }) }) })));
|
|
1771
|
+
const getColor = ({ value, hover, rating }) => {
|
|
1772
|
+
if (value && hover) {
|
|
1773
|
+
return value <= hover ? GREEN_COLOR : GREY_COLOR;
|
|
1774
|
+
}
|
|
1775
|
+
if (value && rating) {
|
|
1776
|
+
return value <= rating ? GREEN_COLOR : GREY_COLOR;
|
|
1777
|
+
}
|
|
1778
|
+
return GREY_COLOR;
|
|
1779
|
+
};
|
|
1780
|
+
|
|
1781
|
+
const stars$1 = Array.from('12345', () => Star);
|
|
1782
|
+
const TITLE$1 = {
|
|
1783
|
+
NPS: 'Оцените, пожалуйста, от 1 до 5,\nнасколько вероятно, что вы порекомендуете Россельхозбанк коллегам, друзьям и знакомым?',
|
|
1784
|
+
CSI: 'Оцените, пожалуйста, удовлетворённость пользования сайтом',
|
|
1785
|
+
};
|
|
1786
|
+
const FirstStep = JSX(({ currentRating, surveyType, isSending, setCurrentRating, onNextStep, onSubmit }) => {
|
|
1787
|
+
const [currentHover, setCurrentHover] = useState();
|
|
1788
|
+
const setRatingFn = (value) => {
|
|
1789
|
+
setCurrentRating(value);
|
|
1790
|
+
if (value < 5) {
|
|
1791
|
+
onNextStep();
|
|
1792
|
+
}
|
|
1793
|
+
};
|
|
1794
|
+
return (jsxs("div", { className: "flex flex-col gap-xl items-center", children: [jsx(Heading, { className: "text-center whitespace-pre-line", headingType: "h5", title: TITLE$1[surveyType] }), jsx("div", { className: "flex justify-center", children: stars$1.map((StarItem, index) => (jsx(StarItem, { value: index + 1, rating: currentRating, hover: currentHover, setRating: setRatingFn, setHover: setCurrentHover }, index.toString()))) }), currentRating === 5 ? (jsx(SubmitButton$1, { onClick: () => onSubmit(), isLoading: isSending, children: "\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C" })) : null] }));
|
|
1795
|
+
});
|
|
1796
|
+
|
|
1797
|
+
const SVG = JSX(({ className, viewBox, fill = 'none', width, height, paths, ...commonOptions }) => {
|
|
1798
|
+
return (jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: className, viewBox: viewBox, fill: fill, width: width, height: height, children: paths.map(({ d, fill: pathFill, ...options }, i) => {
|
|
1799
|
+
const resultOptions = { ...commonOptions, ...options };
|
|
1800
|
+
return (jsx("path", { d: d, fill: pathFill || 'currentColor', stroke: resultOptions.stroke, strokeLinecap: resultOptions.strokeLinecap, strokeLinejoin: resultOptions.strokeLinejoin, strokeWidth: resultOptions.strokeWidth, strokeMiterlimit: resultOptions.strokeMiterlimit }, i));
|
|
1801
|
+
}) }));
|
|
1802
|
+
});
|
|
1803
|
+
|
|
1804
|
+
const defaultCheckStyle = 'appearance-none w-5 h-5 border-solid flex-none';
|
|
1805
|
+
|
|
1806
|
+
const CHECK_PATHS = [
|
|
1807
|
+
{
|
|
1808
|
+
d: 'M10.207.793a1 1 0 0 1 0 1.414l-6 6a1 1 0 0 1-1.414 0l-2.5-2.5a1 1 0 0 1 1.414-1.414L3.5 6.086 8.793.793a1 1 0 0 1 1.414 0Z',
|
|
1809
|
+
fillRule: 'evenodd',
|
|
1810
|
+
clipRule: 'evenodd',
|
|
1811
|
+
fill: 'white',
|
|
1812
|
+
},
|
|
1813
|
+
];
|
|
1814
|
+
const Checkbox = JSX(({ className, value, text, disabled, isRadio, onChange, name }) => {
|
|
1815
|
+
const handleChange = useCallback((e) => {
|
|
1816
|
+
if (disabled) {
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
e.preventDefault();
|
|
1820
|
+
onChange && onChange(!value);
|
|
1821
|
+
}, [onChange, disabled, value]);
|
|
1822
|
+
const icon = isRadio ? (jsx("div", { className: "absolute left-1 w-3 h-3 rounded-full bg-primary-main" })) : (jsx(SVG, { paths: CHECK_PATHS, className: "absolute left-1 ml-px block", width: "11", height: "9", fill: "white", viewBox: "0 0 11 9" }));
|
|
1823
|
+
return (jsx("div", { className: className, children: jsxs("label", { className: style('flex items-center relative group/box', getCursorStyle(disabled)), "data-test-id": name, onClick: handleChange, children: [jsx("div", { className: style(defaultCheckStyle, 'm-0', isRadio ? 'rounded-full border-2' : checkboxStyle(value), !disabled && value ? 'border-primary-main' : 'border-gray', disabled ? 'bg-main-disabled' : 'group-hover/box:border-primary-hover'), role: role(isRadio), "aria-checked": Boolean(value), "aria-disabled": Boolean(disabled), "aria-label": text }), value ? icon : null, renderText$3(text)] }) }));
|
|
1824
|
+
});
|
|
1825
|
+
const renderText$3 = (text) => text ? (jsx("div", { className: "ml-s", children: jsx(Text, { size: "text-l", font: "font-light", children: text }) })) : null;
|
|
1826
|
+
const getCursorStyle = (disabled = false) => (disabled ? 'cursor-not-allowed' : 'cursor-pointer');
|
|
1827
|
+
const role = (isRadio = false) => (isRadio ? 'radio' : 'checkbox');
|
|
1828
|
+
const checkboxStyle = (value = false) => style('rounded border', { 'bg-primary-main': value });
|
|
1829
|
+
|
|
1830
|
+
const orientationStyleMap = {
|
|
1831
|
+
horizontal: '@lg:flex-row',
|
|
1832
|
+
vertical: '',
|
|
1833
|
+
};
|
|
1834
|
+
const RadioButtonGroup = JSX(({ label, items, value, className, disabled = false, orientation = 'horizontal', onChange: onChangeCheckedItem, }) => (jsxs("div", { className: "grid gap-xs whitespace-nowrap", children: [label ? (jsx("div", { role: "radiogroup", "aria-label": label, children: jsx(Text, { color: "text-secondary-text", font: "font-light", children: label }) })) : null, jsx("div", { className: style('flex flex-col gap-s', orientationStyleMap[orientation], className), role: "radiogroup", "aria-label": "\u0413\u0440\u0443\u043F\u043F\u0430 \u043A\u043D\u043E\u043F\u043E\u043A", children: items?.map(({ id, text }) => (jsx(Checkbox, { isRadio: true, text: text, value: value === id, onChange: () => onChangeCheckedItem?.(id, text), disabled: disabled, name: id }, String(id)))) })] })));
|
|
1835
|
+
|
|
1836
|
+
function useEventListener(target, type, listener, options) {
|
|
1837
|
+
useEffect(() => {
|
|
1838
|
+
if (!target || !listener) {
|
|
1839
|
+
return;
|
|
1840
|
+
}
|
|
1841
|
+
target.addEventListener(type, listener, options);
|
|
1842
|
+
return () => {
|
|
1843
|
+
target.removeEventListener(type, listener, options);
|
|
1844
|
+
};
|
|
1845
|
+
}, [target, type, listener]);
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
function useOutsideClick(onClick) {
|
|
1849
|
+
const targetRef = useRef(null);
|
|
1850
|
+
const handleClickOutside = useCallback((event) => {
|
|
1851
|
+
if (targetRef && targetRef.current && event.target instanceof Node && !targetRef.current.contains(event.target)) {
|
|
1852
|
+
onClick();
|
|
1853
|
+
}
|
|
1854
|
+
}, [onClick]);
|
|
1855
|
+
useEventListener(globalThis.document, 'click', handleClickOutside);
|
|
1856
|
+
return targetRef;
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
// TODO Базовая функицональность всех Control - надо вынести и привязать к required флагу
|
|
1860
|
+
const getRequiredLabel = ({ label, required = false }) => label && required ? `${label}*` : label;
|
|
1861
|
+
|
|
1862
|
+
const inputValidStyle = 'border border-solid outline-none border-gray hover:border-primary-hover active:border-primary-text focus:border-primary-text rounded';
|
|
1863
|
+
|
|
1864
|
+
const getValidStyle = (valid) => (valid ? inputValidStyle : 'border-error');
|
|
1865
|
+
|
|
1866
|
+
const renderLabel$1 = (label) => label ? (jsx(Text, { size: "text-m", color: "text-primary-text", font: "font-light", children: label })) : null;
|
|
1867
|
+
|
|
1868
|
+
const defaultStyle$1 = 'w-full border rounded-md text-primary-text outline-none p-m';
|
|
1869
|
+
const borderStyle = 'border-dashed';
|
|
1870
|
+
|
|
1871
|
+
const Input = JSX(
|
|
1872
|
+
// eslint-disable-next-line max-lines-per-function
|
|
1873
|
+
({ key, className, id, name, type = 'text', label, placeholder, value = '', valid = true, pattern, autoFocus = false, isTextarea = false, disabled = false, children, onChange, onFocus, onBlur, }) => {
|
|
1874
|
+
const inputRef = useRef(null);
|
|
1875
|
+
const handleChange = useCallback((e) => {
|
|
1876
|
+
const valueWithoutSpace = (e.target?.value ?? '').trimStart();
|
|
1877
|
+
onChange && onChange(valueWithoutSpace);
|
|
1878
|
+
}, [onChange]);
|
|
1879
|
+
useEffect(() => {
|
|
1880
|
+
if (autoFocus) {
|
|
1881
|
+
inputRef.current?.focus();
|
|
1882
|
+
}
|
|
1883
|
+
}, [autoFocus, inputRef]);
|
|
1884
|
+
const paddingStyle = children ? 'pr-3xl' : '';
|
|
1885
|
+
const validStyle = getValidStyle(valid);
|
|
1886
|
+
const ariaLabel = label ?? name ?? id;
|
|
1887
|
+
return (jsxs("div", { className: style('relative', className), children: [jsxs("label", { className: "space-y-xs", children: [renderLabel$1(label), isTextarea ? (jsx("textarea", { className: style('block resize-y min-h-24', defaultStyle$1, validStyle), id: style('textarea', id), value: value, name: name || id, placeholder: placeholder, disabled: disabled, "aria-label": ariaLabel, onChange: handleChange, onFocus: onFocus, onBlur: onBlur }, key)) : (jsx("input", { ref: inputRef, className: style('h-14', defaultStyle$1, paddingStyle, validStyle), id: id, type: type, value: value, name: name || id, placeholder: placeholder, pattern: pattern, disabled: disabled, "aria-label": ariaLabel, onChange: handleChange, onFocus: onFocus, onBlur: onBlur, "data-test-id": name }, key))] }), children] }));
|
|
1888
|
+
});
|
|
1889
|
+
|
|
1890
|
+
const renderErrorText = (error) => (jsx("div", { className: "min-h-6", children: error ? (jsx(Text, { size: "text-xs", font: "font-light", color: "text-error", children: error })) : null }));
|
|
1891
|
+
|
|
1892
|
+
const InputWrapper = JSX(({ className, label, value = '', error, errors, type, isInteger, placeholder, maxLength, inputRef, isOpen, onOpen, onClose, required, onChange = noop, ...rest }) => {
|
|
1893
|
+
const popupRef = useOutsideClick(onClose);
|
|
1894
|
+
const handleChange = useCallback((v) => {
|
|
1895
|
+
const isOverMax = maxLength && v.length > maxLength;
|
|
1896
|
+
!isOpen && onOpen();
|
|
1897
|
+
if (!isOverMax) {
|
|
1898
|
+
onChange(normalizeInteger(v, isInteger));
|
|
1899
|
+
}
|
|
1900
|
+
}, [isOpen, onChange]);
|
|
1901
|
+
return (jsxs("div", { className: style('shrink-0 w-full', className), ref: popupRef, onBlur: onClose, onFocus: onOpen, children: [jsx("div", { ref: inputRef, children: jsx(Input, { type: type || 'text', "aria-label": label, label: getRequiredLabel({ label, required }), valid: Boolean(!error), onChange: handleChange, placeholder: getPlaceholder({ placeholder, errors, label }), value: value, ...rest }) }), renderErrorText(error)] }));
|
|
1902
|
+
});
|
|
1903
|
+
const normalizeInteger = (val = '', isInteger = false) => isInteger && val ? val.replace(/[^\d]+/g, '') : val;
|
|
1904
|
+
const getPlaceholder = ({ placeholder, errors, label }) => errors && !label ? `${placeholder}*` : placeholder;
|
|
1905
|
+
|
|
1906
|
+
const InputControl = JSX((props) => {
|
|
1907
|
+
const [isOpen, { setFalse: close, setTrue: open }] = useBool();
|
|
1908
|
+
return jsx(InputWrapper, { isOpen: isOpen, onOpen: open, onClose: close, ...props });
|
|
1909
|
+
});
|
|
1910
|
+
|
|
1911
|
+
const stars = Array.from('12345', () => Star);
|
|
1912
|
+
const TITLE = 'Что бы мы могли улучшить?';
|
|
1913
|
+
const SecondStep = JSX(({ currentRating, currentReason, reasons = [], isSending, setCurrentReason, onSubmit }) => {
|
|
1914
|
+
const [comment, setComment] = useState();
|
|
1915
|
+
const handleReasonChange = (id, text) => {
|
|
1916
|
+
setCurrentReason?.({
|
|
1917
|
+
id,
|
|
1918
|
+
text,
|
|
1919
|
+
});
|
|
1920
|
+
};
|
|
1921
|
+
return (jsxs("div", { className: "flex flex-col gap-xl items-center", children: [jsx(Heading, { className: "text-center", headingType: "h5", title: TITLE }), jsx("div", { className: "flex justify-center", children: stars.map((StarItem, index) => (jsx(StarItem, { value: index + 1, rating: currentRating }, index.toString()))) }), jsx(RadioButtonGroup, { className: "w-full text-wrap", orientation: "vertical", items: reasons, value: currentReason?.id, onChange: handleReasonChange }), currentReason?.text === 'Другое' ? (jsx(InputControl, { className: "w-full", placeholder: "\u041D\u0430\u043F\u0438\u0448\u0438\u0442\u0435, \u043F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0441\u0432\u043E\u0439 \u0432\u0430\u0440\u0438\u0430\u043D\u0442 \u043E\u0442\u0432\u0435\u0442\u0430", isTextarea: true, value: comment, onChange: setComment, maxLength: 255 })) : null, currentReason ? (jsx(SubmitButton$1, { onClick: () => onSubmit(comment), isLoading: isSending, children: "\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C" })) : null] }));
|
|
1922
|
+
});
|
|
1923
|
+
|
|
1924
|
+
const STEPS$3 = [FirstStep, SecondStep, FinalStep];
|
|
1925
|
+
const LAST_STEP_INDEX = 2;
|
|
1926
|
+
const UserSurveyDialog = UniBlock(({ onClose = noop, isAfterTargetAction = false, reasonsSource = {} }) => {
|
|
1927
|
+
const [isSending, { setTrue: startSending, setFalse: endSending }] = useBool(false);
|
|
1928
|
+
const [currentRating, setCurrentRating] = useState(0);
|
|
1929
|
+
const [currentReason, setCurrentReason] = useState();
|
|
1930
|
+
const [step, setStep] = useState(0);
|
|
1931
|
+
const userSurveyStore = useLocalStore();
|
|
1932
|
+
const surveyType = getUserSurveyType(userSurveyStore.userSurvey?.lastShownType);
|
|
1933
|
+
const { reasons } = reasonsSource;
|
|
1934
|
+
const ActiveStep = STEPS$3[step];
|
|
1935
|
+
const handleNextStep = useCallback(() => {
|
|
1936
|
+
setStep((_) => _ + 1);
|
|
1937
|
+
}, []);
|
|
1938
|
+
const handleSubmit = useCallback(async (message) => {
|
|
1939
|
+
startSending();
|
|
1940
|
+
await sendUserSurvey({
|
|
1941
|
+
rate: currentRating,
|
|
1942
|
+
reason: currentReason?.text,
|
|
1943
|
+
message: getMessage(currentReason, message),
|
|
1944
|
+
url: globalThis.location.href,
|
|
1945
|
+
type: surveyType,
|
|
1946
|
+
ip: isAfterTargetAction ? 'after_target_action' : 'time_on_site',
|
|
1947
|
+
});
|
|
1948
|
+
endSending();
|
|
1949
|
+
userSurveyStore.userSurvey = {
|
|
1950
|
+
lastShownType: surveyType,
|
|
1951
|
+
nextDueAt: getTimeAfter30days(),
|
|
1952
|
+
};
|
|
1953
|
+
setStep(LAST_STEP_INDEX);
|
|
1954
|
+
}, [currentRating, currentReason]);
|
|
1955
|
+
return (jsx(Dialog, { maxWidth: "xl", onClose: onClose, children: jsx(ActiveStep, { currentRating: currentRating, currentReason: currentReason, reasons: reasons, surveyType: surveyType, isSending: isSending, setCurrentReason: setCurrentReason, setCurrentRating: setCurrentRating, onSubmit: handleSubmit, onNextStep: handleNextStep }) }));
|
|
1956
|
+
});
|
|
1957
|
+
const getMessage = (currentReason, message) => {
|
|
1958
|
+
if (currentReason?.text !== 'Другое') {
|
|
1959
|
+
return undefined;
|
|
1960
|
+
}
|
|
1961
|
+
return message?.length ? message : 'Другое. Клиент не оставил комментариев';
|
|
1962
|
+
};
|
|
1963
|
+
// Отсчитываем месяц с текущей даты
|
|
1964
|
+
const getTimeAfter30days = () => Date.now() + 30 * 24 * 60 * 60 * 1000;
|
|
1965
|
+
// Если пользователь проходил опрос то показываем другой, иначе показываем случайный тип опроса
|
|
1966
|
+
const getUserSurveyType = (lastShownType) => {
|
|
1967
|
+
console.log('Расчитал');
|
|
1968
|
+
if (lastShownType) {
|
|
1969
|
+
return lastShownType === 'NPS' ? 'CSI' : 'NPS';
|
|
1970
|
+
}
|
|
1971
|
+
return ['NPS', 'CSI'][Date.now() % 2];
|
|
1972
|
+
};
|
|
1973
|
+
|
|
1974
|
+
const DELAY = 5 * 60 * 1000;
|
|
1975
|
+
// Хук отвечает за показ пользователю опроса
|
|
1976
|
+
const useUserSurveyDialog = (withoutTimer = false) => {
|
|
1977
|
+
const userSurveyDialog = useDialog(UserSurveyDialog);
|
|
1978
|
+
const userSurveyStore = useLocalStore();
|
|
1979
|
+
const sessionStore = useSessionStore();
|
|
1980
|
+
const surveyTimer = sessionStore.surveyTimerId;
|
|
1981
|
+
const isSurveySkipped = sessionStore.isSurveySkipped;
|
|
1982
|
+
const elapsedTime = sessionStore.surveyTimerStart
|
|
1983
|
+
? Date.now() - Number.parseInt(sessionStore.surveyTimerStart)
|
|
1984
|
+
: 0;
|
|
1985
|
+
const isShowSurvey = !isSurveySkipped &&
|
|
1986
|
+
(!userSurveyStore.userSurvey || userSurveyStore.userSurvey?.nextDueAt <= Date.now());
|
|
1987
|
+
const handleCloseSurvey = useCallback(() => {
|
|
1988
|
+
sessionStore.isSurveySkipped = true;
|
|
1989
|
+
}, []);
|
|
1990
|
+
const openUserSurveyDialog = useCallback((isAfterTargetAction = false) => {
|
|
1991
|
+
userSurveyDialog.open({
|
|
1992
|
+
reasonsSource: {
|
|
1993
|
+
$ref: '/wcms-resources/user-survey-reasons.json',
|
|
1994
|
+
},
|
|
1995
|
+
isAfterTargetAction,
|
|
1996
|
+
onClose: handleCloseSurvey,
|
|
1997
|
+
});
|
|
1998
|
+
}, []);
|
|
1999
|
+
const handleOpenSurveyAction = useCallback(() => {
|
|
2000
|
+
if (isShowSurvey) {
|
|
2001
|
+
surveyTimer && clearTimeout(surveyTimer);
|
|
2002
|
+
openUserSurveyDialog(true);
|
|
2003
|
+
}
|
|
2004
|
+
}, [surveyTimer, isShowSurvey]);
|
|
2005
|
+
useEffect(() => {
|
|
2006
|
+
// Опрос показывается только если ранее пользоваютелю не показывался опрос или с того момента прошел месяц
|
|
2007
|
+
if (!withoutTimer && isShowSurvey) {
|
|
2008
|
+
// начинаем отсчитывать время от первого захода на сайт
|
|
2009
|
+
if (!sessionStore.surveyTimerStart) {
|
|
2010
|
+
sessionStore.surveyTimerStart = Date.now().toString();
|
|
2011
|
+
}
|
|
2012
|
+
// Опрос показывается спустя 5 минут нахождения на сайте
|
|
2013
|
+
const timeout = setTimeout(openUserSurveyDialog, DELAY - elapsedTime);
|
|
2014
|
+
sessionStore.surveyTimerId = timeout;
|
|
2015
|
+
return () => {
|
|
2016
|
+
clearTimeout(timeout);
|
|
2017
|
+
sessionStore.surveyTimerId = null;
|
|
2018
|
+
};
|
|
2019
|
+
}
|
|
2020
|
+
return noop;
|
|
2021
|
+
}, [isShowSurvey]);
|
|
2022
|
+
return handleOpenSurveyAction;
|
|
2023
|
+
};
|
|
2024
|
+
|
|
1379
2025
|
const SERVICE_TYPES = [{ key: 'ULTRASERVICE', text: 'Ультра' }];
|
|
1380
2026
|
const SERVICE_DIRECTIONS = [
|
|
1381
2027
|
{ key: 'Физическое лицо' },
|
|
@@ -1484,98 +2130,23 @@
|
|
|
1484
2130
|
{ key: 'Специалитет', text: 'Специалитет' },
|
|
1485
2131
|
{ key: 'Магистратура', text: 'Магистратура' },
|
|
1486
2132
|
{ key: 'Аспирантура', text: 'Аспирантура' },
|
|
1487
|
-
];
|
|
1488
|
-
|
|
1489
|
-
// TODO Базовая функицональность всех Control - надо вынести и привязать к required флагу
|
|
1490
|
-
const getRequiredLabel = ({ label, required = false }) => label && required ? `${label}*` : label;
|
|
1491
|
-
|
|
1492
|
-
const renderErrorText = (error) => (jsx("div", { className: "min-h-6", children: error ? (jsx(Text, { size: "text-xs", font: "font-light", color: "text-error", children: error })) : null }));
|
|
1493
|
-
|
|
1494
|
-
const debounce = (fn, delay = 600) => {
|
|
1495
|
-
let timerId;
|
|
1496
|
-
const debouncedCallback = (...args) => {
|
|
1497
|
-
debouncedCallback.dispose();
|
|
1498
|
-
timerId = setTimeout(() => {
|
|
1499
|
-
fn(...args);
|
|
1500
|
-
}, delay);
|
|
1501
|
-
};
|
|
1502
|
-
debouncedCallback.dispose = () => {
|
|
1503
|
-
if (timerId) {
|
|
1504
|
-
clearTimeout(timerId);
|
|
1505
|
-
}
|
|
1506
|
-
};
|
|
1507
|
-
return debouncedCallback;
|
|
1508
|
-
};
|
|
1509
|
-
|
|
1510
|
-
const renderLabel$1 = (label) => label ? (jsx(Text, { size: "text-m", color: "text-primary-text", font: "font-light", children: label })) : null;
|
|
1511
|
-
|
|
1512
|
-
function useEventListener(target, type, listener, options) {
|
|
1513
|
-
useEffect(() => {
|
|
1514
|
-
if (!target || !listener) {
|
|
1515
|
-
return;
|
|
1516
|
-
}
|
|
1517
|
-
target.addEventListener(type, listener, options);
|
|
1518
|
-
return () => {
|
|
1519
|
-
target.removeEventListener(type, listener, options);
|
|
1520
|
-
};
|
|
1521
|
-
}, [target, type, listener]);
|
|
1522
|
-
}
|
|
1523
|
-
|
|
1524
|
-
function useOutsideClick(onClick) {
|
|
1525
|
-
const targetRef = useRef(null);
|
|
1526
|
-
const handleClickOutside = useCallback((event) => {
|
|
1527
|
-
if (targetRef && targetRef.current && event.target instanceof Node && !targetRef.current.contains(event.target)) {
|
|
1528
|
-
onClick();
|
|
1529
|
-
}
|
|
1530
|
-
}, [onClick]);
|
|
1531
|
-
useEventListener(globalThis.document, 'click', handleClickOutside);
|
|
1532
|
-
return targetRef;
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
|
-
const inputValidStyle = 'border border-solid outline-none border-gray hover:border-primary-hover active:border-primary-text focus:border-primary-text rounded';
|
|
1536
|
-
|
|
1537
|
-
const getValidStyle = (valid) => (valid ? inputValidStyle : 'border-error');
|
|
1538
|
-
|
|
1539
|
-
const defaultStyle$1 = 'w-full border rounded-md text-primary-text outline-none p-m';
|
|
1540
|
-
const borderStyle = 'border-dashed';
|
|
1541
|
-
|
|
1542
|
-
const Input = JSX(
|
|
1543
|
-
// eslint-disable-next-line max-lines-per-function
|
|
1544
|
-
({ key, className, id, name, type = 'text', label, placeholder, value = '', valid = true, pattern, autoFocus = false, isTextarea = false, disabled = false, children, onChange, onFocus, onBlur, }) => {
|
|
1545
|
-
const inputRef = useRef(null);
|
|
1546
|
-
const handleChange = useCallback((e) => {
|
|
1547
|
-
const valueWithoutSpace = (e.target?.value ?? '').trimStart();
|
|
1548
|
-
onChange && onChange(valueWithoutSpace);
|
|
1549
|
-
}, [onChange]);
|
|
1550
|
-
useEffect(() => {
|
|
1551
|
-
if (autoFocus) {
|
|
1552
|
-
inputRef.current?.focus();
|
|
1553
|
-
}
|
|
1554
|
-
}, [autoFocus, inputRef]);
|
|
1555
|
-
const paddingStyle = children ? 'pr-3xl' : '';
|
|
1556
|
-
const validStyle = getValidStyle(valid);
|
|
1557
|
-
const ariaLabel = label ?? name ?? id;
|
|
1558
|
-
return (jsxs("div", { className: style('relative', className), children: [jsxs("label", { className: "space-y-xs", children: [renderLabel$1(label), isTextarea ? (jsx("textarea", { className: style('block resize-y min-h-24', defaultStyle$1, validStyle), id: style('textarea', id), value: value, name: name || id, placeholder: placeholder, disabled: disabled, "aria-label": ariaLabel, onChange: handleChange, onFocus: onFocus, onBlur: onBlur }, key)) : (jsx("input", { ref: inputRef, className: style('h-14', defaultStyle$1, paddingStyle, validStyle), id: id, type: type, value: value, name: name || id, placeholder: placeholder, pattern: pattern, disabled: disabled, "aria-label": ariaLabel, onChange: handleChange, onFocus: onFocus, onBlur: onBlur, "data-test-id": name }, key))] }), children] }));
|
|
1559
|
-
});
|
|
2133
|
+
];
|
|
1560
2134
|
|
|
1561
|
-
const
|
|
1562
|
-
|
|
1563
|
-
const
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
2135
|
+
const debounce = (fn, delay = 600) => {
|
|
2136
|
+
let timerId;
|
|
2137
|
+
const debouncedCallback = (...args) => {
|
|
2138
|
+
debouncedCallback.dispose();
|
|
2139
|
+
timerId = setTimeout(() => {
|
|
2140
|
+
fn(...args);
|
|
2141
|
+
}, delay);
|
|
2142
|
+
};
|
|
2143
|
+
debouncedCallback.dispose = () => {
|
|
2144
|
+
if (timerId) {
|
|
2145
|
+
clearTimeout(timerId);
|
|
1568
2146
|
}
|
|
1569
|
-
}
|
|
1570
|
-
return
|
|
1571
|
-
}
|
|
1572
|
-
const normalizeInteger = (val = '', isInteger = false) => isInteger && val ? val.replace(/[^\d]+/g, '') : val;
|
|
1573
|
-
const getPlaceholder = ({ placeholder, errors, label }) => errors && !label ? `${placeholder}*` : placeholder;
|
|
1574
|
-
|
|
1575
|
-
const InputControl = JSX((props) => {
|
|
1576
|
-
const [isOpen, { setFalse: close, setTrue: open }] = useBool();
|
|
1577
|
-
return jsx(InputWrapper, { isOpen: isOpen, onOpen: open, onClose: close, ...props });
|
|
1578
|
-
});
|
|
2147
|
+
};
|
|
2148
|
+
return debouncedCallback;
|
|
2149
|
+
};
|
|
1579
2150
|
|
|
1580
2151
|
const renderSearchInput = ({ query, isDisabled, onChangeQuery, inputProps, }) => (jsx("div", { className: "absolute top-0 w-full z-20", children: jsx(InputControl, { type: "text", value: query, autoFocus: true, disabled: isDisabled, onChange: (value) => onChangeQuery(value), maxLength: inputProps?.maxLength, isInteger: inputProps?.isInteger ?? false }) }));
|
|
1581
2152
|
|
|
@@ -1717,7 +2288,7 @@
|
|
|
1717
2288
|
const formatData = {
|
|
1718
2289
|
...usedData,
|
|
1719
2290
|
...getVedTypes(vedTypes),
|
|
1720
|
-
...getRegion
|
|
2291
|
+
...getRegion(region),
|
|
1721
2292
|
...(inn && { inn }),
|
|
1722
2293
|
...(partnerComments ? { partnerComments } : {}),
|
|
1723
2294
|
...(serviceType ? { typeForm: serviceType } : {}),
|
|
@@ -1734,7 +2305,7 @@
|
|
|
1734
2305
|
const getIncidentComment = (sufferedFrom, situationDescription) => sufferedFrom || situationDescription
|
|
1735
2306
|
? { comment: `${sufferedFrom || ''};${situationDescription || ''}` }
|
|
1736
2307
|
: {};
|
|
1737
|
-
const getRegion
|
|
2308
|
+
const getRegion = (region) => region?.key || region?.text ? { region: region?.text || region?.key } : {};
|
|
1738
2309
|
const getVedTypes = (vedTypes) => vedTypes
|
|
1739
2310
|
? {
|
|
1740
2311
|
vedTypes: Object.fromEntries(VED_TYPES.map(({ id }) => [id, id === vedTypes])),
|
|
@@ -1768,239 +2339,20 @@
|
|
|
1768
2339
|
vedTypes: VED_TYPES[0].id,
|
|
1769
2340
|
birthday: undefined,
|
|
1770
2341
|
isClient: false,
|
|
1771
|
-
onlineCheckout: false,
|
|
1772
|
-
posTerminal: false,
|
|
1773
|
-
consentToReceiveMaterials: false,
|
|
1774
|
-
consentDataProcessing: false,
|
|
1775
|
-
addressRetail: { key: '', text: '' },
|
|
1776
|
-
fileUpload: '',
|
|
1777
|
-
fileId: '',
|
|
1778
|
-
};
|
|
1779
|
-
const getInitialFormState$2 = (inputs, typeForm = '') => {
|
|
1780
|
-
const formState = Object.fromEntries(inputs.map((_) => [
|
|
1781
|
-
_.name,
|
|
1782
|
-
(_?.name === 'vedTypes' && _?.defaultValue) || initialFormState$1[_.name || ''],
|
|
1783
|
-
]));
|
|
1784
|
-
return { ...formState, typeForm: { key: typeForm, text: '' } };
|
|
1785
|
-
};
|
|
1786
|
-
|
|
1787
|
-
const getUserTimezoneOffset = () => {
|
|
1788
|
-
const offset = new Date().getTimezoneOffset();
|
|
1789
|
-
const absOffset = Math.abs(offset);
|
|
1790
|
-
const hours = Math.floor(absOffset / 60);
|
|
1791
|
-
const minutes = absOffset % 60;
|
|
1792
|
-
const sign = offset < 0 ? '+' : '-';
|
|
1793
|
-
return `GMT${sign}${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
|
1794
|
-
};
|
|
1795
|
-
|
|
1796
|
-
const API_BASE_URI = '/api/v1';
|
|
1797
|
-
|
|
1798
|
-
const ENDPOINT_MAPPING = {
|
|
1799
|
-
lead: {
|
|
1800
|
-
withTypeForm: true,
|
|
1801
|
-
isNaturalEndpoint: true,
|
|
1802
|
-
},
|
|
1803
|
-
sendcorporatelead: {
|
|
1804
|
-
withTypeForm: true,
|
|
1805
|
-
isNaturalEndpoint: false,
|
|
1806
|
-
},
|
|
1807
|
-
practice: {
|
|
1808
|
-
withTypeForm: false,
|
|
1809
|
-
isNaturalEndpoint: true,
|
|
1810
|
-
},
|
|
1811
|
-
internship: {
|
|
1812
|
-
withTypeForm: false,
|
|
1813
|
-
isNaturalEndpoint: true,
|
|
1814
|
-
},
|
|
1815
|
-
initcorporatelead: {
|
|
1816
|
-
withTypeForm: true,
|
|
1817
|
-
isNaturalEndpoint: false,
|
|
1818
|
-
},
|
|
1819
|
-
confirmCorporateLead: {
|
|
1820
|
-
withTypeForm: true,
|
|
1821
|
-
isNaturalEndpoint: false,
|
|
1822
|
-
},
|
|
1823
|
-
callback: {
|
|
1824
|
-
withTypeForm: false,
|
|
1825
|
-
isNaturalEndpoint: true,
|
|
1826
|
-
},
|
|
1827
|
-
};
|
|
1828
|
-
|
|
1829
|
-
const formatDate = (date, toTimeStamp = false) => {
|
|
1830
|
-
if (typeof date === 'string') {
|
|
1831
|
-
return date.split('-').reverse().join('.');
|
|
1832
|
-
}
|
|
1833
|
-
else {
|
|
1834
|
-
const day = String(date.getDate()).padStart(2, '0');
|
|
1835
|
-
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
1836
|
-
const year = String(date.getFullYear());
|
|
1837
|
-
return toTimeStamp ? `${year}-${month}-${day}` : `${day}.${month}.${year}`;
|
|
1838
|
-
}
|
|
1839
|
-
};
|
|
1840
|
-
|
|
1841
|
-
const formatPhone = (phone) => phone?.replace(/[^+\d]/g, '');
|
|
1842
|
-
|
|
1843
|
-
const getSubmitBody = ({ body, endpoint, router }) => {
|
|
1844
|
-
const isNaturalPerson = endpoint && ENDPOINT_MAPPING[endpoint].isNaturalEndpoint;
|
|
1845
|
-
const withTypeForm = endpoint && ENDPOINT_MAPPING[endpoint].withTypeForm;
|
|
1846
|
-
const { typeForm, region, phone = '', email, birthday, desiredMeetingDate, fullRegion, addressBranch, secondaryPhone = '', bankEmpolee, applicationDate, partnerName, russianPhone, partnerSymbolCode, internshipEndDate, internshipStartDate, ...staticBody } = body;
|
|
1847
|
-
return {
|
|
1848
|
-
...(withTypeForm ? { typeForm } : {}),
|
|
1849
|
-
...getRegion(region, isNaturalPerson),
|
|
1850
|
-
...getEmail(email, isNaturalPerson),
|
|
1851
|
-
...getPhone(phone),
|
|
1852
|
-
...getPhone(russianPhone),
|
|
1853
|
-
...(isNaturalPerson ? getFormatDate([[birthday, 'birthday']]) : { birthday }),
|
|
1854
|
-
...getFormatDate([
|
|
1855
|
-
[desiredMeetingDate, 'desiredMeetingDate'],
|
|
1856
|
-
[internshipEndDate, 'internshipEndDate'],
|
|
1857
|
-
[internshipStartDate, 'internshipStartDate'],
|
|
1858
|
-
]),
|
|
1859
|
-
...(typeForm === 'FEEDBACK'
|
|
1860
|
-
? {}
|
|
1861
|
-
: {
|
|
1862
|
-
addressBranch,
|
|
1863
|
-
bankEmpolee,
|
|
1864
|
-
applicationDate,
|
|
1865
|
-
...getSecondaryPhone(secondaryPhone),
|
|
1866
|
-
}),
|
|
1867
|
-
...addPageSlug(typeForm, router),
|
|
1868
|
-
...formatPFForm(typeForm, {
|
|
1869
|
-
fullRegion,
|
|
1870
|
-
partnerName,
|
|
1871
|
-
partnerSymbolCode,
|
|
1872
|
-
}),
|
|
1873
|
-
...getRkoTariffName(typeForm),
|
|
1874
|
-
...staticBody,
|
|
1875
|
-
};
|
|
1876
|
-
};
|
|
1877
|
-
const getPhoneBody = (phone) => {
|
|
1878
|
-
return {
|
|
1879
|
-
...getPhone(phone),
|
|
1880
|
-
};
|
|
1881
|
-
};
|
|
1882
|
-
const getPhone = (phone) => (phone ? { phone: formatPhone(phone) } : {});
|
|
1883
|
-
const getFormatDate = (dates) => Object.fromEntries(dates.filter(([value]) => value).map(([value, key]) => [key, formatDate(value)]));
|
|
1884
|
-
const getRegion = (region, isNaturalPerson = true) => ({
|
|
1885
|
-
[isNaturalPerson ? 'regionBranch' : 'region']: region,
|
|
1886
|
-
});
|
|
1887
|
-
const getEmail = (email, isNaturalPerson = true) => ({
|
|
1888
|
-
[isNaturalPerson ? 'email' : 'mail']: email,
|
|
1889
|
-
});
|
|
1890
|
-
const getSecondaryPhone = (secondaryPhone = '') => !secondaryPhone || secondaryPhone === '+7 ('
|
|
1891
|
-
? {}
|
|
1892
|
-
: { secondaryPhoneNumber: formatPhone(secondaryPhone) };
|
|
1893
|
-
const formatPFForm = (typeForm, data) => typeForm === 'PF'
|
|
1894
|
-
? {
|
|
1895
|
-
region: data?.fullRegion,
|
|
1896
|
-
partner: data?.partnerName,
|
|
1897
|
-
partnerId: data?.partnerSymbolCode,
|
|
1898
|
-
}
|
|
1899
|
-
: {};
|
|
1900
|
-
const addPageSlug = (typeForm, router) => typeForm === 'UNIVERSAL'
|
|
1901
|
-
? {
|
|
1902
|
-
typeForm: router?.pathname?.split('/')?.at(-1) || '/',
|
|
1903
|
-
}
|
|
1904
|
-
: {};
|
|
1905
|
-
const getRkoTariffName = (typeForm) => typeForm === 'CALC'
|
|
1906
|
-
? {
|
|
1907
|
-
partnerComments: globalThis?.sessionStorage.getItem('rkoTariffName') ?? 'Неизвестный тариф',
|
|
1908
|
-
}
|
|
1909
|
-
: {};
|
|
1910
|
-
|
|
1911
|
-
// eslint-disable-next-line max-lines-per-function
|
|
1912
|
-
function LeadServiceAPI() {
|
|
1913
|
-
async function send({ body, router, endpoint }) {
|
|
1914
|
-
const calculatedEndpoint = endpoint && getEndpoint(endpoint, body);
|
|
1915
|
-
const url = `${API_BASE_URI}/${calculatedEndpoint}`;
|
|
1916
|
-
const submitBody = getSubmitBody({
|
|
1917
|
-
body,
|
|
1918
|
-
endpoint,
|
|
1919
|
-
router,
|
|
1920
|
-
});
|
|
1921
|
-
try {
|
|
1922
|
-
const response = await LeadServiceFetch(url, submitBody);
|
|
1923
|
-
if (!response?.ok) {
|
|
1924
|
-
return null;
|
|
1925
|
-
}
|
|
1926
|
-
return await response.json();
|
|
1927
|
-
}
|
|
1928
|
-
catch (e) {
|
|
1929
|
-
return null;
|
|
1930
|
-
}
|
|
1931
|
-
}
|
|
1932
|
-
async function sendCode({ phone }) {
|
|
1933
|
-
const submitBody = getPhoneBody(phone);
|
|
1934
|
-
try {
|
|
1935
|
-
const response = LeadServiceFetch(`${API_BASE_URI}/initCorporateLead`, submitBody).then(async (res) => {
|
|
1936
|
-
if (!res.ok) {
|
|
1937
|
-
throw new Error(`Ошибка HTTP: ${res.status}`);
|
|
1938
|
-
}
|
|
1939
|
-
return await res.text();
|
|
1940
|
-
});
|
|
1941
|
-
return await response;
|
|
1942
|
-
}
|
|
1943
|
-
catch (e) {
|
|
1944
|
-
return null;
|
|
1945
|
-
}
|
|
1946
|
-
}
|
|
1947
|
-
async function checkCode({ reqId, code, body, router, endpoint = 'confirmCorporateLead', }) {
|
|
1948
|
-
const submitBody = {
|
|
1949
|
-
requestId: reqId,
|
|
1950
|
-
confimationCode: code,
|
|
1951
|
-
leadRequest: getSubmitBody({ body, endpoint, router }),
|
|
1952
|
-
};
|
|
1953
|
-
try {
|
|
1954
|
-
const response = await LeadServiceFetch(`${API_BASE_URI}/${endpoint}`, submitBody);
|
|
1955
|
-
return await response.json();
|
|
1956
|
-
}
|
|
1957
|
-
catch (e) {
|
|
1958
|
-
return null;
|
|
1959
|
-
}
|
|
1960
|
-
}
|
|
1961
|
-
async function sendPhoneCallRequest(body, endpoint) {
|
|
1962
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1963
|
-
const submitBody = getSubmitBody({ body, endpoint });
|
|
1964
|
-
const formatSubmitBody = getFormatCallbackSubmitBody(submitBody);
|
|
1965
|
-
try {
|
|
1966
|
-
const response = await LeadServiceFetch(`${API_BASE_URI}/callback`, formatSubmitBody);
|
|
1967
|
-
if (!response?.ok) {
|
|
1968
|
-
return null;
|
|
1969
|
-
}
|
|
1970
|
-
return await response.json();
|
|
1971
|
-
}
|
|
1972
|
-
catch (e) {
|
|
1973
|
-
return null;
|
|
1974
|
-
}
|
|
1975
|
-
}
|
|
1976
|
-
return {
|
|
1977
|
-
send,
|
|
1978
|
-
sendCode,
|
|
1979
|
-
checkCode,
|
|
1980
|
-
sendPhoneCallRequest,
|
|
1981
|
-
};
|
|
1982
|
-
}
|
|
1983
|
-
const LeadServiceFetch = (url, submitBody) => fetch(url, {
|
|
1984
|
-
method: 'POST',
|
|
1985
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1986
|
-
mode: 'cors',
|
|
1987
|
-
body: JSON.stringify(submitBody),
|
|
1988
|
-
});
|
|
1989
|
-
const getFormatCallbackSubmitBody = (submitBody) => {
|
|
1990
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1991
|
-
const { typeForm, consentDataProcessing, phone, ...rest } = submitBody;
|
|
1992
|
-
return {
|
|
1993
|
-
...rest,
|
|
1994
|
-
phone: phone?.startsWith('+') ? phone.slice(1) : phone,
|
|
1995
|
-
clientTimezone: getUserTimezoneOffset(),
|
|
1996
|
-
};
|
|
2342
|
+
onlineCheckout: false,
|
|
2343
|
+
posTerminal: false,
|
|
2344
|
+
consentToReceiveMaterials: false,
|
|
2345
|
+
consentDataProcessing: false,
|
|
2346
|
+
addressRetail: { key: '', text: '' },
|
|
2347
|
+
fileUpload: '',
|
|
2348
|
+
fileId: '',
|
|
1997
2349
|
};
|
|
1998
|
-
const
|
|
1999
|
-
const
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
return
|
|
2350
|
+
const getInitialFormState$2 = (inputs, typeForm = '') => {
|
|
2351
|
+
const formState = Object.fromEntries(inputs.map((_) => [
|
|
2352
|
+
_.name,
|
|
2353
|
+
(_?.name === 'vedTypes' && _?.defaultValue) || initialFormState$1[_.name || ''],
|
|
2354
|
+
]));
|
|
2355
|
+
return { ...formState, typeForm: { key: typeForm, text: '' } };
|
|
2004
2356
|
};
|
|
2005
2357
|
|
|
2006
2358
|
const getAspectsWithInclude = (data, include) => data?.map(({ aspectName, params }) => ({
|
|
@@ -2018,8 +2370,9 @@
|
|
|
2018
2370
|
};
|
|
2019
2371
|
|
|
2020
2372
|
const API$2 = LeadServiceAPI();
|
|
2021
|
-
const handleInitCorporateLead = async ({ formatData = {}, typeForm, responseTypeDialog, verifyPhoneDialog, data = [], aspects = {}, ev, }) => {
|
|
2373
|
+
const handleInitCorporateLead = async ({ formatData = {}, typeForm, responseTypeDialog, verifyPhoneDialog, data = [], aspects = {}, ev, openUserSurvey, }) => {
|
|
2022
2374
|
const { phone } = formatData;
|
|
2375
|
+
const hasSurveyAspect = data?.find((_) => _.aspectName === 'openUserSurvey');
|
|
2023
2376
|
const response = await API$2.sendCode({ phone: String(phone) });
|
|
2024
2377
|
if (!response) {
|
|
2025
2378
|
responseTypeDialog.open({ ok: Boolean(response), typeForm });
|
|
@@ -2037,6 +2390,7 @@
|
|
|
2037
2390
|
phone,
|
|
2038
2391
|
id,
|
|
2039
2392
|
});
|
|
2393
|
+
hasSurveyAspect && openUserSurvey?.();
|
|
2040
2394
|
handleAspects({
|
|
2041
2395
|
aspectsAttributes: getAspectsWithInclude(data, snowplowParams),
|
|
2042
2396
|
aspects,
|
|
@@ -2045,11 +2399,13 @@
|
|
|
2045
2399
|
},
|
|
2046
2400
|
});
|
|
2047
2401
|
};
|
|
2048
|
-
const handleCallback = async ({ formatData, data, aspects = {}, ev, typeForm, responseTypeDialog, onSuccess = noop, endpoint, }) => {
|
|
2402
|
+
const handleCallback = async ({ formatData, data, aspects = {}, ev, typeForm, responseTypeDialog, onSuccess = noop, endpoint, openUserSurvey, }) => {
|
|
2403
|
+
const hasSurveyAspect = data?.find((_) => _.aspectName === 'openUserSurvey');
|
|
2049
2404
|
const response = await API$2.sendPhoneCallRequest(formatData, endpoint);
|
|
2050
2405
|
onSuccess();
|
|
2051
2406
|
if (response?.status === 'success') {
|
|
2052
2407
|
responseTypeDialog.open({ ok: true, typeForm });
|
|
2408
|
+
hasSurveyAspect && openUserSurvey?.();
|
|
2053
2409
|
handleAspects({ aspectsAttributes: data, aspects, ev });
|
|
2054
2410
|
}
|
|
2055
2411
|
else if (response?.status === 'error') {
|
|
@@ -2065,11 +2421,13 @@
|
|
|
2065
2421
|
}
|
|
2066
2422
|
}
|
|
2067
2423
|
};
|
|
2068
|
-
const handleDefault = async ({ formatData, data, aspects = {}, ev, router, responseTypeDialog, endpoint, withSnowplow, }) => {
|
|
2424
|
+
const handleDefault = async ({ formatData, data, aspects = {}, ev, router, responseTypeDialog, endpoint, withSnowplow, openUserSurvey, }) => {
|
|
2425
|
+
const hasSurveyAspect = data?.find((_) => _.aspectName === 'openUserSurvey');
|
|
2069
2426
|
const response = await API$2.send({ body: formatData, router, endpoint });
|
|
2070
2427
|
const ok = Boolean(response);
|
|
2071
2428
|
responseTypeDialog.open({ ok });
|
|
2072
2429
|
if (ok) {
|
|
2430
|
+
hasSurveyAspect && openUserSurvey?.();
|
|
2073
2431
|
const { requestId } = response;
|
|
2074
2432
|
const { phone } = formatData;
|
|
2075
2433
|
const utms = router.pathname.split('?')[1];
|
|
@@ -2090,45 +2448,6 @@
|
|
|
2090
2448
|
}
|
|
2091
2449
|
};
|
|
2092
2450
|
|
|
2093
|
-
const Loader = JSX(({ color = 'text-primary-main', position = 'absolute', blur = true, size = 'big' }) => (jsx("div", { className: style('flex justify-center items-center h-full w-full z-50', position, {
|
|
2094
|
-
'backdrop-blur': blur,
|
|
2095
|
-
}), children: jsx("div", { className: style('inline-block', 'animate-spin rounded-full', 'border-solid border-current', 'border-r-transparent', size === 'extraSmall' && 'border-2 h-4 w-4', size === 'small' && 'border-4 h-8 w-8', size === 'big' && 'border-8 h-28 w-28', color), role: "status" }) })));
|
|
2096
|
-
|
|
2097
|
-
const SubmitButton$1 = JSX(({ isLoading, disabled, children, className, ...rest }) => (jsxs(Button, { type: "submit", className: style('relative', className), disabled: isLoading || disabled, ...rest, children: [isLoading ? jsx(Loader, { blur: true, size: "small" }) : null, children] })));
|
|
2098
|
-
|
|
2099
|
-
const SVG = JSX(({ className, viewBox, fill = 'none', width, height, paths, ...commonOptions }) => {
|
|
2100
|
-
return (jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: className, viewBox: viewBox, fill: fill, width: width, height: height, children: paths.map(({ d, fill: pathFill, ...options }, i) => {
|
|
2101
|
-
const resultOptions = { ...commonOptions, ...options };
|
|
2102
|
-
return (jsx("path", { d: d, fill: pathFill || 'currentColor', stroke: resultOptions.stroke, strokeLinecap: resultOptions.strokeLinecap, strokeLinejoin: resultOptions.strokeLinejoin, strokeWidth: resultOptions.strokeWidth, strokeMiterlimit: resultOptions.strokeMiterlimit }, i));
|
|
2103
|
-
}) }));
|
|
2104
|
-
});
|
|
2105
|
-
|
|
2106
|
-
const defaultCheckStyle = 'appearance-none w-5 h-5 border-solid flex-none';
|
|
2107
|
-
|
|
2108
|
-
const CHECK_PATHS = [
|
|
2109
|
-
{
|
|
2110
|
-
d: 'M10.207.793a1 1 0 0 1 0 1.414l-6 6a1 1 0 0 1-1.414 0l-2.5-2.5a1 1 0 0 1 1.414-1.414L3.5 6.086 8.793.793a1 1 0 0 1 1.414 0Z',
|
|
2111
|
-
fillRule: 'evenodd',
|
|
2112
|
-
clipRule: 'evenodd',
|
|
2113
|
-
fill: 'white',
|
|
2114
|
-
},
|
|
2115
|
-
];
|
|
2116
|
-
const Checkbox = JSX(({ className, value, text, disabled, isRadio, onChange, name }) => {
|
|
2117
|
-
const handleChange = useCallback((e) => {
|
|
2118
|
-
if (disabled) {
|
|
2119
|
-
return;
|
|
2120
|
-
}
|
|
2121
|
-
e.preventDefault();
|
|
2122
|
-
onChange && onChange(!value);
|
|
2123
|
-
}, [onChange, disabled, value]);
|
|
2124
|
-
const icon = isRadio ? (jsx("div", { className: "absolute left-1 w-3 h-3 rounded-full bg-primary-main" })) : (jsx(SVG, { paths: CHECK_PATHS, className: "absolute left-1 ml-px block", width: "11", height: "9", fill: "white", viewBox: "0 0 11 9" }));
|
|
2125
|
-
return (jsx("div", { className: className, children: jsxs("label", { className: style('flex items-center relative group/box', getCursorStyle(disabled)), "data-test-id": name, onClick: handleChange, children: [jsx("div", { className: style(defaultCheckStyle, 'm-0', isRadio ? 'rounded-full border-2' : checkboxStyle(value), !disabled && value ? 'border-primary-main' : 'border-gray', disabled ? 'bg-main-disabled' : 'group-hover/box:border-primary-hover'), role: role(isRadio), "aria-checked": Boolean(value), "aria-disabled": Boolean(disabled), "aria-label": text }), value ? icon : null, renderText$3(text)] }) }));
|
|
2126
|
-
});
|
|
2127
|
-
const renderText$3 = (text) => text ? (jsx("div", { className: "ml-s", children: jsx(Text, { size: "text-l", font: "font-light", children: text }) })) : null;
|
|
2128
|
-
const getCursorStyle = (disabled = false) => (disabled ? 'cursor-not-allowed' : 'cursor-pointer');
|
|
2129
|
-
const role = (isRadio = false) => (isRadio ? 'radio' : 'checkbox');
|
|
2130
|
-
const checkboxStyle = (value = false) => style('rounded border', { 'bg-primary-main': value });
|
|
2131
|
-
|
|
2132
2451
|
const withValidator = (props, validator) => {
|
|
2133
2452
|
const { value, isDirty } = props;
|
|
2134
2453
|
const errors = isDirty ? validator(value) : [];
|
|
@@ -3347,12 +3666,6 @@
|
|
|
3347
3666
|
|
|
3348
3667
|
const UltraPremiumField = JSX(({ field, input }) => (jsx(SelectControl, { label: "\u0422\u0438\u043F \u043E\u0431\u0441\u043B\u0443\u0436\u0438\u0432\u0430\u043D\u0438\u044F", options: SERVICE_TYPES, ...field(input?.name ?? ''), ...input })));
|
|
3349
3668
|
|
|
3350
|
-
const orientationStyleMap = {
|
|
3351
|
-
horizontal: '@lg:flex-row',
|
|
3352
|
-
vertical: '',
|
|
3353
|
-
};
|
|
3354
|
-
const RadioButtonGroup = JSX(({ label, items, value, className, disabled = false, orientation = 'horizontal', onChange: onChangeCheckedItem, }) => (jsxs("div", { className: "grid gap-xs whitespace-nowrap", children: [label ? (jsx("div", { role: "radiogroup", "aria-label": label, children: jsx(Text, { color: "text-secondary-text", font: "font-light", children: label }) })) : null, jsx("div", { className: style('flex flex-col gap-s', orientationStyleMap[orientation], className), role: "radiogroup", "aria-label": "\u0413\u0440\u0443\u043F\u043F\u0430 \u043A\u043D\u043E\u043F\u043E\u043A", children: items?.map(({ id, text }) => (jsx(Checkbox, { isRadio: true, text: text, value: value === id, onChange: () => onChangeCheckedItem?.(id, text), disabled: disabled, name: id }, String(id)))) })] })));
|
|
3355
|
-
|
|
3356
3669
|
const VedField = JSX(({ field, input }) => {
|
|
3357
3670
|
const handleChange = useCallback((_) => {
|
|
3358
3671
|
if (_ !== 'currencyControl') {
|
|
@@ -3602,246 +3915,104 @@
|
|
|
3602
3915
|
};
|
|
3603
3916
|
};
|
|
3604
3917
|
|
|
3605
|
-
const API = LeadServiceAPI();
|
|
3606
|
-
const CODE_LENGTH$1 = 4;
|
|
3607
|
-
const TIME_TO_RESEND$1 = 180;
|
|
3608
|
-
const VerifyPhoneDialog$1 = JSX(({ phone, onSuccess = noop, onClose = noop, formatData = {}, reqId }) => {
|
|
3609
|
-
const [values, setValues] = useState(Array(CODE_LENGTH$1).fill(''));
|
|
3610
|
-
const [requestId, setRequestId] = useState(reqId);
|
|
3611
|
-
const { handleSubmit, hasError, errorText, isLoading, timeNextReq, isSubmitButtonDisabled, setTimeNextReq, setErrorText, } = useVerifyPhoneDialogSubmit$1({
|
|
3612
|
-
values,
|
|
3613
|
-
onSuccess,
|
|
3614
|
-
formatData,
|
|
3615
|
-
reqId: requestId ?? '',
|
|
3616
|
-
});
|
|
3617
|
-
const phoneNumber = formatPhone(phone);
|
|
3618
|
-
const restartTimer = useCountDownTimer({ seconds: timeNextReq, onTick: setTimeNextReq });
|
|
3619
|
-
const handleSendCode = useCallback(async () => {
|
|
3620
|
-
const response = await API.sendCode({ phone: phoneNumber });
|
|
3621
|
-
if (response) {
|
|
3622
|
-
setTimeNextReq(TIME_TO_RESEND$1);
|
|
3623
|
-
restartTimer(TIME_TO_RESEND$1);
|
|
3624
|
-
setErrorText('');
|
|
3625
|
-
setRequestId(String(response));
|
|
3626
|
-
}
|
|
3627
|
-
}, [phoneNumber, restartTimer, onClose]);
|
|
3628
|
-
return (jsx(VerifyPhoneDialogLayout, { isSubmitButtonDisabled: isSubmitButtonDisabled, onSubmit: handleSubmit, onSendCode: handleSendCode, timeNextReq: timeNextReq, values: values, onChange: setValues, phone: phone, isLoading: isLoading, errorText: errorText, hasError: hasError, onClose: onClose }));
|
|
3629
|
-
});
|
|
3630
|
-
|
|
3631
|
-
const handlerMap = {
|
|
3632
|
-
initcorporatelead: handleInitCorporateLead,
|
|
3633
|
-
callback: handleCallback,
|
|
3634
|
-
default: handleDefault,
|
|
3635
|
-
};
|
|
3636
|
-
const ApplicationForm = UniBlock(
|
|
3637
|
-
// eslint-disable-next-line max-lines-per-function
|
|
3638
|
-
({ className, title, typeForm = '', sections = [], button, link, endpoint, additionalParams, withSnowplow, isContacts, data, onSuccess, ...rest }) => {
|
|
3639
|
-
const inputs = useMemo(() => (sections?.flatMap((_) => _?.inputs) || []), [sections]);
|
|
3640
|
-
const initialFormState = useMemo(() => getInitialFormState$2(inputs, typeForm), [inputs, typeForm]);
|
|
3641
|
-
const router = useRouter();
|
|
3642
|
-
const aspects = useAspects();
|
|
3643
|
-
const formValidator = useMemo(() => getFormValidator(inputs), [inputs]);
|
|
3644
|
-
const responseTypeDialog = useDialog(ResponseTypeDialog);
|
|
3645
|
-
const verifyPhoneDialog = useDialog(VerifyPhoneDialog$1);
|
|
3646
|
-
const handleSubmit = useCallback(async (formData, ev) => {
|
|
3647
|
-
const formatData = getFormatData({ ...formData, ...additionalParams });
|
|
3648
|
-
await executeHandler({
|
|
3649
|
-
formatData,
|
|
3650
|
-
ev,
|
|
3651
|
-
typeForm,
|
|
3652
|
-
data,
|
|
3653
|
-
aspects,
|
|
3654
|
-
router,
|
|
3655
|
-
responseTypeDialog,
|
|
3656
|
-
verifyPhoneDialog,
|
|
3657
|
-
onSuccess,
|
|
3658
|
-
withSnowplow,
|
|
3659
|
-
}, endpoint);
|
|
3660
|
-
}, [typeForm]);
|
|
3661
|
-
const [, { field, onSubmit }] = useForm(initialFormState, {
|
|
3662
|
-
resetOnSubmit: true,
|
|
3663
|
-
formValidator,
|
|
3664
|
-
onSubmit: handleSubmit,
|
|
3665
|
-
});
|
|
3666
|
-
const fieldName = getConsentDataProcessing(inputs)?.name;
|
|
3667
|
-
const consentDataProcessing = fieldName ? field('consentDataProcessing') : undefined;
|
|
3668
|
-
return (jsxs(ApplicationFormLayout, { className: style('container space-y-m', className), title: title, ...rest, children: [jsxs("form", { onSubmit: onSubmit, children: [renderSections(sections, field, { typeForm, additionalParams }), renderAgreementSubmit({
|
|
3669
|
-
consentDataProcessing,
|
|
3670
|
-
link,
|
|
3671
|
-
button,
|
|
3672
|
-
typeForm,
|
|
3673
|
-
})] }), isContacts ? renderContacts() : null] }));
|
|
3674
|
-
});
|
|
3675
|
-
const executeHandler = async (context, endpoint) => {
|
|
3676
|
-
const handler = (endpoint && handlerMap[endpoint]) || handlerMap.default;
|
|
3677
|
-
await handler({ ...context, endpoint });
|
|
3678
|
-
};
|
|
3679
|
-
|
|
3680
|
-
const mapProductTypeToName = {
|
|
3681
|
-
creditCard: 'кредитной карты',
|
|
3682
|
-
debitCard: 'дебетовой карты',
|
|
3683
|
-
credit: 'кредита',
|
|
3684
|
-
};
|
|
3685
|
-
const NoConsentDialog = JSX(({ attempts, productType, onClose = noop }) => {
|
|
3686
|
-
const navigator = locationNavigator();
|
|
3687
|
-
const isMaxAttempts = attempts > 1;
|
|
3688
|
-
const returnToMainPage = useCallback(() => {
|
|
3689
|
-
navigator.assign('/natural');
|
|
3690
|
-
}, []);
|
|
3691
|
-
const handleClose = useCallback(() => {
|
|
3692
|
-
if (isMaxAttempts) {
|
|
3693
|
-
returnToMainPage();
|
|
3694
|
-
}
|
|
3695
|
-
else {
|
|
3696
|
-
onClose();
|
|
3697
|
-
}
|
|
3698
|
-
}, [isMaxAttempts]);
|
|
3699
|
-
return (jsx(Dialog, { onClose: handleClose, children: jsxs("div", { className: "flex flex-col gap-xl items-center", children: [jsx(Paragraph, { align: "text-center", children: "\u0423\u0432\u0430\u0436\u0430\u0435\u043C\u044B\u0439 \u043A\u043B\u0438\u0435\u043D\u0442!" }), jsx(Paragraph, { align: "text-center", children: `Для получения ${mapProductTypeToName[productType]} Вам необходимо обратиться в офис Банка` }), jsxs("div", { className: "flex flex-col sm:flex-row gap-xl items-center", children: [jsx(Button, { type: "button", version: "secondary", onClick: returnToMainPage, children: "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C" }), isMaxAttempts ? null : (jsx(Button, { type: "button", onClick: onClose, children: "\u041F\u0440\u043E\u0434\u043E\u043B\u0436\u0438\u0442\u044C" }))] })] }) }));
|
|
3700
|
-
});
|
|
3701
|
-
|
|
3702
|
-
function copy(source, target) {
|
|
3703
|
-
for (const [k, v] of source.entries()) {
|
|
3704
|
-
if (v !== null && v !== undefined) {
|
|
3705
|
-
target.setItem(k, v);
|
|
3706
|
-
}
|
|
3707
|
-
else {
|
|
3708
|
-
target.removeItem(k);
|
|
3709
|
-
}
|
|
3710
|
-
}
|
|
3711
|
-
}
|
|
3712
|
-
|
|
3713
|
-
function replicate(primary, secondary) {
|
|
3714
|
-
copy(primary, secondary);
|
|
3715
|
-
copy(secondary, primary);
|
|
3716
|
-
return primary.bus.watch(({ type, event }) => {
|
|
3717
|
-
if (event !== null && event !== undefined) {
|
|
3718
|
-
secondary.setItem(type, event);
|
|
3719
|
-
}
|
|
3720
|
-
else {
|
|
3721
|
-
secondary.removeItem(type);
|
|
3722
|
-
}
|
|
3723
|
-
});
|
|
3724
|
-
}
|
|
3725
|
-
|
|
3726
|
-
class StorageAdapter {
|
|
3727
|
-
storage;
|
|
3728
|
-
bus;
|
|
3729
|
-
get size() {
|
|
3730
|
-
return this.storage?.length ?? 0;
|
|
3731
|
-
}
|
|
3732
|
-
constructor(storage, bus = new EventBus()) {
|
|
3733
|
-
this.storage = storage;
|
|
3734
|
-
this.bus = bus;
|
|
3735
|
-
}
|
|
3736
|
-
hasItem(key) {
|
|
3737
|
-
return Boolean(this.storage?.getItem(String(key)));
|
|
3738
|
-
}
|
|
3739
|
-
getItem(key) {
|
|
3740
|
-
const _ = this.storage?.getItem(String(key)) ?? null;
|
|
3741
|
-
try {
|
|
3742
|
-
return JSON.parse(String(_));
|
|
3743
|
-
}
|
|
3744
|
-
catch (ex) {
|
|
3745
|
-
return null;
|
|
3746
|
-
}
|
|
3747
|
-
}
|
|
3748
|
-
entries() {
|
|
3749
|
-
return Array.from({ length: this.size }, (_, i) => {
|
|
3750
|
-
const k = String(this.storage?.key(i));
|
|
3751
|
-
return [k, this.getItem(k)];
|
|
3752
|
-
});
|
|
3753
|
-
}
|
|
3754
|
-
setItem(key, value) {
|
|
3755
|
-
if (value !== null) {
|
|
3756
|
-
this.storage?.setItem(String(key), JSON.stringify(value));
|
|
3757
|
-
}
|
|
3758
|
-
else {
|
|
3759
|
-
this.storage?.removeItem(String(key));
|
|
3760
|
-
}
|
|
3761
|
-
this.bus?.subject(key, value);
|
|
3762
|
-
}
|
|
3763
|
-
removeItem(key) {
|
|
3764
|
-
this.storage?.removeItem(String(key));
|
|
3765
|
-
this.bus?.subject(key, null);
|
|
3766
|
-
}
|
|
3767
|
-
}
|
|
3768
|
-
|
|
3769
|
-
class Store {
|
|
3770
|
-
bus;
|
|
3771
|
-
store = new Map();
|
|
3772
|
-
get size() {
|
|
3773
|
-
return this.store.size;
|
|
3774
|
-
}
|
|
3775
|
-
constructor(bus = new EventBus()) {
|
|
3776
|
-
this.bus = bus;
|
|
3777
|
-
}
|
|
3778
|
-
hasItem(key) {
|
|
3779
|
-
return this.store.has(key);
|
|
3780
|
-
}
|
|
3781
|
-
getItem(key) {
|
|
3782
|
-
return this.store.get(key);
|
|
3783
|
-
}
|
|
3784
|
-
entries() {
|
|
3785
|
-
return this.store.entries();
|
|
3786
|
-
}
|
|
3787
|
-
setItem(key, value) {
|
|
3788
|
-
this.store.set(key, value);
|
|
3789
|
-
this.bus.subject(key, value);
|
|
3790
|
-
}
|
|
3791
|
-
removeItem(key) {
|
|
3792
|
-
this.store.delete(key);
|
|
3793
|
-
this.bus.subject(key, null);
|
|
3794
|
-
}
|
|
3795
|
-
}
|
|
3796
|
-
|
|
3797
|
-
function useRerender() {
|
|
3798
|
-
const [, setCount] = useState(0);
|
|
3799
|
-
return useCallback(() => setCount(_ => (_ + 1) % (1 << 16)), []);
|
|
3800
|
-
}
|
|
3918
|
+
const API = LeadServiceAPI();
|
|
3919
|
+
const CODE_LENGTH$1 = 4;
|
|
3920
|
+
const TIME_TO_RESEND$1 = 180;
|
|
3921
|
+
const VerifyPhoneDialog$1 = JSX(({ phone, onSuccess = noop, onClose = noop, formatData = {}, reqId }) => {
|
|
3922
|
+
const [values, setValues] = useState(Array(CODE_LENGTH$1).fill(''));
|
|
3923
|
+
const [requestId, setRequestId] = useState(reqId);
|
|
3924
|
+
const { handleSubmit, hasError, errorText, isLoading, timeNextReq, isSubmitButtonDisabled, setTimeNextReq, setErrorText, } = useVerifyPhoneDialogSubmit$1({
|
|
3925
|
+
values,
|
|
3926
|
+
onSuccess,
|
|
3927
|
+
formatData,
|
|
3928
|
+
reqId: requestId ?? '',
|
|
3929
|
+
});
|
|
3930
|
+
const phoneNumber = formatPhone(phone);
|
|
3931
|
+
const restartTimer = useCountDownTimer({ seconds: timeNextReq, onTick: setTimeNextReq });
|
|
3932
|
+
const handleSendCode = useCallback(async () => {
|
|
3933
|
+
const response = await API.sendCode({ phone: phoneNumber });
|
|
3934
|
+
if (response) {
|
|
3935
|
+
setTimeNextReq(TIME_TO_RESEND$1);
|
|
3936
|
+
restartTimer(TIME_TO_RESEND$1);
|
|
3937
|
+
setErrorText('');
|
|
3938
|
+
setRequestId(String(response));
|
|
3939
|
+
}
|
|
3940
|
+
}, [phoneNumber, restartTimer, onClose]);
|
|
3941
|
+
return (jsx(VerifyPhoneDialogLayout, { isSubmitButtonDisabled: isSubmitButtonDisabled, onSubmit: handleSubmit, onSendCode: handleSendCode, timeNextReq: timeNextReq, values: values, onChange: setValues, phone: phone, isLoading: isLoading, errorText: errorText, hasError: hasError, onClose: onClose }));
|
|
3942
|
+
});
|
|
3801
3943
|
|
|
3802
|
-
const
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
const
|
|
3812
|
-
const
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
},
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3944
|
+
const handlerMap = {
|
|
3945
|
+
initcorporatelead: handleInitCorporateLead,
|
|
3946
|
+
callback: handleCallback,
|
|
3947
|
+
default: handleDefault,
|
|
3948
|
+
};
|
|
3949
|
+
const ApplicationForm = UniBlock(
|
|
3950
|
+
// eslint-disable-next-line max-lines-per-function
|
|
3951
|
+
({ className, title, typeForm = '', sections = [], button, link, endpoint, additionalParams, withSnowplow, isContacts, data, onSuccess, ...rest }) => {
|
|
3952
|
+
const inputs = useMemo(() => (sections?.flatMap((_) => _?.inputs) || []), [sections]);
|
|
3953
|
+
const initialFormState = useMemo(() => getInitialFormState$2(inputs, typeForm), [inputs, typeForm]);
|
|
3954
|
+
const router = useRouter();
|
|
3955
|
+
const aspects = useAspects();
|
|
3956
|
+
const formValidator = useMemo(() => getFormValidator(inputs), [inputs]);
|
|
3957
|
+
const responseTypeDialog = useDialog(ResponseTypeDialog);
|
|
3958
|
+
const verifyPhoneDialog = useDialog(VerifyPhoneDialog$1);
|
|
3959
|
+
const openUserSurvey = useUserSurveyDialog(true);
|
|
3960
|
+
const handleSubmit = useCallback(async (formData, ev) => {
|
|
3961
|
+
const formatData = getFormatData({ ...formData, ...additionalParams });
|
|
3962
|
+
await executeHandler({
|
|
3963
|
+
formatData,
|
|
3964
|
+
ev,
|
|
3965
|
+
typeForm,
|
|
3966
|
+
data,
|
|
3967
|
+
aspects,
|
|
3968
|
+
router,
|
|
3969
|
+
responseTypeDialog,
|
|
3970
|
+
verifyPhoneDialog,
|
|
3971
|
+
onSuccess,
|
|
3972
|
+
withSnowplow,
|
|
3973
|
+
openUserSurvey,
|
|
3974
|
+
}, endpoint);
|
|
3975
|
+
}, [typeForm]);
|
|
3976
|
+
const [, { field, onSubmit }] = useForm(initialFormState, {
|
|
3977
|
+
resetOnSubmit: true,
|
|
3978
|
+
formValidator,
|
|
3979
|
+
onSubmit: handleSubmit,
|
|
3980
|
+
});
|
|
3981
|
+
const fieldName = getConsentDataProcessing(inputs)?.name;
|
|
3982
|
+
const consentDataProcessing = fieldName ? field('consentDataProcessing') : undefined;
|
|
3983
|
+
return (jsxs(ApplicationFormLayout, { className: style('container space-y-m', className), title: title, ...rest, children: [jsxs("form", { onSubmit: onSubmit, children: [renderSections(sections, field, { typeForm, additionalParams }), renderAgreementSubmit({
|
|
3984
|
+
consentDataProcessing,
|
|
3985
|
+
link,
|
|
3986
|
+
button,
|
|
3987
|
+
typeForm,
|
|
3988
|
+
})] }), isContacts ? renderContacts() : null] }));
|
|
3989
|
+
});
|
|
3990
|
+
const executeHandler = async (context, endpoint) => {
|
|
3991
|
+
const handler = (endpoint && handlerMap[endpoint]) || handlerMap.default;
|
|
3992
|
+
await handler({ ...context, endpoint });
|
|
3993
|
+
};
|
|
3839
3994
|
|
|
3840
|
-
const
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
}
|
|
3995
|
+
const mapProductTypeToName = {
|
|
3996
|
+
creditCard: 'кредитной карты',
|
|
3997
|
+
debitCard: 'дебетовой карты',
|
|
3998
|
+
credit: 'кредита',
|
|
3999
|
+
};
|
|
4000
|
+
const NoConsentDialog = JSX(({ attempts, productType, onClose = noop }) => {
|
|
4001
|
+
const navigator = locationNavigator();
|
|
4002
|
+
const isMaxAttempts = attempts > 1;
|
|
4003
|
+
const returnToMainPage = useCallback(() => {
|
|
4004
|
+
navigator.assign('/natural');
|
|
4005
|
+
}, []);
|
|
4006
|
+
const handleClose = useCallback(() => {
|
|
4007
|
+
if (isMaxAttempts) {
|
|
4008
|
+
returnToMainPage();
|
|
4009
|
+
}
|
|
4010
|
+
else {
|
|
4011
|
+
onClose();
|
|
4012
|
+
}
|
|
4013
|
+
}, [isMaxAttempts]);
|
|
4014
|
+
return (jsx(Dialog, { onClose: handleClose, children: jsxs("div", { className: "flex flex-col gap-xl items-center", children: [jsx(Paragraph, { align: "text-center", children: "\u0423\u0432\u0430\u0436\u0430\u0435\u043C\u044B\u0439 \u043A\u043B\u0438\u0435\u043D\u0442!" }), jsx(Paragraph, { align: "text-center", children: `Для получения ${mapProductTypeToName[productType]} Вам необходимо обратиться в офис Банка` }), jsxs("div", { className: "flex flex-col sm:flex-row gap-xl items-center", children: [jsx(Button, { type: "button", version: "secondary", onClick: returnToMainPage, children: "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C" }), isMaxAttempts ? null : (jsx(Button, { type: "button", onClick: onClose, children: "\u041F\u0440\u043E\u0434\u043E\u043B\u0436\u0438\u0442\u044C" }))] })] }) }));
|
|
4015
|
+
});
|
|
3845
4016
|
|
|
3846
4017
|
const getNS = (_) => globalThis[_];
|
|
3847
4018
|
const initializeExternalNS = (namespaceName, url, isModule = false) => {
|
|
@@ -5158,12 +5329,6 @@
|
|
|
5158
5329
|
return result || [];
|
|
5159
5330
|
};
|
|
5160
5331
|
|
|
5161
|
-
const localStore = new Store(); // localStorage cache
|
|
5162
|
-
replicate(localStore, new StorageAdapter(globalThis?.localStorage));
|
|
5163
|
-
function useLocalStore(methods) {
|
|
5164
|
-
return useStore(localStore, methods);
|
|
5165
|
-
}
|
|
5166
|
-
|
|
5167
5332
|
const useRetailFormStore = () => {
|
|
5168
5333
|
return useLocalStore();
|
|
5169
5334
|
};
|
|
@@ -11048,7 +11213,7 @@
|
|
|
11048
11213
|
DELIVERY_CREDIT_CARD_CONTENT,
|
|
11049
11214
|
];
|
|
11050
11215
|
|
|
11051
|
-
const STEPS$
|
|
11216
|
+
const STEPS$2 = 6;
|
|
11052
11217
|
const TITLES = [
|
|
11053
11218
|
'Параметры карты',
|
|
11054
11219
|
'Персональные данные',
|
|
@@ -11063,7 +11228,7 @@
|
|
|
11063
11228
|
const scrollToTop = useCallback(() => formContainerRef?.current?.scrollIntoView({ behavior: 'smooth' }), [formContainerRef]);
|
|
11064
11229
|
useEffect(updateRefreshToken, []);
|
|
11065
11230
|
const handleNextStep = useCallback(() => {
|
|
11066
|
-
setStep((_) => Math.min(_ + 1, STEPS$
|
|
11231
|
+
setStep((_) => Math.min(_ + 1, STEPS$2));
|
|
11067
11232
|
scrollToTop();
|
|
11068
11233
|
}, []);
|
|
11069
11234
|
const handlePrevStep = useCallback(() => {
|
|
@@ -11073,7 +11238,7 @@
|
|
|
11073
11238
|
}, []);
|
|
11074
11239
|
const sections = stepsSectionsMap$2[step];
|
|
11075
11240
|
const [isFormFinished, { setTrue: handleFinish }] = useBool(false);
|
|
11076
|
-
return (jsx(BlockWrapper, { className: className, ...rest, children: jsxs("div", { ref: formContainerRef, className: "container grid grid-cols-12", children: [isFormFinished ? null : (jsx(CreditCardFormProgress, { stepsTitles: TITLES, step: step, totalSteps: STEPS$
|
|
11241
|
+
return (jsx(BlockWrapper, { className: className, ...rest, children: jsxs("div", { ref: formContainerRef, className: "container grid grid-cols-12", children: [isFormFinished ? null : (jsx(CreditCardFormProgress, { stepsTitles: TITLES, step: step, totalSteps: STEPS$2 })), jsx("div", { className: "py-lg px-5xl mt-2xs bg-white col-span-12", children: isFormFinished ? (jsx(CreditCardFormStatusTracker, {})) : (jsx(CreditCardFormStep, { step: step, sections: sections, onNextStep: handleNextStep, onPrevStep: handlePrevStep, onFinish: handleFinish }, String(step))) })] }) }));
|
|
11077
11242
|
});
|
|
11078
11243
|
|
|
11079
11244
|
const CreditFormProgress = JSX(({ step = 1, totalSteps = 5, stepsTitles = [] }) => {
|
|
@@ -11634,7 +11799,7 @@
|
|
|
11634
11799
|
DELIVERY_CREDIT_CONTENT,
|
|
11635
11800
|
];
|
|
11636
11801
|
|
|
11637
|
-
const STEPS$
|
|
11802
|
+
const STEPS$1 = 4;
|
|
11638
11803
|
const STEP_TITLES$1 = [
|
|
11639
11804
|
'',
|
|
11640
11805
|
'Персональные данные',
|
|
@@ -11648,7 +11813,7 @@
|
|
|
11648
11813
|
const scrollToTop = useCallback(() => formContainerRef?.current?.scrollIntoView({ behavior: 'smooth' }), [formContainerRef]);
|
|
11649
11814
|
useEffect(updateRefreshToken, []);
|
|
11650
11815
|
const handleNextStep = useCallback(() => {
|
|
11651
|
-
setStep((_) => Math.min(_ + 1, STEPS$
|
|
11816
|
+
setStep((_) => Math.min(_ + 1, STEPS$1));
|
|
11652
11817
|
scrollToTop();
|
|
11653
11818
|
}, []);
|
|
11654
11819
|
const handlePrevStep = useCallback(() => {
|
|
@@ -11659,7 +11824,7 @@
|
|
|
11659
11824
|
const sections = stepsSectionsMap$1[step];
|
|
11660
11825
|
const isStartStep = step === 0;
|
|
11661
11826
|
const [isFormFinished, { setTrue: handleFinish }] = useBool(false);
|
|
11662
|
-
return (jsx(BlockWrapper, { className: className, ...rest, children: jsxs("div", { ref: formContainerRef, className: "container grid grid-cols-12", children: [isStartStep || isFormFinished ? null : (jsx(CreditFormProgress, { stepsTitles: STEP_TITLES$1, step: step, totalSteps: STEPS$
|
|
11827
|
+
return (jsx(BlockWrapper, { className: className, ...rest, children: jsxs("div", { ref: formContainerRef, className: "container grid grid-cols-12", children: [isStartStep || isFormFinished ? null : (jsx(CreditFormProgress, { stepsTitles: STEP_TITLES$1, step: step, totalSteps: STEPS$1 })), jsx("div", { className: "py-lg px-5xl mt-2xs bg-white col-span-12", children: isFormFinished ? (jsx(CreditFormStatusTracker, {})) : (jsx(CreditFormStep, { step: step, sections: sections, programsSource: programsSource, onNextStep: handleNextStep, onPrevStep: handlePrevStep, onFinish: handleFinish }, String(step))) })] }) }));
|
|
11663
11828
|
});
|
|
11664
11829
|
|
|
11665
11830
|
const DebitFormProgress = JSX(({ step = 1, totalSteps = 2, stepsTitles = [] }) => {
|
|
@@ -12206,7 +12371,7 @@
|
|
|
12206
12371
|
DEBIT_CARD_CONTENT,
|
|
12207
12372
|
];
|
|
12208
12373
|
|
|
12209
|
-
const STEPS
|
|
12374
|
+
const STEPS = 2;
|
|
12210
12375
|
const STEP_TITLES = ['', 'Персональные данные', 'Платежная система'];
|
|
12211
12376
|
const DebitForm = UniBlock(({ className, ...rest }) => {
|
|
12212
12377
|
const [step, setStep] = useState(0);
|
|
@@ -12214,7 +12379,7 @@
|
|
|
12214
12379
|
const scrollToTop = useCallback(() => formContainerRef?.current?.scrollIntoView({ behavior: 'smooth' }), [formContainerRef]);
|
|
12215
12380
|
useEffect(updateRefreshToken, []);
|
|
12216
12381
|
const handleNextStep = useCallback(() => {
|
|
12217
|
-
setStep((_) => Math.min(_ + 1, STEPS
|
|
12382
|
+
setStep((_) => Math.min(_ + 1, STEPS));
|
|
12218
12383
|
scrollToTop();
|
|
12219
12384
|
}, []);
|
|
12220
12385
|
const handlePrevStep = useCallback(() => {
|
|
@@ -12229,7 +12394,7 @@
|
|
|
12229
12394
|
setIsFormFinished();
|
|
12230
12395
|
scrollToTop();
|
|
12231
12396
|
}, []);
|
|
12232
|
-
return (jsx(BlockWrapper, { className: className, ...rest, children: jsxs("div", { ref: formContainerRef, className: "container grid grid-cols-12", children: [isStartStep || isFormFinished ? null : (jsx(DebitFormProgress, { stepsTitles: STEP_TITLES, step: step, totalSteps: STEPS
|
|
12397
|
+
return (jsx(BlockWrapper, { className: className, ...rest, children: jsxs("div", { ref: formContainerRef, className: "container grid grid-cols-12", children: [isStartStep || isFormFinished ? null : (jsx(DebitFormProgress, { stepsTitles: STEP_TITLES, step: step, totalSteps: STEPS })), jsx("div", { className: "py-lg px-5xl mt-2xs bg-white col-span-12", children: isFormFinished ? (jsx(DebitFormStatusTracker, {})) : (jsx(DebitFormStep, { step: step, sections: sections, onNextStep: handleNextStep, onPrevStep: handlePrevStep, onFinish: handleFinish }, String(step))) })] }) }));
|
|
12233
12398
|
});
|
|
12234
12399
|
|
|
12235
12400
|
const isRateRow = (rateRow) => typeof rateRow?.minMonths === 'number' && typeof rateRow?.maxMonths === 'number';
|
|
@@ -13087,9 +13252,7 @@
|
|
|
13087
13252
|
const handleChatClick = useCallback((ev) => {
|
|
13088
13253
|
const openChatBot = aspects[CHAT_BOT_ASPECT_NAME];
|
|
13089
13254
|
if (openChatBot && ev) {
|
|
13090
|
-
|
|
13091
|
-
openChatBot(ev).finally();
|
|
13092
|
-
}
|
|
13255
|
+
openChatBot(ev).finally();
|
|
13093
13256
|
}
|
|
13094
13257
|
}, []);
|
|
13095
13258
|
return {
|
|
@@ -14174,128 +14337,6 @@
|
|
|
14174
14337
|
}, role: "dialog", title: "\u0412\u0441\u043F\u043B\u044B\u0432\u0430\u044E\u0449\u0435\u0435 \u043E\u043A\u043D\u043E", children: popup.popup })) : null;
|
|
14175
14338
|
});
|
|
14176
14339
|
|
|
14177
|
-
const sendUserSurvey = async (body) => {
|
|
14178
|
-
try {
|
|
14179
|
-
const response = await LeadServiceFetch(`${API_BASE_URI}/survey`, body);
|
|
14180
|
-
return await response;
|
|
14181
|
-
}
|
|
14182
|
-
catch (e) {
|
|
14183
|
-
return null;
|
|
14184
|
-
}
|
|
14185
|
-
};
|
|
14186
|
-
|
|
14187
|
-
const FinalStep = JSX(() => {
|
|
14188
|
-
return (jsxs("div", { className: "flex flex-col items-center", children: [jsx(Heading, { className: "text-center", headingType: "h5", title: "\u0421\u043F\u0430\u0441\u0438\u0431\u043E \u0437\u0430 \u0443\u0447\u0430\u0441\u0442\u0438\u0435!" }), jsx(Paragraph, { children: "\u0412\u0430\u0448\u0435 \u043C\u043D\u0435\u043D\u0438\u0435 \u043E\u0447\u0435\u043D\u044C \u0432\u0430\u0436\u043D\u043E \u0434\u043B\u044F \u043D\u0430\u0441" })] }));
|
|
14189
|
-
});
|
|
14190
|
-
|
|
14191
|
-
const Star = JSX(({ value, hover, rating, setHover, setRating }) => {
|
|
14192
|
-
const fillColor = value <= (hover || rating) ? '#42AB44' : '#C9CACC';
|
|
14193
|
-
return (jsx("div", { onClick: () => setRating?.(value), onMouseEnter: () => setHover?.(value), onMouseLeave: () => setHover?.(null), children: jsx("svg", { "data-rating": value, fill: fillColor, width: "57", height: "57", viewBox: "0 0 57 57", children: jsx("path", { d: "M47.7803 18.2879L47.7836 18.2884C50.566 18.7521 53.0867 20.1374 53.9176 22.7226C54.7498 25.3116 53.5025 27.9027 51.4977 29.8954L51.4942 29.8989L45.7132 35.6799C45.5729 35.8202 45.3591 36.1532 45.2186 36.6438C45.0796 37.1295 45.0808 37.5314 45.1257 37.7381L45.1268 37.743L46.78 44.8909C47.4787 47.9228 47.3175 51.2217 44.8924 52.9896C42.4714 54.7546 39.2808 53.9093 36.5999 52.3257L29.6214 48.1946C29.4392 48.0866 29.0426 47.96 28.5087 47.96C27.9816 47.96 27.5736 48.0831 27.3687 48.2004L27.3634 48.2035L20.4041 52.3232L20.4019 52.3246C17.7218 53.9145 14.5351 54.7459 12.1155 52.9803C9.69339 51.213 9.51826 47.9236 10.22 44.8909L11.8731 37.743L11.8743 37.7379C11.9191 37.5311 11.9203 37.1293 11.7813 36.6438C11.6409 36.1532 11.4271 35.8202 11.2867 35.6799L5.50006 29.8932C3.50738 27.9006 2.26429 25.3118 3.08972 22.7269C3.91586 20.1398 6.43161 18.7525 9.21638 18.2884L16.6527 17.0529L16.6552 17.0525C16.8169 17.0243 17.1619 16.8935 17.5523 16.604C17.945 16.3128 18.1668 16.022 18.2378 15.877L18.2462 15.8598L22.3508 7.65087L22.352 7.6485C23.629 5.08222 25.7146 3.01416 28.4796 3.01416C31.2412 3.01416 33.3328 5.07832 34.6215 7.64213L34.6236 7.64649L38.7303 15.8598L38.75 15.9001C38.7884 15.9807 38.8225 16.0591 38.8511 16.1283C38.9197 16.1891 39.0148 16.2702 39.1464 16.3781C39.1829 16.394 39.242 16.4185 39.3288 16.4505C39.5779 16.5424 39.9286 16.6512 40.3732 16.7719C41.2573 17.0121 42.3688 17.2611 43.4823 17.4894C44.5886 17.7163 45.6648 17.9163 46.4667 18.0598C46.8669 18.1315 47.1972 18.1888 47.4266 18.2281L47.6909 18.2729L47.7589 18.2843L47.7803 18.2879Z" }) }) }));
|
|
14194
|
-
});
|
|
14195
|
-
|
|
14196
|
-
const stars$1 = new Array(5).fill(Star);
|
|
14197
|
-
const TITLE$1 = {
|
|
14198
|
-
NPS: 'Оцените, пожалуйста, от 1 до 5 насколько вероятно, что вы порекомендуете Россельхозбанк коллегам, друзьям и знакомым?',
|
|
14199
|
-
CSI: 'Оцените, пожалуйста, удовлетворённость пользования сайтом',
|
|
14200
|
-
};
|
|
14201
|
-
const FirstStep = JSX(({ currentRating, surveyType, isSending, setCurrentRating, onNextStep, onSubmit }) => {
|
|
14202
|
-
const [currentHover, setCurrentHover] = useState();
|
|
14203
|
-
const setRatingFn = (value) => {
|
|
14204
|
-
setCurrentRating(value);
|
|
14205
|
-
if (value < 5) {
|
|
14206
|
-
onNextStep();
|
|
14207
|
-
}
|
|
14208
|
-
};
|
|
14209
|
-
return (jsxs("div", { className: "flex flex-col gap-xl items-center", children: [jsx(Heading, { className: "text-center", headingType: "h5", title: TITLE$1[surveyType] }), jsx("div", { className: "flex justify-center", children: stars$1.map((StarItem, index) => (jsx(StarItem, { value: index + 1, rating: currentRating, hover: currentHover, setRating: setRatingFn, setHover: setCurrentHover, className: "modal-feedback__star" }, index))) }), currentRating === 5 ? (jsx(SubmitButton$1, { onClick: () => onSubmit(), isLoading: isSending, children: "\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C" })) : null] }));
|
|
14210
|
-
});
|
|
14211
|
-
|
|
14212
|
-
const stars = new Array(5).fill(Star);
|
|
14213
|
-
const TITLE = 'Что бы мы могли улучшить?';
|
|
14214
|
-
const SecondStep = JSX(({ currentRating, currentReason, reasons = [], isSending, setCurrentReason, onSubmit }) => {
|
|
14215
|
-
const [comment, setComment] = useState();
|
|
14216
|
-
const handleReasonChange = (id, text) => {
|
|
14217
|
-
setCurrentReason?.({
|
|
14218
|
-
id,
|
|
14219
|
-
text,
|
|
14220
|
-
});
|
|
14221
|
-
};
|
|
14222
|
-
return (jsxs("div", { className: "flex flex-col gap-xl items-center", children: [jsx(Heading, { className: "text-center", headingType: "h5", title: TITLE }), jsx("div", { className: "flex justify-center", children: stars.map((StarItem, index) => (jsx(StarItem, { value: index + 1, rating: currentRating }, index))) }), jsx(RadioButtonGroup, { className: "w-full text-wrap", orientation: "vertical", items: reasons, value: currentReason?.id, onChange: handleReasonChange }), currentReason?.text === 'Другое' ? (jsx(InputControl, { className: "w-full", placeholder: "\u041D\u0430\u043F\u0438\u0448\u0438\u0442\u0435, \u043F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0441\u0432\u043E\u0439 \u0432\u0430\u0440\u0438\u0430\u043D\u0442 \u043E\u0442\u0432\u0435\u0442\u0430", isTextarea: true, value: comment, onChange: setComment, maxLength: 255 })) : null, currentReason ? (jsx(SubmitButton$1, { onClick: () => onSubmit(comment), isLoading: isSending, children: "\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C" })) : null] }));
|
|
14223
|
-
});
|
|
14224
|
-
|
|
14225
|
-
const STEPS = [FirstStep, SecondStep, FinalStep];
|
|
14226
|
-
const LAST_STEP_INDEX = 2;
|
|
14227
|
-
const UserSurveyDialog = UniBlock(({ onClose = noop, reasonsSource = {} }) => {
|
|
14228
|
-
const [isSending, { setTrue: startSending, setFalse: endSending }] = useBool(false);
|
|
14229
|
-
const [currentRating, setCurrentRating] = useState(0);
|
|
14230
|
-
const [currentReason, setCurrentReason] = useState();
|
|
14231
|
-
const [step, setStep] = useState(0);
|
|
14232
|
-
const userSurveyStore = useLocalStore();
|
|
14233
|
-
const surveyType = userSurveyStore.userSurvey?.lastShownType ?? 'NPS';
|
|
14234
|
-
const { reasons } = reasonsSource;
|
|
14235
|
-
const ActiveStep = STEPS[step];
|
|
14236
|
-
const handleNextStep = useCallback(() => {
|
|
14237
|
-
setStep((_) => _ + 1);
|
|
14238
|
-
}, []);
|
|
14239
|
-
const handleSubmit = useCallback(async (message) => {
|
|
14240
|
-
startSending();
|
|
14241
|
-
await sendUserSurvey({
|
|
14242
|
-
rate: currentRating,
|
|
14243
|
-
reason: currentReason?.text,
|
|
14244
|
-
message: getMessage(currentReason, message),
|
|
14245
|
-
url: globalThis.location.href,
|
|
14246
|
-
type: surveyType,
|
|
14247
|
-
});
|
|
14248
|
-
endSending();
|
|
14249
|
-
setStep(LAST_STEP_INDEX);
|
|
14250
|
-
}, [currentRating, currentReason]);
|
|
14251
|
-
return (jsx(Dialog, { maxWidth: "xl", onClose: onClose, children: jsx(ActiveStep, { currentRating: currentRating, currentReason: currentReason, reasons: reasons, surveyType: surveyType, isSending: isSending, setCurrentReason: setCurrentReason, setCurrentRating: setCurrentRating, onSubmit: handleSubmit, onNextStep: handleNextStep }) }));
|
|
14252
|
-
});
|
|
14253
|
-
const getMessage = (currentReason, message) => {
|
|
14254
|
-
if (currentReason?.text !== 'Другое') {
|
|
14255
|
-
return undefined;
|
|
14256
|
-
}
|
|
14257
|
-
return message?.length ? message : 'Другое. Клиент не оставил комментариев';
|
|
14258
|
-
};
|
|
14259
|
-
|
|
14260
|
-
const DELAY = 5 * 60 * 1000;
|
|
14261
|
-
// Хук отвечает за показ пользователю опроса
|
|
14262
|
-
const useUserSurveyDialog = () => {
|
|
14263
|
-
const userSurveyDialog = useDialog(UserSurveyDialog);
|
|
14264
|
-
const userSurveyStore = useLocalStore();
|
|
14265
|
-
const sessionStore = useSessionStore();
|
|
14266
|
-
const elapsedTime = sessionStore.surveyTimerStart
|
|
14267
|
-
? Date.now() - Number.parseInt(sessionStore.surveyTimerStart)
|
|
14268
|
-
: 0;
|
|
14269
|
-
const openUserSurveyDialog = () => {
|
|
14270
|
-
userSurveyStore.userSurvey = {
|
|
14271
|
-
lastShownType: userSurveyStore.userSurvey?.lastShownType === 'NPS' ? 'CSI' : 'NPS',
|
|
14272
|
-
nextDueAt: getTimeAfter30days(),
|
|
14273
|
-
};
|
|
14274
|
-
userSurveyDialog.open({
|
|
14275
|
-
reasonsSource: {
|
|
14276
|
-
$ref: '/wcms-resources/user-survey-reasons.json',
|
|
14277
|
-
},
|
|
14278
|
-
});
|
|
14279
|
-
};
|
|
14280
|
-
useEffect(() => {
|
|
14281
|
-
// Опрос показывается только если ранее пользоваютелю не показывался опрос или с того момента прошел месяц
|
|
14282
|
-
if (!userSurveyStore.userSurvey || userSurveyStore.userSurvey?.nextDueAt <= Date.now()) {
|
|
14283
|
-
// начинаем отсчитывать время от первого захода на сайт
|
|
14284
|
-
if (!sessionStore.surveyTimerStart) {
|
|
14285
|
-
sessionStore.surveyTimerStart = Date.now().toString();
|
|
14286
|
-
}
|
|
14287
|
-
// Опрос показывается спустя 5 минут нахождения на сайте
|
|
14288
|
-
const timeout = setTimeout(openUserSurveyDialog, DELAY - elapsedTime);
|
|
14289
|
-
return () => {
|
|
14290
|
-
clearTimeout(timeout);
|
|
14291
|
-
};
|
|
14292
|
-
}
|
|
14293
|
-
return noop;
|
|
14294
|
-
}, []);
|
|
14295
|
-
};
|
|
14296
|
-
// Отсчитываем месяц с текущей даты
|
|
14297
|
-
const getTimeAfter30days = () => Date.now() + 30 * 24 * 60 * 60 * 1000;
|
|
14298
|
-
|
|
14299
14340
|
const HEADER_SLOT = 'header';
|
|
14300
14341
|
const FOOTER_SLOT = 'footer';
|
|
14301
14342
|
const STICKY_FOOTER_SLOT = 'sticky-footer';
|
|
@@ -14329,7 +14370,7 @@
|
|
|
14329
14370
|
slots: () => [HEADER_SLOT, FOOTER_SLOT, STICKY_FOOTER_SLOT],
|
|
14330
14371
|
});
|
|
14331
14372
|
|
|
14332
|
-
const packageVersion = "0.14.
|
|
14373
|
+
const packageVersion = "0.14.1023";
|
|
14333
14374
|
|
|
14334
14375
|
exports.Blocks = Blocks;
|
|
14335
14376
|
exports.ContentPage = ContentPage;
|