@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
@@ -1384,6 +1384,644 @@
1384
1384
  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" })] }) }));
1385
1385
  });
1386
1386
 
1387
+ function copy(source, target) {
1388
+ for (const [k, v] of source.entries()) {
1389
+ if (v !== null && v !== undefined) {
1390
+ target.setItem(k, v);
1391
+ }
1392
+ else {
1393
+ target.removeItem(k);
1394
+ }
1395
+ }
1396
+ }
1397
+
1398
+ function replicate(primary, secondary) {
1399
+ copy(primary, secondary);
1400
+ copy(secondary, primary);
1401
+ return primary.bus.watch(({ type, event }) => {
1402
+ if (event !== null && event !== undefined) {
1403
+ secondary.setItem(type, event);
1404
+ }
1405
+ else {
1406
+ secondary.removeItem(type);
1407
+ }
1408
+ });
1409
+ }
1410
+
1411
+ class StorageAdapter {
1412
+ storage;
1413
+ bus;
1414
+ get size() {
1415
+ return this.storage?.length ?? 0;
1416
+ }
1417
+ constructor(storage, bus = new EventBus()) {
1418
+ this.storage = storage;
1419
+ this.bus = bus;
1420
+ }
1421
+ hasItem(key) {
1422
+ return Boolean(this.storage?.getItem(String(key)));
1423
+ }
1424
+ getItem(key) {
1425
+ const _ = this.storage?.getItem(String(key)) ?? null;
1426
+ try {
1427
+ return JSON.parse(String(_));
1428
+ }
1429
+ catch (ex) {
1430
+ return null;
1431
+ }
1432
+ }
1433
+ entries() {
1434
+ return Array.from({ length: this.size }, (_, i) => {
1435
+ const k = String(this.storage?.key(i));
1436
+ return [k, this.getItem(k)];
1437
+ });
1438
+ }
1439
+ setItem(key, value) {
1440
+ if (value !== null) {
1441
+ this.storage?.setItem(String(key), JSON.stringify(value));
1442
+ }
1443
+ else {
1444
+ this.storage?.removeItem(String(key));
1445
+ }
1446
+ this.bus?.subject(key, value);
1447
+ }
1448
+ removeItem(key) {
1449
+ this.storage?.removeItem(String(key));
1450
+ this.bus?.subject(key, null);
1451
+ }
1452
+ }
1453
+
1454
+ class Store {
1455
+ bus;
1456
+ store = new Map();
1457
+ get size() {
1458
+ return this.store.size;
1459
+ }
1460
+ constructor(bus = new EventBus()) {
1461
+ this.bus = bus;
1462
+ }
1463
+ hasItem(key) {
1464
+ return this.store.has(key);
1465
+ }
1466
+ getItem(key) {
1467
+ return this.store.get(key);
1468
+ }
1469
+ entries() {
1470
+ return this.store.entries();
1471
+ }
1472
+ setItem(key, value) {
1473
+ this.store.set(key, value);
1474
+ this.bus.subject(key, value);
1475
+ }
1476
+ removeItem(key) {
1477
+ this.store.delete(key);
1478
+ this.bus.subject(key, null);
1479
+ }
1480
+ }
1481
+
1482
+ function useRerender() {
1483
+ const [, setCount] = useState(0);
1484
+ return useCallback(() => setCount(_ => (_ + 1) % (1 << 16)), []);
1485
+ }
1486
+
1487
+ const DEFAULT_METHODS = {};
1488
+ /**
1489
+ * MobX like reactivity (simplified).
1490
+ * Can be used to migrate from Redux/MobX or something else
1491
+ *
1492
+ * @param store
1493
+ * @returns reactive proxy backed by store
1494
+ */
1495
+ function useStore(store, methods = DEFAULT_METHODS) {
1496
+ const deps = useRef(null);
1497
+ const render = useRerender();
1498
+ useEffect(() => store.bus.watch(ev => {
1499
+ if (deps.current?.has(String(ev.type))) {
1500
+ render();
1501
+ }
1502
+ }), [store, render]);
1503
+ return useMemo(() => new Proxy(methods, {
1504
+ get(_, key) {
1505
+ deps.current ||= new Set();
1506
+ deps.current.add(key);
1507
+ return store.getItem(key);
1508
+ },
1509
+ has(_, key) {
1510
+ deps.current ||= new Set();
1511
+ deps.current.add(key);
1512
+ return store.hasItem(key);
1513
+ },
1514
+ set(_, key, value) {
1515
+ store.setItem(key, value);
1516
+ return true;
1517
+ },
1518
+ deleteProperty(_, key) {
1519
+ store.removeItem(key);
1520
+ return true;
1521
+ }
1522
+ }), [store]);
1523
+ }
1524
+
1525
+ const localStore = new Store(); // localStorage cache
1526
+ replicate(localStore, new StorageAdapter(globalThis?.localStorage));
1527
+ function useLocalStore(methods) {
1528
+ return useStore(localStore, methods);
1529
+ }
1530
+
1531
+ const sessionStore = new Store(); // sessionStorage cache
1532
+ replicate(sessionStore, new StorageAdapter(globalThis?.sessionStorage));
1533
+ function useSessionStore() {
1534
+ return useStore(sessionStore);
1535
+ }
1536
+
1537
+ const API_BASE_URI = '/api/v1';
1538
+
1539
+ const getUserTimezoneOffset = () => {
1540
+ const offset = new Date().getTimezoneOffset();
1541
+ const absOffset = Math.abs(offset);
1542
+ const hours = Math.floor(absOffset / 60);
1543
+ const minutes = absOffset % 60;
1544
+ const sign = offset < 0 ? '+' : '-';
1545
+ return `GMT${sign}${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
1546
+ };
1547
+
1548
+ const ENDPOINT_MAPPING = {
1549
+ lead: {
1550
+ withTypeForm: true,
1551
+ isNaturalEndpoint: true,
1552
+ },
1553
+ sendcorporatelead: {
1554
+ withTypeForm: true,
1555
+ isNaturalEndpoint: false,
1556
+ },
1557
+ practice: {
1558
+ withTypeForm: false,
1559
+ isNaturalEndpoint: true,
1560
+ },
1561
+ internship: {
1562
+ withTypeForm: false,
1563
+ isNaturalEndpoint: true,
1564
+ },
1565
+ initcorporatelead: {
1566
+ withTypeForm: true,
1567
+ isNaturalEndpoint: false,
1568
+ },
1569
+ confirmCorporateLead: {
1570
+ withTypeForm: true,
1571
+ isNaturalEndpoint: false,
1572
+ },
1573
+ callback: {
1574
+ withTypeForm: false,
1575
+ isNaturalEndpoint: true,
1576
+ },
1577
+ };
1578
+
1579
+ const formatDate = (date, toTimeStamp = false) => {
1580
+ if (typeof date === 'string') {
1581
+ return date.split('-').reverse().join('.');
1582
+ }
1583
+ else {
1584
+ const day = String(date.getDate()).padStart(2, '0');
1585
+ const month = String(date.getMonth() + 1).padStart(2, '0');
1586
+ const year = String(date.getFullYear());
1587
+ return toTimeStamp ? `${year}-${month}-${day}` : `${day}.${month}.${year}`;
1588
+ }
1589
+ };
1590
+
1591
+ const formatPhone = (phone) => phone?.replace(/[^+\d]/g, '');
1592
+
1593
+ const getSubmitBody = ({ body, endpoint, router }) => {
1594
+ const isNaturalPerson = endpoint && ENDPOINT_MAPPING[endpoint].isNaturalEndpoint;
1595
+ const withTypeForm = endpoint && ENDPOINT_MAPPING[endpoint].withTypeForm;
1596
+ const { typeForm, region, phone = '', email, birthday, desiredMeetingDate, fullRegion, addressBranch, secondaryPhone = '', bankEmpolee, applicationDate, partnerName, russianPhone, partnerSymbolCode, internshipEndDate, internshipStartDate, ...staticBody } = body;
1597
+ return {
1598
+ ...(withTypeForm ? { typeForm } : {}),
1599
+ ...getRegion$1(region, isNaturalPerson),
1600
+ ...getEmail(email, isNaturalPerson),
1601
+ ...getPhone(phone),
1602
+ ...getPhone(russianPhone),
1603
+ ...(isNaturalPerson ? getFormatDate([[birthday, 'birthday']]) : { birthday }),
1604
+ ...getFormatDate([
1605
+ [desiredMeetingDate, 'desiredMeetingDate'],
1606
+ [internshipEndDate, 'internshipEndDate'],
1607
+ [internshipStartDate, 'internshipStartDate'],
1608
+ ]),
1609
+ ...(typeForm === 'FEEDBACK'
1610
+ ? {}
1611
+ : {
1612
+ addressBranch,
1613
+ bankEmpolee,
1614
+ applicationDate,
1615
+ ...getSecondaryPhone(secondaryPhone),
1616
+ }),
1617
+ ...addPageSlug(typeForm, router),
1618
+ ...formatPFForm(typeForm, {
1619
+ fullRegion,
1620
+ partnerName,
1621
+ partnerSymbolCode,
1622
+ }),
1623
+ ...getRkoTariffName(typeForm),
1624
+ ...staticBody,
1625
+ };
1626
+ };
1627
+ const getPhoneBody = (phone) => {
1628
+ return {
1629
+ ...getPhone(phone),
1630
+ };
1631
+ };
1632
+ const getPhone = (phone) => (phone ? { phone: formatPhone(phone) } : {});
1633
+ const getFormatDate = (dates) => Object.fromEntries(dates.filter(([value]) => value).map(([value, key]) => [key, formatDate(value)]));
1634
+ const getRegion$1 = (region, isNaturalPerson = true) => ({
1635
+ [isNaturalPerson ? 'regionBranch' : 'region']: region,
1636
+ });
1637
+ const getEmail = (email, isNaturalPerson = true) => ({
1638
+ [isNaturalPerson ? 'email' : 'mail']: email,
1639
+ });
1640
+ const getSecondaryPhone = (secondaryPhone = '') => !secondaryPhone || secondaryPhone === '+7 ('
1641
+ ? {}
1642
+ : { secondaryPhoneNumber: formatPhone(secondaryPhone) };
1643
+ const formatPFForm = (typeForm, data) => typeForm === 'PF'
1644
+ ? {
1645
+ region: data?.fullRegion,
1646
+ partner: data?.partnerName,
1647
+ partnerId: data?.partnerSymbolCode,
1648
+ }
1649
+ : {};
1650
+ const addPageSlug = (typeForm, router) => typeForm === 'UNIVERSAL'
1651
+ ? {
1652
+ typeForm: router?.pathname?.split('/')?.at(-1) || '/',
1653
+ }
1654
+ : {};
1655
+ const getRkoTariffName = (typeForm) => typeForm === 'CALC'
1656
+ ? {
1657
+ partnerComments: globalThis?.sessionStorage.getItem('rkoTariffName') ?? 'Неизвестный тариф',
1658
+ }
1659
+ : {};
1660
+
1661
+ // eslint-disable-next-line max-lines-per-function
1662
+ function LeadServiceAPI() {
1663
+ async function send({ body, router, endpoint }) {
1664
+ const calculatedEndpoint = endpoint && getEndpoint(endpoint, body);
1665
+ const url = `${API_BASE_URI}/${calculatedEndpoint}`;
1666
+ const submitBody = getSubmitBody({
1667
+ body,
1668
+ endpoint,
1669
+ router,
1670
+ });
1671
+ try {
1672
+ const response = await LeadServiceFetch(url, submitBody);
1673
+ if (!response?.ok) {
1674
+ return null;
1675
+ }
1676
+ return await response.json();
1677
+ }
1678
+ catch (e) {
1679
+ return null;
1680
+ }
1681
+ }
1682
+ async function sendCode({ phone }) {
1683
+ const submitBody = getPhoneBody(phone);
1684
+ try {
1685
+ const response = LeadServiceFetch(`${API_BASE_URI}/initCorporateLead`, submitBody).then(async (res) => {
1686
+ if (!res.ok) {
1687
+ throw new Error(`Ошибка HTTP: ${res.status}`);
1688
+ }
1689
+ return await res.text();
1690
+ });
1691
+ return await response;
1692
+ }
1693
+ catch (e) {
1694
+ return null;
1695
+ }
1696
+ }
1697
+ async function checkCode({ reqId, code, body, router, endpoint = 'confirmCorporateLead', }) {
1698
+ const submitBody = {
1699
+ requestId: reqId,
1700
+ confimationCode: code,
1701
+ leadRequest: getSubmitBody({ body, endpoint, router }),
1702
+ };
1703
+ try {
1704
+ const response = await LeadServiceFetch(`${API_BASE_URI}/${endpoint}`, submitBody);
1705
+ return await response.json();
1706
+ }
1707
+ catch (e) {
1708
+ return null;
1709
+ }
1710
+ }
1711
+ async function sendPhoneCallRequest(body, endpoint) {
1712
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1713
+ const submitBody = getSubmitBody({ body, endpoint });
1714
+ const formatSubmitBody = getFormatCallbackSubmitBody(submitBody);
1715
+ try {
1716
+ const response = await LeadServiceFetch(`${API_BASE_URI}/callback`, formatSubmitBody);
1717
+ if (!response?.ok) {
1718
+ return null;
1719
+ }
1720
+ return await response.json();
1721
+ }
1722
+ catch (e) {
1723
+ return null;
1724
+ }
1725
+ }
1726
+ return {
1727
+ send,
1728
+ sendCode,
1729
+ checkCode,
1730
+ sendPhoneCallRequest,
1731
+ };
1732
+ }
1733
+ const LeadServiceFetch = (url, submitBody) => fetch(url, {
1734
+ method: 'POST',
1735
+ headers: { 'Content-Type': 'application/json' },
1736
+ mode: 'cors',
1737
+ body: JSON.stringify(submitBody),
1738
+ });
1739
+ const getFormatCallbackSubmitBody = (submitBody) => {
1740
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1741
+ const { typeForm, consentDataProcessing, phone, ...rest } = submitBody;
1742
+ return {
1743
+ ...rest,
1744
+ phone: phone?.startsWith('+') ? phone.slice(1) : phone,
1745
+ clientTimezone: getUserTimezoneOffset(),
1746
+ };
1747
+ };
1748
+ const getEndpoint = (endpoint, body) => {
1749
+ const { serviceDirection } = body;
1750
+ if (endpoint === 'lead' && serviceDirection !== 'Юридическое лицо / ИП') {
1751
+ return 'lead';
1752
+ }
1753
+ return endpoint;
1754
+ };
1755
+
1756
+ const sendUserSurvey = async (body) => {
1757
+ try {
1758
+ const response = await LeadServiceFetch(`${API_BASE_URI}/survey`, body);
1759
+ return await response;
1760
+ }
1761
+ catch (e) {
1762
+ return null;
1763
+ }
1764
+ };
1765
+
1766
+ const FinalStep = JSX(() => {
1767
+ 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" })] }));
1768
+ });
1769
+
1770
+ 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, {
1771
+ 'backdrop-blur': blur,
1772
+ }), 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" }) })));
1773
+
1774
+ 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] })));
1775
+
1776
+ const Star = JSX(({ value, hover, rating, setHover, setRating }) => {
1777
+ const fillColor = value <= (hover || rating) ? '#42AB44' : '#C9CACC';
1778
+ 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" }) }) }));
1779
+ });
1780
+
1781
+ const stars$1 = new Array(5).fill(Star);
1782
+ const TITLE$1 = {
1783
+ NPS: 'Оцените, пожалуйста, от 1 до 5,\nнасколько вероятно, что вы порекомендуете Россельхозбанк коллегам, друзьям и знакомым?',
1784
+ CSI: 'Оцените, пожалуйста, удовлетворённость пользования сайтом',
1785
+ };
1786
+ const FirstStep = JSX(({ currentRating, surveyType, isSending, setCurrentRating, onNextStep, onSubmit }) => {
1787
+ const [currentHover, setCurrentHover] = useState();
1788
+ const setRatingFn = (value) => {
1789
+ setCurrentRating(value);
1790
+ if (value < 5) {
1791
+ onNextStep();
1792
+ }
1793
+ };
1794
+ return (jsxs("div", { className: "flex flex-col gap-xl items-center", children: [jsx(Heading, { className: "text-center whitespace-pre-line", headingType: "h5", title: TITLE$1[surveyType] }), jsx("div", { className: "flex justify-center", children: stars$1.map((StarItem, index) => (jsx(StarItem, { value: index + 1, rating: currentRating, hover: currentHover, setRating: setRatingFn, setHover: setCurrentHover, 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] }));
1795
+ });
1796
+
1797
+ const SVG = JSX(({ className, viewBox, fill = 'none', width, height, paths, ...commonOptions }) => {
1798
+ return (jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: className, viewBox: viewBox, fill: fill, width: width, height: height, children: paths.map(({ d, fill: pathFill, ...options }, i) => {
1799
+ const resultOptions = { ...commonOptions, ...options };
1800
+ return (jsx("path", { d: d, fill: pathFill || 'currentColor', stroke: resultOptions.stroke, strokeLinecap: resultOptions.strokeLinecap, strokeLinejoin: resultOptions.strokeLinejoin, strokeWidth: resultOptions.strokeWidth, strokeMiterlimit: resultOptions.strokeMiterlimit }, i));
1801
+ }) }));
1802
+ });
1803
+
1804
+ const defaultCheckStyle = 'appearance-none w-5 h-5 border-solid flex-none';
1805
+
1806
+ const CHECK_PATHS = [
1807
+ {
1808
+ d: 'M10.207.793a1 1 0 0 1 0 1.414l-6 6a1 1 0 0 1-1.414 0l-2.5-2.5a1 1 0 0 1 1.414-1.414L3.5 6.086 8.793.793a1 1 0 0 1 1.414 0Z',
1809
+ fillRule: 'evenodd',
1810
+ clipRule: 'evenodd',
1811
+ fill: 'white',
1812
+ },
1813
+ ];
1814
+ const Checkbox = JSX(({ className, value, text, disabled, isRadio, onChange, name }) => {
1815
+ const handleChange = useCallback((e) => {
1816
+ if (disabled) {
1817
+ return;
1818
+ }
1819
+ e.preventDefault();
1820
+ onChange && onChange(!value);
1821
+ }, [onChange, disabled, value]);
1822
+ const icon = isRadio ? (jsx("div", { className: "absolute left-1 w-3 h-3 rounded-full bg-primary-main" })) : (jsx(SVG, { paths: CHECK_PATHS, className: "absolute left-1 ml-px block", width: "11", height: "9", fill: "white", viewBox: "0 0 11 9" }));
1823
+ return (jsx("div", { className: className, children: jsxs("label", { className: style('flex items-center relative group/box', getCursorStyle(disabled)), "data-test-id": name, onClick: handleChange, children: [jsx("div", { className: style(defaultCheckStyle, 'm-0', isRadio ? 'rounded-full border-2' : checkboxStyle(value), !disabled && value ? 'border-primary-main' : 'border-gray', disabled ? 'bg-main-disabled' : 'group-hover/box:border-primary-hover'), role: role(isRadio), "aria-checked": Boolean(value), "aria-disabled": Boolean(disabled), "aria-label": text }), value ? icon : null, renderText$4(text)] }) }));
1824
+ });
1825
+ const renderText$4 = (text) => text ? (jsx("div", { className: "ml-s", children: jsx(Text, { size: "text-l", font: "font-light", children: text }) })) : null;
1826
+ const getCursorStyle = (disabled = false) => (disabled ? 'cursor-not-allowed' : 'cursor-pointer');
1827
+ const role = (isRadio = false) => (isRadio ? 'radio' : 'checkbox');
1828
+ const checkboxStyle = (value = false) => style('rounded border', { 'bg-primary-main': value });
1829
+
1830
+ const orientationStyleMap = {
1831
+ horizontal: '@lg:flex-row',
1832
+ vertical: '',
1833
+ };
1834
+ const RadioButtonGroup = JSX(({ label, items, value, className, disabled = false, orientation = 'horizontal', onChange: onChangeCheckedItem, }) => (jsxs("div", { className: "grid gap-xs whitespace-nowrap", children: [label ? (jsx("div", { role: "radiogroup", "aria-label": label, children: jsx(Text, { color: "text-secondary-text", font: "font-light", children: label }) })) : null, jsx("div", { className: style('flex flex-col gap-s', orientationStyleMap[orientation], className), role: "radiogroup", "aria-label": "\u0413\u0440\u0443\u043F\u043F\u0430 \u043A\u043D\u043E\u043F\u043E\u043A", children: items?.map(({ id, text }) => (jsx(Checkbox, { isRadio: true, text: text, value: value === id, onChange: () => onChangeCheckedItem?.(id, text), disabled: disabled, name: id }, String(id)))) })] })));
1835
+
1836
+ function useEventListener(target, type, listener, options) {
1837
+ useEffect(() => {
1838
+ if (!target || !listener) {
1839
+ return;
1840
+ }
1841
+ target.addEventListener(type, listener, options);
1842
+ return () => {
1843
+ target.removeEventListener(type, listener, options);
1844
+ };
1845
+ }, [target, type, listener]);
1846
+ }
1847
+
1848
+ function useOutsideClick(onClick) {
1849
+ const targetRef = useRef(null);
1850
+ const handleClickOutside = useCallback((event) => {
1851
+ if (targetRef && targetRef.current && event.target instanceof Node && !targetRef.current.contains(event.target)) {
1852
+ onClick();
1853
+ }
1854
+ }, [onClick]);
1855
+ useEventListener(globalThis.document, 'click', handleClickOutside);
1856
+ return targetRef;
1857
+ }
1858
+
1859
+ // TODO Базовая функицональность всех Control - надо вынести и привязать к required флагу
1860
+ const getRequiredLabel = ({ label, required = false }) => label && required ? `${label}*` : label;
1861
+
1862
+ const inputValidStyle = 'border border-solid outline-none border-gray hover:border-primary-hover active:border-primary-text focus:border-primary-text rounded';
1863
+
1864
+ const getValidStyle = (valid) => (valid ? inputValidStyle : 'border-error');
1865
+
1866
+ const renderLabel$1 = (label) => label ? (jsx(Text, { size: "text-m", color: "text-primary-text", font: "font-light", children: label })) : null;
1867
+
1868
+ const defaultStyle$1 = 'w-full border rounded-md text-primary-text outline-none p-m';
1869
+ const borderStyle = 'border-dashed';
1870
+
1871
+ const Input = JSX(
1872
+ // eslint-disable-next-line max-lines-per-function
1873
+ ({ key, className, id, name, type = 'text', label, placeholder, value = '', valid = true, pattern, autoFocus = false, isTextarea = false, disabled = false, children, onChange, onFocus, onBlur, }) => {
1874
+ const inputRef = useRef(null);
1875
+ const handleChange = useCallback((e) => {
1876
+ const valueWithoutSpace = (e.target?.value ?? '').trimStart();
1877
+ onChange && onChange(valueWithoutSpace);
1878
+ }, [onChange]);
1879
+ useEffect(() => {
1880
+ if (autoFocus) {
1881
+ inputRef.current?.focus();
1882
+ }
1883
+ }, [autoFocus, inputRef]);
1884
+ const paddingStyle = children ? 'pr-3xl' : '';
1885
+ const validStyle = getValidStyle(valid);
1886
+ const ariaLabel = label ?? name ?? id;
1887
+ return (jsxs("div", { className: style('relative', className), children: [jsxs("label", { className: "space-y-xs", children: [renderLabel$1(label), isTextarea ? (jsx("textarea", { className: style('block resize-y min-h-24', defaultStyle$1, validStyle), id: style('textarea', id), value: value, name: name || id, placeholder: placeholder, disabled: disabled, "aria-label": ariaLabel, onChange: handleChange, onFocus: onFocus, onBlur: onBlur }, key)) : (jsx("input", { ref: inputRef, className: style('h-14', defaultStyle$1, paddingStyle, validStyle), id: id, type: type, value: value, name: name || id, placeholder: placeholder, pattern: pattern, disabled: disabled, "aria-label": ariaLabel, onChange: handleChange, onFocus: onFocus, onBlur: onBlur, "data-test-id": name }, key))] }), children] }));
1888
+ });
1889
+
1890
+ const renderErrorText = (error) => (jsx("div", { className: "min-h-6", children: error ? (jsx(Text, { size: "text-xs", font: "font-light", color: "text-error", children: error })) : null }));
1891
+
1892
+ const InputWrapper = JSX(({ className, label, value = '', error, errors, type, isInteger, placeholder, maxLength, inputRef, isOpen, onOpen, onClose, required, onChange = noop, ...rest }) => {
1893
+ const popupRef = useOutsideClick(onClose);
1894
+ const handleChange = useCallback((v) => {
1895
+ const isOverMax = maxLength && v.length > maxLength;
1896
+ !isOpen && onOpen();
1897
+ if (!isOverMax) {
1898
+ onChange(normalizeInteger(v, isInteger));
1899
+ }
1900
+ }, [isOpen, onChange]);
1901
+ return (jsxs("div", { className: style('shrink-0 w-full', className), ref: popupRef, onBlur: onClose, onFocus: onOpen, children: [jsx("div", { ref: inputRef, children: jsx(Input, { type: type || 'text', "aria-label": label, label: getRequiredLabel({ label, required }), valid: Boolean(!error), onChange: handleChange, placeholder: getPlaceholder({ placeholder, errors, label }), value: value, ...rest }) }), renderErrorText(error)] }));
1902
+ });
1903
+ const normalizeInteger = (val = '', isInteger = false) => isInteger && val ? val.replace(/[^\d]+/g, '') : val;
1904
+ const getPlaceholder = ({ placeholder, errors, label }) => errors && !label ? `${placeholder}*` : placeholder;
1905
+
1906
+ const InputControl = JSX((props) => {
1907
+ const [isOpen, { setFalse: close, setTrue: open }] = useBool();
1908
+ return jsx(InputWrapper, { isOpen: isOpen, onOpen: open, onClose: close, ...props });
1909
+ });
1910
+
1911
+ const stars = new Array(5).fill(Star);
1912
+ const TITLE = 'Что бы мы могли улучшить?';
1913
+ const SecondStep = JSX(({ currentRating, currentReason, reasons = [], isSending, setCurrentReason, onSubmit }) => {
1914
+ const [comment, setComment] = useState();
1915
+ const handleReasonChange = (id, text) => {
1916
+ setCurrentReason?.({
1917
+ id,
1918
+ text,
1919
+ });
1920
+ };
1921
+ return (jsxs("div", { className: "flex flex-col gap-xl items-center", children: [jsx(Heading, { className: "text-center", headingType: "h5", title: TITLE }), jsx("div", { className: "flex justify-center", children: stars.map((StarItem, index) => (jsx(StarItem, { value: index + 1, rating: currentRating }, index))) }), jsx(RadioButtonGroup, { className: "w-full text-wrap", orientation: "vertical", items: reasons, value: currentReason?.id, onChange: handleReasonChange }), currentReason?.text === 'Другое' ? (jsx(InputControl, { className: "w-full", placeholder: "\u041D\u0430\u043F\u0438\u0448\u0438\u0442\u0435, \u043F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, \u0441\u0432\u043E\u0439 \u0432\u0430\u0440\u0438\u0430\u043D\u0442 \u043E\u0442\u0432\u0435\u0442\u0430", isTextarea: true, value: comment, onChange: setComment, maxLength: 255 })) : null, currentReason ? (jsx(SubmitButton$1, { onClick: () => onSubmit(comment), isLoading: isSending, children: "\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C" })) : null] }));
1922
+ });
1923
+
1924
+ const STEPS$3 = [FirstStep, SecondStep, FinalStep];
1925
+ const LAST_STEP_INDEX = 2;
1926
+ const UserSurveyDialog = UniBlock(({ onClose = noop, isAfterTargetAction = false, reasonsSource = {} }) => {
1927
+ const [isSending, { setTrue: startSending, setFalse: endSending }] = useBool(false);
1928
+ const [currentRating, setCurrentRating] = useState(0);
1929
+ const [currentReason, setCurrentReason] = useState();
1930
+ const [step, setStep] = useState(0);
1931
+ const userSurveyStore = useLocalStore();
1932
+ const surveyType = getUserSurveyType(userSurveyStore.userSurvey?.lastShownType);
1933
+ const { reasons } = reasonsSource;
1934
+ const ActiveStep = STEPS$3[step];
1935
+ const handleNextStep = useCallback(() => {
1936
+ setStep((_) => _ + 1);
1937
+ }, []);
1938
+ const handleSubmit = useCallback(async (message) => {
1939
+ startSending();
1940
+ await sendUserSurvey({
1941
+ rate: currentRating,
1942
+ reason: currentReason?.text,
1943
+ message: getMessage(currentReason, message),
1944
+ url: globalThis.location.href,
1945
+ type: surveyType,
1946
+ ip: isAfterTargetAction ? 'after_target_action' : 'time_on_site',
1947
+ });
1948
+ endSending();
1949
+ userSurveyStore.userSurvey = {
1950
+ lastShownType: surveyType,
1951
+ nextDueAt: getTimeAfter30days(),
1952
+ };
1953
+ setStep(LAST_STEP_INDEX);
1954
+ }, [currentRating, currentReason]);
1955
+ return (jsx(Dialog, { maxWidth: "xl", onClose: onClose, children: jsx(ActiveStep, { currentRating: currentRating, currentReason: currentReason, reasons: reasons, surveyType: surveyType, isSending: isSending, setCurrentReason: setCurrentReason, setCurrentRating: setCurrentRating, onSubmit: handleSubmit, onNextStep: handleNextStep }) }));
1956
+ });
1957
+ const getMessage = (currentReason, message) => {
1958
+ if (currentReason?.text !== 'Другое') {
1959
+ return undefined;
1960
+ }
1961
+ return message?.length ? message : 'Другое. Клиент не оставил комментариев';
1962
+ };
1963
+ // Отсчитываем месяц с текущей даты
1964
+ const getTimeAfter30days = () => Date.now() + 30 * 24 * 60 * 60 * 1000;
1965
+ // Если пользователь проходил опрос то показываем другой, иначе показываем случайный тип опроса
1966
+ const getUserSurveyType = (lastShownType) => {
1967
+ console.log('Расчитал');
1968
+ if (lastShownType) {
1969
+ return lastShownType === 'NPS' ? 'CSI' : 'NPS';
1970
+ }
1971
+ return ['NPS', 'CSI'][Date.now() % 2];
1972
+ };
1973
+
1974
+ const DELAY = 5 * 60 * 1000;
1975
+ // Хук отвечает за показ пользователю опроса
1976
+ const useUserSurveyDialog = (withoutTimer) => {
1977
+ const userSurveyDialog = useDialog(UserSurveyDialog);
1978
+ const userSurveyStore = useLocalStore();
1979
+ const sessionStore = useSessionStore();
1980
+ const surveyTimer = sessionStore.surveyTimerId;
1981
+ const isSurveySkipped = sessionStore.isSurveySkipped;
1982
+ const elapsedTime = sessionStore.surveyTimerStart
1983
+ ? Date.now() - Number.parseInt(sessionStore.surveyTimerStart)
1984
+ : 0;
1985
+ const isShowSurvey = !isSurveySkipped &&
1986
+ (!userSurveyStore.userSurvey || userSurveyStore.userSurvey?.nextDueAt <= Date.now());
1987
+ const handleCloseSurvey = useCallback(() => {
1988
+ sessionStore.isSurveySkipped = true;
1989
+ }, []);
1990
+ const openUserSurveyDialog = useCallback((isAfterTargetAction) => {
1991
+ userSurveyDialog.open({
1992
+ reasonsSource: {
1993
+ $ref: '/wcms-resources/user-survey-reasons.json',
1994
+ },
1995
+ isAfterTargetAction,
1996
+ onClose: handleCloseSurvey,
1997
+ });
1998
+ }, []);
1999
+ const handleOpenSurveyAction = useCallback(() => {
2000
+ if (isShowSurvey) {
2001
+ surveyTimer && clearTimeout(surveyTimer);
2002
+ openUserSurveyDialog(true);
2003
+ }
2004
+ }, [surveyTimer, isShowSurvey]);
2005
+ useEffect(() => {
2006
+ // Опрос показывается только если ранее пользоваютелю не показывался опрос или с того момента прошел месяц
2007
+ if (!withoutTimer && isShowSurvey) {
2008
+ // начинаем отсчитывать время от первого захода на сайт
2009
+ if (!sessionStore.surveyTimerStart) {
2010
+ sessionStore.surveyTimerStart = Date.now().toString();
2011
+ }
2012
+ // Опрос показывается спустя 5 минут нахождения на сайте
2013
+ const timeout = setTimeout(openUserSurveyDialog, DELAY - elapsedTime);
2014
+ sessionStore.surveyTimerId = timeout;
2015
+ return () => {
2016
+ clearTimeout(timeout);
2017
+ sessionStore.surveyTimerId = null;
2018
+ };
2019
+ }
2020
+ return noop;
2021
+ }, [isShowSurvey]);
2022
+ return handleOpenSurveyAction;
2023
+ };
2024
+
1387
2025
  const SERVICE_TYPES = [{ key: 'ULTRASERVICE', text: 'Ультра' }];
1388
2026
  const SERVICE_DIRECTIONS = [
1389
2027
  { key: 'Физическое лицо' },
@@ -1492,98 +2130,23 @@
1492
2130
  { key: 'Специалитет', text: 'Специалитет' },
1493
2131
  { key: 'Магистратура', text: 'Магистратура' },
1494
2132
  { key: 'Аспирантура', text: 'Аспирантура' },
1495
- ];
1496
-
1497
- // TODO Базовая функицональность всех Control - надо вынести и привязать к required флагу
1498
- const getRequiredLabel = ({ label, required = false }) => label && required ? `${label}*` : label;
1499
-
1500
- 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 }));
1501
-
1502
- const debounce = (fn, delay = 600) => {
1503
- let timerId;
1504
- const debouncedCallback = (...args) => {
1505
- debouncedCallback.dispose();
1506
- timerId = setTimeout(() => {
1507
- fn(...args);
1508
- }, delay);
1509
- };
1510
- debouncedCallback.dispose = () => {
1511
- if (timerId) {
1512
- clearTimeout(timerId);
1513
- }
1514
- };
1515
- return debouncedCallback;
1516
- };
1517
-
1518
- const renderLabel$1 = (label) => label ? (jsx(Text, { size: "text-m", color: "text-primary-text", font: "font-light", children: label })) : null;
1519
-
1520
- function useEventListener(target, type, listener, options) {
1521
- useEffect(() => {
1522
- if (!target || !listener) {
1523
- return;
1524
- }
1525
- target.addEventListener(type, listener, options);
1526
- return () => {
1527
- target.removeEventListener(type, listener, options);
1528
- };
1529
- }, [target, type, listener]);
1530
- }
1531
-
1532
- function useOutsideClick(onClick) {
1533
- const targetRef = useRef(null);
1534
- const handleClickOutside = useCallback((event) => {
1535
- if (targetRef && targetRef.current && event.target instanceof Node && !targetRef.current.contains(event.target)) {
1536
- onClick();
1537
- }
1538
- }, [onClick]);
1539
- useEventListener(globalThis.document, 'click', handleClickOutside);
1540
- return targetRef;
1541
- }
1542
-
1543
- const inputValidStyle = 'border border-solid outline-none border-gray hover:border-primary-hover active:border-primary-text focus:border-primary-text rounded';
1544
-
1545
- const getValidStyle = (valid) => (valid ? inputValidStyle : 'border-error');
1546
-
1547
- const defaultStyle$1 = 'w-full border rounded-md text-primary-text outline-none p-m';
1548
- const borderStyle = 'border-dashed';
1549
-
1550
- const Input = JSX(
1551
- // eslint-disable-next-line max-lines-per-function
1552
- ({ key, className, id, name, type = 'text', label, placeholder, value = '', valid = true, pattern, autoFocus = false, isTextarea = false, disabled = false, children, onChange, onFocus, onBlur, }) => {
1553
- const inputRef = useRef(null);
1554
- const handleChange = useCallback((e) => {
1555
- const valueWithoutSpace = (e.target?.value ?? '').trimStart();
1556
- onChange && onChange(valueWithoutSpace);
1557
- }, [onChange]);
1558
- useEffect(() => {
1559
- if (autoFocus) {
1560
- inputRef.current?.focus();
1561
- }
1562
- }, [autoFocus, inputRef]);
1563
- const paddingStyle = children ? 'pr-3xl' : '';
1564
- const validStyle = getValidStyle(valid);
1565
- const ariaLabel = label ?? name ?? id;
1566
- 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] }));
1567
- });
2133
+ ];
1568
2134
 
1569
- const InputWrapper = JSX(({ className, label, value = '', error, errors, type, isInteger, placeholder, maxLength, inputRef, isOpen, onOpen, onClose, required, onChange = noop, ...rest }) => {
1570
- const popupRef = useOutsideClick(onClose);
1571
- const handleChange = useCallback((v) => {
1572
- const isOverMax = maxLength && v.length > maxLength;
1573
- !isOpen && onOpen();
1574
- if (!isOverMax) {
1575
- onChange(normalizeInteger(v, isInteger));
2135
+ const debounce = (fn, delay = 600) => {
2136
+ let timerId;
2137
+ const debouncedCallback = (...args) => {
2138
+ debouncedCallback.dispose();
2139
+ timerId = setTimeout(() => {
2140
+ fn(...args);
2141
+ }, delay);
2142
+ };
2143
+ debouncedCallback.dispose = () => {
2144
+ if (timerId) {
2145
+ clearTimeout(timerId);
1576
2146
  }
1577
- }, [isOpen, onChange]);
1578
- 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)] }));
1579
- });
1580
- const normalizeInteger = (val = '', isInteger = false) => isInteger && val ? val.replace(/[^\d]+/g, '') : val;
1581
- const getPlaceholder = ({ placeholder, errors, label }) => errors && !label ? `${placeholder}*` : placeholder;
1582
-
1583
- const InputControl = JSX((props) => {
1584
- const [isOpen, { setFalse: close, setTrue: open }] = useBool();
1585
- return jsx(InputWrapper, { isOpen: isOpen, onOpen: open, onClose: close, ...props });
1586
- });
2147
+ };
2148
+ return debouncedCallback;
2149
+ };
1587
2150
 
1588
2151
  const renderSearchInput = ({ query, isDisabled, onChangeQuery, inputProps, }) => (jsx("div", { className: "absolute top-0 w-full z-20", children: jsx(InputControl, { type: "text", value: query, autoFocus: true, disabled: isDisabled, onChange: (value) => onChangeQuery(value), maxLength: inputProps?.maxLength, isInteger: inputProps?.isInteger ?? false }) }));
1589
2152
 
@@ -1725,7 +2288,7 @@
1725
2288
  const formatData = {
1726
2289
  ...usedData,
1727
2290
  ...getVedTypes(vedTypes),
1728
- ...getRegion$1(region),
2291
+ ...getRegion(region),
1729
2292
  ...(inn && { inn }),
1730
2293
  ...(partnerComments ? { partnerComments } : {}),
1731
2294
  ...(serviceType ? { typeForm: serviceType } : {}),
@@ -1742,7 +2305,7 @@
1742
2305
  const getIncidentComment = (sufferedFrom, situationDescription) => sufferedFrom || situationDescription
1743
2306
  ? { comment: `${sufferedFrom || ''};${situationDescription || ''}` }
1744
2307
  : {};
1745
- const getRegion$1 = (region) => region?.key || region?.text ? { region: region?.text || region?.key } : {};
2308
+ const getRegion = (region) => region?.key || region?.text ? { region: region?.text || region?.key } : {};
1746
2309
  const getVedTypes = (vedTypes) => vedTypes
1747
2310
  ? {
1748
2311
  vedTypes: Object.fromEntries(VED_TYPES.map(({ id }) => [id, id === vedTypes])),
@@ -1776,239 +2339,20 @@
1776
2339
  vedTypes: VED_TYPES[0].id,
1777
2340
  birthday: undefined,
1778
2341
  isClient: false,
1779
- onlineCheckout: false,
1780
- posTerminal: false,
1781
- consentToReceiveMaterials: false,
1782
- consentDataProcessing: false,
1783
- addressRetail: { key: '', text: '' },
1784
- fileUpload: '',
1785
- fileId: '',
1786
- };
1787
- const getInitialFormState$2 = (inputs, typeForm = '') => {
1788
- const formState = Object.fromEntries(inputs.map((_) => [
1789
- _.name,
1790
- (_?.name === 'vedTypes' && _?.defaultValue) || initialFormState$1[_.name || ''],
1791
- ]));
1792
- return { ...formState, typeForm: { key: typeForm, text: '' } };
1793
- };
1794
-
1795
- const getUserTimezoneOffset = () => {
1796
- const offset = new Date().getTimezoneOffset();
1797
- const absOffset = Math.abs(offset);
1798
- const hours = Math.floor(absOffset / 60);
1799
- const minutes = absOffset % 60;
1800
- const sign = offset < 0 ? '+' : '-';
1801
- return `GMT${sign}${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
1802
- };
1803
-
1804
- const API_BASE_URI = '/api/v1';
1805
-
1806
- const ENDPOINT_MAPPING = {
1807
- lead: {
1808
- withTypeForm: true,
1809
- isNaturalEndpoint: true,
1810
- },
1811
- sendcorporatelead: {
1812
- withTypeForm: true,
1813
- isNaturalEndpoint: false,
1814
- },
1815
- practice: {
1816
- withTypeForm: false,
1817
- isNaturalEndpoint: true,
1818
- },
1819
- internship: {
1820
- withTypeForm: false,
1821
- isNaturalEndpoint: true,
1822
- },
1823
- initcorporatelead: {
1824
- withTypeForm: true,
1825
- isNaturalEndpoint: false,
1826
- },
1827
- confirmCorporateLead: {
1828
- withTypeForm: true,
1829
- isNaturalEndpoint: false,
1830
- },
1831
- callback: {
1832
- withTypeForm: false,
1833
- isNaturalEndpoint: true,
1834
- },
1835
- };
1836
-
1837
- const formatDate = (date, toTimeStamp = false) => {
1838
- if (typeof date === 'string') {
1839
- return date.split('-').reverse().join('.');
1840
- }
1841
- else {
1842
- const day = String(date.getDate()).padStart(2, '0');
1843
- const month = String(date.getMonth() + 1).padStart(2, '0');
1844
- const year = String(date.getFullYear());
1845
- return toTimeStamp ? `${year}-${month}-${day}` : `${day}.${month}.${year}`;
1846
- }
1847
- };
1848
-
1849
- const formatPhone = (phone) => phone?.replace(/[^+\d]/g, '');
1850
-
1851
- const getSubmitBody = ({ body, endpoint, router }) => {
1852
- const isNaturalPerson = endpoint && ENDPOINT_MAPPING[endpoint].isNaturalEndpoint;
1853
- const withTypeForm = endpoint && ENDPOINT_MAPPING[endpoint].withTypeForm;
1854
- const { typeForm, region, phone = '', email, birthday, desiredMeetingDate, fullRegion, addressBranch, secondaryPhone = '', bankEmpolee, applicationDate, partnerName, russianPhone, partnerSymbolCode, internshipEndDate, internshipStartDate, ...staticBody } = body;
1855
- return {
1856
- ...(withTypeForm ? { typeForm } : {}),
1857
- ...getRegion(region, isNaturalPerson),
1858
- ...getEmail(email, isNaturalPerson),
1859
- ...getPhone(phone),
1860
- ...getPhone(russianPhone),
1861
- ...(isNaturalPerson ? getFormatDate([[birthday, 'birthday']]) : { birthday }),
1862
- ...getFormatDate([
1863
- [desiredMeetingDate, 'desiredMeetingDate'],
1864
- [internshipEndDate, 'internshipEndDate'],
1865
- [internshipStartDate, 'internshipStartDate'],
1866
- ]),
1867
- ...(typeForm === 'FEEDBACK'
1868
- ? {}
1869
- : {
1870
- addressBranch,
1871
- bankEmpolee,
1872
- applicationDate,
1873
- ...getSecondaryPhone(secondaryPhone),
1874
- }),
1875
- ...addPageSlug(typeForm, router),
1876
- ...formatPFForm(typeForm, {
1877
- fullRegion,
1878
- partnerName,
1879
- partnerSymbolCode,
1880
- }),
1881
- ...getRkoTariffName(typeForm),
1882
- ...staticBody,
1883
- };
1884
- };
1885
- const getPhoneBody = (phone) => {
1886
- return {
1887
- ...getPhone(phone),
1888
- };
1889
- };
1890
- const getPhone = (phone) => (phone ? { phone: formatPhone(phone) } : {});
1891
- const getFormatDate = (dates) => Object.fromEntries(dates.filter(([value]) => value).map(([value, key]) => [key, formatDate(value)]));
1892
- const getRegion = (region, isNaturalPerson = true) => ({
1893
- [isNaturalPerson ? 'regionBranch' : 'region']: region,
1894
- });
1895
- const getEmail = (email, isNaturalPerson = true) => ({
1896
- [isNaturalPerson ? 'email' : 'mail']: email,
1897
- });
1898
- const getSecondaryPhone = (secondaryPhone = '') => !secondaryPhone || secondaryPhone === '+7 ('
1899
- ? {}
1900
- : { secondaryPhoneNumber: formatPhone(secondaryPhone) };
1901
- const formatPFForm = (typeForm, data) => typeForm === 'PF'
1902
- ? {
1903
- region: data?.fullRegion,
1904
- partner: data?.partnerName,
1905
- partnerId: data?.partnerSymbolCode,
1906
- }
1907
- : {};
1908
- const addPageSlug = (typeForm, router) => typeForm === 'UNIVERSAL'
1909
- ? {
1910
- typeForm: router?.pathname?.split('/')?.at(-1) || '/',
1911
- }
1912
- : {};
1913
- const getRkoTariffName = (typeForm) => typeForm === 'CALC'
1914
- ? {
1915
- partnerComments: globalThis?.sessionStorage.getItem('rkoTariffName') ?? 'Неизвестный тариф',
1916
- }
1917
- : {};
1918
-
1919
- // eslint-disable-next-line max-lines-per-function
1920
- function LeadServiceAPI() {
1921
- async function send({ body, router, endpoint }) {
1922
- const calculatedEndpoint = endpoint && getEndpoint(endpoint, body);
1923
- const url = `${API_BASE_URI}/${calculatedEndpoint}`;
1924
- const submitBody = getSubmitBody({
1925
- body,
1926
- endpoint,
1927
- router,
1928
- });
1929
- try {
1930
- const response = await LeadServiceFetch(url, submitBody);
1931
- if (!response?.ok) {
1932
- return null;
1933
- }
1934
- return await response.json();
1935
- }
1936
- catch (e) {
1937
- return null;
1938
- }
1939
- }
1940
- async function sendCode({ phone }) {
1941
- const submitBody = getPhoneBody(phone);
1942
- try {
1943
- const response = LeadServiceFetch(`${API_BASE_URI}/initCorporateLead`, submitBody).then(async (res) => {
1944
- if (!res.ok) {
1945
- throw new Error(`Ошибка HTTP: ${res.status}`);
1946
- }
1947
- return await res.text();
1948
- });
1949
- return await response;
1950
- }
1951
- catch (e) {
1952
- return null;
1953
- }
1954
- }
1955
- async function checkCode({ reqId, code, body, router, endpoint = 'confirmCorporateLead', }) {
1956
- const submitBody = {
1957
- requestId: reqId,
1958
- confimationCode: code,
1959
- leadRequest: getSubmitBody({ body, endpoint, router }),
1960
- };
1961
- try {
1962
- const response = await LeadServiceFetch(`${API_BASE_URI}/${endpoint}`, submitBody);
1963
- return await response.json();
1964
- }
1965
- catch (e) {
1966
- return null;
1967
- }
1968
- }
1969
- async function sendPhoneCallRequest(body, endpoint) {
1970
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1971
- const submitBody = getSubmitBody({ body, endpoint });
1972
- const formatSubmitBody = getFormatCallbackSubmitBody(submitBody);
1973
- try {
1974
- const response = await LeadServiceFetch(`${API_BASE_URI}/callback`, formatSubmitBody);
1975
- if (!response?.ok) {
1976
- return null;
1977
- }
1978
- return await response.json();
1979
- }
1980
- catch (e) {
1981
- return null;
1982
- }
1983
- }
1984
- return {
1985
- send,
1986
- sendCode,
1987
- checkCode,
1988
- sendPhoneCallRequest,
1989
- };
1990
- }
1991
- const LeadServiceFetch = (url, submitBody) => fetch(url, {
1992
- method: 'POST',
1993
- headers: { 'Content-Type': 'application/json' },
1994
- mode: 'cors',
1995
- body: JSON.stringify(submitBody),
1996
- });
1997
- const getFormatCallbackSubmitBody = (submitBody) => {
1998
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1999
- const { typeForm, consentDataProcessing, phone, ...rest } = submitBody;
2000
- return {
2001
- ...rest,
2002
- phone: phone?.startsWith('+') ? phone.slice(1) : phone,
2003
- clientTimezone: getUserTimezoneOffset(),
2004
- };
2342
+ onlineCheckout: false,
2343
+ posTerminal: false,
2344
+ consentToReceiveMaterials: false,
2345
+ consentDataProcessing: false,
2346
+ addressRetail: { key: '', text: '' },
2347
+ fileUpload: '',
2348
+ fileId: '',
2005
2349
  };
2006
- const getEndpoint = (endpoint, body) => {
2007
- const { serviceDirection } = body;
2008
- if (endpoint === 'lead' && serviceDirection !== 'Юридическое лицо / ИП') {
2009
- return 'lead';
2010
- }
2011
- return endpoint;
2350
+ const getInitialFormState$2 = (inputs, typeForm = '') => {
2351
+ const formState = Object.fromEntries(inputs.map((_) => [
2352
+ _.name,
2353
+ (_?.name === 'vedTypes' && _?.defaultValue) || initialFormState$1[_.name || ''],
2354
+ ]));
2355
+ return { ...formState, typeForm: { key: typeForm, text: '' } };
2012
2356
  };
2013
2357
 
2014
2358
  const getAspectsWithInclude = (data, include) => data?.map(({ aspectName, params }) => ({
@@ -2026,8 +2370,9 @@
2026
2370
  };
2027
2371
 
2028
2372
  const API$2 = LeadServiceAPI();
2029
- const handleInitCorporateLead = async ({ formatData = {}, typeForm, responseTypeDialog, verifyPhoneDialog, data = [], aspects = {}, ev, }) => {
2373
+ const handleInitCorporateLead = async ({ formatData = {}, typeForm, responseTypeDialog, verifyPhoneDialog, data = [], aspects = {}, ev, openUserSurvey, }) => {
2030
2374
  const { phone } = formatData;
2375
+ const hasSurveyAspect = data?.find((_) => _.aspectName === 'openUserSurvey');
2031
2376
  const response = await API$2.sendCode({ phone: String(phone) });
2032
2377
  if (!response) {
2033
2378
  responseTypeDialog.open({ ok: Boolean(response), typeForm });
@@ -2045,6 +2390,7 @@
2045
2390
  phone,
2046
2391
  id,
2047
2392
  });
2393
+ hasSurveyAspect && openUserSurvey?.();
2048
2394
  handleAspects({
2049
2395
  aspectsAttributes: getAspectsWithInclude(data, snowplowParams),
2050
2396
  aspects,
@@ -2053,11 +2399,13 @@
2053
2399
  },
2054
2400
  });
2055
2401
  };
2056
- const handleCallback = async ({ formatData, data, aspects = {}, ev, typeForm, responseTypeDialog, onSuccess = noop, endpoint, }) => {
2402
+ const handleCallback = async ({ formatData, data, aspects = {}, ev, typeForm, responseTypeDialog, onSuccess = noop, endpoint, openUserSurvey, }) => {
2403
+ const hasSurveyAspect = data?.find((_) => _.aspectName === 'openUserSurvey');
2057
2404
  const response = await API$2.sendPhoneCallRequest(formatData, endpoint);
2058
2405
  onSuccess();
2059
2406
  if (response?.status === 'success') {
2060
2407
  responseTypeDialog.open({ ok: true, typeForm });
2408
+ hasSurveyAspect && openUserSurvey?.();
2061
2409
  handleAspects({ aspectsAttributes: data, aspects, ev });
2062
2410
  }
2063
2411
  else if (response?.status === 'error') {
@@ -2073,11 +2421,13 @@
2073
2421
  }
2074
2422
  }
2075
2423
  };
2076
- const handleDefault = async ({ formatData, data, aspects = {}, ev, router, responseTypeDialog, endpoint, withSnowplow, }) => {
2424
+ const handleDefault = async ({ formatData, data, aspects = {}, ev, router, responseTypeDialog, endpoint, withSnowplow, openUserSurvey, }) => {
2425
+ const hasSurveyAspect = data?.find((_) => _.aspectName === 'openUserSurvey');
2077
2426
  const response = await API$2.send({ body: formatData, router, endpoint });
2078
2427
  const ok = Boolean(response);
2079
2428
  responseTypeDialog.open({ ok });
2080
2429
  if (ok) {
2430
+ hasSurveyAspect && openUserSurvey?.();
2081
2431
  const { requestId } = response;
2082
2432
  const { phone } = formatData;
2083
2433
  const utms = router.pathname.split('?')[1];
@@ -2098,45 +2448,6 @@
2098
2448
  }
2099
2449
  };
2100
2450
 
2101
- 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, {
2102
- 'backdrop-blur': blur,
2103
- }), 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" }) })));
2104
-
2105
- 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] })));
2106
-
2107
- const SVG = JSX(({ className, viewBox, fill = 'none', width, height, paths, ...commonOptions }) => {
2108
- 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) => {
2109
- const resultOptions = { ...commonOptions, ...options };
2110
- return (jsx("path", { d: d, fill: pathFill || 'currentColor', stroke: resultOptions.stroke, strokeLinecap: resultOptions.strokeLinecap, strokeLinejoin: resultOptions.strokeLinejoin, strokeWidth: resultOptions.strokeWidth, strokeMiterlimit: resultOptions.strokeMiterlimit }, i));
2111
- }) }));
2112
- });
2113
-
2114
- const defaultCheckStyle = 'appearance-none w-5 h-5 border-solid flex-none';
2115
-
2116
- const CHECK_PATHS = [
2117
- {
2118
- 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',
2119
- fillRule: 'evenodd',
2120
- clipRule: 'evenodd',
2121
- fill: 'white',
2122
- },
2123
- ];
2124
- const Checkbox = JSX(({ className, value, text, disabled, isRadio, onChange, name }) => {
2125
- const handleChange = useCallback((e) => {
2126
- if (disabled) {
2127
- return;
2128
- }
2129
- e.preventDefault();
2130
- onChange && onChange(!value);
2131
- }, [onChange, disabled, value]);
2132
- 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" }));
2133
- 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$4(text)] }) }));
2134
- });
2135
- const renderText$4 = (text) => text ? (jsx("div", { className: "ml-s", children: jsx(Text, { size: "text-l", font: "font-light", children: text }) })) : null;
2136
- const getCursorStyle = (disabled = false) => (disabled ? 'cursor-not-allowed' : 'cursor-pointer');
2137
- const role = (isRadio = false) => (isRadio ? 'radio' : 'checkbox');
2138
- const checkboxStyle = (value = false) => style('rounded border', { 'bg-primary-main': value });
2139
-
2140
2451
  const withValidator = (props, validator) => {
2141
2452
  const { value, isDirty } = props;
2142
2453
  const errors = isDirty ? validator(value) : [];
@@ -3355,12 +3666,6 @@
3355
3666
 
3356
3667
  const UltraPremiumField = JSX(({ field, input }) => (jsx(SelectControl, { label: "\u0422\u0438\u043F \u043E\u0431\u0441\u043B\u0443\u0436\u0438\u0432\u0430\u043D\u0438\u044F", options: SERVICE_TYPES, ...field(input?.name ?? ''), ...input })));
3357
3668
 
3358
- const orientationStyleMap = {
3359
- horizontal: '@lg:flex-row',
3360
- vertical: '',
3361
- };
3362
- 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)))) })] })));
3363
-
3364
3669
  const VedField = JSX(({ field, input }) => {
3365
3670
  const handleChange = useCallback((_) => {
3366
3671
  if (_ !== 'currencyControl') {
@@ -3614,242 +3919,100 @@
3614
3919
  const CODE_LENGTH$1 = 4;
3615
3920
  const TIME_TO_RESEND$1 = 180;
3616
3921
  const VerifyPhoneDialog$1 = JSX(({ phone, onSuccess = noop, onClose = noop, formatData = {}, reqId }) => {
3617
- const [values, setValues] = useState(Array(CODE_LENGTH$1).fill(''));
3618
- const [requestId, setRequestId] = useState(reqId);
3619
- const { handleSubmit, hasError, errorText, isLoading, timeNextReq, isSubmitButtonDisabled, setTimeNextReq, setErrorText, } = useVerifyPhoneDialogSubmit$1({
3620
- values,
3621
- onSuccess,
3622
- formatData,
3623
- reqId: requestId ?? '',
3624
- });
3625
- const phoneNumber = formatPhone(phone);
3626
- const restartTimer = useCountDownTimer({ seconds: timeNextReq, onTick: setTimeNextReq });
3627
- const handleSendCode = useCallback(async () => {
3628
- const response = await API.sendCode({ phone: phoneNumber });
3629
- if (response) {
3630
- setTimeNextReq(TIME_TO_RESEND$1);
3631
- restartTimer(TIME_TO_RESEND$1);
3632
- setErrorText('');
3633
- setRequestId(String(response));
3634
- }
3635
- }, [phoneNumber, restartTimer, onClose]);
3636
- 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 }));
3637
- });
3638
-
3639
- const handlerMap = {
3640
- initcorporatelead: handleInitCorporateLead,
3641
- callback: handleCallback,
3642
- default: handleDefault,
3643
- };
3644
- const ApplicationForm = UniBlock(
3645
- // eslint-disable-next-line max-lines-per-function
3646
- ({ className, title, typeForm = '', sections = [], button, link, endpoint, additionalParams, withSnowplow, isContacts, data, onSuccess, ...rest }) => {
3647
- const inputs = useMemo(() => (sections?.flatMap((_) => _?.inputs) || []), [sections]);
3648
- const initialFormState = useMemo(() => getInitialFormState$2(inputs, typeForm), [inputs, typeForm]);
3649
- const router = useRouter();
3650
- const aspects = useAspects();
3651
- const formValidator = useMemo(() => getFormValidator(inputs), [inputs]);
3652
- const responseTypeDialog = useDialog(ResponseTypeDialog);
3653
- const verifyPhoneDialog = useDialog(VerifyPhoneDialog$1);
3654
- const handleSubmit = useCallback(async (formData, ev) => {
3655
- const formatData = getFormatData({ ...formData, ...additionalParams });
3656
- await executeHandler({
3657
- formatData,
3658
- ev,
3659
- typeForm,
3660
- data,
3661
- aspects,
3662
- router,
3663
- responseTypeDialog,
3664
- verifyPhoneDialog,
3665
- onSuccess,
3666
- withSnowplow,
3667
- }, endpoint);
3668
- }, [typeForm]);
3669
- const [, { field, onSubmit }] = useForm(initialFormState, {
3670
- resetOnSubmit: true,
3671
- formValidator,
3672
- onSubmit: handleSubmit,
3673
- });
3674
- const fieldName = getConsentDataProcessing(inputs)?.name;
3675
- const consentDataProcessing = fieldName ? field('consentDataProcessing') : undefined;
3676
- 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({
3677
- consentDataProcessing,
3678
- link,
3679
- button,
3680
- typeForm,
3681
- })] }), isContacts ? renderContacts() : null] }));
3682
- });
3683
- const executeHandler = async (context, endpoint) => {
3684
- const handler = (endpoint && handlerMap[endpoint]) || handlerMap.default;
3685
- await handler({ ...context, endpoint });
3686
- };
3687
-
3688
- const mapProductTypeToName = {
3689
- creditCard: 'кредитной карты',
3690
- debitCard: 'дебетовой карты',
3691
- credit: 'кредита',
3692
- };
3693
- const NoConsentDialog = JSX(({ attempts, productType, onClose = noop }) => {
3694
- const navigator = locationNavigator();
3695
- const isMaxAttempts = attempts > 1;
3696
- const returnToMainPage = useCallback(() => {
3697
- navigator.assign('/natural');
3698
- }, []);
3699
- const handleClose = useCallback(() => {
3700
- if (isMaxAttempts) {
3701
- returnToMainPage();
3702
- }
3703
- else {
3704
- onClose();
3705
- }
3706
- }, [isMaxAttempts]);
3707
- 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" }))] })] }) }));
3708
- });
3709
-
3710
- function copy(source, target) {
3711
- for (const [k, v] of source.entries()) {
3712
- if (v !== null && v !== undefined) {
3713
- target.setItem(k, v);
3714
- }
3715
- else {
3716
- target.removeItem(k);
3717
- }
3718
- }
3719
- }
3720
-
3721
- function replicate(primary, secondary) {
3722
- copy(primary, secondary);
3723
- copy(secondary, primary);
3724
- return primary.bus.watch(({ type, event }) => {
3725
- if (event !== null && event !== undefined) {
3726
- secondary.setItem(type, event);
3727
- }
3728
- else {
3729
- secondary.removeItem(type);
3730
- }
3731
- });
3732
- }
3733
-
3734
- class StorageAdapter {
3735
- storage;
3736
- bus;
3737
- get size() {
3738
- return this.storage?.length ?? 0;
3739
- }
3740
- constructor(storage, bus = new EventBus()) {
3741
- this.storage = storage;
3742
- this.bus = bus;
3743
- }
3744
- hasItem(key) {
3745
- return Boolean(this.storage?.getItem(String(key)));
3746
- }
3747
- getItem(key) {
3748
- const _ = this.storage?.getItem(String(key)) ?? null;
3749
- try {
3750
- return JSON.parse(String(_));
3751
- }
3752
- catch (ex) {
3753
- return null;
3754
- }
3755
- }
3756
- entries() {
3757
- return Array.from({ length: this.size }, (_, i) => {
3758
- const k = String(this.storage?.key(i));
3759
- return [k, this.getItem(k)];
3760
- });
3761
- }
3762
- setItem(key, value) {
3763
- if (value !== null) {
3764
- this.storage?.setItem(String(key), JSON.stringify(value));
3765
- }
3766
- else {
3767
- this.storage?.removeItem(String(key));
3768
- }
3769
- this.bus?.subject(key, value);
3770
- }
3771
- removeItem(key) {
3772
- this.storage?.removeItem(String(key));
3773
- this.bus?.subject(key, null);
3774
- }
3775
- }
3776
-
3777
- class Store {
3778
- bus;
3779
- store = new Map();
3780
- get size() {
3781
- return this.store.size;
3782
- }
3783
- constructor(bus = new EventBus()) {
3784
- this.bus = bus;
3785
- }
3786
- hasItem(key) {
3787
- return this.store.has(key);
3788
- }
3789
- getItem(key) {
3790
- return this.store.get(key);
3791
- }
3792
- entries() {
3793
- return this.store.entries();
3794
- }
3795
- setItem(key, value) {
3796
- this.store.set(key, value);
3797
- this.bus.subject(key, value);
3798
- }
3799
- removeItem(key) {
3800
- this.store.delete(key);
3801
- this.bus.subject(key, null);
3802
- }
3803
- }
3804
-
3805
- function useRerender() {
3806
- const [, setCount] = useState(0);
3807
- return useCallback(() => setCount(_ => (_ + 1) % (1 << 16)), []);
3808
- }
3922
+ const [values, setValues] = useState(Array(CODE_LENGTH$1).fill(''));
3923
+ const [requestId, setRequestId] = useState(reqId);
3924
+ const { handleSubmit, hasError, errorText, isLoading, timeNextReq, isSubmitButtonDisabled, setTimeNextReq, setErrorText, } = useVerifyPhoneDialogSubmit$1({
3925
+ values,
3926
+ onSuccess,
3927
+ formatData,
3928
+ reqId: requestId ?? '',
3929
+ });
3930
+ const phoneNumber = formatPhone(phone);
3931
+ const restartTimer = useCountDownTimer({ seconds: timeNextReq, onTick: setTimeNextReq });
3932
+ const handleSendCode = useCallback(async () => {
3933
+ const response = await API.sendCode({ phone: phoneNumber });
3934
+ if (response) {
3935
+ setTimeNextReq(TIME_TO_RESEND$1);
3936
+ restartTimer(TIME_TO_RESEND$1);
3937
+ setErrorText('');
3938
+ setRequestId(String(response));
3939
+ }
3940
+ }, [phoneNumber, restartTimer, onClose]);
3941
+ return (jsx(VerifyPhoneDialogLayout, { isSubmitButtonDisabled: isSubmitButtonDisabled, onSubmit: handleSubmit, onSendCode: handleSendCode, timeNextReq: timeNextReq, values: values, onChange: setValues, phone: phone, isLoading: isLoading, errorText: errorText, hasError: hasError, onClose: onClose }));
3942
+ });
3809
3943
 
