@redneckz/wildless-cms-uni-blocks 0.14.1021 → 0.14.1023

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/bundle/api/sendUserSurvey.d.ts +1 -0
  2. package/bundle/blocks.schema.json +1 -1
  3. package/bundle/bundle.umd.js +786 -745
  4. package/bundle/bundle.umd.min.js +1 -1
  5. package/bundle/components/ApplicationForm/handlers.d.ts +4 -3
  6. package/bundle/model/AspectsProps.d.ts +7 -1
  7. package/bundle/ui-kit/UserSurveyDialog/UserSurveyDialogContent.d.ts +4 -2
  8. package/bundle/ui-kit/UserSurveyDialog/useUserSurveyDialog.d.ts +1 -1
  9. package/dist/api/sendUserSurvey.d.ts +1 -0
  10. package/dist/api/sendUserSurvey.js.map +1 -1
  11. package/dist/components/ApplicationForm/ApplicationForm.js +3 -0
  12. package/dist/components/ApplicationForm/ApplicationForm.js.map +1 -1
  13. package/dist/components/ApplicationForm/handlers.d.ts +4 -3
  14. package/dist/components/ApplicationForm/handlers.js +9 -3
  15. package/dist/components/ApplicationForm/handlers.js.map +1 -1
  16. package/dist/components/ApplicationLeadForm/getLeadFormTaskData.js +3 -0
  17. package/dist/components/ApplicationLeadForm/getLeadFormTaskData.js.map +1 -1
  18. package/dist/components/DebitForm/DebitFormStatus.js +5 -1
  19. package/dist/components/DebitForm/DebitFormStatus.js.map +1 -1
  20. package/dist/model/AspectsProps.d.ts +7 -1
  21. package/dist/ui-kit/UserSurveyDialog/FirstStep.js +2 -2
  22. package/dist/ui-kit/UserSurveyDialog/FirstStep.js.map +1 -1
  23. package/dist/ui-kit/UserSurveyDialog/UserSurveyDialog.js +17 -2
  24. package/dist/ui-kit/UserSurveyDialog/UserSurveyDialog.js.map +1 -1
  25. package/dist/ui-kit/UserSurveyDialog/UserSurveyDialogContent.d.ts +4 -2
  26. package/dist/ui-kit/UserSurveyDialog/useUserSurveyDialog.d.ts +1 -1
  27. package/dist/ui-kit/UserSurveyDialog/useUserSurveyDialog.js +23 -11
  28. package/dist/ui-kit/UserSurveyDialog/useUserSurveyDialog.js.map +1 -1
  29. package/lib/api/sendUserSurvey.d.ts +1 -0
  30. package/lib/api/sendUserSurvey.js.map +1 -1
  31. package/lib/components/ApplicationForm/ApplicationForm.js +3 -0
  32. package/lib/components/ApplicationForm/ApplicationForm.js.map +1 -1
  33. package/lib/components/ApplicationForm/handlers.d.ts +4 -3
  34. package/lib/components/ApplicationForm/handlers.js +9 -3
  35. package/lib/components/ApplicationForm/handlers.js.map +1 -1
  36. package/lib/components/ApplicationLeadForm/getLeadFormTaskData.js +3 -0
  37. package/lib/components/ApplicationLeadForm/getLeadFormTaskData.js.map +1 -1
  38. package/lib/components/DebitForm/DebitFormStatus.js +5 -1
  39. package/lib/components/DebitForm/DebitFormStatus.js.map +1 -1
  40. package/lib/model/AspectsProps.d.ts +7 -1
  41. package/lib/ui-kit/UserSurveyDialog/FirstStep.js +2 -2
  42. package/lib/ui-kit/UserSurveyDialog/FirstStep.js.map +1 -1
  43. package/lib/ui-kit/UserSurveyDialog/UserSurveyDialog.js +17 -2
  44. package/lib/ui-kit/UserSurveyDialog/UserSurveyDialog.js.map +1 -1
  45. package/lib/ui-kit/UserSurveyDialog/UserSurveyDialogContent.d.ts +4 -2
  46. package/lib/ui-kit/UserSurveyDialog/useUserSurveyDialog.d.ts +1 -1
  47. package/lib/ui-kit/UserSurveyDialog/useUserSurveyDialog.js +24 -12
  48. package/lib/ui-kit/UserSurveyDialog/useUserSurveyDialog.js.map +1 -1
  49. package/mobile/bundle/api/sendUserSurvey.d.ts +1 -0
  50. package/mobile/bundle/bundle.umd.js +786 -745
  51. package/mobile/bundle/bundle.umd.min.js +1 -1
  52. package/mobile/bundle/components/ApplicationForm/handlers.d.ts +4 -3
  53. package/mobile/bundle/model/AspectsProps.d.ts +7 -1
  54. package/mobile/bundle/ui-kit/UserSurveyDialog/UserSurveyDialogContent.d.ts +4 -2
  55. package/mobile/bundle/ui-kit/UserSurveyDialog/useUserSurveyDialog.d.ts +1 -1
  56. package/mobile/dist/api/sendUserSurvey.d.ts +1 -0
  57. package/mobile/dist/api/sendUserSurvey.js.map +1 -1
  58. package/mobile/dist/components/ApplicationForm/ApplicationForm.js +3 -0
  59. package/mobile/dist/components/ApplicationForm/ApplicationForm.js.map +1 -1
  60. package/mobile/dist/components/ApplicationForm/handlers.d.ts +4 -3
  61. package/mobile/dist/components/ApplicationForm/handlers.js +9 -3
  62. package/mobile/dist/components/ApplicationForm/handlers.js.map +1 -1
  63. package/mobile/dist/components/ApplicationLeadForm/getLeadFormTaskData.js +3 -0
  64. package/mobile/dist/components/ApplicationLeadForm/getLeadFormTaskData.js.map +1 -1
  65. package/mobile/dist/components/DebitForm/DebitFormStatus.js +5 -1
  66. package/mobile/dist/components/DebitForm/DebitFormStatus.js.map +1 -1
  67. package/mobile/dist/model/AspectsProps.d.ts +7 -1
  68. package/mobile/dist/ui-kit/UserSurveyDialog/FirstStep.js +2 -2
  69. package/mobile/dist/ui-kit/UserSurveyDialog/FirstStep.js.map +1 -1
  70. package/mobile/dist/ui-kit/UserSurveyDialog/UserSurveyDialog.js +17 -2
  71. package/mobile/dist/ui-kit/UserSurveyDialog/UserSurveyDialog.js.map +1 -1
  72. package/mobile/dist/ui-kit/UserSurveyDialog/UserSurveyDialogContent.d.ts +4 -2
  73. package/mobile/dist/ui-kit/UserSurveyDialog/useUserSurveyDialog.d.ts +1 -1
  74. package/mobile/dist/ui-kit/UserSurveyDialog/useUserSurveyDialog.js +23 -11
  75. package/mobile/dist/ui-kit/UserSurveyDialog/useUserSurveyDialog.js.map +1 -1
  76. package/mobile/lib/api/sendUserSurvey.d.ts +1 -0
  77. package/mobile/lib/api/sendUserSurvey.js.map +1 -1
  78. package/mobile/lib/components/ApplicationForm/ApplicationForm.js +3 -0
  79. package/mobile/lib/components/ApplicationForm/ApplicationForm.js.map +1 -1
  80. package/mobile/lib/components/ApplicationForm/handlers.d.ts +4 -3
  81. package/mobile/lib/components/ApplicationForm/handlers.js +9 -3
  82. package/mobile/lib/components/ApplicationForm/handlers.js.map +1 -1
  83. package/mobile/lib/components/ApplicationLeadForm/getLeadFormTaskData.js +3 -0
  84. package/mobile/lib/components/ApplicationLeadForm/getLeadFormTaskData.js.map +1 -1
  85. package/mobile/lib/components/DebitForm/DebitFormStatus.js +5 -1
  86. package/mobile/lib/components/DebitForm/DebitFormStatus.js.map +1 -1
  87. package/mobile/lib/model/AspectsProps.d.ts +7 -1
  88. package/mobile/lib/ui-kit/UserSurveyDialog/FirstStep.js +2 -2
  89. package/mobile/lib/ui-kit/UserSurveyDialog/FirstStep.js.map +1 -1
  90. package/mobile/lib/ui-kit/UserSurveyDialog/UserSurveyDialog.js +17 -2
  91. package/mobile/lib/ui-kit/UserSurveyDialog/UserSurveyDialog.js.map +1 -1
  92. package/mobile/lib/ui-kit/UserSurveyDialog/UserSurveyDialogContent.d.ts +4 -2
  93. package/mobile/lib/ui-kit/UserSurveyDialog/useUserSurveyDialog.d.ts +1 -1
  94. package/mobile/lib/ui-kit/UserSurveyDialog/useUserSurveyDialog.js +24 -12
  95. package/mobile/lib/ui-kit/UserSurveyDialog/useUserSurveyDialog.js.map +1 -1
  96. package/mobile/src/api/sendUserSurvey.ts +1 -0
  97. package/mobile/src/components/ApplicationForm/ApplicationForm.tsx +3 -0
  98. package/mobile/src/components/ApplicationForm/handlers.ts +11 -0
  99. package/mobile/src/components/ApplicationLeadForm/getLeadFormTaskData.ts +3 -0
  100. package/mobile/src/components/DebitForm/DebitFormStatus.tsx +11 -5
  101. package/mobile/src/model/AspectsProps.ts +9 -1
  102. package/mobile/src/ui-kit/UserSurveyDialog/FirstStep.tsx +6 -2
  103. package/mobile/src/ui-kit/UserSurveyDialog/UserSurveyDialog.tsx +21 -2
  104. package/mobile/src/ui-kit/UserSurveyDialog/UserSurveyDialogContent.ts +5 -2
  105. package/mobile/src/ui-kit/UserSurveyDialog/useUserSurveyDialog.ts +30 -13
  106. package/package.json +1 -1
  107. package/src/api/sendUserSurvey.ts +1 -0
  108. package/src/components/ApplicationForm/ApplicationForm.tsx +3 -0
  109. package/src/components/ApplicationForm/handlers.ts +11 -0
  110. package/src/components/ApplicationLeadForm/getLeadFormTaskData.ts +3 -0
  111. package/src/components/DebitForm/DebitFormStatus.tsx +11 -5
  112. package/src/model/AspectsProps.ts +9 -1
  113. package/src/ui-kit/UserSurveyDialog/FirstStep.tsx +6 -2
  114. package/src/ui-kit/UserSurveyDialog/UserSurveyDialog.tsx +21 -2
  115. package/src/ui-kit/UserSurveyDialog/UserSurveyDialogContent.ts +5 -2
  116. package/src/ui-kit/UserSurveyDialog/useUserSurveyDialog.ts +30 -13
