@redneckz/wildless-cms-uni-blocks 0.14.888 → 0.14.890
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/api/LeadServiceAPI.d.ts +8 -0
- package/bundle/api/getSubmitBody.d.ts +494 -0
- package/bundle/bundle.umd.js +659 -556
- package/bundle/bundle.umd.min.js +1 -1
- package/bundle/components/ApplicationForm/ApplicationFormContent.d.ts +1 -1
- package/bundle/retail/api/checkCode.d.ts +9 -1
- package/bundle/retail/api/sendCode.d.ts +1 -1
- package/bundle/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.d.ts +4 -0
- package/bundle/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.d.ts +6 -1
- package/dist/api/LeadServiceAPI.d.ts +8 -0
- package/dist/api/LeadServiceAPI.js +41 -49
- package/dist/api/LeadServiceAPI.js.map +1 -1
- package/dist/api/getSubmitBody.d.ts +494 -0
- package/dist/api/getSubmitBody.js +59 -0
- package/dist/api/getSubmitBody.js.map +1 -0
- package/dist/components/ApplicationForm/ApplicationForm.js +30 -5
- package/dist/components/ApplicationForm/ApplicationForm.js.map +1 -1
- package/dist/components/ApplicationForm/ApplicationFormContent.d.ts +1 -1
- package/dist/components/DebitForm/DebitFormProgress.js +3 -3
- package/dist/components/DebitForm/DebitFormProgress.js.map +1 -1
- package/dist/components/DebitForm/PendingStatusContent.js +1 -1
- package/dist/components/DebitForm/PendingStatusContent.js.map +1 -1
- package/dist/retail/api/checkCode.d.ts +9 -1
- package/dist/retail/api/checkCode.js +22 -1
- package/dist/retail/api/checkCode.js.map +1 -1
- package/dist/retail/api/sendCode.d.ts +1 -1
- package/dist/retail/api/sendCode.js +8 -2
- package/dist/retail/api/sendCode.js.map +1 -1
- package/dist/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.d.ts +4 -0
- package/dist/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js +10 -4
- package/dist/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js.map +1 -1
- package/dist/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.d.ts +6 -1
- package/dist/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.js +7 -4
- package/dist/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.js.map +1 -1
- package/dist/retail/utils/mockLocalStorage.js +2 -2
- package/dist/retail/utils/mockLocalStorage.js.map +1 -1
- package/lib/api/LeadServiceAPI.d.ts +8 -0
- package/lib/api/LeadServiceAPI.js +41 -49
- package/lib/api/LeadServiceAPI.js.map +1 -1
- package/lib/api/getSubmitBody.d.ts +494 -0
- package/lib/api/getSubmitBody.js +54 -0
- package/lib/api/getSubmitBody.js.map +1 -0
- package/lib/components/ApplicationForm/ApplicationForm.fixture.d.ts +1 -0
- package/lib/components/ApplicationForm/ApplicationForm.js +30 -5
- package/lib/components/ApplicationForm/ApplicationForm.js.map +1 -1
- package/lib/components/ApplicationForm/ApplicationFormContent.d.ts +1 -1
- package/lib/components/DebitForm/DebitFormProgress.js +4 -4
- package/lib/components/DebitForm/DebitFormProgress.js.map +1 -1
- package/lib/components/DebitForm/PendingStatusContent.js +1 -1
- package/lib/components/DebitForm/PendingStatusContent.js.map +1 -1
- package/lib/retail/api/checkCode.d.ts +9 -1
- package/lib/retail/api/checkCode.js +22 -1
- package/lib/retail/api/checkCode.js.map +1 -1
- package/lib/retail/api/sendCode.d.ts +1 -1
- package/lib/retail/api/sendCode.js +7 -1
- package/lib/retail/api/sendCode.js.map +1 -1
- package/lib/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.d.ts +4 -0
- package/lib/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js +10 -4
- package/lib/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js.map +1 -1
- package/lib/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.d.ts +6 -1
- package/lib/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.js +6 -3
- package/lib/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.js.map +1 -1
- package/lib/retail/utils/mockLocalStorage.js +2 -2
- package/lib/retail/utils/mockLocalStorage.js.map +1 -1
- package/mobile/bundle/api/LeadServiceAPI.d.ts +8 -0
- package/mobile/bundle/api/getSubmitBody.d.ts +494 -0
- package/mobile/bundle/bundle.umd.js +659 -556
- package/mobile/bundle/bundle.umd.min.js +1 -1
- package/mobile/bundle/components/ApplicationForm/ApplicationFormContent.d.ts +1 -1
- package/mobile/bundle/retail/api/checkCode.d.ts +9 -1
- package/mobile/bundle/retail/api/sendCode.d.ts +1 -1
- package/mobile/bundle/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.d.ts +4 -0
- package/mobile/bundle/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.d.ts +6 -1
- package/mobile/dist/api/LeadServiceAPI.d.ts +8 -0
- package/mobile/dist/api/LeadServiceAPI.js +41 -49
- package/mobile/dist/api/LeadServiceAPI.js.map +1 -1
- package/mobile/dist/api/getSubmitBody.d.ts +494 -0
- package/mobile/dist/api/getSubmitBody.js +59 -0
- package/mobile/dist/api/getSubmitBody.js.map +1 -0
- package/mobile/dist/components/ApplicationForm/ApplicationForm.js +30 -5
- package/mobile/dist/components/ApplicationForm/ApplicationForm.js.map +1 -1
- package/mobile/dist/components/ApplicationForm/ApplicationFormContent.d.ts +1 -1
- package/mobile/dist/components/DebitForm/DebitFormProgress.js +3 -3
- package/mobile/dist/components/DebitForm/DebitFormProgress.js.map +1 -1
- package/mobile/dist/components/DebitForm/PendingStatusContent.js +1 -1
- package/mobile/dist/components/DebitForm/PendingStatusContent.js.map +1 -1
- package/mobile/dist/retail/api/checkCode.d.ts +9 -1
- package/mobile/dist/retail/api/checkCode.js +22 -1
- package/mobile/dist/retail/api/checkCode.js.map +1 -1
- package/mobile/dist/retail/api/sendCode.d.ts +1 -1
- package/mobile/dist/retail/api/sendCode.js +8 -2
- package/mobile/dist/retail/api/sendCode.js.map +1 -1
- package/mobile/dist/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.d.ts +4 -0
- package/mobile/dist/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js +10 -4
- package/mobile/dist/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js.map +1 -1
- package/mobile/dist/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.d.ts +6 -1
- package/mobile/dist/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.js +7 -4
- package/mobile/dist/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.js.map +1 -1
- package/mobile/dist/retail/utils/mockLocalStorage.js +2 -2
- package/mobile/dist/retail/utils/mockLocalStorage.js.map +1 -1
- package/mobile/lib/api/LeadServiceAPI.d.ts +8 -0
- package/mobile/lib/api/LeadServiceAPI.js +41 -49
- package/mobile/lib/api/LeadServiceAPI.js.map +1 -1
- package/mobile/lib/api/getSubmitBody.d.ts +494 -0
- package/mobile/lib/api/getSubmitBody.js +54 -0
- package/mobile/lib/api/getSubmitBody.js.map +1 -0
- package/mobile/lib/components/ApplicationForm/ApplicationForm.js +30 -5
- package/mobile/lib/components/ApplicationForm/ApplicationForm.js.map +1 -1
- package/mobile/lib/components/ApplicationForm/ApplicationFormContent.d.ts +1 -1
- package/mobile/lib/components/DebitForm/DebitFormProgress.js +4 -4
- package/mobile/lib/components/DebitForm/DebitFormProgress.js.map +1 -1
- package/mobile/lib/components/DebitForm/PendingStatusContent.js +1 -1
- package/mobile/lib/components/DebitForm/PendingStatusContent.js.map +1 -1
- package/mobile/lib/retail/api/checkCode.d.ts +9 -1
- package/mobile/lib/retail/api/checkCode.js +22 -1
- package/mobile/lib/retail/api/checkCode.js.map +1 -1
- package/mobile/lib/retail/api/sendCode.d.ts +1 -1
- package/mobile/lib/retail/api/sendCode.js +7 -1
- package/mobile/lib/retail/api/sendCode.js.map +1 -1
- package/mobile/lib/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.d.ts +4 -0
- package/mobile/lib/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js +10 -4
- package/mobile/lib/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js.map +1 -1
- package/mobile/lib/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.d.ts +6 -1
- package/mobile/lib/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.js +6 -3
- package/mobile/lib/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.js.map +1 -1
- package/mobile/lib/retail/utils/mockLocalStorage.js +2 -2
- package/mobile/lib/retail/utils/mockLocalStorage.js.map +1 -1
- package/mobile/src/api/LeadServiceAPI.ts +64 -82
- package/mobile/src/api/getSubmitBody.ts +94 -0
- package/mobile/src/components/ApplicationForm/ApplicationForm.example.json +2 -2
- package/mobile/src/components/ApplicationForm/ApplicationForm.tsx +33 -4
- package/mobile/src/components/ApplicationForm/ApplicationFormContent.ts +1 -1
- package/mobile/src/components/DebitForm/DebitFormProgress.tsx +4 -9
- package/mobile/src/components/DebitForm/PendingStatusContent.tsx +1 -1
- package/mobile/src/retail/api/checkCode.ts +47 -2
- package/mobile/src/retail/api/sendCode.ts +9 -1
- package/mobile/src/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.tsx +29 -8
- package/mobile/src/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.tsx +18 -5
- package/mobile/src/retail/utils/mockLocalStorage.ts +15 -9
- package/package.json +1 -1
- package/src/api/LeadServiceAPI.ts +64 -82
- package/src/api/getSubmitBody.ts +94 -0
- package/src/components/ApplicationForm/ApplicationForm.example.json +2 -2
- package/src/components/ApplicationForm/ApplicationForm.fixture.mobile.tsx +2 -2
- package/src/components/ApplicationForm/ApplicationForm.fixture.tsx +24 -2
- package/src/components/ApplicationForm/ApplicationForm.tsx +33 -4
- package/src/components/ApplicationForm/ApplicationFormContent.ts +1 -1
- package/src/components/DebitForm/DebitFormProgress.tsx +4 -9
- package/src/components/DebitForm/PendingStatusContent.tsx +1 -1
- package/src/retail/api/checkCode.ts +47 -2
- package/src/retail/api/sendCode.ts +9 -1
- package/src/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.tsx +29 -8
- package/src/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.tsx +18 -5
- package/src/retail/utils/mockLocalStorage.ts +15 -9
package/bundle/bundle.umd.js
CHANGED
|
@@ -987,6 +987,9 @@
|
|
|
987
987
|
});
|
|
988
988
|
const randomNumber = (min = 0, max = 0) => Math.floor(Math.random() * (max - min) + min);
|
|
989
989
|
|
|
990
|
+
const API_BASE_URI$1 = '/api/v1';
|
|
991
|
+
const RETAIL_API_BASE_URI = '/light-api-cash/v1';
|
|
992
|
+
|
|
990
993
|
const formatDate = (date, toTimeStamp = false) => {
|
|
991
994
|
if (typeof date === 'string') {
|
|
992
995
|
return date.split('-').reverse().join('.');
|
|
@@ -1001,53 +1004,33 @@
|
|
|
1001
1004
|
|
|
1002
1005
|
const formatPhone = (phone) => phone?.replace(/[^+\d]/g, '');
|
|
1003
1006
|
|
|
1004
|
-
const
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
function LeadServiceAPI() {
|
|
1008
|
-
async function send(body, router, isIndividualType = false) {
|
|
1009
|
-
const { typeForm, region, phone = '', email, birthday, desiredMeetingDate, inn, innDadata, fullRegion, addressBranch, secondaryPhone = '', bankEmpolee, applicationDate, serviceDirection, partnerSymbolCode, companyNameByInn, ...staticBody } = body;
|
|
1010
|
-
const isNaturalPerson = isIndividualType && serviceDirection !== 'Юридическое лицо / ИП';
|
|
1011
|
-
const url = `${API_BASE_URI$1}${isNaturalPerson ? '/lead' : '/sendcorporatelead'}`;
|
|
1012
|
-
const submitBody = {
|
|
1013
|
-
typeForm,
|
|
1014
|
-
...getRegion$1(region, isNaturalPerson),
|
|
1015
|
-
...getEmail(email, isNaturalPerson),
|
|
1016
|
-
...getPhone(phone),
|
|
1017
|
-
...getFormatDate(desiredMeetingDate, 'desiredMeetingDate'),
|
|
1018
|
-
...(isNaturalPerson ? getFormatDate(birthday) : { inn }),
|
|
1019
|
-
...(typeForm === 'FEEDBACK'
|
|
1020
|
-
? {}
|
|
1021
|
-
: {
|
|
1022
|
-
addressBranch,
|
|
1023
|
-
bankEmpolee,
|
|
1024
|
-
applicationDate,
|
|
1025
|
-
...getSecondaryPhone(secondaryPhone),
|
|
1026
|
-
}),
|
|
1027
|
-
...addPageSlug(typeForm, router),
|
|
1028
|
-
...formatPFForm(typeForm, { innDadata, fullRegion, partnerSymbolCode, companyNameByInn }),
|
|
1029
|
-
...staticBody,
|
|
1030
|
-
};
|
|
1031
|
-
try {
|
|
1032
|
-
const response = await fetch(url, {
|
|
1033
|
-
method: 'POST',
|
|
1034
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1035
|
-
mode: 'cors',
|
|
1036
|
-
body: JSON.stringify(submitBody),
|
|
1037
|
-
});
|
|
1038
|
-
if (!response?.ok) {
|
|
1039
|
-
return null;
|
|
1040
|
-
}
|
|
1041
|
-
return await response.json();
|
|
1042
|
-
}
|
|
1043
|
-
catch (e) {
|
|
1044
|
-
return null;
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1007
|
+
const getSubmitBody = (body, isNaturalPerson, router) => {
|
|
1008
|
+
const { typeForm, region, phone = '', email, birthday, desiredMeetingDate, inn, innDadata, fullRegion, addressBranch, secondaryPhone = '', bankEmpolee, applicationDate, partnerSymbolCode, companyNameByInn, ...staticBody } = body;
|
|
1047
1009
|
return {
|
|
1048
|
-
|
|
1010
|
+
typeForm,
|
|
1011
|
+
...getRegion$1(region, isNaturalPerson),
|
|
1012
|
+
...getEmail(email, isNaturalPerson),
|
|
1013
|
+
...getPhone(phone),
|
|
1014
|
+
...getFormatDate(desiredMeetingDate, 'desiredMeetingDate'),
|
|
1015
|
+
...(isNaturalPerson ? getFormatDate(birthday) : { inn }),
|
|
1016
|
+
...(typeForm === 'FEEDBACK'
|
|
1017
|
+
? {}
|
|
1018
|
+
: {
|
|
1019
|
+
addressBranch,
|
|
1020
|
+
bankEmpolee,
|
|
1021
|
+
applicationDate,
|
|
1022
|
+
...getSecondaryPhone(secondaryPhone),
|
|
1023
|
+
}),
|
|
1024
|
+
...addPageSlug(typeForm, router),
|
|
1025
|
+
...formatPFForm(typeForm, { innDadata, fullRegion, partnerSymbolCode, companyNameByInn }),
|
|
1026
|
+
...staticBody,
|
|
1049
1027
|
};
|
|
1050
|
-
}
|
|
1028
|
+
};
|
|
1029
|
+
const getPhoneBody = (phone) => {
|
|
1030
|
+
return {
|
|
1031
|
+
...getPhone(phone),
|
|
1032
|
+
};
|
|
1033
|
+
};
|
|
1051
1034
|
const getPhone = (phone) => (phone ? { phone: formatPhone(phone) } : {});
|
|
1052
1035
|
const getFormatDate = (date, key = 'birthday') => date ? { [key]: formatDate(date) } : {};
|
|
1053
1036
|
const getRegion$1 = (region, isNaturalPerson = true) => ({
|
|
@@ -1073,6 +1056,68 @@
|
|
|
1073
1056
|
}
|
|
1074
1057
|
: {};
|
|
1075
1058
|
|
|
1059
|
+
function LeadServiceAPI() {
|
|
1060
|
+
async function send(body, router, isIndividualType = false) {
|
|
1061
|
+
const { serviceDirection } = body;
|
|
1062
|
+
const isNaturalPerson = isIndividualType && serviceDirection !== 'Юридическое лицо / ИП';
|
|
1063
|
+
const url = `${API_BASE_URI$1}${isNaturalPerson ? '/lead' : '/sendcorporatelead'}`;
|
|
1064
|
+
const submitBody = getSubmitBody(body, isNaturalPerson, router);
|
|
1065
|
+
try {
|
|
1066
|
+
const response = await LeadServiceFetch(url, submitBody);
|
|
1067
|
+
if (!response?.ok) {
|
|
1068
|
+
return null;
|
|
1069
|
+
}
|
|
1070
|
+
return await response.json();
|
|
1071
|
+
}
|
|
1072
|
+
catch (e) {
|
|
1073
|
+
return null;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
async function sendCode({ phone }) {
|
|
1077
|
+
const submitBody = getPhoneBody(phone);
|
|
1078
|
+
try {
|
|
1079
|
+
const response = LeadServiceFetch(`${API_BASE_URI$1}/initCorporateLead`, submitBody).then(async (res) => {
|
|
1080
|
+
if (!res.ok) {
|
|
1081
|
+
throw new Error(`Ошибка HTTP: ${res.status}`);
|
|
1082
|
+
}
|
|
1083
|
+
return await res.text();
|
|
1084
|
+
});
|
|
1085
|
+
return await response;
|
|
1086
|
+
}
|
|
1087
|
+
catch (e) {
|
|
1088
|
+
return null;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
async function checkCode({ reqId, code, body }) {
|
|
1092
|
+
const submitBody = {
|
|
1093
|
+
requestId: reqId,
|
|
1094
|
+
confimationCode: code,
|
|
1095
|
+
leadRequest: getSubmitBody(body, false),
|
|
1096
|
+
};
|
|
1097
|
+
try {
|
|
1098
|
+
const response = await LeadServiceFetch(`${API_BASE_URI$1}/confirmCorporateLead`, submitBody);
|
|
1099
|
+
if (!response?.ok) {
|
|
1100
|
+
return null;
|
|
1101
|
+
}
|
|
1102
|
+
return await response.json();
|
|
1103
|
+
}
|
|
1104
|
+
catch (e) {
|
|
1105
|
+
return null;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
return {
|
|
1109
|
+
send,
|
|
1110
|
+
sendCode,
|
|
1111
|
+
checkCode,
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
const LeadServiceFetch = (url, submitBody) => fetch(url, {
|
|
1115
|
+
method: 'POST',
|
|
1116
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1117
|
+
mode: 'cors',
|
|
1118
|
+
body: JSON.stringify(submitBody),
|
|
1119
|
+
});
|
|
1120
|
+
|
|
1076
1121
|
const handleAspects = async ({ aspectsAttributes, aspects, ev }) => {
|
|
1077
1122
|
for (const { aspectName, params } of aspectsAttributes ?? []) {
|
|
1078
1123
|
const aspectFn = aspects[aspectName ?? ''];
|
|
@@ -1238,11 +1283,183 @@
|
|
|
1238
1283
|
return [formState, { errors, field, update, reset, onSubmit: handleSubmit }];
|
|
1239
1284
|
}
|
|
1240
1285
|
|
|
1241
|
-
|
|
1242
|
-
const
|
|
1243
|
-
|
|
1286
|
+
function copy(source, target) {
|
|
1287
|
+
for (const [k, v] of source.entries()) {
|
|
1288
|
+
if (v !== null && v !== undefined) {
|
|
1289
|
+
target.setItem(k, v);
|
|
1290
|
+
}
|
|
1291
|
+
else {
|
|
1292
|
+
target.removeItem(k);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
function replicate(primary, secondary) {
|
|
1298
|
+
copy(primary, secondary);
|
|
1299
|
+
copy(secondary, primary);
|
|
1300
|
+
return primary.bus.watch(({ type, event }) => {
|
|
1301
|
+
if (event !== null && event !== undefined) {
|
|
1302
|
+
secondary.setItem(type, event);
|
|
1303
|
+
}
|
|
1304
|
+
else {
|
|
1305
|
+
secondary.removeItem(type);
|
|
1306
|
+
}
|
|
1307
|
+
});
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
class StorageAdapter {
|
|
1311
|
+
storage;
|
|
1312
|
+
bus;
|
|
1313
|
+
get size() {
|
|
1314
|
+
return this.storage?.length ?? 0;
|
|
1315
|
+
}
|
|
1316
|
+
constructor(storage, bus = new EventBus()) {
|
|
1317
|
+
this.storage = storage;
|
|
1318
|
+
this.bus = bus;
|
|
1319
|
+
}
|
|
1320
|
+
hasItem(key) {
|
|
1321
|
+
return Boolean(this.storage?.getItem(String(key)));
|
|
1322
|
+
}
|
|
1323
|
+
getItem(key) {
|
|
1324
|
+
const _ = this.storage?.getItem(String(key)) ?? null;
|
|
1325
|
+
try {
|
|
1326
|
+
return JSON.parse(String(_));
|
|
1327
|
+
}
|
|
1328
|
+
catch (ex) {
|
|
1329
|
+
return null;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
entries() {
|
|
1333
|
+
return Array.from({ length: this.size }, (_, i) => {
|
|
1334
|
+
const k = String(this.storage?.key(i));
|
|
1335
|
+
return [k, this.getItem(k)];
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
1338
|
+
setItem(key, value) {
|
|
1339
|
+
if (value !== null) {
|
|
1340
|
+
this.storage?.setItem(String(key), JSON.stringify(value));
|
|
1341
|
+
}
|
|
1342
|
+
else {
|
|
1343
|
+
this.storage?.removeItem(String(key));
|
|
1344
|
+
}
|
|
1345
|
+
this.bus?.subject(key, value);
|
|
1346
|
+
}
|
|
1347
|
+
removeItem(key) {
|
|
1348
|
+
this.storage?.removeItem(String(key));
|
|
1349
|
+
this.bus?.subject(key, null);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
class Store {
|
|
1354
|
+
bus;
|
|
1355
|
+
store = new Map();
|
|
1356
|
+
get size() {
|
|
1357
|
+
return this.store.size;
|
|
1358
|
+
}
|
|
1359
|
+
constructor(bus = new EventBus()) {
|
|
1360
|
+
this.bus = bus;
|
|
1361
|
+
}
|
|
1362
|
+
hasItem(key) {
|
|
1363
|
+
return this.store.has(key);
|
|
1364
|
+
}
|
|
1365
|
+
getItem(key) {
|
|
1366
|
+
return this.store.get(key);
|
|
1367
|
+
}
|
|
1368
|
+
entries() {
|
|
1369
|
+
return this.store.entries();
|
|
1370
|
+
}
|
|
1371
|
+
setItem(key, value) {
|
|
1372
|
+
this.store.set(key, value);
|
|
1373
|
+
this.bus.subject(key, value);
|
|
1374
|
+
}
|
|
1375
|
+
removeItem(key) {
|
|
1376
|
+
this.store.delete(key);
|
|
1377
|
+
this.bus.subject(key, null);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
function useRerender() {
|
|
1382
|
+
const [, setCount] = useState(0);
|
|
1383
|
+
return useCallback(() => setCount(_ => (_ + 1) % (1 << 16)), []);
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
const DEFAULT_METHODS = {};
|
|
1387
|
+
/**
|
|
1388
|
+
* MobX like reactivity (simplified).
|
|
1389
|
+
* Can be used to migrate from Redux/MobX or something else
|
|
1390
|
+
*
|
|
1391
|
+
* @param store
|
|
1392
|
+
* @returns reactive proxy backed by store
|
|
1393
|
+
*/
|
|
1394
|
+
function useStore(store, methods = DEFAULT_METHODS) {
|
|
1395
|
+
const deps = useRef(null);
|
|
1396
|
+
const render = useRerender();
|
|
1397
|
+
useEffect(() => store.bus.watch(ev => {
|
|
1398
|
+
if (deps.current?.has(String(ev.type))) {
|
|
1399
|
+
render();
|
|
1400
|
+
}
|
|
1401
|
+
}), [store, render]);
|
|
1402
|
+
return useMemo(() => new Proxy(methods, {
|
|
1403
|
+
get(_, key) {
|
|
1404
|
+
deps.current ||= new Set();
|
|
1405
|
+
deps.current.add(key);
|
|
1406
|
+
return store.getItem(key);
|
|
1407
|
+
},
|
|
1408
|
+
has(_, key) {
|
|
1409
|
+
deps.current ||= new Set();
|
|
1410
|
+
deps.current.add(key);
|
|
1411
|
+
return store.hasItem(key);
|
|
1412
|
+
},
|
|
1413
|
+
set(_, key, value) {
|
|
1414
|
+
store.setItem(key, value);
|
|
1415
|
+
return true;
|
|
1416
|
+
},
|
|
1417
|
+
deleteProperty(_, key) {
|
|
1418
|
+
store.removeItem(key);
|
|
1419
|
+
return true;
|
|
1420
|
+
}
|
|
1421
|
+
}), [store]);
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
const sessionStore = new Store(); // sessionStorage cache
|
|
1425
|
+
replicate(sessionStore, new StorageAdapter(globalThis?.sessionStorage));
|
|
1426
|
+
function useSessionStore() {
|
|
1427
|
+
return useStore(sessionStore);
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
const noop = () => {
|
|
1431
|
+
// Do nothing
|
|
1432
|
+
};
|
|
1433
|
+
|
|
1434
|
+
const themeStyle$1 = {
|
|
1435
|
+
primary: style('text-white bg-primary-main hover:bg-primary-hover active:bg-primary-active', 'group-data-secondary:text-primary-main group-data-secondary:bg-white', 'group-data-secondary:hover:text-white group-data-secondary:hover:bg-primary-hover', 'group-data-secondary:active:bg-primary-active'),
|
|
1436
|
+
secondary: style('text-primary-main bg-main-divider hover:text-white hover:bg-primary-hover active:bg-primary-active', 'group-data-secondary:text-white group-data-secondary:bg-white/20', 'group-data-secondary:hover:bg-primary-hover', 'group-data-secondary:active:bg-primary-active'),
|
|
1437
|
+
};
|
|
1438
|
+
const embeddedStyle = style('group/btn-embedded', 'bg-transparent border border-transparent outline-none');
|
|
1439
|
+
const disabledStyle = style('bg-main-gray text-main-disabled cursor-not-allowed');
|
|
1440
|
+
const Button = JSX(({ className, type = 'button', version = 'primary', shape = 'default', embedded, disabled, role, ariaLabel, data, dataTheme, children, wcmsIgnore, onClick = noop, }) => {
|
|
1441
|
+
const handleClick = useCallback(role !== 'tab' ? handlerDecorator(onClick) : onClick, [
|
|
1442
|
+
role,
|
|
1443
|
+
onClick,
|
|
1444
|
+
]);
|
|
1445
|
+
const aspectsAttrs = useMemo(() => getAspectsAttributes(data), [data]);
|
|
1446
|
+
const isRound = shape === 'round';
|
|
1447
|
+
return (jsx("button", { className: style('font-sans flex items-center gap-xs', {
|
|
1448
|
+
[themeStyle$1[version]]: !disabled && !embedded,
|
|
1449
|
+
[embeddedStyle]: embedded,
|
|
1450
|
+
[disabledStyle]: disabled,
|
|
1451
|
+
}, embedded ? 'justify-between' : 'justify-center', embedded || isRound ? 'p-0' : 'px-9 py-4', {
|
|
1452
|
+
'rounded-md': shape === 'default',
|
|
1453
|
+
'rounded-full': isRound,
|
|
1454
|
+
}, className), type: type, role: role, "aria-label": ariaLabel, disabled: disabled, "aria-disabled": disabled ? 'true' : undefined, "data-theme": dataTheme, "data-wcms-ignore": wcmsIgnore, ...aspectsAttrs, onClick: handleClick, children: children }));
|
|
1244
1455
|
});
|
|
1245
1456
|
|
|
1457
|
+
const ButtonTitle = JSX(({ className, children }) => (jsx("span", { className: style('inline-flex items-center text-start gap-s group-[]/btn-embedded:text-primary-main', className), children: children })));
|
|
1458
|
+
|
|
1459
|
+
const CloseButton = JSX(({ className, onClose }) => (jsx("button", { className: style('flex justify-center items-center w-12 h-12 p-2xs bg-transparent border-none', className), onClick: onClose, title: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C", type: "button", children: jsx(Icon, { name: "CloseIcon", width: "20", height: "20", iconVersion: "gray" }) })));
|
|
1460
|
+
|
|
1461
|
+
const Dialog = JSX(({ className, head, children, onClose, onClick }) => (jsxs("div", { className: style('relative bg-white pt-0 p-lg', className), role: "dialog", title: "\u0414\u0438\u0430\u043B\u043E\u0433", onClick: onClick, children: [jsxs("div", { className: "sticky py-xl top-0 bg-white z-10", children: [jsx(CloseButton, { className: "absolute top-0 right-0", onClose: onClose }), jsx("div", { className: "container", children: head })] }), jsx("div", { className: "container pb-m mb-[74px] lg:mb-0", children: children })] })));
|
|
1462
|
+
|
|
1246
1463
|
function useDialog(Dialog, initialProps = {}) {
|
|
1247
1464
|
const { open, close, ...rest } = useDialogManager();
|
|
1248
1465
|
const openDialog = useCallback((props, options = {}) => open({
|
|
@@ -1255,28 +1472,98 @@
|
|
|
1255
1472
|
return { open: openDialog, close, ...rest };
|
|
1256
1473
|
}
|
|
1257
1474
|
|
|
1258
|
-
const
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
const getRequiredLabel = ({ label, errors }) => label && errors ? `${label}*` : label;
|
|
1475
|
+
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, {
|
|
1476
|
+
'backdrop-blur': blur,
|
|
1477
|
+
}), 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" }) })));
|
|
1262
1478
|
|
|
1263
|
-
const
|
|
1479
|
+
const Timer = JSX(({ className, seconds }) => (jsx("span", { className: className, children: formatTimer(seconds) })));
|
|
1480
|
+
const formatTimer = (seconds) => {
|
|
1481
|
+
const minutes = Math.floor(seconds / 60);
|
|
1482
|
+
return [minutes, seconds % 60].map((_) => String(_).padStart(2, '0')).join(':');
|
|
1483
|
+
};
|
|
1264
1484
|
|
|
1265
|
-
const
|
|
1266
|
-
|
|
1267
|
-
const
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1485
|
+
const useInterval = (handler, period) => {
|
|
1486
|
+
const timer = useRef(null);
|
|
1487
|
+
const stop = useCallback(() => clearInterval(timer.current), []);
|
|
1488
|
+
const start = useCallback(() => {
|
|
1489
|
+
stop();
|
|
1490
|
+
timer.current = setInterval(() => handler(stop), period);
|
|
1491
|
+
}, [handler, period, stop]);
|
|
1492
|
+
useEffect(() => {
|
|
1493
|
+
start();
|
|
1494
|
+
return stop;
|
|
1495
|
+
}, [start, stop]);
|
|
1496
|
+
return { start, stop };
|
|
1497
|
+
};
|
|
1498
|
+
|
|
1499
|
+
function useCountDownTimer({ seconds, period = 1000, onTick, onEnd }) {
|
|
1500
|
+
const counter = useRef(seconds);
|
|
1501
|
+
const handleTick = useCallback((stop) => {
|
|
1502
|
+
counter.current ||= 0;
|
|
1503
|
+
counter.current = Math.max(0, counter.current - 1);
|
|
1504
|
+
try {
|
|
1505
|
+
onTick?.(counter.current);
|
|
1276
1506
|
}
|
|
1277
|
-
|
|
1278
|
-
|
|
1507
|
+
finally {
|
|
1508
|
+
if (counter.current <= 0) {
|
|
1509
|
+
stop();
|
|
1510
|
+
onEnd?.();
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
}, [onTick, onEnd]);
|
|
1514
|
+
const { start } = useInterval(handleTick, period);
|
|
1515
|
+
return useCallback((_) => {
|
|
1516
|
+
counter.current = _;
|
|
1517
|
+
start();
|
|
1518
|
+
}, []);
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
const getTraceId = () => {
|
|
1522
|
+
const result = new Uint8Array(8);
|
|
1523
|
+
globalThis.crypto.getRandomValues(result);
|
|
1524
|
+
return result.reduce((acc, _) => `${acc}${_.toString(16).padStart(2, '0')}`, '');
|
|
1525
|
+
};
|
|
1526
|
+
|
|
1527
|
+
const fetchRetailJSON = async (url, method, body) => {
|
|
1528
|
+
try {
|
|
1529
|
+
const response = await doRequest(url, method, body);
|
|
1530
|
+
return response.json();
|
|
1531
|
+
}
|
|
1532
|
+
catch (err) {
|
|
1533
|
+
console.error(err);
|
|
1534
|
+
return null;
|
|
1535
|
+
}
|
|
1536
|
+
};
|
|
1537
|
+
async function doRequest(url, method, body) {
|
|
1538
|
+
const traceId = getTraceId();
|
|
1539
|
+
return globalThis?.fetch?.(`${RETAIL_API_BASE_URI}${url}`, {
|
|
1540
|
+
method,
|
|
1541
|
+
headers: {
|
|
1542
|
+
'Content-Type': 'application/json',
|
|
1543
|
+
'X-B3-Sampled': '1',
|
|
1544
|
+
'X-B3-Spanid': traceId,
|
|
1545
|
+
'X-B3-Traceid': traceId,
|
|
1546
|
+
...getAuthorizationHeaders(),
|
|
1547
|
+
},
|
|
1548
|
+
credentials: 'include',
|
|
1549
|
+
body: body ? JSON.stringify(body) : null,
|
|
1550
|
+
});
|
|
1551
|
+
}
|
|
1552
|
+
const getAuthorizationHeaders = () => {
|
|
1553
|
+
const token = sessionStorage.getItem('accessToken');
|
|
1554
|
+
return token ? { Authorization: `Bearer ${token}` } : null;
|
|
1555
|
+
};
|
|
1556
|
+
|
|
1557
|
+
const API$2 = LeadServiceAPI();
|
|
1558
|
+
const sendCode = (body, isRetail) => {
|
|
1559
|
+
return isRetail ? fetchRetail(body) : fetchMain$1(body);
|
|
1279
1560
|
};
|
|
1561
|
+
const fetchRetail = (body) => doRequest('/sms/sendCode', 'POST', body)
|
|
1562
|
+
.then((res) => res.text())
|
|
1563
|
+
.then((text) => text === 'OK');
|
|
1564
|
+
const fetchMain$1 = (body) => API$2.sendCode({ phone: body.phoneNumber });
|
|
1565
|
+
|
|
1566
|
+
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] })));
|
|
1280
1567
|
|
|
1281
1568
|
const inputValidStyle = 'border border-solid outline-none border-gray hover:border-primary-hover active:border-primary-text focus:border-primary-text rounded';
|
|
1282
1569
|
|
|
@@ -1302,7 +1589,265 @@
|
|
|
1302
1589
|
const ariaLabel = label ?? name ?? id;
|
|
1303
1590
|
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 }, key))] }), children] }));
|
|
1304
1591
|
});
|
|
1305
|
-
const defaultStyle$1 = 'w-full border rounded-md text-primary-text outline-none p-m';
|
|
1592
|
+
const defaultStyle$1 = 'w-full border rounded-md text-primary-text outline-none p-m';
|
|
1593
|
+
|
|
1594
|
+
const ICON_SIZE = { width: '118', height: '24' };
|
|
1595
|
+
|
|
1596
|
+
const logoTitleSizeStyle = '';
|
|
1597
|
+
|
|
1598
|
+
const ICON_VERSION_MAP = {
|
|
1599
|
+
'bg-white': 'color',
|
|
1600
|
+
transparent: 'white',
|
|
1601
|
+
};
|
|
1602
|
+
const SVG_COLOR = {
|
|
1603
|
+
'bg-white': 'text-primary-main',
|
|
1604
|
+
transparent: 'text-white',
|
|
1605
|
+
};
|
|
1606
|
+
const renderImage = (bgColor, image, size) => {
|
|
1607
|
+
const img = image?.src
|
|
1608
|
+
? image
|
|
1609
|
+
: {
|
|
1610
|
+
icon: image?.icon || 'LogoIcon',
|
|
1611
|
+
iconVersion: ICON_VERSION_MAP[bgColor],
|
|
1612
|
+
};
|
|
1613
|
+
return (jsx(Img, { image: img, className: SVG_COLOR[bgColor], width: size?.width, height: size?.height }));
|
|
1614
|
+
};
|
|
1615
|
+
|
|
1616
|
+
const TEXT_COLOR = {
|
|
1617
|
+
'bg-white': 'text-primary-text',
|
|
1618
|
+
transparent: 'text-white',
|
|
1619
|
+
};
|
|
1620
|
+
const Logo = JSX(({ className, href = '/', logo, children, targetBlank, bgColor = 'bg-white', showTitle = true, data, }) => (jsxs("a", { className: style('inline-flex items-center font-sans no-underline', className), href: logo?.href ?? href, target: targetBlank ? '_blank' : '_self', "aria-label": logo?.title ?? 'Россельхозбанк', ...getAspectsAttributes(data), children: [renderImage(bgColor, logo?.image, ICON_SIZE), showTitle
|
|
1621
|
+
? children ?? (jsx("div", { className: "ml-s", children: jsx(Text, { font: "font-medium", color: TEXT_COLOR[bgColor], size: logoTitleSizeStyle, children: logo?.title ?? 'Россельхозбанк' }) }))
|
|
1622
|
+
: null] })));
|
|
1623
|
+
|
|
1624
|
+
const checkCaptcha = (body) => doRequest('/sms/checkCaptcha', 'POST', body)
|
|
1625
|
+
.then((res) => res.text())
|
|
1626
|
+
.then((text) => text !== 'ERROR');
|
|
1627
|
+
|
|
1628
|
+
const createCaptcha = (phoneNumber) => doRequest(`/sms/createCaptcha?phoneNumber=${encodeURIComponent(phoneNumber)}`, 'GET').then(async (res) => (res ? res.blob() : new Blob()));
|
|
1629
|
+
|
|
1630
|
+
const CaptchaDialog = JSX(({ phoneNumber, sendCode, onClose }) => {
|
|
1631
|
+
const [captcha, setCaptcha] = useState('');
|
|
1632
|
+
const [code, setCode] = useState('');
|
|
1633
|
+
const [hasError, setHasError] = useState(false);
|
|
1634
|
+
const [isLoading, { setTrue: startLoading, setFalse: endLoading }] = useBool(false);
|
|
1635
|
+
const { closeAll } = useDialogManager();
|
|
1636
|
+
const handleCheckCaptcha = useCallback(async () => {
|
|
1637
|
+
startLoading();
|
|
1638
|
+
const isValidCode = await checkCaptcha({ captchaText: code });
|
|
1639
|
+
if (isValidCode) {
|
|
1640
|
+
onClose?.();
|
|
1641
|
+
sendCode?.();
|
|
1642
|
+
}
|
|
1643
|
+
else {
|
|
1644
|
+
setHasError(true);
|
|
1645
|
+
}
|
|
1646
|
+
endLoading();
|
|
1647
|
+
}, [code, sendCode]);
|
|
1648
|
+
const handleCreateCaptcha = useCallback(() => {
|
|
1649
|
+
(async () => setCaptcha(URL.createObjectURL(await createCaptcha(phoneNumber))))();
|
|
1650
|
+
}, []);
|
|
1651
|
+
useEffect(handleCreateCaptcha, []);
|
|
1652
|
+
return (jsx(Dialog, { className: "my-6xl max-w-lg w-full min-h-fit mx-auto rounded-lg", head: jsx(Logo, {}), onClose: onClose, children: jsxs("div", { className: "flex flex-col gap-lg items-center", children: [jsxs("div", { className: "flex", children: [jsx("img", { className: "grow", src: captcha }), jsx(Button, { className: "w-8", embedded: true, onClick: handleCreateCaptcha, children: jsx(Icon, { iconVersion: "normal", name: "RefreshIcon" }) })] }), jsx(Input, { className: "w-80", onChange: setCode, value: code, placeholder: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043A\u043E\u0434 \u0441 \u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0438" }), hasError ? jsx("div", { className: "text-error", children: "\u041D\u0435\u0432\u0435\u0440\u043D\u044B\u0439 \u043A\u043E\u0434" }) : null, jsxs("div", { className: "flex w-80 justify-between", children: [jsx(Button, { version: "secondary", onClick: closeAll, children: "\u0412\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F" }), jsx(SubmitButton$1, { version: "secondary", disabled: !code, onClick: handleCheckCaptcha, children: "\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C" })] }), isLoading ? jsx(Loader, { blur: false }) : null] }) }));
|
|
1653
|
+
});
|
|
1654
|
+
|
|
1655
|
+
const InputCode = JSX(({ values, setValues, hasError, errorText }) => {
|
|
1656
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
|
1657
|
+
const inputRefs = useRef([]);
|
|
1658
|
+
useEffect(() => {
|
|
1659
|
+
inputRefs.current?.[activeIndex]?.focus();
|
|
1660
|
+
}, [activeIndex]);
|
|
1661
|
+
const handleChange = useCallback((index) => (event) => {
|
|
1662
|
+
const { value } = event.currentTarget;
|
|
1663
|
+
const oneValue = value.slice(0, 1);
|
|
1664
|
+
setValues(values.map((_, i) => (i === index ? oneValue : _)));
|
|
1665
|
+
setActiveIndex(index + 1);
|
|
1666
|
+
}, [values]);
|
|
1667
|
+
const handleKeyDown = useCallback((currentIndex) => (event) => {
|
|
1668
|
+
const { key } = event;
|
|
1669
|
+
if (key === 'Backspace' && !values[currentIndex]) {
|
|
1670
|
+
const previousIndex = currentIndex > 0 ? currentIndex - 1 : values.length - 1;
|
|
1671
|
+
const updatedValues = values.map((value, index) => (index === previousIndex ? '' : value));
|
|
1672
|
+
setValues(updatedValues);
|
|
1673
|
+
setActiveIndex(previousIndex);
|
|
1674
|
+
}
|
|
1675
|
+
}, [values]);
|
|
1676
|
+
const handlePaste = useCallback((event) => {
|
|
1677
|
+
event.preventDefault();
|
|
1678
|
+
const pastedData = event.clipboardData.getData('text');
|
|
1679
|
+
const updatedValues = values.map((_, idx) => (idx < pastedData.length ? pastedData[idx] : _));
|
|
1680
|
+
setValues(updatedValues);
|
|
1681
|
+
setActiveIndex(updatedValues.length - 1);
|
|
1682
|
+
}, [values]);
|
|
1683
|
+
return (jsxs("div", { className: "flex flex-col gap-2 text-center", children: [jsx("div", { children: values.map((value, index) => (jsx("input", { type: "number", maxLength: 1, value: value, onChange: handleChange(index), onPaste: handlePaste, ref: (ref) => {
|
|
1684
|
+
if (!inputRefs.current) {
|
|
1685
|
+
inputRefs.current = [];
|
|
1686
|
+
}
|
|
1687
|
+
inputRefs.current[index] = ref;
|
|
1688
|
+
}, onFocus: (event) => event.target.select(), onKeyDown: handleKeyDown(index), className: getInputStyle(index, values, hasError) }, index))) }), hasError ? jsx("div", { className: "text-error", children: errorText }) : null] }));
|
|
1689
|
+
});
|
|
1690
|
+
const getInputStyle = (index, values, hasError = false) => {
|
|
1691
|
+
const isInputEmpty = !values[index];
|
|
1692
|
+
return `w-16 sm:w-20 h-24 text-5xl text-center p-md m-2 border ${getValidStyle(!hasError || !isInputEmpty)} rounded-md caret-transparent outline-none`;
|
|
1693
|
+
};
|
|
1694
|
+
|
|
1695
|
+
const SubmitButton = JSX(({ disabled = false, onClick, text }) => (jsx(Button, { type: "button", onClick: onClick, disabled: disabled, children: jsx(Text, { font: "font-normal", children: text }) })));
|
|
1696
|
+
|
|
1697
|
+
const API$1 = LeadServiceAPI();
|
|
1698
|
+
const checkCode = async (body, isRetail) => {
|
|
1699
|
+
const transformedBody = transformBody(body, isRetail);
|
|
1700
|
+
return isRetail
|
|
1701
|
+
? fetchRetailJSON('/sms/checkCode', 'POST', transformedBody).then(saveToken)
|
|
1702
|
+
: fetchMain(transformedBody).then((res) => {
|
|
1703
|
+
if (res === null) {
|
|
1704
|
+
throw new Error('Неверный код');
|
|
1705
|
+
}
|
|
1706
|
+
});
|
|
1707
|
+
};
|
|
1708
|
+
const saveToken = (data) => {
|
|
1709
|
+
if (data?.access_token && data?.refresh_token) {
|
|
1710
|
+
globalThis.sessionStorage.setItem('accessToken', data.access_token);
|
|
1711
|
+
globalThis.sessionStorage.setItem('refreshToken', data.refresh_token);
|
|
1712
|
+
}
|
|
1713
|
+
};
|
|
1714
|
+
const fetchMain = (body) => API$1.checkCode(body);
|
|
1715
|
+
const transformBody = ({ smsText, smsCodesSetName, body, reqId }, isRetail) => {
|
|
1716
|
+
if (isRetail) {
|
|
1717
|
+
return { smsText, smsCodesSetName };
|
|
1718
|
+
}
|
|
1719
|
+
if (!reqId || !body) {
|
|
1720
|
+
throw new Error('Произошла ошибка, попробуйте позднее');
|
|
1721
|
+
}
|
|
1722
|
+
return { code: smsText, reqId, body };
|
|
1723
|
+
};
|
|
1724
|
+
|
|
1725
|
+
const TIME_TO_RESEND = 180;
|
|
1726
|
+
const useVerifyPhoneDialogSubmit = ({ values, onSuccess, formatData, reqId, isRetail = true, }) => {
|
|
1727
|
+
const sessionStore = useSessionStore();
|
|
1728
|
+
const attempts = sessionStore.smsCode?.attempts || 0;
|
|
1729
|
+
const timer = Math.max(getTimer(sessionStore.smsCode?.sendTime || Date.now()), 0);
|
|
1730
|
+
const [errorText, setErrorText] = useState('');
|
|
1731
|
+
const [isLoading, { setTrue: startLoading, setFalse: endLoading }] = useBool(false);
|
|
1732
|
+
const [timeNextReq, setTimeNextReq] = useState(timer);
|
|
1733
|
+
const resetError = useCallback(() => setErrorText(''), []);
|
|
1734
|
+
const isTimeExpired = Boolean(timeNextReq === 0 && sessionStore.smsCode?.sendTime);
|
|
1735
|
+
const isSubmitButtonDisabled = attempts > 2 || isTimeExpired || !values.every(Boolean);
|
|
1736
|
+
const handleSubmit = useCallback(async () => {
|
|
1737
|
+
try {
|
|
1738
|
+
sessionStore.smsCode = {
|
|
1739
|
+
...sessionStore.smsCode,
|
|
1740
|
+
attempts: attempts + 1,
|
|
1741
|
+
};
|
|
1742
|
+
startLoading();
|
|
1743
|
+
await checkCode({
|
|
1744
|
+
smsText: values.join(''),
|
|
1745
|
+
smsCodesSetName: { key: 'AUTHENTICATION' },
|
|
1746
|
+
body: isRetail ? undefined : formatData,
|
|
1747
|
+
reqId: isRetail ? undefined : reqId,
|
|
1748
|
+
}, isRetail);
|
|
1749
|
+
setTimeNextReq(0);
|
|
1750
|
+
resetError();
|
|
1751
|
+
sessionStore.smsCode = null;
|
|
1752
|
+
await onSuccess?.(values.join(''));
|
|
1753
|
+
}
|
|
1754
|
+
catch {
|
|
1755
|
+
setErrorText(attempts > 1 ? 'Исчерпан лимит ввода смс-кода' : 'Неверный код');
|
|
1756
|
+
}
|
|
1757
|
+
finally {
|
|
1758
|
+
endLoading();
|
|
1759
|
+
}
|
|
1760
|
+
}, [values, attempts]);
|
|
1761
|
+
useEffect(() => {
|
|
1762
|
+
if (isTimeExpired && isRetail) {
|
|
1763
|
+
setErrorText('Код просрочен');
|
|
1764
|
+
}
|
|
1765
|
+
else if (attempts > 2) {
|
|
1766
|
+
setErrorText('Исчерпан лимит ввода смс-кода');
|
|
1767
|
+
}
|
|
1768
|
+
}, [isTimeExpired]);
|
|
1769
|
+
return {
|
|
1770
|
+
handleSubmit,
|
|
1771
|
+
hasError: Boolean(errorText),
|
|
1772
|
+
errorText,
|
|
1773
|
+
isLoading,
|
|
1774
|
+
timeNextReq,
|
|
1775
|
+
isSubmitButtonDisabled,
|
|
1776
|
+
setTimeNextReq,
|
|
1777
|
+
setErrorText,
|
|
1778
|
+
};
|
|
1779
|
+
};
|
|
1780
|
+
const getTimer = (sendTime) => TIME_TO_RESEND - Math.floor((Date.now() - sendTime) / 1000);
|
|
1781
|
+
|
|
1782
|
+
const CODE_LENGTH = 4;
|
|
1783
|
+
const VerifyPhoneDialog = JSX(({ phone, withDescription = true, consents, onSuccess = noop, onClose = noop, formatData, reqId, isRetail = true, }) => {
|
|
1784
|
+
const [values, setValues] = useState(Array(CODE_LENGTH).fill(''));
|
|
1785
|
+
const sessionStore = useSessionStore();
|
|
1786
|
+
const { handleSubmit, hasError, errorText, isLoading, timeNextReq, isSubmitButtonDisabled, setTimeNextReq, setErrorText, } = useVerifyPhoneDialogSubmit({
|
|
1787
|
+
values,
|
|
1788
|
+
onSuccess,
|
|
1789
|
+
formatData,
|
|
1790
|
+
reqId,
|
|
1791
|
+
isRetail,
|
|
1792
|
+
});
|
|
1793
|
+
const captchaDialog = useDialog(CaptchaDialog);
|
|
1794
|
+
const phoneNumber = formatPhone(phone);
|
|
1795
|
+
const restartTimer = useCountDownTimer({ seconds: timeNextReq, onTick: setTimeNextReq });
|
|
1796
|
+
const handleSendCode = useCallback(async () => {
|
|
1797
|
+
const isSuccessSendCode = await sendCode({
|
|
1798
|
+
phoneNumber,
|
|
1799
|
+
smsCodesSetName: { key: 'AUTHENTICATION' },
|
|
1800
|
+
}, isRetail);
|
|
1801
|
+
if (isSuccessSendCode) {
|
|
1802
|
+
setTimeNextReq(TIME_TO_RESEND);
|
|
1803
|
+
restartTimer(TIME_TO_RESEND);
|
|
1804
|
+
setErrorText('');
|
|
1805
|
+
sessionStore.smsCode = {
|
|
1806
|
+
sendTime: Date.now(),
|
|
1807
|
+
attempts: 0,
|
|
1808
|
+
};
|
|
1809
|
+
}
|
|
1810
|
+
else {
|
|
1811
|
+
captchaDialog.open({ phoneNumber, sendCode: handleSendCode });
|
|
1812
|
+
}
|
|
1813
|
+
}, [phoneNumber, restartTimer, onClose]);
|
|
1814
|
+
useEffect(() => {
|
|
1815
|
+
if (!sessionStore.smsCode?.sendTime && isRetail) {
|
|
1816
|
+
handleSendCode();
|
|
1817
|
+
}
|
|
1818
|
+
}, []);
|
|
1819
|
+
return (jsx(Dialog, { className: "my-6xl max-w-3xl w-full min-h-fit mx-auto rounded-xl p-m", onClose: onClose, children: jsxs("div", { className: "flex flex-col gap-xl items-center rounded-md", children: [jsx(Headline, { className: "w-full", title: "\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430", description: `Мы отправили код на ${phone}`, headlineVersion: "XS", isEmbedded: true, as: "h6" }), jsx(InputCode, { values: values, setValues: setValues, errorText: errorText, hasError: hasError }), renderText$3(timeNextReq, handleSendCode), withDescription ? (jsxs(RichText, { itemSize: "list-s", children: [jsx("span", { children: "\u0412\u0432\u043E\u0434\u044F \u043A\u043E\u0434, \u044F \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u044E, \u0447\u0442\u043E \u043E\u0437\u043D\u0430\u043A\u043E\u043C\u043B\u0435\u043D \u0438 \u043F\u043E\u0434\u043F\u0438\u0441\u044B\u0432\u0430\u044E: " }), jsx("ul", { children: consents?.map((_, i) => (jsx("li", { children: _ }, `${_}-${i}`))) })] })) : null, renderNextButton(isSubmitButtonDisabled, handleSubmit), isLoading ? jsx(Loader, { blur: false }) : null] }) }));
|
|
1820
|
+
});
|
|
1821
|
+
const renderNextButton = (disabled, onClick) => (jsx(SubmitButton, { text: "\u0414\u0430\u043B\u0435\u0435", disabled: disabled, onClick: onClick }));
|
|
1822
|
+
const renderText$3 = (timeNextReq, handleSendCode) => timeNextReq ? (jsxs("div", { className: "flex flex-row text-l font-light text-base", children: ["\u041F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u043A\u043E\u0434 \u043C\u043E\u0436\u043D\u043E \u0447\u0435\u0440\u0435\u0437", jsx(Timer, { className: "pl-2xs", seconds: timeNextReq })] })) : (jsx(Button, { embedded: true, onClick: handleSendCode, children: jsx(ButtonTitle, { children: "\u041F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u043A\u043E\u0434" }) }));
|
|
1823
|
+
|
|
1824
|
+
const ApplicationFormLayout = JSX((props) => {
|
|
1825
|
+
const { className, title, children, ...rest } = props;
|
|
1826
|
+
return (jsx(BlockWrapper, { className: className, defaultPadding: "p-6xl", ...rest, children: jsxs("div", { className: "container space-y-lg", children: [title ? jsx(Heading, { headingType: "h3", title: title, className: "@xl:text-center" }) : null, children] }) }));
|
|
1827
|
+
});
|
|
1828
|
+
|
|
1829
|
+
const getConsentDataProcessing = (inputs) => inputs?.find((_) => _?.name === 'consentDataProcessing');
|
|
1830
|
+
|
|
1831
|
+
// TODO Базовая функицональность всех Control - надо вынести и привязать к required флагу
|
|
1832
|
+
const getRequiredLabel = ({ label, errors }) => label && errors ? `${label}*` : label;
|
|
1833
|
+
|
|
1834
|
+
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 }));
|
|
1835
|
+
|
|
1836
|
+
const debounce = (fn, delay = 600) => {
|
|
1837
|
+
let timerId;
|
|
1838
|
+
const debouncedCallback = (...args) => {
|
|
1839
|
+
debouncedCallback.dispose();
|
|
1840
|
+
timerId = setTimeout(() => {
|
|
1841
|
+
fn(...args);
|
|
1842
|
+
}, delay);
|
|
1843
|
+
};
|
|
1844
|
+
debouncedCallback.dispose = () => {
|
|
1845
|
+
if (timerId) {
|
|
1846
|
+
clearTimeout(timerId);
|
|
1847
|
+
}
|
|
1848
|
+
};
|
|
1849
|
+
return debouncedCallback;
|
|
1850
|
+
};
|
|
1306
1851
|
|
|
1307
1852
|
const formatOption = (_) => _?.text || _?.key || '';
|
|
1308
1853
|
|
|
@@ -1623,10 +2168,6 @@
|
|
|
1623
2168
|
const ITEMS_CREDIT_AMOUNT = ['От 1 000 ₽', 'До 1 000 000 000 ₽'];
|
|
1624
2169
|
const AmountField = JSX(({ field, input }) => (jsx(InputRange, { title: "\u0421\u0443\u043C\u043C\u0430, \u20BD", items: ITEMS_CREDIT_AMOUNT, min: MIN_CREDIT_AMOUNT, max: MAX_CREDIT_AMOUNT, ...field(input?.name ?? '') })));
|
|
1625
2170
|
|
|
1626
|
-
const noop = () => {
|
|
1627
|
-
// Do nothing
|
|
1628
|
-
};
|
|
1629
|
-
|
|
1630
2171
|
const InputWrapper = JSX(({ className, label, value = '', error, errors, type, isInteger, placeholder, maxLength, inputRef, isOpen, onOpen, onClose, onChange = noop, ...rest }) => {
|
|
1631
2172
|
const popupRef = useOutsideClick(onClose);
|
|
1632
2173
|
const handleChange = useCallback((v) => {
|
|
@@ -2109,9 +2650,9 @@
|
|
|
2109
2650
|
onChange && onChange(!value);
|
|
2110
2651
|
}, [onChange, disabled, value]);
|
|
2111
2652
|
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" }));
|
|
2112
|
-
return (jsx("div", { className: className, children: jsxs("label", { className: style('flex items-center relative group/box', getCursorStyle(disabled)), 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$
|
|
2653
|
+
return (jsx("div", { className: className, children: jsxs("label", { className: style('flex items-center relative group/box', getCursorStyle(disabled)), 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$2(text)] }) }));
|
|
2113
2654
|
});
|
|
2114
|
-
const renderText$
|
|
2655
|
+
const renderText$2 = (text) => text ? (jsx("div", { className: "ml-s", children: jsx(Text, { size: "text-l", font: "font-light", children: text }) })) : null;
|
|
2115
2656
|
const getCursorStyle = (disabled = false) => (disabled ? 'cursor-not-allowed' : 'cursor-pointer');
|
|
2116
2657
|
const role = (isRadio = false) => (isRadio ? 'radio' : 'checkbox');
|
|
2117
2658
|
const checkboxStyle = (value = false) => style('rounded border', { 'bg-primary-main': value });
|
|
@@ -2435,33 +2976,6 @@
|
|
|
2435
2976
|
|
|
2436
2977
|
const renderTitle = (title) => title ? (jsx("div", { className: "@xl:text-center @xl:col-span-2 mb-m", children: jsx(Text, { size: "text-h6", children: title }) })) : null;
|
|
2437
2978
|
|
|
2438
|
-
const themeStyle$1 = {
|
|
2439
|
-
primary: style('text-white bg-primary-main hover:bg-primary-hover active:bg-primary-active', 'group-data-secondary:text-primary-main group-data-secondary:bg-white', 'group-data-secondary:hover:text-white group-data-secondary:hover:bg-primary-hover', 'group-data-secondary:active:bg-primary-active'),
|
|
2440
|
-
secondary: style('text-primary-main bg-main-divider hover:text-white hover:bg-primary-hover active:bg-primary-active', 'group-data-secondary:text-white group-data-secondary:bg-white/20', 'group-data-secondary:hover:bg-primary-hover', 'group-data-secondary:active:bg-primary-active'),
|
|
2441
|
-
};
|
|
2442
|
-
const embeddedStyle = style('group/btn-embedded', 'bg-transparent border border-transparent outline-none');
|
|
2443
|
-
const disabledStyle = style('bg-main-gray text-main-disabled cursor-not-allowed');
|
|
2444
|
-
const Button = JSX(({ className, type = 'button', version = 'primary', shape = 'default', embedded, disabled, role, ariaLabel, data, dataTheme, children, wcmsIgnore, onClick = noop, }) => {
|
|
2445
|
-
const handleClick = useCallback(role !== 'tab' ? handlerDecorator(onClick) : onClick, [
|
|
2446
|
-
role,
|
|
2447
|
-
onClick,
|
|
2448
|
-
]);
|
|
2449
|
-
const aspectsAttrs = useMemo(() => getAspectsAttributes(data), [data]);
|
|
2450
|
-
const isRound = shape === 'round';
|
|
2451
|
-
return (jsx("button", { className: style('font-sans flex items-center gap-xs', {
|
|
2452
|
-
[themeStyle$1[version]]: !disabled && !embedded,
|
|
2453
|
-
[embeddedStyle]: embedded,
|
|
2454
|
-
[disabledStyle]: disabled,
|
|
2455
|
-
}, embedded ? 'justify-between' : 'justify-center', embedded || isRound ? 'p-0' : 'px-9 py-4', {
|
|
2456
|
-
'rounded-md': shape === 'default',
|
|
2457
|
-
'rounded-full': isRound,
|
|
2458
|
-
}, className), type: type, role: role, "aria-label": ariaLabel, disabled: disabled, "aria-disabled": disabled ? 'true' : undefined, "data-theme": dataTheme, "data-wcms-ignore": wcmsIgnore, ...aspectsAttrs, onClick: handleClick, children: children }));
|
|
2459
|
-
});
|
|
2460
|
-
|
|
2461
|
-
const CloseButton = JSX(({ className, onClose }) => (jsx("button", { className: style('flex justify-center items-center w-12 h-12 p-2xs bg-transparent border-none', className), onClick: onClose, title: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C", type: "button", children: jsx(Icon, { name: "CloseIcon", width: "20", height: "20", iconVersion: "gray" }) })));
|
|
2462
|
-
|
|
2463
|
-
const Dialog = JSX(({ className, head, children, onClose, onClick }) => (jsxs("div", { className: style('relative bg-white pt-0 p-lg', className), role: "dialog", title: "\u0414\u0438\u0430\u043B\u043E\u0433", onClick: onClick, children: [jsxs("div", { className: "sticky py-xl top-0 bg-white z-10", children: [jsx(CloseButton, { className: "absolute top-0 right-0", onClose: onClose }), jsx("div", { className: "container", children: head })] }), jsx("div", { className: "container pb-m mb-[74px] lg:mb-0", children: children })] })));
|
|
2464
|
-
|
|
2465
2979
|
const ResponseTypeDialog = JSX(({ ok, typeForm, onClose }) => {
|
|
2466
2980
|
const statusIcon = ok ? 'ResponseOKIcon' : 'ResponseFailIcon';
|
|
2467
2981
|
const responseOKDescription = typeForm === 'ANTIFRAUD'
|
|
@@ -2546,12 +3060,6 @@
|
|
|
2546
3060
|
return { ...formState, typeForm: { key: typeForm, text: '' } };
|
|
2547
3061
|
};
|
|
2548
3062
|
|
|
2549
|
-
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, {
|
|
2550
|
-
'backdrop-blur': blur,
|
|
2551
|
-
}), 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" }) })));
|
|
2552
|
-
|
|
2553
|
-
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] })));
|
|
2554
|
-
|
|
2555
3063
|
const themeStyle = {
|
|
2556
3064
|
primary: themeStyle$1.primary,
|
|
2557
3065
|
secondary: themeStyle$1.secondary,
|
|
@@ -2569,9 +3077,9 @@
|
|
|
2569
3077
|
[themeStyle[version]]: Boolean(version),
|
|
2570
3078
|
[aboveText ? 'px-9 py-2.5' : 'px-9 py-4']: buttonLike,
|
|
2571
3079
|
'rounded-md': buttonLike,
|
|
2572
|
-
}, className), href: href, target: target, rel: rel, "aria-label": ariaLabel ?? `Ссылка на ${text}`, role: href ? 'link' : 'button', onClick: onClick, ...getAspectsAttributes(data), children: children ?? renderText$
|
|
3080
|
+
}, className), href: href, target: target, rel: rel, "aria-label": ariaLabel ?? `Ссылка на ${text}`, role: href ? 'link' : 'button', onClick: onClick, ...getAspectsAttributes(data), children: children ?? renderText$1(text, aboveText) }));
|
|
2573
3081
|
});
|
|
2574
|
-
const renderText$
|
|
3082
|
+
const renderText$1 = (text, aboveText) => text || aboveText ? (jsxs("div", { className: "whitespace-pre", children: [aboveText ? jsx("div", { className: "font-light text-left text-xs", children: aboveText }) : null, jsx("div", { className: style('text-left', { 'text-s -mt-3xs': Boolean(aboveText) }), children: text })] })) : null;
|
|
2575
3083
|
|
|
2576
3084
|
const Footnote = JSX(({ text, link }) => (jsxs(Paragraph, { size: "text-l", font: "font-light", color: "text-secondary-text", children: [text ? jsx(Text, { children: text }) : null, link ? (jsx(Link, { ...link, ariaLabel: "\u0443\u0441\u043B\u043E\u0432\u0438\u044F \u043F\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043D\u043D\u044B\u0445", children: link.text })) : null] })));
|
|
2577
3085
|
|
|
@@ -2582,19 +3090,43 @@
|
|
|
2582
3090
|
const renderContacts = () => (jsxs("div", { className: "space-y-m", children: [jsx(Heading, { headingType: "h6", title: "\u0418\u043B\u0438 \u0441\u0432\u044F\u0436\u0438\u0442\u0435\u0441\u044C \u0441 \u043D\u0430\u043C\u0438 \u0443\u0434\u043E\u0431\u043D\u044B\u043C \u0441\u043F\u043E\u0441\u043E\u0431\u043E\u043C", className: "@xl:text-center" }), jsxs("div", { className: "flex sm:justify-center gap-xl", children: [jsxs("a", { className: "flex gap-s items-center text-primary-text no-underline", href: `tel:8 (800) 200-78-70`, "aria-label": "\u0442\u0435\u043B\u0435\u0444\u043E\u043D 8 (800) 200-78-70", children: [jsx(Img, { image: { icon: 'PhoneIcon' }, width: "24", height: "24" }), jsx("span", { children: "8 (800) 200-78-70" })] }), jsxs("a", { className: "flex gap-s items-center text-primary-text no-underline", "aria-label": "\u043F\u043E\u0447\u0442\u0430 ved@rshb.ru", href: `mailto:ved@rshb.ru`, children: [jsx(Img, { image: { icon: 'MailIcon' }, width: "24", height: "24" }), jsx("span", { children: "ved@rshb.ru" })] })] })] }));
|
|
2583
3091
|
|
|
2584
3092
|
const API = LeadServiceAPI();
|
|
2585
|
-
const ApplicationForm = UniBlock(
|
|
3093
|
+
const ApplicationForm = UniBlock(
|
|
3094
|
+
// eslint-disable-next-line max-lines-per-function
|
|
3095
|
+
({ className, title, typeForm = '', sections = [], button, link, endpoint, additionalParams, isContacts, data, ...rest }) => {
|
|
2586
3096
|
const inputs = useMemo(() => (sections?.flatMap((_) => _?.inputs) || []), [sections]);
|
|
2587
3097
|
const initialFormState = useMemo(() => getInitialFormState$2(inputs, typeForm), [inputs, typeForm]);
|
|
2588
3098
|
const router = useRouter();
|
|
2589
3099
|
const formValidator = useMemo(() => getFormValidator(inputs), [inputs]);
|
|
2590
3100
|
const responseTypeDialog = useDialog(ResponseTypeDialog);
|
|
2591
3101
|
const aspects = useAspects();
|
|
3102
|
+
const verifyPhoneDialog = useDialog(VerifyPhoneDialog);
|
|
2592
3103
|
const handleSubmit = useCallback(async (formData, ev) => {
|
|
2593
3104
|
const formatData = getFormatData({ ...formData, ...additionalParams });
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
3105
|
+
if (endpoint === 'initcorporatelead') {
|
|
3106
|
+
const { phone } = formatData;
|
|
3107
|
+
const response = await API.sendCode({ phone: String(phone) });
|
|
3108
|
+
if (!response) {
|
|
3109
|
+
responseTypeDialog.open({ ok: Boolean(response), typeForm });
|
|
3110
|
+
return;
|
|
3111
|
+
}
|
|
3112
|
+
verifyPhoneDialog.open({
|
|
3113
|
+
phone,
|
|
3114
|
+
withDescription: false,
|
|
3115
|
+
formatData,
|
|
3116
|
+
reqId: String(response),
|
|
3117
|
+
isRetail: false,
|
|
3118
|
+
onSuccess: () => {
|
|
3119
|
+
verifyPhoneDialog.close();
|
|
3120
|
+
responseTypeDialog.open({ ok: true, typeForm });
|
|
3121
|
+
},
|
|
3122
|
+
});
|
|
3123
|
+
}
|
|
3124
|
+
else {
|
|
3125
|
+
const ok = Boolean(await API.send(formatData, router, endpoint === 'lead'));
|
|
3126
|
+
responseTypeDialog.open({ ok, typeForm });
|
|
3127
|
+
if (ok) {
|
|
3128
|
+
handleAspects({ aspectsAttributes: data, aspects, ev });
|
|
3129
|
+
}
|
|
2598
3130
|
}
|
|
2599
3131
|
}, [typeForm]);
|
|
2600
3132
|
const [, { field, onSubmit }] = useForm(initialFormState, {
|
|
@@ -2885,42 +3417,6 @@
|
|
|
2885
3417
|
EsiaStatuses["Pending"] = "PENDING";
|
|
2886
3418
|
})(EsiaStatuses || (EsiaStatuses = {}));
|
|
2887
3419
|
|
|
2888
|
-
const getTraceId = () => {
|
|
2889
|
-
const result = new Uint8Array(8);
|
|
2890
|
-
globalThis.crypto.getRandomValues(result);
|
|
2891
|
-
return result.reduce((acc, _) => `${acc}${_.toString(16).padStart(2, '0')}`, '');
|
|
2892
|
-
};
|
|
2893
|
-
|
|
2894
|
-
const fetchRetailJSON = async (url, method, body) => {
|
|
2895
|
-
try {
|
|
2896
|
-
const response = await doRequest(url, method, body);
|
|
2897
|
-
return response.json();
|
|
2898
|
-
}
|
|
2899
|
-
catch (err) {
|
|
2900
|
-
console.error(err);
|
|
2901
|
-
return null;
|
|
2902
|
-
}
|
|
2903
|
-
};
|
|
2904
|
-
async function doRequest(url, method, body) {
|
|
2905
|
-
const traceId = getTraceId();
|
|
2906
|
-
return globalThis?.fetch?.(`${RETAIL_API_BASE_URI}${url}`, {
|
|
2907
|
-
method,
|
|
2908
|
-
headers: {
|
|
2909
|
-
'Content-Type': 'application/json',
|
|
2910
|
-
'X-B3-Sampled': '1',
|
|
2911
|
-
'X-B3-Spanid': traceId,
|
|
2912
|
-
'X-B3-Traceid': traceId,
|
|
2913
|
-
...getAuthorizationHeaders(),
|
|
2914
|
-
},
|
|
2915
|
-
credentials: 'include',
|
|
2916
|
-
body: body ? JSON.stringify(body) : null,
|
|
2917
|
-
});
|
|
2918
|
-
}
|
|
2919
|
-
const getAuthorizationHeaders = () => {
|
|
2920
|
-
const token = sessionStorage.getItem('accessToken');
|
|
2921
|
-
return token ? { Authorization: `Bearer ${token}` } : null;
|
|
2922
|
-
};
|
|
2923
|
-
|
|
2924
3420
|
const getLink = (body) => fetchRetailJSON('/esia/getLink', 'POST', body);
|
|
2925
3421
|
|
|
2926
3422
|
const EsiaLoginBanner = JSX(({ onChangeEsiaStatus, productType }) => {
|
|
@@ -3273,8 +3769,6 @@
|
|
|
3273
3769
|
|
|
3274
3770
|
const CardRow = JSX(({ className, children }) => (jsx("div", { className: style('flex flex-col sm:flex-row sm:border-t sm:border-solid sm:border-main-divider py-xl gap-x-6xl gap-y-xl', className), children: children })));
|
|
3275
3771
|
|
|
3276
|
-
const ButtonTitle = JSX(({ className, children }) => (jsx("span", { className: style('inline-flex items-center text-start gap-s group-[]/btn-embedded:text-primary-main', className), children: children })));
|
|
3277
|
-
|
|
3278
3772
|
const ToggleIcon = JSX(({ isUnfolded, ...rest }) => (jsx(Icon, { name: isUnfolded ? 'ArrowUpIcon' : 'ArrowDownIcon', size: "small", iconVersion: "", ...rest })));
|
|
3279
3773
|
|
|
3280
3774
|
const DefaultFoldButton = JSX(({ className, isUnfolded, short, label = isUnfolded ? 'Скрыть' : 'Развернуть', embedded, ...rest }) => (jsxs(Button, { className: style({ 'w-full': !short }, className), embedded: embedded, shape: short ? 'default' : 'square', role: "tab", "aria-label": "\u041A\u043D\u043E\u043F\u043A\u0430 \u0441\u0432\u043E\u0440\u0430\u0447\u0438\u0432\u0430\u044E\u0449\u0435\u0439\u0441\u044F \u0441\u0435\u043A\u0446\u0438\u0438", ...rest, children: [jsx(ButtonTitle, { children: label }), jsx(ToggleIcon, { isUnfolded: isUnfolded, iconVersion: embedded ? 'color' : '' })] })));
|
|
@@ -3838,153 +4332,15 @@
|
|
|
3838
4332
|
}
|
|
3839
4333
|
}, [regionValue.key]);
|
|
3840
4334
|
const { points } = useOfficesAtmsMapData({
|
|
3841
|
-
data: offices,
|
|
3842
|
-
filtrationState: {},
|
|
3843
|
-
getBalloon: getOfficePoint,
|
|
3844
|
-
});
|
|
3845
|
-
return (jsxs("div", { children: [jsx(SelectControl, { label: "\u0410\u0434\u0440\u0435\u0441 \u043E\u0442\u0434\u0435\u043B\u0435\u043D\u0438\u044F", placeholder: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043E\u0442\u0434\u0435\u043B\u0435\u043D\u0438\u0435", options: offices.map(({ id, address = '' }) => ({
|
|
3846
|
-
key: id?.toString() || '',
|
|
3847
|
-
text: address,
|
|
3848
|
-
})), ...addressField, isSearch: true }), jsx("div", { className: "h-[600px]", children: jsx(ClientOnly, { children: jsx(YandexMap, { points: points, isLoad: !data, className: "h-full", selectedAddress: addressField?.value?.text }) }) })] }));
|
|
3849
|
-
});
|
|
3850
|
-
|
|
3851
|
-
function copy(source, target) {
|
|
3852
|
-
for (const [k, v] of source.entries()) {
|
|
3853
|
-
if (v !== null && v !== undefined) {
|
|
3854
|
-
target.setItem(k, v);
|
|
3855
|
-
}
|
|
3856
|
-
else {
|
|
3857
|
-
target.removeItem(k);
|
|
3858
|
-
}
|
|
3859
|
-
}
|
|
3860
|
-
}
|
|
3861
|
-
|
|
3862
|
-
function replicate(primary, secondary) {
|
|
3863
|
-
copy(primary, secondary);
|
|
3864
|
-
copy(secondary, primary);
|
|
3865
|
-
return primary.bus.watch(({ type, event }) => {
|
|
3866
|
-
if (event !== null && event !== undefined) {
|
|
3867
|
-
secondary.setItem(type, event);
|
|
3868
|
-
}
|
|
3869
|
-
else {
|
|
3870
|
-
secondary.removeItem(type);
|
|
3871
|
-
}
|
|
3872
|
-
});
|
|
3873
|
-
}
|
|
3874
|
-
|
|
3875
|
-
class StorageAdapter {
|
|
3876
|
-
storage;
|
|
3877
|
-
bus;
|
|
3878
|
-
get size() {
|
|
3879
|
-
return this.storage?.length ?? 0;
|
|
3880
|
-
}
|
|
3881
|
-
constructor(storage, bus = new EventBus()) {
|
|
3882
|
-
this.storage = storage;
|
|
3883
|
-
this.bus = bus;
|
|
3884
|
-
}
|
|
3885
|
-
hasItem(key) {
|
|
3886
|
-
return Boolean(this.storage?.getItem(String(key)));
|
|
3887
|
-
}
|
|
3888
|
-
getItem(key) {
|
|
3889
|
-
const _ = this.storage?.getItem(String(key)) ?? null;
|
|
3890
|
-
try {
|
|
3891
|
-
return JSON.parse(String(_));
|
|
3892
|
-
}
|
|
3893
|
-
catch (ex) {
|
|
3894
|
-
return null;
|
|
3895
|
-
}
|
|
3896
|
-
}
|
|
3897
|
-
entries() {
|
|
3898
|
-
return Array.from({ length: this.size }, (_, i) => {
|
|
3899
|
-
const k = String(this.storage?.key(i));
|
|
3900
|
-
return [k, this.getItem(k)];
|
|
3901
|
-
});
|
|
3902
|
-
}
|
|
3903
|
-
setItem(key, value) {
|
|
3904
|
-
if (value !== null) {
|
|
3905
|
-
this.storage?.setItem(String(key), JSON.stringify(value));
|
|
3906
|
-
}
|
|
3907
|
-
else {
|
|
3908
|
-
this.storage?.removeItem(String(key));
|
|
3909
|
-
}
|
|
3910
|
-
this.bus?.subject(key, value);
|
|
3911
|
-
}
|
|
3912
|
-
removeItem(key) {
|
|
3913
|
-
this.storage?.removeItem(String(key));
|
|
3914
|
-
this.bus?.subject(key, null);
|
|
3915
|
-
}
|
|
3916
|
-
}
|
|
3917
|
-
|
|
3918
|
-
class Store {
|
|
3919
|
-
bus;
|
|
3920
|
-
store = new Map();
|
|
3921
|
-
get size() {
|
|
3922
|
-
return this.store.size;
|
|
3923
|
-
}
|
|
3924
|
-
constructor(bus = new EventBus()) {
|
|
3925
|
-
this.bus = bus;
|
|
3926
|
-
}
|
|
3927
|
-
hasItem(key) {
|
|
3928
|
-
return this.store.has(key);
|
|
3929
|
-
}
|
|
3930
|
-
getItem(key) {
|
|
3931
|
-
return this.store.get(key);
|
|
3932
|
-
}
|
|
3933
|
-
entries() {
|
|
3934
|
-
return this.store.entries();
|
|
3935
|
-
}
|
|
3936
|
-
setItem(key, value) {
|
|
3937
|
-
this.store.set(key, value);
|
|
3938
|
-
this.bus.subject(key, value);
|
|
3939
|
-
}
|
|
3940
|
-
removeItem(key) {
|
|
3941
|
-
this.store.delete(key);
|
|
3942
|
-
this.bus.subject(key, null);
|
|
3943
|
-
}
|
|
3944
|
-
}
|
|
3945
|
-
|
|
3946
|
-
function useRerender() {
|
|
3947
|
-
const [, setCount] = useState(0);
|
|
3948
|
-
return useCallback(() => setCount(_ => (_ + 1) % (1 << 16)), []);
|
|
3949
|
-
}
|
|
3950
|
-
|
|
3951
|
-
const DEFAULT_METHODS = {};
|
|
3952
|
-
/**
|
|
3953
|
-
* MobX like reactivity (simplified).
|
|
3954
|
-
* Can be used to migrate from Redux/MobX or something else
|
|
3955
|
-
*
|
|
3956
|
-
* @param store
|
|
3957
|
-
* @returns reactive proxy backed by store
|
|
3958
|
-
*/
|
|
3959
|
-
function useStore(store, methods = DEFAULT_METHODS) {
|
|
3960
|
-
const deps = useRef(null);
|
|
3961
|
-
const render = useRerender();
|
|
3962
|
-
useEffect(() => store.bus.watch(ev => {
|
|
3963
|
-
if (deps.current?.has(String(ev.type))) {
|
|
3964
|
-
render();
|
|
3965
|
-
}
|
|
3966
|
-
}), [store, render]);
|
|
3967
|
-
return useMemo(() => new Proxy(methods, {
|
|
3968
|
-
get(_, key) {
|
|
3969
|
-
deps.current ||= new Set();
|
|
3970
|
-
deps.current.add(key);
|
|
3971
|
-
return store.getItem(key);
|
|
3972
|
-
},
|
|
3973
|
-
has(_, key) {
|
|
3974
|
-
deps.current ||= new Set();
|
|
3975
|
-
deps.current.add(key);
|
|
3976
|
-
return store.hasItem(key);
|
|
3977
|
-
},
|
|
3978
|
-
set(_, key, value) {
|
|
3979
|
-
store.setItem(key, value);
|
|
3980
|
-
return true;
|
|
3981
|
-
},
|
|
3982
|
-
deleteProperty(_, key) {
|
|
3983
|
-
store.removeItem(key);
|
|
3984
|
-
return true;
|
|
3985
|
-
}
|
|
3986
|
-
}), [store]);
|
|
3987
|
-
}
|
|
4335
|
+
data: offices,
|
|
4336
|
+
filtrationState: {},
|
|
4337
|
+
getBalloon: getOfficePoint,
|
|
4338
|
+
});
|
|
4339
|
+
return (jsxs("div", { children: [jsx(SelectControl, { label: "\u0410\u0434\u0440\u0435\u0441 \u043E\u0442\u0434\u0435\u043B\u0435\u043D\u0438\u044F", placeholder: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043E\u0442\u0434\u0435\u043B\u0435\u043D\u0438\u0435", options: offices.map(({ id, address = '' }) => ({
|
|
4340
|
+
key: id?.toString() || '',
|
|
4341
|
+
text: address,
|
|
4342
|
+
})), ...addressField, isSearch: true }), jsx("div", { className: "h-[600px]", children: jsx(ClientOnly, { children: jsx(YandexMap, { points: points, isLoad: !data, className: "h-full", selectedAddress: addressField?.value?.text }) }) })] }));
|
|
4343
|
+
});
|
|
3988
4344
|
|
|
3989
4345
|
const localStore = new Store(); // localStorage cache
|
|
3990
4346
|
replicate(localStore, new StorageAdapter(globalThis?.localStorage));
|
|
@@ -5209,12 +5565,6 @@
|
|
|
5209
5565
|
|
|
5210
5566
|
const renderSubmitButton = (button, isSending = false) => (jsx(SubmitButton$1, { className: "w-full @xl:w-auto", isLoading: isSending, children: button?.text ? button.text : 'Отправить заявку' }));
|
|
5211
5567
|
|
|
5212
|
-
const sessionStore = new Store(); // sessionStorage cache
|
|
5213
|
-
replicate(sessionStore, new StorageAdapter(globalThis?.sessionStorage));
|
|
5214
|
-
function useSessionStore() {
|
|
5215
|
-
return useStore(sessionStore);
|
|
5216
|
-
}
|
|
5217
|
-
|
|
5218
5568
|
const createDraftTask = async (body) => {
|
|
5219
5569
|
const res = await fetchRetailJSON('/user-data/createDraftTask', 'POST', body);
|
|
5220
5570
|
return res || {};
|
|
@@ -5243,254 +5593,6 @@
|
|
|
5243
5593
|
|
|
5244
5594
|
const updateUserTask = (body) => doRequest('/user-data/updateUserTask', 'PUT', body);
|
|
5245
5595
|
|
|
5246
|
-
const Timer = JSX(({ className, seconds }) => (jsx("span", { className: className, children: formatTimer(seconds) })));
|
|
5247
|
-
const formatTimer = (seconds) => {
|
|
5248
|
-
const minutes = Math.floor(seconds / 60);
|
|
5249
|
-
return [minutes, seconds % 60].map((_) => String(_).padStart(2, '0')).join(':');
|
|
5250
|
-
};
|
|
5251
|
-
|
|
5252
|
-
const useInterval = (handler, period) => {
|
|
5253
|
-
const timer = useRef(null);
|
|
5254
|
-
const stop = useCallback(() => clearInterval(timer.current), []);
|
|
5255
|
-
const start = useCallback(() => {
|
|
5256
|
-
stop();
|
|
5257
|
-
timer.current = setInterval(() => handler(stop), period);
|
|
5258
|
-
}, [handler, period, stop]);
|
|
5259
|
-
useEffect(() => {
|
|
5260
|
-
start();
|
|
5261
|
-
return stop;
|
|
5262
|
-
}, [start, stop]);
|
|
5263
|
-
return { start, stop };
|
|
5264
|
-
};
|
|
5265
|
-
|
|
5266
|
-
function useCountDownTimer({ seconds, period = 1000, onTick, onEnd }) {
|
|
5267
|
-
const counter = useRef(seconds);
|
|
5268
|
-
const handleTick = useCallback((stop) => {
|
|
5269
|
-
counter.current ||= 0;
|
|
5270
|
-
counter.current = Math.max(0, counter.current - 1);
|
|
5271
|
-
try {
|
|
5272
|
-
onTick?.(counter.current);
|
|
5273
|
-
}
|
|
5274
|
-
finally {
|
|
5275
|
-
if (counter.current <= 0) {
|
|
5276
|
-
stop();
|
|
5277
|
-
onEnd?.();
|
|
5278
|
-
}
|
|
5279
|
-
}
|
|
5280
|
-
}, [onTick, onEnd]);
|
|
5281
|
-
const { start } = useInterval(handleTick, period);
|
|
5282
|
-
return useCallback((_) => {
|
|
5283
|
-
counter.current = _;
|
|
5284
|
-
start();
|
|
5285
|
-
}, []);
|
|
5286
|
-
}
|
|
5287
|
-
|
|
5288
|
-
const sendCode = (body) => doRequest('/sms/sendCode', 'POST', body)
|
|
5289
|
-
.then((res) => res.text())
|
|
5290
|
-
.then((text) => text === 'OK');
|
|
5291
|
-
|
|
5292
|
-
const ICON_SIZE = { width: '118', height: '24' };
|
|
5293
|
-
|
|
5294
|
-
const logoTitleSizeStyle = '';
|
|
5295
|
-
|
|
5296
|
-
const ICON_VERSION_MAP = {
|
|
5297
|
-
'bg-white': 'color',
|
|
5298
|
-
transparent: 'white',
|
|
5299
|
-
};
|
|
5300
|
-
const SVG_COLOR = {
|
|
5301
|
-
'bg-white': 'text-primary-main',
|
|
5302
|
-
transparent: 'text-white',
|
|
5303
|
-
};
|
|
5304
|
-
const renderImage = (bgColor, image, size) => {
|
|
5305
|
-
const img = image?.src
|
|
5306
|
-
? image
|
|
5307
|
-
: {
|
|
5308
|
-
icon: image?.icon || 'LogoIcon',
|
|
5309
|
-
iconVersion: ICON_VERSION_MAP[bgColor],
|
|
5310
|
-
};
|
|
5311
|
-
return (jsx(Img, { image: img, className: SVG_COLOR[bgColor], width: size?.width, height: size?.height }));
|
|
5312
|
-
};
|
|
5313
|
-
|
|
5314
|
-
const TEXT_COLOR = {
|
|
5315
|
-
'bg-white': 'text-primary-text',
|
|
5316
|
-
transparent: 'text-white',
|
|
5317
|
-
};
|
|
5318
|
-
const Logo = JSX(({ className, href = '/', logo, children, targetBlank, bgColor = 'bg-white', showTitle = true, data, }) => (jsxs("a", { className: style('inline-flex items-center font-sans no-underline', className), href: logo?.href ?? href, target: targetBlank ? '_blank' : '_self', "aria-label": logo?.title ?? 'Россельхозбанк', ...getAspectsAttributes(data), children: [renderImage(bgColor, logo?.image, ICON_SIZE), showTitle
|
|
5319
|
-
? children ?? (jsx("div", { className: "ml-s", children: jsx(Text, { font: "font-medium", color: TEXT_COLOR[bgColor], size: logoTitleSizeStyle, children: logo?.title ?? 'Россельхозбанк' }) }))
|
|
5320
|
-
: null] })));
|
|
5321
|
-
|
|
5322
|
-
const checkCaptcha = (body) => doRequest('/sms/checkCaptcha', 'POST', body)
|
|
5323
|
-
.then((res) => res.text())
|
|
5324
|
-
.then((text) => text !== 'ERROR');
|
|
5325
|
-
|
|
5326
|
-
const createCaptcha = (phoneNumber) => doRequest(`/sms/createCaptcha?phoneNumber=${encodeURIComponent(phoneNumber)}`, 'GET').then(async (res) => (res ? res.blob() : new Blob()));
|
|
5327
|
-
|
|
5328
|
-
const CaptchaDialog = JSX(({ phoneNumber, sendCode, onClose }) => {
|
|
5329
|
-
const [captcha, setCaptcha] = useState('');
|
|
5330
|
-
const [code, setCode] = useState('');
|
|
5331
|
-
const [hasError, setHasError] = useState(false);
|
|
5332
|
-
const [isLoading, { setTrue: startLoading, setFalse: endLoading }] = useBool(false);
|
|
5333
|
-
const { closeAll } = useDialogManager();
|
|
5334
|
-
const handleCheckCaptcha = useCallback(async () => {
|
|
5335
|
-
startLoading();
|
|
5336
|
-
const isValidCode = await checkCaptcha({ captchaText: code });
|
|
5337
|
-
if (isValidCode) {
|
|
5338
|
-
onClose?.();
|
|
5339
|
-
sendCode?.();
|
|
5340
|
-
}
|
|
5341
|
-
else {
|
|
5342
|
-
setHasError(true);
|
|
5343
|
-
}
|
|
5344
|
-
endLoading();
|
|
5345
|
-
}, [code, sendCode]);
|
|
5346
|
-
const handleCreateCaptcha = useCallback(() => {
|
|
5347
|
-
(async () => setCaptcha(URL.createObjectURL(await createCaptcha(phoneNumber))))();
|
|
5348
|
-
}, []);
|
|
5349
|
-
useEffect(handleCreateCaptcha, []);
|
|
5350
|
-
return (jsx(Dialog, { className: "my-6xl max-w-lg w-full min-h-fit mx-auto rounded-lg", head: jsx(Logo, {}), onClose: onClose, children: jsxs("div", { className: "flex flex-col gap-lg items-center", children: [jsxs("div", { className: "flex", children: [jsx("img", { className: "grow", src: captcha }), jsx(Button, { className: "w-8", embedded: true, onClick: handleCreateCaptcha, children: jsx(Icon, { iconVersion: "normal", name: "RefreshIcon" }) })] }), jsx(Input, { className: "w-80", onChange: setCode, value: code, placeholder: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043A\u043E\u0434 \u0441 \u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0438" }), hasError ? jsx("div", { className: "text-error", children: "\u041D\u0435\u0432\u0435\u0440\u043D\u044B\u0439 \u043A\u043E\u0434" }) : null, jsxs("div", { className: "flex w-80 justify-between", children: [jsx(Button, { version: "secondary", onClick: closeAll, children: "\u0412\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F" }), jsx(SubmitButton$1, { version: "secondary", disabled: !code, onClick: handleCheckCaptcha, children: "\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C" })] }), isLoading ? jsx(Loader, { blur: false }) : null] }) }));
|
|
5351
|
-
});
|
|
5352
|
-
|
|
5353
|
-
const InputCode = JSX(({ values, setValues, hasError, errorText }) => {
|
|
5354
|
-
const [activeIndex, setActiveIndex] = useState(0);
|
|
5355
|
-
const inputRefs = useRef([]);
|
|
5356
|
-
useEffect(() => {
|
|
5357
|
-
inputRefs.current?.[activeIndex]?.focus();
|
|
5358
|
-
}, [activeIndex]);
|
|
5359
|
-
const handleChange = useCallback((index) => (event) => {
|
|
5360
|
-
const { value } = event.currentTarget;
|
|
5361
|
-
const oneValue = value.slice(0, 1);
|
|
5362
|
-
setValues(values.map((_, i) => (i === index ? oneValue : _)));
|
|
5363
|
-
setActiveIndex(index + 1);
|
|
5364
|
-
}, [values]);
|
|
5365
|
-
const handleKeyDown = useCallback((currentIndex) => (event) => {
|
|
5366
|
-
const { key } = event;
|
|
5367
|
-
if (key === 'Backspace' && !values[currentIndex]) {
|
|
5368
|
-
const previousIndex = currentIndex > 0 ? currentIndex - 1 : values.length - 1;
|
|
5369
|
-
const updatedValues = values.map((value, index) => (index === previousIndex ? '' : value));
|
|
5370
|
-
setValues(updatedValues);
|
|
5371
|
-
setActiveIndex(previousIndex);
|
|
5372
|
-
}
|
|
5373
|
-
}, [values]);
|
|
5374
|
-
const handlePaste = useCallback((event) => {
|
|
5375
|
-
event.preventDefault();
|
|
5376
|
-
const pastedData = event.clipboardData.getData('text');
|
|
5377
|
-
const updatedValues = values.map((_, idx) => (idx < pastedData.length ? pastedData[idx] : _));
|
|
5378
|
-
setValues(updatedValues);
|
|
5379
|
-
setActiveIndex(updatedValues.length - 1);
|
|
5380
|
-
}, [values]);
|
|
5381
|
-
return (jsxs("div", { className: "flex flex-col gap-2 text-center", children: [jsx("div", { children: values.map((value, index) => (jsx("input", { type: "number", maxLength: 1, value: value, onChange: handleChange(index), onPaste: handlePaste, ref: (ref) => {
|
|
5382
|
-
if (!inputRefs.current) {
|
|
5383
|
-
inputRefs.current = [];
|
|
5384
|
-
}
|
|
5385
|
-
inputRefs.current[index] = ref;
|
|
5386
|
-
}, onFocus: (event) => event.target.select(), onKeyDown: handleKeyDown(index), className: getInputStyle(index, values, hasError) }, index))) }), hasError ? jsx("div", { className: "text-error", children: errorText }) : null] }));
|
|
5387
|
-
});
|
|
5388
|
-
const getInputStyle = (index, values, hasError = false) => {
|
|
5389
|
-
const isInputEmpty = !values[index];
|
|
5390
|
-
return `w-16 sm:w-20 h-24 text-5xl text-center p-md m-2 border ${getValidStyle(!hasError || !isInputEmpty)} rounded-md caret-transparent outline-none`;
|
|
5391
|
-
};
|
|
5392
|
-
|
|
5393
|
-
const SubmitButton = JSX(({ disabled = false, onClick, text }) => (jsx(Button, { type: "button", onClick: onClick, disabled: disabled, children: jsx(Text, { font: "font-normal", children: text }) })));
|
|
5394
|
-
|
|
5395
|
-
const checkCode = async (body) => fetchRetailJSON('/sms/checkCode', 'POST', body).then(saveToken);
|
|
5396
|
-
const saveToken = (data) => {
|
|
5397
|
-
if (data?.access_token && data?.refresh_token) {
|
|
5398
|
-
globalThis.sessionStorage.setItem('accessToken', data.access_token);
|
|
5399
|
-
globalThis.sessionStorage.setItem('refreshToken', data.refresh_token);
|
|
5400
|
-
}
|
|
5401
|
-
};
|
|
5402
|
-
|
|
5403
|
-
const TIME_TO_RESEND = 180;
|
|
5404
|
-
const useVerifyPhoneDialogSubmit = ({ values, onSuccess, }) => {
|
|
5405
|
-
const sessionStore = useSessionStore();
|
|
5406
|
-
const attempts = sessionStore.smsCode?.attempts || 0;
|
|
5407
|
-
const timer = Math.max(getTimer(sessionStore.smsCode?.sendTime || Date.now()), 0);
|
|
5408
|
-
const [errorText, setErrorText] = useState('');
|
|
5409
|
-
const [isLoading, { setTrue: startLoading, setFalse: endLoading }] = useBool(false);
|
|
5410
|
-
const [timeNextReq, setTimeNextReq] = useState(timer);
|
|
5411
|
-
const resetError = useCallback(() => setErrorText(''), []);
|
|
5412
|
-
const isTimeExpired = Boolean(timeNextReq === 0 && sessionStore.smsCode?.sendTime);
|
|
5413
|
-
const isSubmitButtonDisabled = attempts > 2 || isTimeExpired || !values.every(Boolean);
|
|
5414
|
-
const handleSubmit = useCallback(async () => {
|
|
5415
|
-
try {
|
|
5416
|
-
sessionStore.smsCode = {
|
|
5417
|
-
...sessionStore.smsCode,
|
|
5418
|
-
attempts: attempts + 1,
|
|
5419
|
-
};
|
|
5420
|
-
startLoading();
|
|
5421
|
-
await checkCode({
|
|
5422
|
-
smsText: values.join(''),
|
|
5423
|
-
smsCodesSetName: { key: 'AUTHENTICATION' },
|
|
5424
|
-
});
|
|
5425
|
-
setTimeNextReq(0);
|
|
5426
|
-
resetError();
|
|
5427
|
-
sessionStore.smsCode = null;
|
|
5428
|
-
await onSuccess?.(values.join(''));
|
|
5429
|
-
}
|
|
5430
|
-
catch {
|
|
5431
|
-
setErrorText(attempts > 1 ? 'Исчерпан лимит ввода смс-кода' : 'Неверный код');
|
|
5432
|
-
}
|
|
5433
|
-
finally {
|
|
5434
|
-
endLoading();
|
|
5435
|
-
}
|
|
5436
|
-
}, [values, attempts]);
|
|
5437
|
-
useEffect(() => {
|
|
5438
|
-
if (isTimeExpired) {
|
|
5439
|
-
setErrorText('Код просрочен');
|
|
5440
|
-
}
|
|
5441
|
-
else if (attempts > 2) {
|
|
5442
|
-
setErrorText('Исчерпан лимит ввода смс-кода');
|
|
5443
|
-
}
|
|
5444
|
-
}, [isTimeExpired]);
|
|
5445
|
-
return {
|
|
5446
|
-
handleSubmit,
|
|
5447
|
-
hasError: Boolean(errorText),
|
|
5448
|
-
errorText,
|
|
5449
|
-
isLoading,
|
|
5450
|
-
timeNextReq,
|
|
5451
|
-
isSubmitButtonDisabled,
|
|
5452
|
-
setTimeNextReq,
|
|
5453
|
-
setErrorText,
|
|
5454
|
-
};
|
|
5455
|
-
};
|
|
5456
|
-
const getTimer = (sendTime) => TIME_TO_RESEND - Math.floor((Date.now() - sendTime) / 1000);
|
|
5457
|
-
|
|
5458
|
-
const CODE_LENGTH = 4;
|
|
5459
|
-
const VerifyPhoneDialog = JSX(({ phone, withDescription = true, consents, onSuccess = noop, onClose = noop }) => {
|
|
5460
|
-
const [values, setValues] = useState(Array(CODE_LENGTH).fill(''));
|
|
5461
|
-
const sessionStore = useSessionStore();
|
|
5462
|
-
const { handleSubmit, hasError, errorText, isLoading, timeNextReq, isSubmitButtonDisabled, setTimeNextReq, setErrorText, } = useVerifyPhoneDialogSubmit({ values, onSuccess });
|
|
5463
|
-
const captchaDialog = useDialog(CaptchaDialog);
|
|
5464
|
-
const phoneNumber = formatPhone(phone);
|
|
5465
|
-
const restartTimer = useCountDownTimer({ seconds: timeNextReq, onTick: setTimeNextReq });
|
|
5466
|
-
const handleSendCode = useCallback(async () => {
|
|
5467
|
-
const isSuccessSendCode = await sendCode({
|
|
5468
|
-
phoneNumber,
|
|
5469
|
-
smsCodesSetName: { key: 'AUTHENTICATION' },
|
|
5470
|
-
});
|
|
5471
|
-
if (isSuccessSendCode) {
|
|
5472
|
-
setTimeNextReq(TIME_TO_RESEND);
|
|
5473
|
-
restartTimer(TIME_TO_RESEND);
|
|
5474
|
-
setErrorText('');
|
|
5475
|
-
sessionStore.smsCode = {
|
|
5476
|
-
sendTime: Date.now(),
|
|
5477
|
-
attempts: 0,
|
|
5478
|
-
};
|
|
5479
|
-
}
|
|
5480
|
-
else {
|
|
5481
|
-
captchaDialog.open({ phoneNumber, sendCode: handleSendCode });
|
|
5482
|
-
}
|
|
5483
|
-
}, [phoneNumber, restartTimer, onClose]);
|
|
5484
|
-
useEffect(() => {
|
|
5485
|
-
if (!sessionStore.smsCode?.sendTime) {
|
|
5486
|
-
handleSendCode();
|
|
5487
|
-
}
|
|
5488
|
-
}, []);
|
|
5489
|
-
return (jsx(Dialog, { className: "my-6xl max-w-3xl w-full min-h-fit mx-auto rounded-xl p-m", onClose: onClose, children: jsxs("div", { className: "flex flex-col gap-xl items-center rounded-md", children: [jsx(Headline, { className: "w-full", title: "\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430", description: `Мы отправили код на ${phone}`, headlineVersion: "XS", isEmbedded: true, as: "h6" }), jsx(InputCode, { values: values, setValues: setValues, errorText: errorText, hasError: hasError }), renderText$1(timeNextReq, handleSendCode), withDescription ? (jsxs(RichText, { itemSize: "list-s", children: [jsx("span", { children: "\u0412\u0432\u043E\u0434\u044F \u043A\u043E\u0434, \u044F \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u044E, \u0447\u0442\u043E \u043E\u0437\u043D\u0430\u043A\u043E\u043C\u043B\u0435\u043D \u0438 \u043F\u043E\u0434\u043F\u0438\u0441\u044B\u0432\u0430\u044E: " }), jsx("ul", { children: consents?.map((_, i) => (jsx("li", { children: _ }, `${_}-${i}`))) })] })) : null, renderNextButton(isSubmitButtonDisabled, handleSubmit), isLoading ? jsx(Loader, { blur: false }) : null] }) }));
|
|
5490
|
-
});
|
|
5491
|
-
const renderNextButton = (disabled, onClick) => (jsx(SubmitButton, { text: "\u0414\u0430\u043B\u0435\u0435", disabled: disabled, onClick: onClick }));
|
|
5492
|
-
const renderText$1 = (timeNextReq, handleSendCode) => timeNextReq ? (jsxs("div", { className: "flex flex-row text-l font-light text-base", children: ["\u041F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u043A\u043E\u0434 \u043C\u043E\u0436\u043D\u043E \u0447\u0435\u0440\u0435\u0437", jsx(Timer, { className: "pl-2xs", seconds: timeNextReq })] })) : (jsx(Button, { embedded: true, onClick: handleSendCode, children: jsx(ButtonTitle, { children: "\u041F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u043A\u043E\u0434" }) }));
|
|
5493
|
-
|
|
5494
5596
|
const defaultConsentText = {
|
|
5495
5597
|
title: 'Подпишите согласие на запрос в БКИ',
|
|
5496
5598
|
description: 'Согласие на запрос в Бюро кредитных историй (БКИ) ускорит решение по кредиту',
|
|
@@ -9428,8 +9530,9 @@
|
|
|
9428
9530
|
});
|
|
9429
9531
|
|
|
9430
9532
|
const DebitFormProgress = JSX(({ step = 1, totalSteps = 2, stepsTitles = [] }) => {
|
|
9431
|
-
const
|
|
9432
|
-
|
|
9533
|
+
const isFinalStep = step === totalSteps;
|
|
9534
|
+
const progress = isFinalStep ? 100 : 85;
|
|
9535
|
+
return (jsxs("div", { className: "py-lg px-5xl bg-white col-span-12", children: [stepsTitles[step] || null, jsx(ProgressBar, { step: progress, showPercentage: false })] }));
|
|
9433
9536
|
});
|
|
9434
9537
|
|
|
9435
9538
|
const INTERNET_BANK_LINK = 'https://online.rshb.ru/ib6/wf2/retail/ib/loginretaildefault';
|
|
@@ -9476,7 +9579,7 @@
|
|
|
9476
9579
|
|
|
9477
9580
|
const FailedStatusContent = JSX(() => (jsx(DebitFormStatus, { title: "\u0412\u0440\u0435\u043C\u044F \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F \u043F\u0440\u0435\u0432\u044B\u0448\u0435\u043D\u043E", description: "\u041F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0437\u0430\u044F\u0432\u043A\u0443 \u043F\u043E\u0437\u0436\u0435", buttonText: "\u0412\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F \u043D\u0430 \u0433\u043B\u0430\u0432\u043D\u0443\u044E" })));
|
|
9478
9581
|
|
|
9479
|
-
const PendingStatusContent = JSX(() => (jsx(DebitFormStatus, { title: "\
|
|
9582
|
+
const PendingStatusContent = JSX(() => (jsx(DebitFormStatus, { title: "\u041D\u0435 \u0437\u0430\u043A\u0440\u044B\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u044F\u0432\u043A\u0443", description: "\u0418\u0434\u0451\u0442 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u0434\u0430\u043D\u043D\u044B\u0445" })));
|
|
9480
9583
|
|
|
9481
9584
|
const SalaryDboClientStatusContent = JSX(() => (jsx(DebitFormStatus, { description: "\u0412\u044B \u0443\u0436\u0435 \u044F\u0432\u043B\u044F\u0435\u0442\u0435\u0441\u044C \u043A\u043B\u0438\u0435\u043D\u0442\u043E\u043C \u0410\u041E \u00AB\u0420\u043E\u0441\u0441\u0435\u043B\u044C\u0445\u043E\u0437\u0431\u0430\u043D\u043A\u00BB, \u0434\u043B\u044F \u0412\u0430\u0441 \u043E\u0444\u043E\u0440\u043C\u043B\u0435\u043D\u0438\u0435 \u0437\u0430\u0440\u043F\u043B\u0430\u0442\u043D\u043E\u0439 \u043A\u0430\u0440\u0442\u044B \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E \u0432 \u043F\u0435\u0440\u0432\u044B\u0439 \u0440\u0430\u0431\u043E\u0447\u0438\u0439 \u0434\u0435\u043D\u044C", buttonText: "\u041D\u0430 \u0433\u043B\u0430\u0432\u043D\u0443\u044E" })));
|
|
9482
9585
|
|
|
@@ -11537,7 +11640,7 @@
|
|
|
11537
11640
|
slots: () => [HEADER_SLOT, FOOTER_SLOT, STICKY_FOOTER_SLOT],
|
|
11538
11641
|
});
|
|
11539
11642
|
|
|
11540
|
-
const packageVersion = "0.14.
|
|
11643
|
+
const packageVersion = "0.14.889";
|
|
11541
11644
|
|
|
11542
11645
|
exports.Blocks = Blocks;
|
|
11543
11646
|
exports.ContentPage = ContentPage;
|