3810
- const DEFAULT_METHODS = {};
3811
- /**
3812
- * MobX like reactivity (simplified).
3813
- * Can be used to migrate from Redux/MobX or something else
3814
- *
3815
- * @param store
3816
- * @returns reactive proxy backed by store
3817
- */
3818
- function useStore(store, methods = DEFAULT_METHODS) {
3819
- const deps = useRef(null);
3820
- const render = useRerender();
3821
- useEffect(() => store.bus.watch(ev => {
3822
- if (deps.current?.has(String(ev.type))) {
3823
- render();
3824
- }
3825
- }), [store, render]);
3826
- return useMemo(() => new Proxy(methods, {
3827
- get(_, key) {
3828
- deps.current ||= new Set();
3829
- deps.current.add(key);
3830
- return store.getItem(key);
3831
- },
3832
- has(_, key) {
3833
- deps.current ||= new Set();
3834
- deps.current.add(key);
3835
- return store.hasItem(key);
3836
- },
3837
- set(_, key, value) {
3838
- store.setItem(key, value);
3839
- return true;
3840
- },
3841
- deleteProperty(_, key) {
3842
- store.removeItem(key);
3843
- return true;
3844
- }
3845
- }), [store]);
3846
- }
3944
+ const handlerMap = {
3945
+ initcorporatelead: handleInitCorporateLead,
3946
+ callback: handleCallback,
3947
+ default: handleDefault,
3948
+ };
3949
+ const ApplicationForm = UniBlock(
3950
+ // eslint-disable-next-line max-lines-per-function
3951
+ ({ className, title, typeForm = '', sections = [], button, link, endpoint, additionalParams, withSnowplow, isContacts, data, onSuccess, ...rest }) => {
3952
+ const inputs = useMemo(() => (sections?.flatMap((_) => _?.inputs) || []), [sections]);
3953
+ const initialFormState = useMemo(() => getInitialFormState$2(inputs, typeForm), [inputs, typeForm]);
3954
+ const router = useRouter();
3955
+ const aspects = useAspects();
3956
+ const formValidator = useMemo(() => getFormValidator(inputs), [inputs]);
3957
+ const responseTypeDialog = useDialog(ResponseTypeDialog);
3958
+ const verifyPhoneDialog = useDialog(VerifyPhoneDialog$1);
3959
+ const openUserSurvey = useUserSurveyDialog(true);
3960
+ const handleSubmit = useCallback(async (formData, ev) => {
3961
+ const formatData = getFormatData({ ...formData, ...additionalParams });
3962
+ await executeHandler({
3963
+ formatData,
3964
+ ev,
3965
+ typeForm,
3966
+ data,
3967
+ aspects,
3968
+ router,
3969
+ responseTypeDialog,
3970
+ verifyPhoneDialog,
3971
+ onSuccess,
3972
+ withSnowplow,
3973
+ openUserSurvey,
3974
+ }, endpoint);
3975
+ }, [typeForm]);
3976
+ const [, { field, onSubmit }] = useForm(initialFormState, {
3977
+ resetOnSubmit: true,
3978
+ formValidator,
3979
+ onSubmit: handleSubmit,
3980
+ });
3981
+ const fieldName = getConsentDataProcessing(inputs)?.name;
3982
+ const consentDataProcessing = fieldName ? field('consentDataProcessing') : undefined;
3983
+ return (jsxs(ApplicationFormLayout, { className: style('container space-y-m', className), title: title, ...rest, children: [jsxs("form", { onSubmit: onSubmit, children: [renderSections(sections, field, { typeForm, additionalParams }), renderAgreementSubmit({
3984
+ consentDataProcessing,
3985
+ link,
3986
+ button,
3987
+ typeForm,
3988
+ })] }), isContacts ? renderContacts() : null] }));
3989
+ });
3990
+ const executeHandler = async (context, endpoint) => {
3991
+ const handler = (endpoint && handlerMap[endpoint]) || handlerMap.default;
3992
+ await handler({ ...context, endpoint });
3993
+ };
3847
3994
 