@@ -1376,6 +1376,644 @@
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 await 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 Star = JSX(({ value, hover, rating, setHover, setRating }) => {
1769
+ const fillColor = value <= (hover || rating) ? '#42AB44' : '#C9CACC';
1770
+ 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" }) }) }));
1771
+ });
1772
+
1773
+ const stars$1 = new Array(5).fill(Star);
1774
+ const TITLE$1 = {
1775
+ NPS: 'Оцените, пожалуйста, от 1 до 5,\nнасколько вероятно, что вы порекомендуете Россельхозбанк коллегам, друзьям и знакомым?',
1776
+ CSI: 'Оцените, пожалуйста, удовлетворённость пользования сайтом',
1777
+ };
1778
+ const FirstStep = JSX(({ currentRating, surveyType, isSending, setCurrentRating, onNextStep, onSubmit }) => {
1779
+ const [currentHover, setCurrentHover] = useState();
1780
+ const setRatingFn = (value) => {
1781
+ setCurrentRating(value);
1782
+ if (value < 5) {
1783
+ onNextStep();
1784
+ }
1785
+ };
1786
+ 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, 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] }));
1787
+ });
1788
+
1789
+ const SVG = JSX(({ className, viewBox, fill = 'none', width, height, paths, ...commonOptions }) => {
1790
+ 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) => {
1791
+ const resultOptions = { ...commonOptions, ...options };
1792
+ return (jsx("path", { d: d, fill: pathFill || 'currentColor', stroke: resultOptions.stroke, strokeLinecap: resultOptions.strokeLinecap, strokeLinejoin: resultOptions.strokeLinejoin, strokeWidth: resultOptions.strokeWidth, strokeMiterlimit: resultOptions.strokeMiterlimit }, i));
1793
+ }) }));
1794
+ });
1795
+
1796
+ const defaultCheckStyle = 'appearance-none w-5 h-5 border-solid flex-none';
1797
+
1798
+ const CHECK_PATHS = [
1799
+ {
1800
+ 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',
1801
+ fillRule: 'evenodd',
1802
+ clipRule: 'evenodd',
1803
+ fill: 'white',
1804
+ },
1805
+ ];
1806
+ const Checkbox = JSX(({ className, value, text, disabled, isRadio, onChange, name }) => {
1807
+ const handleChange = useCallback((e) => {
1808
+ if (disabled) {
1809
+ return;
1810
+ }
1811
+ e.preventDefault();
1812
+ onChange && onChange(!value);
1813
+ }, [onChange, disabled, value]);
1814
+ 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" }));
1815
+ 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)] }) }));
1816
+ });
1817
+ const renderText$3 = (text) => text ? (jsx("div", { className: "ml-s", children: jsx(Text, { size: "text-l", font: "font-light", children: text }) })) : null;
1818
+ const getCursorStyle = (disabled = false) => (disabled ? 'cursor-not-allowed' : 'cursor-pointer');
1819
+ const role = (isRadio = false) => (isRadio ? 'radio' : 'checkbox');
1820
+ const checkboxStyle = (value = false) => style('rounded border', { 'bg-primary-main': value });
1821
+
1822
+ const orientationStyleMap = {
1823
+ horizontal: '@lg:flex-row',
1824
+ vertical: '',
1825
+ };
1826
+ 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)))) })] })));
1827
+
1828
+ function useEventListener(target, type, listener, options) {
1829
+ useEffect(() => {
1830
+ if (!target || !listener) {
1831
+ return;
1832
+ }
1833
+ target.addEventListener(type, listener, options);
1834
+ return () => {
1835
+ target.removeEventListener(type, listener, options);
1836
+ };
1837
+ }, [target, type, listener]);
1838
+ }
1839
+
1840
+ function useOutsideClick(onClick) {
1841
+ const targetRef = useRef(null);
1842
+ const handleClickOutside = useCallback((event) => {
1843
+ if (targetRef && targetRef.current && event.target instanceof Node && !targetRef.current.contains(event.target)) {
1844
+ onClick();
1845
+ }
1846
+ }, [onClick]);
1847
+ useEventListener(globalThis.document, 'click', handleClickOutside);
1848
+ return targetRef;
1849
+ }
1850
+
1851
+ // TODO Базовая функицональность всех Control - надо вынести и привязать к required флагу
1852
+ const getRequiredLabel = ({ label, required = false }) => label && required ? `${label}*` : label;
1853
+
1854
+ const inputValidStyle = 'border border-solid outline-none border-gray hover:border-primary-hover active:border-primary-text focus:border-primary-text rounded';
1855
+
1856
+ const getValidStyle = (valid) => (valid ? inputValidStyle : 'border-error');
1857
+
1858
+ const renderLabel$1 = (label) => label ? (jsx(Text, { size: "text-m", color: "text-primary-text", font: "font-light", children: label })) : null;
1859
+
1860
+ const defaultStyle$1 = 'w-full border rounded-md text-primary-text outline-none p-m';
1861
+ const borderStyle = 'border-dashed';
1862
+
1863
+ const Input = JSX(
1864
+ // eslint-disable-next-line max-lines-per-function
1865
+ ({ key, className, id, name, type = 'text', label, placeholder, value = '', valid = true, pattern, autoFocus = false, isTextarea = false, disabled = false, children, onChange, onFocus, onBlur, }) => {
1866
+ const inputRef = useRef(null);
1867
+ const handleChange = useCallback((e) => {
1868
+ const valueWithoutSpace = (e.target?.value ?? '').trimStart();
1869
+ onChange && onChange(valueWithoutSpace);
1870
+ }, [onChange]);
1871
+ useEffect(() => {
1872
+ if (autoFocus) {
1873
+ inputRef.current?.focus();
1874
+ }
1875
+ }, [autoFocus, inputRef]);
1876
+ const paddingStyle = children ? 'pr-3xl' : '';
1877
+ const validStyle = getValidStyle(valid);
1878
+ const ariaLabel = label ?? name ?? id;
1879
+ 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] }));
1880
+ });
1881
+
1882
+ 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 }));
1883
+
1884
+ const InputWrapper = JSX(({ className, label, value = '', error, errors, type, isInteger, placeholder, maxLength, inputRef, isOpen, onOpen, onClose, required, onChange = noop, ...rest }) => {
1885
+ const popupRef = useOutsideClick(onClose);
1886
+ const handleChange = useCallback((v) => {
1887
+ const isOverMax = maxLength && v.length > maxLength;
1888
+ !isOpen && onOpen();
1889
+ if (!isOverMax) {
1890
+ onChange(normalizeInteger(v, isInteger));
1891
+ }
1892
+ }, [isOpen, onChange]);
1893
+ 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)] }));
1894
+ });
1895
+ const normalizeInteger = (val = '', isInteger = false) => isInteger && val ? val.replace(/[^\d]+/g, '') : val;
1896
+ const getPlaceholder = ({ placeholder, errors, label }) => errors && !label ? `${placeholder}*` : placeholder;
1897
+
1898
+ const InputControl = JSX((props) => {
1899
+ const [isOpen, { setFalse: close, setTrue: open }] = useBool();
1900
+ return jsx(InputWrapper, { isOpen: isOpen, onOpen: open, onClose: close, ...props });
1901
+ });
1902
+
1903
+ const stars = new Array(5).fill(Star);
1904
+ const TITLE = 'Что бы мы могли улучшить?';
1905
+ const SecondStep = JSX(({ currentRating, currentReason, reasons = [], isSending, setCurrentReason, onSubmit }) => {
1906
+ const [comment, setComment] = useState();
1907
+ const handleReasonChange = (id, text) => {
1908
+ setCurrentReason?.({
1909
+ id,
1910
+ text,
1911
+ });
1912
+ };
1913
+ 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] }));
1914
+ });
1915
+
1916
+ const STEPS$3 = [FirstStep, SecondStep, FinalStep];
1917
+ const LAST_STEP_INDEX = 2;
1918
+ const UserSurveyDialog = UniBlock(({ onClose = noop, isAfterTargetAction = false, reasonsSource = {} }) => {
1919
+ const [isSending, { setTrue: startSending, setFalse: endSending }] = useBool(false);
1920
+ const [currentRating, setCurrentRating] = useState(0);
1921
+ const [currentReason, setCurrentReason] = useState();
1922
+ const [step, setStep] = useState(0);
1923
+ const userSurveyStore = useLocalStore();
1924
+ const surveyType = getUserSurveyType(userSurveyStore.userSurvey?.lastShownType);
1925
+ const { reasons } = reasonsSource;
1926
+ const ActiveStep = STEPS$3[step];
1927
+ const handleNextStep = useCallback(() => {
1928
+ setStep((_) => _ + 1);
1929
+ }, []);
1930
+ const handleSubmit = useCallback(async (message) => {
1931
+ startSending();
1932
+ await sendUserSurvey({
1933
+ rate: currentRating,
1934
+ reason: currentReason?.text,
1935
+ message: getMessage(currentReason, message),
1936
+ url: globalThis.location.href,
1937
+ type: surveyType,
1938
+ ip: isAfterTargetAction ? 'after_target_action' : 'time_on_site',
1939
+ });
1940
+ endSending();
1941
+ userSurveyStore.userSurvey = {
1942
+ lastShownType: surveyType,
1943
+ nextDueAt: getTimeAfter30days(),
1944
+ };
1945
+ setStep(LAST_STEP_INDEX);
1946
+ }, [currentRating, currentReason]);
1947
+ 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 }) }));
1948
+ });
1949
+ const getMessage = (currentReason, message) => {
1950
+ if (currentReason?.text !== 'Другое') {
1951
+ return undefined;
1952
+ }
1953
+ return message?.length ? message : 'Другое. Клиент не оставил комментариев';
1954
+ };
1955
+ // Отсчитываем месяц с текущей даты
1956
+ const getTimeAfter30days = () => Date.now() + 30 * 24 * 60 * 60 * 1000;
1957
+ // Если пользователь проходил опрос то показываем другой, иначе показываем случайный тип опроса
1958
+ const getUserSurveyType = (lastShownType) => {
1959
+ console.log('Расчитал');
1960
+ if (lastShownType) {
1961
+ return lastShownType === 'NPS' ? 'CSI' : 'NPS';
1962
+ }
1963
+ return ['NPS', 'CSI'][Date.now() % 2];
1964
+ };
1965
+
1966
+ const DELAY = 5 * 60 * 1000;
1967
+ // Хук отвечает за показ пользователю опроса
1968
+ const useUserSurveyDialog = (withoutTimer) => {
1969
+ const userSurveyDialog = useDialog(UserSurveyDialog);
1970
+ const userSurveyStore = useLocalStore();
1971
+ const sessionStore = useSessionStore();
1972
+ const surveyTimer = sessionStore.surveyTimerId;
1973
+ const isSurveySkipped = sessionStore.isSurveySkipped;
1974
+ const elapsedTime = sessionStore.surveyTimerStart
1975
+ ? Date.now() - Number.parseInt(sessionStore.surveyTimerStart)
1976
+ : 0;
1977
+ const isShowSurvey = !isSurveySkipped &&
1978
+ (!userSurveyStore.userSurvey || userSurveyStore.userSurvey?.nextDueAt <= Date.now());
1979
+ const handleCloseSurvey = useCallback(() => {
1980
+ sessionStore.isSurveySkipped = true;
1981
+ }, []);
1982
+ const openUserSurveyDialog = useCallback((isAfterTargetAction) => {
1983
+ userSurveyDialog.open({
1984
+ reasonsSource: {
1985
+ $ref: '/wcms-resources/user-survey-reasons.json',
1986
+ },
1987
+ isAfterTargetAction,
1988
+ onClose: handleCloseSurvey,
1989
+ });
1990
+ }, []);
1991
+ const handleOpenSurveyAction = useCallback(() => {
1992
+ if (isShowSurvey) {
1993
+ surveyTimer && clearTimeout(surveyTimer);
1994
+ openUserSurveyDialog(true);
1995
+ }
1996
+ }, [surveyTimer, isShowSurvey]);
1997
+ useEffect(() => {
1998
+ // Опрос показывается только если ранее пользоваютелю не показывался опрос или с того момента прошел месяц
1999
+ if (!withoutTimer && isShowSurvey) {
2000
+ // начинаем отсчитывать время от первого захода на сайт
2001
+ if (!sessionStore.surveyTimerStart) {
2002
+ sessionStore.surveyTimerStart = Date.now().toString();
2003
+ }
2004
+ // Опрос показывается спустя 5 минут нахождения на сайте
2005
+ const timeout = setTimeout(openUserSurveyDialog, DELAY - elapsedTime);
2006
+ sessionStore.surveyTimerId = timeout;
2007
+ return () => {
2008
+ clearTimeout(timeout);
2009
+ sessionStore.surveyTimerId = null;
2010
+ };
2011
+ }
2012
+ return noop;
2013
+ }, [isShowSurvey]);
2014
+ return handleOpenSurveyAction;
2015
+ };
2016
+
1379
2017
  const SERVICE_TYPES = [{ key: 'ULTRASERVICE', text: 'Ультра' }];
1380
2018
  const SERVICE_DIRECTIONS = [
1381
2019
  { key: 'Физическое лицо' },
@@ -1484,98 +2122,23 @@
1484
2122
  { key: 'Специалитет', text: 'Специалитет' },
1485
2123
  { key: 'Магистратура', text: 'Магистратура' },
1486
2124
  { 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
- });
2125
+ ];
1560
2126
 
1561
- const InputWrapper = JSX(({ className, label, value = '', error, errors, type, isInteger, placeholder, maxLength, inputRef, isOpen, onOpen, onClose, required, onChange = noop, ...rest }) => {
1562
- const popupRef = useOutsideClick(onClose);
1563
- const handleChange = useCallback((v) => {
1564
- const isOverMax = maxLength && v.length > maxLength;
1565
- !isOpen && onOpen();
1566
- if (!isOverMax) {
1567
- onChange(normalizeInteger(v, isInteger));
2127
+ const debounce = (fn, delay = 600) => {
2128
+ let timerId;
2129
+ const debouncedCallback = (...args) => {
2130
+ debouncedCallback.dispose();
2131
+ timerId = setTimeout(() => {
2132
+ fn(...args);
2133
+ }, delay);
2134
+ };
2135
+ debouncedCallback.dispose = () => {
2136
+ if (timerId) {
2137
+ clearTimeout(timerId);
1568
2138
  }
1569
- }, [isOpen, onChange]);
1570
- 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)] }));
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
- });
2139
+ };
2140
+ return debouncedCallback;
2141
+ };
1579
2142
 