3848
- const sessionStore = new Store(); // sessionStorage cache
3849
- replicate(sessionStore, new StorageAdapter(globalThis?.sessionStorage));
3850
- function useSessionStore() {
3851
- return useStore(sessionStore);
3852
- }
3995
+ const mapProductTypeToName = {
3996
+ creditCard: 'кредитной карты',
3997
+ debitCard: 'дебетовой карты',
3998
+ credit: 'кредита',
3999
+ };
4000
+ const NoConsentDialog = JSX(({ attempts, productType, onClose = noop }) => {
4001
+ const navigator = locationNavigator();
4002
+ const isMaxAttempts = attempts > 1;
4003
+ const returnToMainPage = useCallback(() => {
4004
+ navigator.assign('/natural');
4005
+ }, []);
4006
+ const handleClose = useCallback(() => {
4007
+ if (isMaxAttempts) {
4008
+ returnToMainPage();
4009
+ }
4010
+ else {
4011
+ onClose();
4012
+ }
4013
+ }, [isMaxAttempts]);
4014
+ return (jsx(Dialog, { onClose: handleClose, children: jsxs("div", { className: "flex flex-col gap-xl items-center", children: [jsx(Paragraph, { align: "text-center", children: "\u0423\u0432\u0430\u0436\u0430\u0435\u043C\u044B\u0439 \u043A\u043B\u0438\u0435\u043D\u0442!" }), jsx(Paragraph, { align: "text-center", children: `Для получения ${mapProductTypeToName[productType]} Вам необходимо обратиться в офис Банка` }), jsxs("div", { className: "flex flex-col sm:flex-row gap-xl items-center", children: [jsx(Button, { type: "button", version: "secondary", onClick: returnToMainPage, children: "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044C" }), isMaxAttempts ? null : (jsx(Button, { type: "button", onClick: onClose, children: "\u041F\u0440\u043E\u0434\u043E\u043B\u0436\u0438\u0442\u044C" }))] })] }) }));
4015
+ });
3853
4016
 