1580
2143
  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
2144
 
@@ -1717,7 +2280,7 @@
1717
2280
  const formatData = {
1718
2281
  ...usedData,
1719
2282
  ...getVedTypes(vedTypes),
1720
- ...getRegion$1(region),
2283
+ ...getRegion(region),
1721
2284
  ...(inn && { inn }),
1722
2285
  ...(partnerComments ? { partnerComments } : {}),
1723
2286
  ...(serviceType ? { typeForm: serviceType } : {}),
@@ -1734,7 +2297,7 @@
1734
2297
  const getIncidentComment = (sufferedFrom, situationDescription) => sufferedFrom || situationDescription
1735
2298
  ? { comment: `${sufferedFrom || ''};${situationDescription || ''}` }
1736
2299
  : {};
1737
- const getRegion$1 = (region) => region?.key || region?.text ? { region: region?.text || region?.key } : {};
2300
+ const getRegion = (region) => region?.key || region?.text ? { region: region?.text || region?.key } : {};
1738
2301
  const getVedTypes = (vedTypes) => vedTypes
1739
2302
  ? {
1740
2303
  vedTypes: Object.fromEntries(VED_TYPES.map(({ id }) => [id, id === vedTypes])),
@@ -1768,239 +2331,20 @@
1768
2331
  vedTypes: VED_TYPES[0].id,
1769
2332
  birthday: undefined,
1770
2333
  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
- };
2334
+ onlineCheckout: false,
2335
+ posTerminal: false,
2336
+ consentToReceiveMaterials: false,
2337
+ consentDataProcessing: false,
2338
+ addressRetail: { key: '', text: '' },
2339
+ fileUpload: '',
2340
+ fileId: '',
1997
2341
  };
1998
- const getEndpoint = (endpoint, body) => {
1999
- const { serviceDirection } = body;
2000
- if (endpoint === 'lead' && serviceDirection !== 'Юридическое лицо / ИП') {
2001
- return 'lead';
2002
- }
2003
- return endpoint;
2342
+ const getInitialFormState$2 = (inputs, typeForm = '') => {
2343
+ const formState = Object.fromEntries(inputs.map((_) => [
2344
+ _.name,
2345
+ (_?.name === 'vedTypes' && _?.defaultValue) || initialFormState$1[_.name || ''],
2346
+ ]));
2347
+ return { ...formState, typeForm: { key: typeForm, text: '' } };
2004
2348
  };
2005
2349
 
2006
2350
  const getAspectsWithInclude = (data, include) => data?.map(({ aspectName, params }) => ({
@@ -2018,8 +2362,9 @@
2018
2362
  };
2019
2363
 
2020
2364
  const API$2 = LeadServiceAPI();
2021
- const handleInitCorporateLead = async ({ formatData = {}, typeForm, responseTypeDialog, verifyPhoneDialog, data = [], aspects = {}, ev, }) => {
2365
+ const handleInitCorporateLead = async ({ formatData = {}, typeForm, responseTypeDialog, verifyPhoneDialog, data = [], aspects = {}, ev, openUserSurvey, }) => {
2022
2366
  const { phone } = formatData;
2367
+ const hasSurveyAspect = data?.find((_) => _.aspectName === 'openUserSurvey');
2023
2368
  const response = await API$2.sendCode({ phone: String(phone) });
2024
2369
  if (!response) {
2025
2370
  responseTypeDialog.open({ ok: Boolean(response), typeForm });
@@ -2037,6 +2382,7 @@
2037
2382
  phone,
2038
2383
  id,
2039
2384
  });
2385
+ hasSurveyAspect && openUserSurvey?.();
2040
2386
  handleAspects({
2041
2387
  aspectsAttributes: getAspectsWithInclude(data, snowplowParams),
2042
2388
  aspects,
@@ -2045,11 +2391,13 @@
2045
2391
  },
2046
2392
  });
2047
2393
  };
2048
- const handleCallback = async ({ formatData, data, aspects = {}, ev, typeForm, responseTypeDialog, onSuccess = noop, endpoint, }) => {
2394
+ const handleCallback = async ({ formatData, data, aspects = {}, ev, typeForm, responseTypeDialog, onSuccess = noop, endpoint, openUserSurvey, }) => {
2395
+ const hasSurveyAspect = data?.find((_) => _.aspectName === 'openUserSurvey');
2049
2396
  const response = await API$2.sendPhoneCallRequest(formatData, endpoint);
2050
2397
  onSuccess();
2051
2398
  if (response?.status === 'success') {
2052
2399
  responseTypeDialog.open({ ok: true, typeForm });
2400
+ hasSurveyAspect && openUserSurvey?.();
2053
2401
  handleAspects({ aspectsAttributes: data, aspects, ev });
2054
2402
  }
2055
2403
  else if (response?.status === 'error') {
@@ -2065,11 +2413,13 @@
2065
2413
  }
2066
2414
  }
2067
2415
  };
2068
- const handleDefault = async ({ formatData, data, aspects = {}, ev, router, responseTypeDialog, endpoint, withSnowplow, }) => {
2416
+ const handleDefault = async ({ formatData, data, aspects = {}, ev, router, responseTypeDialog, endpoint, withSnowplow, openUserSurvey, }) => {
2417
+ const hasSurveyAspect = data?.find((_) => _.aspectName === 'openUserSurvey');
2069
2418
  const response = await API$2.send({ body: formatData, router, endpoint });
2070
2419
  const ok = Boolean(response);
2071
2420
  responseTypeDialog.open({ ok });
2072
2421
  if (ok) {
2422
+ hasSurveyAspect && openUserSurvey?.();
2073
2423
  const { requestId } = response;
2074
2424
  const { phone } = formatData;
2075
2425
  const utms = router.pathname.split('?')[1];
@@ -2090,45 +2440,6 @@
2090
2440
  }
2091
2441
  };
2092
2442
 
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
2443
  const withValidator = (props, validator) => {
2133
2444
  const { value, isDirty } = props;
2134
2445
  const errors = isDirty ? validator(value) : [];
@@ -3347,12 +3658,6 @@
3347
3658
 
3348
3659
  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
3660
 
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
3661
  const VedField = JSX(({ field, input }) => {
3357
3662
  const handleChange = useCallback((_) => {
3358
3663
  if (_ !== 'currencyControl') {
@@ -3606,242 +3911,100 @@
3606
3911
  const CODE_LENGTH$1 = 4;
3607
3912
  const TIME_TO_RESEND$1 = 180;
3608
3913
  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
- }
3914
+ const [values, setValues] = useState(Array(CODE_LENGTH$1).fill(''));
3915
+ const [requestId, setRequestId] = useState(reqId);
3916
+ const { handleSubmit, hasError, errorText, isLoading, timeNextReq, isSubmitButtonDisabled, setTimeNextReq, setErrorText, } = useVerifyPhoneDialogSubmit$1({
3917
+ values,
3918
+ onSuccess,
3919
+ formatData,
3920
+ reqId: requestId ?? '',
3921
+ });
3922
+ const phoneNumber = formatPhone(phone);
3923
+ const restartTimer = useCountDownTimer({ seconds: timeNextReq, onTick: setTimeNextReq });
3924
+ const handleSendCode = useCallback(async () => {
3925
+ const response = await API.sendCode({ phone: phoneNumber });
3926
+ if (response) {
3927
+ setTimeNextReq(TIME_TO_RESEND$1);
3928
+ restartTimer(TIME_TO_RESEND$1);
3929
+ setErrorText('');
3930
+ setRequestId(String(response));
3931
+ }
3932
+ }, [phoneNumber, restartTimer, onClose]);
3933
+ 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 }));
3934
+ });
3801
3935
 
3802
- const DEFAULT_METHODS = {};
3803
- /**
3804
- * MobX like reactivity (simplified).
3805
- * Can be used to migrate from Redux/MobX or something else
3806
- *
3807
- * @param store
3808
- * @returns reactive proxy backed by store
3809
- */
3810
- function useStore(store, methods = DEFAULT_METHODS) {
3811
- const deps = useRef(null);
3812
- const render = useRerender();
3813
- useEffect(() => store.bus.watch(ev => {
3814
- if (deps.current?.has(String(ev.type))) {
3815
- render();
3816
- }
3817
- }), [store, render]);
3818
- return useMemo(() => new Proxy(methods, {
3819
- get(_, key) {
3820
- deps.current ||= new Set();
3821
- deps.current.add(key);
3822
- return store.getItem(key);
3823
- },
3824
- has(_, key) {
3825
- deps.current ||= new Set();
3826
- deps.current.add(key);
3827
- return store.hasItem(key);
3828
- },
3829
- set(_, key, value) {
3830
- store.setItem(key, value);
3831
- return true;
3832
- },
3833
- deleteProperty(_, key) {
3834
- store.removeItem(key);
3835
- return true;
3836
- }
3837
- }), [store]);
3838
- }
3936
+ const handlerMap = {
3937
+ initcorporatelead: handleInitCorporateLead,
3938
+ callback: handleCallback,
3939
+ default: handleDefault,
3940
+ };
3941
+ const ApplicationForm = UniBlock(
3942
+ // eslint-disable-next-line max-lines-per-function
3943
+ ({ className, title, typeForm = '', sections = [], button, link, endpoint, additionalParams, withSnowplow, isContacts, data, onSuccess, ...rest }) => {
3944
+ const inputs = useMemo(() => (sections?.flatMap((_) => _?.inputs) || []), [sections]);
3945
+ const initialFormState = useMemo(() => getInitialFormState$2(inputs, typeForm), [inputs, typeForm]);
3946
+ const router = useRouter();
3947
+ const aspects = useAspects();
3948
+ const formValidator = useMemo(() => getFormValidator(inputs), [inputs]);
3949
+ const responseTypeDialog = useDialog(ResponseTypeDialog);
3950
+ const verifyPhoneDialog = useDialog(VerifyPhoneDialog$1);
3951
+ const openUserSurvey = useUserSurveyDialog(true);
3952
+ const handleSubmit = useCallback(async (formData, ev) => {
3953
+ const formatData = getFormatData({ ...formData, ...additionalParams });
3954
+ await executeHandler({
3955
+ formatData,
3956
+ ev,
3957
+ typeForm,
3958
+ data,
3959
+ aspects,
3960
+ router,
3961
+ responseTypeDialog,
3962
+ verifyPhoneDialog,
3963
+ onSuccess,
3964
+ withSnowplow,
3965
+ openUserSurvey,
3966
+ }, endpoint);
3967
+ }, [typeForm]);
3968
+ const [, { field, onSubmit }] = useForm(initialFormState, {
3969
+ resetOnSubmit: true,
3970
+ formValidator,
3971
+ onSubmit: handleSubmit,
3972
+ });
3973
+ const fieldName = getConsentDataProcessing(inputs)?.name;
3974
+ const consentDataProcessing = fieldName ? field('consentDataProcessing') : undefined;
3975
+ 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({
3976
+ consentDataProcessing,
3977
+ link,
3978
+ button,
3979
+ typeForm,
3980
+ })] }), isContacts ? renderContacts() : null] }));
3981
+ });
3982
+ const executeHandler = async (context, endpoint) => {
3983
+ const handler = (endpoint && handlerMap[endpoint]) || handlerMap.default;
3984
+ await handler({ ...context, endpoint });
3985
+ };
3839
3986
 