3854
4017
  const getNS = (_) => globalThis[_];
3855
4018
  const initializeExternalNS = (namespaceName, url, isModule = false) => {
@@ -5166,12 +5329,6 @@
5166
5329
  return result || [];
5167
5330
  };
5168
5331
 
5169
- const localStore = new Store(); // localStorage cache
5170
- replicate(localStore, new StorageAdapter(globalThis?.localStorage));
5171
- function useLocalStore(methods) {
5172
- return useStore(localStore, methods);
5173
- }
5174
-
5175
5332
  const useRetailFormStore = () => {
5176
5333
  return useLocalStore();
5177
5334
  };
@@ -7383,6 +7540,9 @@
7383
7540
  };
7384
7541
  const getTaskSource = (source) => {
7385
7542
  switch (source) {
7543
+ case 'banki_ru': {
7544
+ return 'banki_ru';
7545
+ }
7386
7546
  case 'referal_sf': {
7387
7547
  return 'ReferalSF';
7388
7548
  }
@@ -11037,7 +11197,7 @@
11037
11197
  DELIVERY_CREDIT_CARD_CONTENT,
11038
11198
  ];
11039
11199
 
11040
- const STEPS$3 = 6;
11200
+ const STEPS$2 = 6;
11041
11201
  const TITLES = [
11042
11202
  'Параметры карты',
11043
11203
  'Персональные данные',
@@ -11052,7 +11212,7 @@
11052
11212
  const scrollToTop = useCallback(() => formContainerRef?.current?.scrollIntoView({ behavior: 'smooth' }), [formContainerRef]);
11053
11213
  useEffect(updateRefreshToken, []);
11054
11214
  const handleNextStep = useCallback(() => {
11055
- setStep((_) => Math.min(_ + 1, STEPS$3));
11215
+ setStep((_) => Math.min(_ + 1, STEPS$2));
11056
11216
  scrollToTop();
11057
11217
  }, []);
11058
11218
  const handlePrevStep = useCallback(() => {
@@ -11062,7 +11222,7 @@
11062
11222
  }, []);
11063
11223
  const sections = stepsSectionsMap$2[step];
11064
11224
  const [isFormFinished, { setTrue: handleFinish }] = useBool(false);
11065
- 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))) })] }) }));
11225
+ 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))) })] }) }));
11066
11226
  });