3840
- const sessionStore = new Store(); // sessionStorage cache
3841
- replicate(sessionStore, new StorageAdapter(globalThis?.sessionStorage));
3842
- function useSessionStore() {
3843
- return useStore(sessionStore);
3844
- }
3987
+ const mapProductTypeToName = {
3988
+ creditCard: 'кредитной карты',
3989
+ debitCard: 'дебетовой карты',
3990
+ credit: 'кредита',
3991
+ };
3992
+ const NoConsentDialog = JSX(({ attempts, productType, onClose = noop }) => {
3993
+ const navigator = locationNavigator();
3994
+ const isMaxAttempts = attempts > 1;
3995
+ const returnToMainPage = useCallback(() => {
3996
+ navigator.assign('/natural');
3997
+ }, []);
3998
+ const handleClose = useCallback(() => {
3999
+ if (isMaxAttempts) {
4000
+ returnToMainPage();
4001
+ }
4002
+ else {
4003
+ onClose();
4004
+ }
4005
+ }, [isMaxAttempts]);
4006
+ 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" }))] })] }) }));
4007
+ });
3845
4008
 
3846
4009
  const getNS = (_) => globalThis[_];
3847
4010
  const initializeExternalNS = (namespaceName, url, isModule = false) => {
@@ -5158,12 +5321,6 @@
5158
5321
  return result || [];
5159
5322
  };
5160
5323
 
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
5324
  const useRetailFormStore = () => {
5168
5325
  return useLocalStore();
5169
5326
  };
@@ -7375,6 +7532,9 @@
7375
7532
  };
7376
7533
  const getTaskSource = (source) => {
7377
7534
  switch (source) {
7535
+ case 'banki_ru': {
7536
+ return 'banki_ru';
7537
+ }
7378
7538
  case 'referal_sf': {
7379
7539
  return 'ReferalSF';
7380
7540
  }
@@ -11045,7 +11205,7 @@
11045
11205
  DELIVERY_CREDIT_CARD_CONTENT,
11046
11206
  ];
11047
11207
 
11048
- const STEPS$3 = 6;
11208
+ const STEPS$2 = 6;
11049
11209
  const TITLES = [
11050
11210
  'Параметры карты',
11051
11211
  'Персональные данные',
@@ -11060,7 +11220,7 @@
11060
11220
  const scrollToTop = useCallback(() => formContainerRef?.current?.scrollIntoView({ behavior: 'smooth' }), [formContainerRef]);
11061
11221
  useEffect(updateRefreshToken, []);
11062
11222
  const handleNextStep = useCallback(() => {
11063
- setStep((_) => Math.min(_ + 1, STEPS$3));
11223
+ setStep((_) => Math.min(_ + 1, STEPS$2));
11064
11224
  scrollToTop();
11065
11225
  }, []);
11066
11226
  const handlePrevStep = useCallback(() => {
@@ -11070,7 +11230,7 @@
11070
11230
  }, []);
11071
11231
  const sections = stepsSectionsMap$2[step];
11072
11232
  const [isFormFinished, { setTrue: handleFinish }] = useBool(false);
11073
- 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$3 })), 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))) })] }) }));
11233
+ 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))) })] }) }));
11074
11234
  });
11075
11235
 