11067
11227
 
11068
11228
  const CreditFormProgress = JSX(({ step = 1, totalSteps = 5, stepsTitles = [] }) => {
@@ -11623,7 +11783,7 @@
11623
11783
  DELIVERY_CREDIT_CONTENT,
11624
11784
  ];
11625
11785
 
11626
- const STEPS$2 = 4;
11786
+ const STEPS$1 = 4;
11627
11787
  const STEP_TITLES$1 = [
11628
11788
  '',
11629
11789
  'Персональные данные',
@@ -11637,7 +11797,7 @@
11637
11797
  const scrollToTop = useCallback(() => formContainerRef?.current?.scrollIntoView({ behavior: 'smooth' }), [formContainerRef]);
11638
11798
  useEffect(updateRefreshToken, []);
11639
11799
  const handleNextStep = useCallback(() => {
11640
- setStep((_) => Math.min(_ + 1, STEPS$2));
11800
+ setStep((_) => Math.min(_ + 1, STEPS$1));
11641
11801
  scrollToTop();
11642
11802
  }, []);
11643
11803
  const handlePrevStep = useCallback(() => {
@@ -11648,7 +11808,7 @@
11648
11808
  const sections = stepsSectionsMap$1[step];
11649
11809
  const isStartStep = step === 0;
11650
11810
  const [isFormFinished, { setTrue: handleFinish }] = useBool(false);
11651
- 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))) })] }) }));
11811
+ 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))) })] }) }));
11652
11812
  });