11076
11236
  const CreditFormProgress = JSX(({ step = 1, totalSteps = 5, stepsTitles = [] }) => {
@@ -11631,7 +11791,7 @@
11631
11791
  DELIVERY_CREDIT_CONTENT,
11632
11792
  ];
11633
11793
 
11634
- const STEPS$2 = 4;
11794
+ const STEPS$1 = 4;
11635
11795
  const STEP_TITLES$1 = [
11636
11796
  '',
11637
11797
  'Персональные данные',
@@ -11645,7 +11805,7 @@
11645
11805
  const scrollToTop = useCallback(() => formContainerRef?.current?.scrollIntoView({ behavior: 'smooth' }), [formContainerRef]);
11646
11806
  useEffect(updateRefreshToken, []);
11647
11807
  const handleNextStep = useCallback(() => {
11648
- setStep((_) => Math.min(_ + 1, STEPS$2));
11808
+ setStep((_) => Math.min(_ + 1, STEPS$1));
11649
11809
  scrollToTop();
11650
11810
  }, []);
11651
11811
  const handlePrevStep = useCallback(() => {
@@ -11656,7 +11816,7 @@
11656
11816
  const sections = stepsSectionsMap$1[step];
11657
11817
  const isStartStep = step === 0;
11658
11818
  const [isFormFinished, { setTrue: handleFinish }] = useBool(false);
11659
- 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$2 })), 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))) })] }) }));
11819
+ 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))) })] }) }));
11660
11820
  });
11661
11821
 
11662
11822
  const DebitFormProgress = JSX(({ step = 1, totalSteps = 2, stepsTitles = [] }) => {
@@ -11667,8 +11827,11 @@
11667
11827
 
11668
11828
  const INTERNET_BANK_LINK = 'https://online.rshb.ru/d?l=dcNqSvOE';
11669
11829
  const PRELOGIN_LINK = 'https://online.rshb.ru/rshb-mbfl/webmodules/prelogin-zone';
11830
+ const openLink = (url) => {
11831
+ window.location.href = url;
11832
+ };
11670
11833
  const DebitFormStatus = JSX(({ title, description: dsc, sectionInfo, buttonText, isDboClient, isOffice, ...props }) => {
11671
- return (jsxs(BlockWrapper, { ...props, children: [jsx("div", { className: "flex flex-col md:flex-row items-center", children: jsx(Headline, { headlineVersion: "M", title: title, description: dsc, align: "text-left", padding: "p-xl", className: "w-full" }) }), jsx(SectionInfo, { items: sectionInfo }), isOffice ? (jsxs("div", { className: "flex flex-col md:flex-row md:gap-lg", children: [jsx(LinkButton, { href: PRELOGIN_LINK, text: "\u0423\u0437\u043D\u0430\u0442\u044C \u0441\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u044F\u0432\u043A\u0438", version: "primary", className: "w-full mt-lg" }), jsx(LinkButton, { href: "/natural", text: "\u0412\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F \u043D\u0430 \u0433\u043B\u0430\u0432\u043D\u0443\u044E", version: "primary", className: "w-full mt-lg" })] })) : null, !isOffice && buttonText ? (jsx(LinkButton, { href: "/natural", text: buttonText, version: "primary", className: "w-full mt-lg" })) : null, isDboClient ? (jsxs("div", { className: "flex flex-col md:flex-row md:gap-lg", children: [jsx(LinkButton, { href: "/natural/debetcards", text: "\u0417\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u0437\u0430\u043D\u043E\u0432\u043E", version: "primary", className: "w-full mt-lg" }), jsx(LinkButton, { href: INTERNET_BANK_LINK, text: "\u0412\u044B\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u043A\u0430\u0440\u0442\u0443 \u0432 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0438", version: "primary", className: "w-full mt-lg" })] })) : null] }));
11834
+ return (jsxs(BlockWrapper, { ...props, children: [jsx("div", { className: "flex flex-col md:flex-row items-center", children: jsx(Headline, { headlineVersion: "M", title: title, description: dsc, align: "text-left", padding: "p-xl", className: "w-full" }) }), jsx(SectionInfo, { items: sectionInfo }), isOffice ? (jsxs("div", { className: "flex flex-col md:flex-row md:gap-lg", children: [jsx(Button, { onClick: () => openLink(PRELOGIN_LINK), className: "w-full mt-lg", version: "primary", children: "\u0423\u0437\u043D\u0430\u0442\u044C \u0441\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u044F\u0432\u043A\u0438" }), jsx(LinkButton, { href: "/natural", text: "\u0412\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F \u043D\u0430 \u0433\u043B\u0430\u0432\u043D\u0443\u044E", version: "primary", className: "w-full mt-lg" })] })) : null, !isOffice && buttonText ? (jsx(LinkButton, { href: "/natural", text: buttonText, version: "primary", className: "w-full mt-lg" })) : null, isDboClient ? (jsxs("div", { className: "flex flex-col md:flex-row md:gap-lg", children: [jsx(LinkButton, { href: "/natural/debetcards", text: "\u0417\u0430\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u0437\u0430\u043D\u043E\u0432\u043E", version: "primary", className: "w-full mt-lg" }), jsx(LinkButton, { href: INTERNET_BANK_LINK, text: "\u0412\u044B\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u043A\u0430\u0440\u0442\u0443 \u0432 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0438", version: "primary", className: "w-full mt-lg" })] })) : null] }));
11672
11835
  });
11673
11836
  const SectionInfo = ({ title, items, }) => {
11674
11837
  if (!items) {
@@ -12200,7 +12363,7 @@
12200
12363
  DEBIT_CARD_CONTENT,
12201
12364
  ];
12202
12365
 
12203
- const STEPS$1 = 2;
12366
+ const STEPS = 2;
12204
12367
  const STEP_TITLES = ['', 'Персональные данные', 'Платежная система'];
12205
12368
  const DebitForm = UniBlock(({ className, ...rest }) => {
12206
12369
  const [step, setStep] = useState(0);
@@ -12208,7 +12371,7 @@
12208
12371
  const scrollToTop = useCallback(() => formContainerRef?.current?.scrollIntoView({ behavior: 'smooth' }), [formContainerRef]);
12209
12372
  useEffect(updateRefreshToken, []);
12210
12373
  const handleNextStep = useCallback(() => {
12211
- setStep((_) => Math.min(_ + 1, STEPS$1));
12374
+ setStep((_) => Math.min(_ + 1, STEPS));
12212
12375
  scrollToTop();
12213
12376
  }, []);
12214
12377
  const handlePrevStep = useCallback(() => {
@@ -12223,7 +12386,7 @@
12223
12386
  setIsFormFinished();
12224
12387
  scrollToTop();
12225
12388
  }, []);
12226
- 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$1 })), 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))) })] }) }));
12389
+ 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))) })] }) }));
12227
12390
  });