11653
11813
 
11654
11814
  const DebitFormProgress = JSX(({ step = 1, totalSteps = 2, stepsTitles = [] }) => {
@@ -11659,8 +11819,11 @@
11659
11819
 
11660
11820
  const INTERNET_BANK_LINK = 'https://online.rshb.ru/d?l=dcNqSvOE';
11661
11821
  const PRELOGIN_LINK = 'https://online.rshb.ru/rshb-mbfl/webmodules/prelogin-zone';
11822
+ const openLink = (url) => {
11823
+ window.location.href = url;
11824
+ };
11662
11825
  const DebitFormStatus = JSX(({ title, description: dsc, sectionInfo, buttonText, isDboClient, isOffice, ...props }) => {
11663
- 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] }));
11826
+ 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] }));
11664
11827
  });
11665
11828
  const SectionInfo = ({ title, items, }) => {
11666
11829
  if (!items) {
@@ -12192,7 +12355,7 @@
12192
12355
  DEBIT_CARD_CONTENT,
12193
12356
  ];
12194
12357
 
12195
- const STEPS$1 = 2;
12358
+ const STEPS = 2;
12196
12359
  const STEP_TITLES = ['', 'Персональные данные', 'Платежная система'];
12197
12360
  const DebitForm = UniBlock(({ className, ...rest }) => {
12198
12361
  const [step, setStep] = useState(0);
@@ -12200,7 +12363,7 @@
12200
12363
  const scrollToTop = useCallback(() => formContainerRef?.current?.scrollIntoView({ behavior: 'smooth' }), [formContainerRef]);
12201
12364
  useEffect(updateRefreshToken, []);
12202
12365
  const handleNextStep = useCallback(() => {
12203
- setStep((_) => Math.min(_ + 1, STEPS$1));
12366
+ setStep((_) => Math.min(_ + 1, STEPS));
12204
12367
  scrollToTop();
12205
12368
  }, []);
12206
12369
  const handlePrevStep = useCallback(() => {
@@ -12215,7 +12378,7 @@
12215
12378
  setIsFormFinished();
12216
12379
  scrollToTop();
12217
12380
  }, []);
12218
- 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))) })] }) }));
12381
+ 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))) })] }) }));
12219
12382
  });