12228
12391
 
12229
12392
  const isRateRow = (rateRow) => typeof rateRow?.minMonths === 'number' && typeof rateRow?.maxMonths === 'number';
@@ -14168,128 +14331,6 @@
14168
14331
  }, role: "dialog", title: "\u0412\u0441\u043F\u043B\u044B\u0432\u0430\u044E\u0449\u0435\u0435 \u043E\u043A\u043D\u043E", children: popup.popup })) : null;
14169
14332
  });
14170
14333
 
14171
- const sendUserSurvey = async (body) => {
14172
- try {
14173
- const response = await LeadServiceFetch(`${API_BASE_URI}/survey`, body);
14174
- return await response;
14175
- }
14176
- catch (e) {
14177
- return null;
14178
- }
14179
- };
14180
-
14181
- const FinalStep = JSX(() => {
14182
- 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" })] }));
14183
- });
14184
-
14185
- const Star = JSX(({ value, hover, rating, setHover, setRating }) => {
14186
- const fillColor = value <= (hover || rating) ? '#42AB44' : '#C9CACC';
14187
- 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" }) }) }));
14188
- });
14189
-
14190
- const stars$1 = new Array(5).fill(Star);
14191
- const TITLE$1 = {
14192
- NPS: 'Оцените, пожалуйста, от 1 до 5 насколько вероятно, что вы порекомендуете Россельхозбанк коллегам, друзьям и знакомым?',
14193
- CSI: 'Оцените, пожалуйста, удовлетворённость пользования сайтом',
14194
- };
14195
- const FirstStep = JSX(({ currentRating, surveyType, isSending, setCurrentRating, onNextStep, onSubmit }) => {
14196
- const [currentHover, setCurrentHover] = useState();
14197
- const setRatingFn = (value) => {
14198
- setCurrentRating(value);
14199
- if (value < 5) {
14200
- onNextStep();
14201
- }
14202
- };
14203
- 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] }));
14204
- });
14205
-
14206
- const stars = new Array(5).fill(Star);
14207
- const TITLE = 'Что бы мы могли улучшить?';
14208
- const SecondStep = JSX(({ currentRating, currentReason, reasons = [], isSending, setCurrentReason, onSubmit }) => {
14209
- const [comment, setComment] = useState();
14210
- const handleReasonChange = (id, text) => {
14211
- setCurrentReason?.({
14212
- id,
14213
- text,
14214
- });
14215
- };
14216
- 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] }));
14217
- });
14218
-
14219
- const STEPS = [FirstStep, SecondStep, FinalStep];
14220
- const LAST_STEP_INDEX = 2;
14221
- const UserSurveyDialog = UniBlock(({ onClose = noop, reasonsSource = {} }) => {
14222
- const [isSending, { setTrue: startSending, setFalse: endSending }] = useBool(false);
14223
- const [currentRating, setCurrentRating] = useState(0);
14224
- const [currentReason, setCurrentReason] = useState();
14225
- const [step, setStep] = useState(0);
14226
- const userSurveyStore = useLocalStore();
14227
- const surveyType = userSurveyStore.userSurvey?.lastShownType ?? 'NPS';
14228
- const { reasons } = reasonsSource;
14229
- const ActiveStep = STEPS[step];
14230
- const handleNextStep = useCallback(() => {
14231
- setStep((_) => _ + 1);
14232
- }, []);
14233
- const handleSubmit = useCallback(async (message) => {
14234
- startSending();
14235
- await sendUserSurvey({
14236
- rate: currentRating,
14237
- reason: currentReason?.text,
14238
- message: getMessage(currentReason, message),
14239
- url: globalThis.location.href,
14240
- type: surveyType,
14241
- });
14242
- endSending();
14243
- setStep(LAST_STEP_INDEX);
14244
- }, [currentRating, currentReason]);
14245
- 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 }) }));
14246
- });
14247
- const getMessage = (currentReason, message) => {
14248
- if (currentReason?.text !== 'Другое') {
14249
- return undefined;
14250
- }
14251
- return message?.length ? message : 'Другое. Клиент не оставил комментариев';
14252
- };
14253
-
14254
- const DELAY = 5 * 60 * 1000;
14255
- // Хук отвечает за показ пользователю опроса
14256
- const useUserSurveyDialog = () => {
14257
- const userSurveyDialog = useDialog(UserSurveyDialog);
14258
- const userSurveyStore = useLocalStore();
14259
- const sessionStore = useSessionStore();
14260
- const elapsedTime = sessionStore.surveyTimerStart
14261
- ? Date.now() - Number.parseInt(sessionStore.surveyTimerStart)
14262
- : 0;
14263
- const openUserSurveyDialog = () => {
14264
- userSurveyStore.userSurvey = {
14265
- lastShownType: userSurveyStore.userSurvey?.lastShownType === 'NPS' ? 'CSI' : 'NPS',
14266
- nextDueAt: getTimeAfter30days(),
14267
- };
14268
- userSurveyDialog.open({
14269
- reasonsSource: {
14270
- $ref: '/wcms-resources/user-survey-reasons.json',
14271
- },
14272
- });
14273
- };
14274
- useEffect(() => {
14275
- // Опрос показывается только если ранее пользоваютелю не показывался опрос или с того момента прошел месяц
14276
- if (!userSurveyStore.userSurvey || userSurveyStore.userSurvey?.nextDueAt <= Date.now()) {
14277
- // начинаем отсчитывать время от первого захода на сайт
14278
- if (!sessionStore.surveyTimerStart) {
14279
- sessionStore.surveyTimerStart = Date.now().toString();
14280
- }
14281
- // Опрос показывается спустя 5 минут нахождения на сайте
14282
- const timeout = setTimeout(openUserSurveyDialog, DELAY - elapsedTime);
14283
- return () => {
14284
- clearTimeout(timeout);
14285
- };
14286
- }
14287
- return noop;
14288
- }, []);
14289
- };
14290
- // Отсчитываем месяц с текущей даты
14291
- const getTimeAfter30days = () => Date.now() + 30 * 24 * 60 * 60 * 1000;
14292
-
14293
14334
  const HEADER_SLOT = 'header';
14294
14335
  const FOOTER_SLOT = 'footer';
14295
14336
  const STICKY_FOOTER_SLOT = 'sticky-footer';
@@ -14323,7 +14364,7 @@
14323
14364
  slots: () => [HEADER_SLOT, FOOTER_SLOT, STICKY_FOOTER_SLOT],
14324
14365
  });
14325
14366
 
14326
- const packageVersion = "0.14.1020";
14367
+ const packageVersion = "0.14.1022";
14327
14368
 
14328
14369
  exports.Blocks = Blocks;
14329
14370
  exports.ContentPage = ContentPage;