12220
12383
 
12221
12384
  const isRateRow = (rateRow) => typeof rateRow?.minMonths === 'number' && typeof rateRow?.maxMonths === 'number';
@@ -13938,128 +14101,6 @@
13938
14101
  }, role: "dialog", title: "\u0412\u0441\u043F\u043B\u044B\u0432\u0430\u044E\u0449\u0435\u0435 \u043E\u043A\u043D\u043E", children: popup.popup })) : null;
13939
14102
  });
13940
14103
 
13941
- const sendUserSurvey = async (body) => {
13942
- try {
13943
- const response = await LeadServiceFetch(`${API_BASE_URI}/survey`, body);
13944
- return await response;
13945
- }
13946
- catch (e) {
13947
- return null;
13948
- }
13949
- };
13950
-
13951
- const FinalStep = JSX(() => {
13952
- 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" })] }));
13953
- });
13954
-
13955
- const Star = JSX(({ value, hover, rating, setHover, setRating }) => {
13956
- const fillColor = value <= (hover || rating) ? '#42AB44' : '#C9CACC';
13957
- 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" }) }) }));
13958
- });
13959
-
13960
- const stars$1 = new Array(5).fill(Star);
13961
- const TITLE$1 = {
13962
- NPS: 'Оцените, пожалуйста, от 1 до 5 насколько вероятно, что вы порекомендуете Россельхозбанк коллегам, друзьям и знакомым?',
13963
- CSI: 'Оцените, пожалуйста, удовлетворённость пользования сайтом',
13964
- };
13965
- const FirstStep = JSX(({ currentRating, surveyType, isSending, setCurrentRating, onNextStep, onSubmit }) => {
13966
- const [currentHover, setCurrentHover] = useState();
13967
- const setRatingFn = (value) => {
13968
- setCurrentRating(value);
13969
- if (value < 5) {
13970
- onNextStep();
13971
- }
13972
- };
13973
- 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] }));
13974
- });
13975
-
13976
- const stars = new Array(5).fill(Star);
13977
- const TITLE = 'Что бы мы могли улучшить?';
13978
- const SecondStep = JSX(({ currentRating, currentReason, reasons = [], isSending, setCurrentReason, onSubmit }) => {
13979
- const [comment, setComment] = useState();
13980
- const handleReasonChange = (id, text) => {
13981
- setCurrentReason?.({
13982
- id,
13983
- text,
13984
- });
13985
- };
13986
- 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] }));
13987
- });
13988
-
13989
- const STEPS = [FirstStep, SecondStep, FinalStep];
13990
- const LAST_STEP_INDEX = 2;
13991
- const UserSurveyDialog = UniBlock(({ onClose = noop, reasonsSource = {} }) => {
13992
- const [isSending, { setTrue: startSending, setFalse: endSending }] = useBool(false);
13993
- const [currentRating, setCurrentRating] = useState(0);
13994
- const [currentReason, setCurrentReason] = useState();
13995
- const [step, setStep] = useState(0);
13996
- const userSurveyStore = useLocalStore();
13997
- const surveyType = userSurveyStore.userSurvey?.lastShownType ?? 'NPS';
13998
- const { reasons } = reasonsSource;
13999
- const ActiveStep = STEPS[step];
14000
- const handleNextStep = useCallback(() => {
14001
- setStep((_) => _ + 1);
14002
- }, []);
14003
- const handleSubmit = useCallback(async (message) => {
14004
- startSending();
14005
- await sendUserSurvey({
14006
- rate: currentRating,
14007
- reason: currentReason?.text,
14008
- message: getMessage(currentReason, message),
14009
- url: globalThis.location.href,
14010
- type: surveyType,
14011
- });
14012
- endSending();
14013
- setStep(LAST_STEP_INDEX);
14014
- }, [currentRating, currentReason]);
14015
- 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 }) }));
14016
- });
14017
- const getMessage = (currentReason, message) => {
14018
- if (currentReason?.text !== 'Другое') {
14019
- return undefined;
14020
- }
14021
- return message?.length ? message : 'Другое. Клиент не оставил комментариев';
14022
- };
14023
-
14024
- const DELAY = 5 * 60 * 1000;
14025
- // Хук отвечает за показ пользователю опроса
14026
- const useUserSurveyDialog = () => {
14027
- const userSurveyDialog = useDialog(UserSurveyDialog);
14028
- const userSurveyStore = useLocalStore();
14029
- const sessionStore = useSessionStore();
14030
- const elapsedTime = sessionStore.surveyTimerStart
14031
- ? Date.now() - Number.parseInt(sessionStore.surveyTimerStart)
14032
- : 0;
14033
- const openUserSurveyDialog = () => {
14034
- userSurveyStore.userSurvey = {
14035
- lastShownType: userSurveyStore.userSurvey?.lastShownType === 'NPS' ? 'CSI' : 'NPS',
14036
- nextDueAt: getTimeAfter30days(),
14037
- };
14038
- userSurveyDialog.open({
14039
- reasonsSource: {
14040
- $ref: '/wcms-resources/user-survey-reasons.json',
14041
- },
14042
- });
14043
- };
14044
- useEffect(() => {
14045
- // Опрос показывается только если ранее пользоваютелю не показывался опрос или с того момента прошел месяц
14046
- if (!userSurveyStore.userSurvey || userSurveyStore.userSurvey?.nextDueAt <= Date.now()) {
14047
- // начинаем отсчитывать время от первого захода на сайт
14048
- if (!sessionStore.surveyTimerStart) {
14049
- sessionStore.surveyTimerStart = Date.now().toString();
14050
- }
14051
- // Опрос показывается спустя 5 минут нахождения на сайте
14052
- const timeout = setTimeout(openUserSurveyDialog, DELAY - elapsedTime);
14053
- return () => {
14054
- clearTimeout(timeout);
14055
- };
14056
- }
14057
- return noop;
14058
- }, []);
14059
- };
14060
- // Отсчитываем месяц с текущей даты
14061
- const getTimeAfter30days = () => Date.now() + 30 * 24 * 60 * 60 * 1000;
14062
-
14063
14104
  const HEADER_SLOT = 'header';
14064
14105
  const FOOTER_SLOT = 'footer';
14065
14106
  const STICKY_FOOTER_SLOT = 'sticky-footer';
@@ -14093,7 +14134,7 @@
14093
14134
  slots: () => [HEADER_SLOT, FOOTER_SLOT, STICKY_FOOTER_SLOT],
14094
14135
  });
14095
14136
 
14096
- const packageVersion = "0.14.1020";
14137
+ const packageVersion = "0.14.1022";
14097
14138
 
14098
14139
  exports.Blocks = Blocks;
14099
14140
  exports.ContentPage = ContentPage;