@redneckz/wildless-cms-uni-blocks 0.14.911 → 0.14.913
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 +12 -3
- package/bundle/bundle.umd.js +716 -684
- package/bundle/bundle.umd.min.js +1 -1
- package/bundle/components/ApplicationForm/VerifyPhoneDialog.d.ts +10 -0
- package/bundle/components/ApplicationForm/useVerifyPhoneDialogSubmit.d.ts +18 -0
- package/bundle/components/TariffsTable/TariffsTableCell.d.ts +1 -1
- package/bundle/retail/api/checkCode.d.ts +1 -9
- package/bundle/retail/api/sendCode.d.ts +1 -1
- package/bundle/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.d.ts +0 -4
- package/bundle/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.d.ts +1 -6
- package/bundle/ui-kit/ResponseTypeDialog/ResponseTypeDialog.d.ts +1 -1
- package/bundle/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.d.ts +16 -0
- package/bundle/utils/getTimer.d.ts +2 -0
- package/dist/api/LeadServiceAPI.d.ts +12 -3
- package/dist/api/LeadServiceAPI.js +0 -3
- package/dist/api/LeadServiceAPI.js.map +1 -1
- package/dist/components/ApplicationForm/ApplicationForm.js +1 -3
- package/dist/components/ApplicationForm/ApplicationForm.js.map +1 -1
- package/dist/components/ApplicationForm/VerifyPhoneDialog.d.ts +10 -0
- package/dist/components/ApplicationForm/VerifyPhoneDialog.js +37 -0
- package/dist/components/ApplicationForm/VerifyPhoneDialog.js.map +1 -0
- package/dist/components/ApplicationForm/useVerifyPhoneDialogSubmit.d.ts +18 -0
- package/dist/components/ApplicationForm/useVerifyPhoneDialogSubmit.js +50 -0
- package/dist/components/ApplicationForm/useVerifyPhoneDialogSubmit.js.map +1 -0
- package/dist/components/ExchangeRateTile/ExchangeCurrencyCalculator.js +2 -2
- package/dist/components/ExchangeRateTile/ExchangeCurrencyCalculator.js.map +1 -1
- package/dist/components/TariffsTable/TariffsTableCell.d.ts +1 -1
- package/dist/retail/api/checkCode.d.ts +1 -9
- package/dist/retail/api/checkCode.js +1 -22
- package/dist/retail/api/checkCode.js.map +1 -1
- package/dist/retail/api/sendCode.d.ts +1 -1
- package/dist/retail/api/sendCode.js +2 -8
- package/dist/retail/api/sendCode.js.map +1 -1
- package/dist/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.d.ts +0 -4
- package/dist/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js +5 -24
- package/dist/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js.map +1 -1
- package/dist/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.d.ts +1 -6
- package/dist/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.js +7 -10
- 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/dist/ui-kit/ResponseTypeDialog/ResponseTypeDialog.d.ts +1 -1
- package/dist/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.d.ts +16 -0
- package/dist/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.js +17 -0
- package/dist/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.js.map +1 -0
- package/dist/utils/getTimer.d.ts +2 -0
- package/dist/utils/getTimer.js +6 -0
- package/dist/utils/getTimer.js.map +1 -0
- package/lib/api/LeadServiceAPI.d.ts +12 -3
- package/lib/api/LeadServiceAPI.js +0 -3
- package/lib/api/LeadServiceAPI.js.map +1 -1
- package/lib/common.css +1 -1
- package/lib/components/ApplicationForm/ApplicationForm.js +1 -3
- package/lib/components/ApplicationForm/ApplicationForm.js.map +1 -1
- package/lib/components/ApplicationForm/VerifyPhoneDialog.d.ts +10 -0
- package/lib/components/ApplicationForm/VerifyPhoneDialog.js +35 -0
- package/lib/components/ApplicationForm/VerifyPhoneDialog.js.map +1 -0
- package/lib/components/ApplicationForm/useVerifyPhoneDialogSubmit.d.ts +18 -0
- package/lib/components/ApplicationForm/useVerifyPhoneDialogSubmit.js +47 -0
- package/lib/components/ApplicationForm/useVerifyPhoneDialogSubmit.js.map +1 -0
- package/lib/components/ExchangeRateTile/ExchangeCurrencyCalculator.js +2 -2
- package/lib/components/ExchangeRateTile/ExchangeCurrencyCalculator.js.map +1 -1
- package/lib/components/TariffsTable/TariffsTableCell.d.ts +1 -1
- package/lib/retail/api/checkCode.d.ts +1 -9
- package/lib/retail/api/checkCode.js +1 -22
- package/lib/retail/api/checkCode.js.map +1 -1
- package/lib/retail/api/sendCode.d.ts +1 -1
- package/lib/retail/api/sendCode.js +1 -7
- package/lib/retail/api/sendCode.js.map +1 -1
- package/lib/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.d.ts +0 -4
- package/lib/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js +5 -24
- package/lib/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js.map +1 -1
- package/lib/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.d.ts +1 -6
- package/lib/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.js +5 -8
- 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/lib/ui-kit/ResponseTypeDialog/ResponseTypeDialog.d.ts +1 -1
- package/lib/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.d.ts +16 -0
- package/lib/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.js +15 -0
- package/lib/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.js.map +1 -0
- package/lib/utils/getTimer.d.ts +2 -0
- package/lib/utils/getTimer.js +3 -0
- package/lib/utils/getTimer.js.map +1 -0
- package/mobile/bundle/api/LeadServiceAPI.d.ts +12 -3
- package/mobile/bundle/bundle.umd.js +716 -684
- package/mobile/bundle/bundle.umd.min.js +1 -1
- package/mobile/bundle/components/ApplicationForm/VerifyPhoneDialog.d.ts +10 -0
- package/mobile/bundle/components/ApplicationForm/useVerifyPhoneDialogSubmit.d.ts +18 -0
- package/mobile/bundle/components/TariffsTable/TariffsTableCell.d.ts +1 -1
- package/mobile/bundle/retail/api/checkCode.d.ts +1 -9
- package/mobile/bundle/retail/api/sendCode.d.ts +1 -1
- package/mobile/bundle/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.d.ts +0 -4
- package/mobile/bundle/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.d.ts +1 -6
- package/mobile/bundle/ui-kit/ResponseTypeDialog/ResponseTypeDialog.d.ts +1 -1
- package/mobile/bundle/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.d.ts +16 -0
- package/mobile/bundle/utils/getTimer.d.ts +2 -0
- package/mobile/dist/api/LeadServiceAPI.d.ts +12 -3
- package/mobile/dist/api/LeadServiceAPI.js +0 -3
- package/mobile/dist/api/LeadServiceAPI.js.map +1 -1
- package/mobile/dist/components/ApplicationForm/ApplicationForm.js +1 -3
- package/mobile/dist/components/ApplicationForm/ApplicationForm.js.map +1 -1
- package/mobile/dist/components/ApplicationForm/VerifyPhoneDialog.d.ts +10 -0
- package/mobile/dist/components/ApplicationForm/VerifyPhoneDialog.js +37 -0
- package/mobile/dist/components/ApplicationForm/VerifyPhoneDialog.js.map +1 -0
- package/mobile/dist/components/ApplicationForm/useVerifyPhoneDialogSubmit.d.ts +18 -0
- package/mobile/dist/components/ApplicationForm/useVerifyPhoneDialogSubmit.js +50 -0
- package/mobile/dist/components/ApplicationForm/useVerifyPhoneDialogSubmit.js.map +1 -0
- package/mobile/dist/components/ExchangeRateTile/ExchangeCurrencyCalculator.js +2 -2
- package/mobile/dist/components/ExchangeRateTile/ExchangeCurrencyCalculator.js.map +1 -1
- package/mobile/dist/components/TariffsTable/TariffsTableCell.d.ts +1 -1
- package/mobile/dist/retail/api/checkCode.d.ts +1 -9
- package/mobile/dist/retail/api/checkCode.js +1 -22
- 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 +2 -8
- package/mobile/dist/retail/api/sendCode.js.map +1 -1
- package/mobile/dist/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.d.ts +0 -4
- package/mobile/dist/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js +5 -24
- package/mobile/dist/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js.map +1 -1
- package/mobile/dist/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.d.ts +1 -6
- package/mobile/dist/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.js +7 -10
- 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/dist/ui-kit/ResponseTypeDialog/ResponseTypeDialog.d.ts +1 -1
- package/mobile/dist/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.d.ts +16 -0
- package/mobile/dist/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.js +17 -0
- package/mobile/dist/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.js.map +1 -0
- package/mobile/dist/utils/getTimer.d.ts +2 -0
- package/mobile/dist/utils/getTimer.js +6 -0
- package/mobile/dist/utils/getTimer.js.map +1 -0
- package/mobile/lib/api/LeadServiceAPI.d.ts +12 -3
- package/mobile/lib/api/LeadServiceAPI.js +0 -3
- package/mobile/lib/api/LeadServiceAPI.js.map +1 -1
- package/mobile/lib/common.css +1 -1
- package/mobile/lib/components/ApplicationForm/ApplicationForm.js +1 -3
- package/mobile/lib/components/ApplicationForm/ApplicationForm.js.map +1 -1
- package/mobile/lib/components/ApplicationForm/VerifyPhoneDialog.d.ts +10 -0
- package/mobile/lib/components/ApplicationForm/VerifyPhoneDialog.js +35 -0
- package/mobile/lib/components/ApplicationForm/VerifyPhoneDialog.js.map +1 -0
- package/mobile/lib/components/ApplicationForm/useVerifyPhoneDialogSubmit.d.ts +18 -0
- package/mobile/lib/components/ApplicationForm/useVerifyPhoneDialogSubmit.js +47 -0
- package/mobile/lib/components/ApplicationForm/useVerifyPhoneDialogSubmit.js.map +1 -0
- package/mobile/lib/components/ExchangeRateTile/ExchangeCurrencyCalculator.js +2 -2
- package/mobile/lib/components/ExchangeRateTile/ExchangeCurrencyCalculator.js.map +1 -1
- package/mobile/lib/components/TariffsTable/TariffsTableCell.d.ts +1 -1
- package/mobile/lib/retail/api/checkCode.d.ts +1 -9
- package/mobile/lib/retail/api/checkCode.js +1 -22
- 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 +1 -7
- package/mobile/lib/retail/api/sendCode.js.map +1 -1
- package/mobile/lib/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.d.ts +0 -4
- package/mobile/lib/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js +5 -24
- package/mobile/lib/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.js.map +1 -1
- package/mobile/lib/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.d.ts +1 -6
- package/mobile/lib/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.js +5 -8
- 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/lib/ui-kit/ResponseTypeDialog/ResponseTypeDialog.d.ts +1 -1
- package/mobile/lib/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.d.ts +16 -0
- package/mobile/lib/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.js +15 -0
- package/mobile/lib/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.js.map +1 -0
- package/mobile/lib/utils/getTimer.d.ts +2 -0
- package/mobile/lib/utils/getTimer.js +3 -0
- package/mobile/lib/utils/getTimer.js.map +1 -0
- package/mobile/src/api/LeadServiceAPI.ts +13 -7
- package/mobile/src/components/ApplicationForm/ApplicationForm.tsx +1 -3
- package/mobile/src/components/ApplicationForm/VerifyPhoneDialog.tsx +73 -0
- package/mobile/src/components/ApplicationForm/useVerifyPhoneDialogSubmit.tsx +63 -0
- package/mobile/src/components/ExchangeRateTile/ExchangeCurrencyCalculator.tsx +2 -2
- package/mobile/src/components/TariffsTable/TariffsTableCell.tsx +1 -1
- package/mobile/src/retail/api/checkCode.ts +2 -47
- package/mobile/src/retail/api/sendCode.ts +1 -9
- package/mobile/src/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.tsx +23 -82
- package/mobile/src/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.tsx +7 -21
- package/mobile/src/retail/utils/mockLocalStorage.ts +9 -15
- package/mobile/src/ui-kit/ResponseTypeDialog/ResponseTypeDialog.tsx +1 -1
- package/mobile/src/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.tsx +80 -0
- package/mobile/src/utils/getTimer.ts +4 -0
- package/package.json +1 -1
- package/src/api/LeadServiceAPI.ts +13 -7
- package/src/components/ApplicationForm/ApplicationForm.tsx +1 -3
- package/src/components/ApplicationForm/VerifyPhoneDialog.tsx +73 -0
- package/src/components/ApplicationForm/useVerifyPhoneDialogSubmit.tsx +63 -0
- package/src/components/ExchangeRateTile/ExchangeCurrencyCalculator.tsx +2 -2
- package/src/components/TariffsTable/TariffsTableCell.tsx +1 -1
- package/src/retail/api/checkCode.ts +2 -47
- package/src/retail/api/sendCode.ts +1 -9
- package/src/retail/components/VerifyPhoneDialog/VerifyPhoneDialog.tsx +23 -82
- package/src/retail/components/VerifyPhoneDialog/useVerifyPhoneDialogSubmit.tsx +7 -21
- package/src/retail/utils/mockLocalStorage.ts +9 -15
- package/src/ui-kit/ResponseTypeDialog/ResponseTypeDialog.tsx +1 -1
- package/src/ui-kit/VerifyPhoneDialogLayout/VerfiyPhoneDialogLayout.tsx +80 -0
- package/src/utils/getTimer.ts +4 -0
- package/bundle/model/onClose.d.ts +0 -3
- package/dist/model/onClose.d.ts +0 -3
- package/dist/model/onClose.js +0 -2
- package/dist/model/onClose.js.map +0 -1
- package/lib/model/onClose.d.ts +0 -3
- package/lib/model/onClose.js +0 -2
- package/lib/model/onClose.js.map +0 -1
- package/mobile/bundle/model/onClose.d.ts +0 -3
- package/mobile/dist/model/onClose.d.ts +0 -3
- package/mobile/dist/model/onClose.js +0 -2
- package/mobile/dist/model/onClose.js.map +0 -1
- package/mobile/lib/model/onClose.d.ts +0 -3
- package/mobile/lib/model/onClose.js +0 -2
- package/mobile/lib/model/onClose.js.map +0 -1
- package/mobile/src/model/onClose.ts +0 -3
- package/src/model/onClose.ts +0 -3
|
@@ -1110,9 +1110,6 @@
|
|
|
1110
1110
|
};
|
|
1111
1111
|
try {
|
|
1112
1112
|
const response = await LeadServiceFetch(`${API_BASE_URI$1}/confirmCorporateLead`, submitBody);
|
|
1113
|
-
if (!response?.ok) {
|
|
1114
|
-
return null;
|
|
1115
|
-
}
|
|
1116
1113
|
return await response.json();
|
|
1117
1114
|
}
|
|
1118
1115
|
catch (e) {
|
|
@@ -1247,630 +1244,90 @@
|
|
|
1247
1244
|
setFormStateUnsafe(normalizer);
|
|
1248
1245
|
}
|
|
1249
1246
|
}, [normalizer]);
|
|
1250
|
-
return [formState, setFormState];
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
function useForm(initialState, { resetOnSubmit, formValidator, normalizer, onChange, onSubmit } = {}) {
|
|
1254
|
-
const [formState, setFormState] = useNormalizedFormState(initialState, normalizer, onChange);
|
|
1255
|
-
const fieldRefs = useRef(getRefsObject(initialState));
|
|
1256
|
-
const [isDirtyForm, { setTrue: markAsDirty, setFalse: markAsClean }] = useBool(false);
|
|
1257
|
-
const dirtyFieldsMap = useRef({});
|
|
1258
|
-
const [fieldValidatorsMap, { isValid, errors }] = useFormValidator(formState, formValidator);
|
|
1259
|
-
const field = useCallback((fieldName, options = {}) => {
|
|
1260
|
-
const { parse, format, onChange: onFieldChange } = options;
|
|
1261
|
-
const value = formState[fieldName];
|
|
1262
|
-
const isDirty = isDirtyForm || dirtyFieldsMap.current?.[String(fieldName)];
|
|
1263
|
-
const fieldValidator = options?.validator ?? fieldValidatorsMap[fieldName];
|
|
1264
|
-
const fieldErrors = isDirty && fieldValidator ? fieldValidator(value) : [];
|
|
1265
|
-
return {
|
|
1266
|
-
setFieldRef: (_) => {
|
|
1267
|
-
if (fieldRefs.current) {
|
|
1268
|
-
fieldRefs.current[fieldName] = _;
|
|
1269
|
-
}
|
|
1270
|
-
},
|
|
1271
|
-
fieldRef: fieldRefs.current?.[fieldName],
|
|
1272
|
-
value: format ? format(value) : value,
|
|
1273
|
-
isDirty,
|
|
1274
|
-
errors: fieldValidator && fieldErrors,
|
|
1275
|
-
error: fieldErrors[0],
|
|
1276
|
-
onChange: (_) => {
|
|
1277
|
-
dirtyFieldsMap.current ||= {};
|
|
1278
|
-
dirtyFieldsMap.current[String(fieldName)] = true;
|
|
1279
|
-
const fieldVal = parse ? parse(_) : _;
|
|
1280
|
-
onFieldChange?.(fieldVal);
|
|
1281
|
-
setFormState((prev) => ({ ...prev, [fieldName]: fieldVal }));
|
|
1282
|
-
},
|
|
1283
|
-
};
|
|
1284
|
-
}, [formState, isDirtyForm, fieldValidatorsMap, setFormState]);
|
|
1285
|
-
const update = useCallback((_) => {
|
|
1286
|
-
dirtyFieldsMap.current = _;
|
|
1287
|
-
setFormState(_);
|
|
1288
|
-
}, [setFormState]);
|
|
1289
|
-
const reset = useCallback(() => {
|
|
1290
|
-
dirtyFieldsMap.current = {};
|
|
1291
|
-
markAsClean();
|
|
1292
|
-
setFormState(initialState);
|
|
1293
|
-
}, [initialState, setFormState]);
|
|
1294
|
-
const handleSubmit = useCallback((ev) => {
|
|
1295
|
-
ev.preventDefault();
|
|
1296
|
-
if (isValid) {
|
|
1297
|
-
resetOnSubmit && reset();
|
|
1298
|
-
onSubmit?.(formState, ev);
|
|
1299
|
-
}
|
|
1300
|
-
else {
|
|
1301
|
-
const errorFieldName = getErrorFieldName(formState, fieldValidatorsMap);
|
|
1302
|
-
markAsDirty();
|
|
1303
|
-
field(errorFieldName).fieldRef?.scrollIntoView({ behavior: 'smooth' });
|
|
1304
|
-
}
|
|
1305
|
-
}, [resetOnSubmit, formState, isValid, reset, onSubmit]);
|
|
1306
|
-
return [formState, { errors, field, update, reset, onSubmit: handleSubmit }];
|
|
1307
|
-
}
|
|
1308
|
-
const getRefsObject = (initialState) => Object.keys(initialState).reduce((acc, key) => ({ ...acc, [key]: null }), {});
|
|
1309
|
-
const getErrorFieldName = (formState, fieldValidatorsMap = {}) => {
|
|
1310
|
-
const [errorFieldName = ''] = Object.entries(formState).find(([fieldName, value]) => {
|
|
1311
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1312
|
-
return fieldValidatorsMap[fieldName]?.(value)?.length;
|
|
1313
|
-
}) ?? [];
|
|
1314
|
-
return errorFieldName;
|
|
1315
|
-
};
|
|
1316
|
-
|
|
1317
|
-
function copy(source, target) {
|
|
1318
|
-
for (const [k, v] of source.entries()) {
|
|
1319
|
-
if (v !== null && v !== undefined) {
|
|
1320
|
-
target.setItem(k, v);
|
|
1321
|
-
}
|
|
1322
|
-
else {
|
|
1323
|
-
target.removeItem(k);
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
function replicate(primary, secondary) {
|
|
1329
|
-
copy(primary, secondary);
|
|
1330
|
-
copy(secondary, primary);
|
|
1331
|
-
return primary.bus.watch(({ type, event }) => {
|
|
1332
|
-
if (event !== null && event !== undefined) {
|
|
1333
|
-
secondary.setItem(type, event);
|
|
1334
|
-
}
|
|
1335
|
-
else {
|
|
1336
|
-
secondary.removeItem(type);
|
|
1337
|
-
}
|
|
1338
|
-
});
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
class StorageAdapter {
|
|
1342
|
-
storage;
|
|
1343
|
-
bus;
|
|
1344
|
-
get size() {
|
|
1345
|
-
return this.storage?.length ?? 0;
|
|
1346
|
-
}
|
|
1347
|
-
constructor(storage, bus = new EventBus()) {
|
|
1348
|
-
this.storage = storage;
|
|
1349
|
-
this.bus = bus;
|
|
1350
|
-
}
|
|
1351
|
-
hasItem(key) {
|
|
1352
|
-
return Boolean(this.storage?.getItem(String(key)));
|
|
1353
|
-
}
|
|
1354
|
-
getItem(key) {
|
|
1355
|
-
const _ = this.storage?.getItem(String(key)) ?? null;
|
|
1356
|
-
try {
|
|
1357
|
-
return JSON.parse(String(_));
|
|
1358
|
-
}
|
|
1359
|
-
catch (ex) {
|
|
1360
|
-
return null;
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
entries() {
|
|
1364
|
-
return Array.from({ length: this.size }, (_, i) => {
|
|
1365
|
-
const k = String(this.storage?.key(i));
|
|
1366
|
-
return [k, this.getItem(k)];
|
|
1367
|
-
});
|
|
1368
|
-
}
|
|
1369
|
-
setItem(key, value) {
|
|
1370
|
-
if (value !== null) {
|
|
1371
|
-
this.storage?.setItem(String(key), JSON.stringify(value));
|
|
1372
|
-
}
|
|
1373
|
-
else {
|
|
1374
|
-
this.storage?.removeItem(String(key));
|
|
1375
|
-
}
|
|
1376
|
-
this.bus?.subject(key, value);
|
|
1377
|
-
}
|
|
1378
|
-
removeItem(key) {
|
|
1379
|
-
this.storage?.removeItem(String(key));
|
|
1380
|
-
this.bus?.subject(key, null);
|
|
1381
|
-
}
|
|
1382
|
-
}
|
|
1383
|
-
|
|
1384
|
-
class Store {
|
|
1385
|
-
bus;
|
|
1386
|
-
store = new Map();
|
|
1387
|
-
get size() {
|
|
1388
|
-
return this.store.size;
|
|
1389
|
-
}
|
|
1390
|
-
constructor(bus = new EventBus()) {
|
|
1391
|
-
this.bus = bus;
|
|
1392
|
-
}
|
|
1393
|
-
hasItem(key) {
|
|
1394
|
-
return this.store.has(key);
|
|
1395
|
-
}
|
|
1396
|
-
getItem(key) {
|
|
1397
|
-
return this.store.get(key);
|
|
1398
|
-
}
|
|
1399
|
-
entries() {
|
|
1400
|
-
return this.store.entries();
|
|
1401
|
-
}
|
|
1402
|
-
setItem(key, value) {
|
|
1403
|
-
this.store.set(key, value);
|
|
1404
|
-
this.bus.subject(key, value);
|
|
1405
|
-
}
|
|
1406
|
-
removeItem(key) {
|
|
1407
|
-
this.store.delete(key);
|
|
1408
|
-
this.bus.subject(key, null);
|
|
1409
|
-
}
|
|
1410
|
-
}
|
|
1411
|
-
|
|
1412
|
-
function useRerender() {
|
|
1413
|
-
const [, setCount] = useState(0);
|
|
1414
|
-
return useCallback(() => setCount(_ => (_ + 1) % (1 << 16)), []);
|
|
1415
|
-
}
|
|
1416
|
-
|
|
1417
|
-
const DEFAULT_METHODS = {};
|
|
1418
|
-
/**
|
|
1419
|
-
* MobX like reactivity (simplified).
|
|
1420
|
-
* Can be used to migrate from Redux/MobX or something else
|
|
1421
|
-
*
|
|
1422
|
-
* @param store
|
|
1423
|
-
* @returns reactive proxy backed by store
|
|
1424
|
-
*/
|
|
1425
|
-
function useStore(store, methods = DEFAULT_METHODS) {
|
|
1426
|
-
const deps = useRef(null);
|
|
1427
|
-
const render = useRerender();
|
|
1428
|
-
useEffect(() => store.bus.watch(ev => {
|
|
1429
|
-
if (deps.current?.has(String(ev.type))) {
|
|
1430
|
-
render();
|
|
1431
|
-
}
|
|
1432
|
-
}), [store, render]);
|
|
1433
|
-
return useMemo(() => new Proxy(methods, {
|
|
1434
|
-
get(_, key) {
|
|
1435
|
-
deps.current ||= new Set();
|
|
1436
|
-
deps.current.add(key);
|
|
1437
|
-
return store.getItem(key);
|
|
1438
|
-
},
|
|
1439
|
-
has(_, key) {
|
|
1440
|
-
deps.current ||= new Set();
|
|
1441
|
-
deps.current.add(key);
|
|
1442
|
-
return store.hasItem(key);
|
|
1443
|
-
},
|
|
1444
|
-
set(_, key, value) {
|
|
1445
|
-
store.setItem(key, value);
|
|
1446
|
-
return true;
|
|
1447
|
-
},
|
|
1448
|
-
deleteProperty(_, key) {
|
|
1449
|
-
store.removeItem(key);
|
|
1450
|
-
return true;
|
|
1451
|
-
}
|
|
1452
|
-
}), [store]);
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1455
|
-
const sessionStore = new Store(); // sessionStorage cache
|
|
1456
|
-
replicate(sessionStore, new StorageAdapter(globalThis?.sessionStorage));
|
|
1457
|
-
function useSessionStore() {
|
|
1458
|
-
return useStore(sessionStore);
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
const noop = () => {
|
|
1462
|
-
// Do nothing
|
|
1463
|
-
};
|
|
1464
|
-
|
|
1465
|
-
const themeStyle$1 = {
|
|
1466
|
-
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'),
|
|
1467
|
-
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'),
|
|
1468
|
-
};
|
|
1469
|
-
const embeddedStyle = style('group/btn-embedded', 'bg-transparent border border-transparent outline-none');
|
|
1470
|
-
const disabledStyle = style('bg-main-gray text-main-disabled cursor-not-allowed');
|
|
1471
|
-
const Button = JSX(({ className, type = 'button', version = 'primary', shape = 'default', embedded, disabled, role, ariaLabel, data, dataTheme, children, wcmsIgnore, onClick = noop, }) => {
|
|
1472
|
-
const handleClick = useCallback(role !== 'tab' ? handlerDecorator(onClick) : onClick, [
|
|
1473
|
-
role,
|
|
1474
|
-
onClick,
|
|
1475
|
-
]);
|
|
1476
|
-
const aspectsAttrs = useMemo(() => getAspectsAttributes(data), [data]);
|
|
1477
|
-
const isRound = shape === 'round';
|
|
1478
|
-
return (jsx("button", { className: style('font-sans flex items-center gap-xs', {
|
|
1479
|
-
[themeStyle$1[version]]: !disabled && !embedded,
|
|
1480
|
-
[embeddedStyle]: embedded,
|
|
1481
|
-
[disabledStyle]: disabled,
|
|
1482
|
-
}, embedded ? 'justify-between' : 'justify-center', embedded || isRound ? 'p-0' : 'px-9 py-4', {
|
|
1483
|
-
'rounded-md': shape === 'default',
|
|
1484
|
-
'rounded-full': isRound,
|
|
1485
|
-
}, 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 }));
|
|
1486
|
-
});
|
|
1487
|
-
|
|
1488
|
-
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 })));
|
|
1489
|
-
|
|
1490
|
-
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" }) })));
|
|
1491
|
-
|
|
1492
|
-
const DIALOG_STYLE = {
|
|
1493
|
-
sm: 'max-w-sm top-1/3',
|
|
1494
|
-
lg: 'max-w-lg',
|
|
1495
|
-
'4xl': 'max-w-4xl',
|
|
1496
|
-
none: 'mt-0',
|
|
1497
|
-
};
|
|
1498
|
-
const Dialog = JSX(({ head, maxWidth = '4xl', children, onClose, onClick }) => (jsxs("div", { className: style('relative bg-white p-lg pb-6xl my-6xl mx-auto rounded-lg w-full', DIALOG_STYLE[maxWidth]), 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 z-10", onClose: onClose }), jsx("div", { className: "container", children: head })] }), jsx("div", { className: "container", children: children })] })));
|
|
1499
|
-
|
|
1500
|
-
function useDialog(Dialog, initialProps = {}) {
|
|
1501
|
-
const { open, close, ...rest } = useDialogManager();
|
|
1502
|
-
const openDialog = useCallback((props, options = {}) => open({
|
|
1503
|
-
dialog: (jsx(Dialog, { ...initialProps, ...props, onClose: () => {
|
|
1504
|
-
close();
|
|
1505
|
-
props.onClose?.();
|
|
1506
|
-
} })),
|
|
1507
|
-
...options,
|
|
1508
|
-
}), [Dialog, open, close]);
|
|
1509
|
-
return { open: openDialog, close, ...rest };
|
|
1510
|
-
}
|
|
1511
|
-
|
|
1512
|
-
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, {
|
|
1513
|
-
'backdrop-blur': blur,
|
|
1514
|
-
}), 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" }) })));
|
|
1515
|
-
|
|
1516
|
-
const Timer = JSX(({ className, seconds }) => (jsx("span", { className: className, children: formatTimer(seconds) })));
|
|
1517
|
-
const formatTimer = (seconds) => {
|
|
1518
|
-
const minutes = Math.floor(seconds / 60);
|
|
1519
|
-
return [minutes, seconds % 60].map((_) => String(_).padStart(2, '0')).join(':');
|
|
1520
|
-
};
|
|
1521
|
-
|
|
1522
|
-
const useInterval = (handler, period) => {
|
|
1523
|
-
const timer = useRef(null);
|
|
1524
|
-
const stop = useCallback(() => clearInterval(timer.current), []);
|
|
1525
|
-
const start = useCallback(() => {
|
|
1526
|
-
stop();
|
|
1527
|
-
timer.current = setInterval(() => handler(stop), period);
|
|
1528
|
-
}, [handler, period, stop]);
|
|
1529
|
-
useEffect(() => {
|
|
1530
|
-
start();
|
|
1531
|
-
return stop;
|
|
1532
|
-
}, [start, stop]);
|
|
1533
|
-
return { start, stop };
|
|
1534
|
-
};
|
|
1535
|
-
|
|
1536
|
-
function useCountDownTimer({ seconds, period = 1000, onTick, onEnd }) {
|
|
1537
|
-
const counter = useRef(seconds);
|
|
1538
|
-
const handleTick = useCallback((stop) => {
|
|
1539
|
-
counter.current ||= 0;
|
|
1540
|
-
counter.current = Math.max(0, counter.current - 1);
|
|
1541
|
-
try {
|
|
1542
|
-
onTick?.(counter.current);
|
|
1543
|
-
}
|
|
1544
|
-
finally {
|
|
1545
|
-
if (counter.current <= 0) {
|
|
1546
|
-
stop();
|
|
1547
|
-
onEnd?.();
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
}, [onTick, onEnd]);
|
|
1551
|
-
const { start } = useInterval(handleTick, period);
|
|
1552
|
-
return useCallback((_) => {
|
|
1553
|
-
counter.current = _;
|
|
1554
|
-
start();
|
|
1555
|
-
}, []);
|
|
1556
|
-
}
|
|
1557
|
-
|
|
1558
|
-
const getTraceId = () => {
|
|
1559
|
-
const result = new Uint8Array(8);
|
|
1560
|
-
globalThis.crypto.getRandomValues(result);
|
|
1561
|
-
return result.reduce((acc, _) => `${acc}${_.toString(16).padStart(2, '0')}`, '');
|
|
1562
|
-
};
|
|
1563
|
-
|
|
1564
|
-
const fetchRetailJSON = async (url, method, body) => {
|
|
1565
|
-
try {
|
|
1566
|
-
const response = await doRequest(url, method, body);
|
|
1567
|
-
return response.json();
|
|
1568
|
-
}
|
|
1569
|
-
catch (err) {
|
|
1570
|
-
console.error(err);
|
|
1571
|
-
return null;
|
|
1572
|
-
}
|
|
1573
|
-
};
|
|
1574
|
-
async function doRequest(url, method, body) {
|
|
1575
|
-
const traceId = getTraceId();
|
|
1576
|
-
return globalThis?.fetch?.(`${RETAIL_API_BASE_URI}${url}`, {
|
|
1577
|
-
method,
|
|
1578
|
-
headers: {
|
|
1579
|
-
'Content-Type': 'application/json',
|
|
1580
|
-
'X-B3-Sampled': '1',
|
|
1581
|
-
'X-B3-Spanid': traceId,
|
|
1582
|
-
'X-B3-Traceid': traceId,
|
|
1583
|
-
...getAuthorizationHeaders(),
|
|
1584
|
-
},
|
|
1585
|
-
credentials: 'include',
|
|
1586
|
-
body: body ? JSON.stringify(body) : null,
|
|
1587
|
-
});
|
|
1588
|
-
}
|
|
1589
|
-
const getAuthorizationHeaders = () => {
|
|
1590
|
-
const token = sessionStorage.getItem('accessToken');
|
|
1591
|
-
return token ? { Authorization: `Bearer ${token}` } : null;
|
|
1592
|
-
};
|
|
1593
|
-
|
|
1594
|
-
const API$2 = LeadServiceAPI();
|
|
1595
|
-
const sendCode = (body, isRetail) => {
|
|
1596
|
-
return isRetail ? fetchRetail(body) : fetchMain$1(body);
|
|
1597
|
-
};
|
|
1598
|
-
const fetchRetail = (body) => doRequest('/sms/sendCode', 'POST', body)
|
|
1599
|
-
.then((res) => res.text())
|
|
1600
|
-
.then((text) => text === 'OK');
|
|
1601
|
-
const fetchMain$1 = (body) => API$2.sendCode({ phone: body.phoneNumber });
|
|
1602
|
-
|
|
1603
|
-
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] })));
|
|
1604
|
-
|
|
1605
|
-
const inputValidStyle = 'border border-solid outline-none border-gray hover:border-primary-hover active:border-primary-text focus:border-primary-text rounded';
|
|
1606
|
-
|
|
1607
|
-
const getValidStyle = (valid) => (valid ? inputValidStyle : 'border-error');
|
|
1608
|
-
|
|
1609
|
-
const renderLabel$1 = (label) => label ? (jsx(Text, { size: "text-m", color: "text-primary-text", font: "font-light", children: label })) : null;
|
|
1610
|
-
|
|
1611
|
-
const Input = JSX(
|
|
1612
|
-
// eslint-disable-next-line max-lines-per-function
|
|
1613
|
-
({ key, className, id, name, type = 'text', label, placeholder, value = '', valid = true, pattern, autoFocus = false, isTextarea = false, disabled = false, children, onChange, onFocus, onBlur, }) => {
|
|
1614
|
-
const inputRef = useRef(null);
|
|
1615
|
-
const handleChange = useCallback((e) => {
|
|
1616
|
-
const valueWithoutSpace = (e.target?.value ?? '').trimStart();
|
|
1617
|
-
onChange && onChange(valueWithoutSpace);
|
|
1618
|
-
}, [onChange]);
|
|
1619
|
-
useEffect(() => {
|
|
1620
|
-
if (autoFocus) {
|
|
1621
|
-
inputRef.current?.focus();
|
|
1622
|
-
}
|
|
1623
|
-
}, [autoFocus, inputRef]);
|
|
1624
|
-
const paddingStyle = children ? 'pr-3xl' : '';
|
|
1625
|
-
const validStyle = getValidStyle(valid);
|
|
1626
|
-
const ariaLabel = label ?? name ?? id;
|
|
1627
|
-
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] }));
|
|
1628
|
-
});
|
|
1629
|
-
const defaultStyle$1 = 'w-full border rounded-md text-primary-text outline-none p-m';
|
|
1630
|
-
|
|
1631
|
-
const ICON_SIZE = { width: '103', height: '21' };
|
|
1632
|
-
|
|
1633
|
-
const logoTitleSizeStyle = 'text-s';
|
|
1634
|
-
|
|
1635
|
-
const ICON_VERSION_MAP = {
|
|
1636
|
-
'bg-white': 'color',
|
|
1637
|
-
transparent: 'white',
|
|
1638
|
-
};
|
|
1639
|
-
const SVG_COLOR = {
|
|
1640
|
-
'bg-white': 'text-primary-main',
|
|
1641
|
-
transparent: 'text-white',
|
|
1642
|
-
};
|
|
1643
|
-
const renderImage = (bgColor, image, size) => {
|
|
1644
|
-
const img = image?.src
|
|
1645
|
-
? image
|
|
1646
|
-
: {
|
|
1647
|
-
icon: image?.icon || 'LogoIcon',
|
|
1648
|
-
iconVersion: ICON_VERSION_MAP[bgColor],
|
|
1649
|
-
};
|
|
1650
|
-
return (jsx(Img, { image: img, className: SVG_COLOR[bgColor], width: size?.width, height: size?.height }));
|
|
1651
|
-
};
|
|
1652
|
-
|
|
1653
|
-
const TEXT_COLOR = {
|
|
1654
|
-
'bg-white': 'text-primary-text',
|
|
1655
|
-
transparent: 'text-white',
|
|
1656
|
-
};
|
|
1657
|
-
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
|
|
1658
|
-
? children ?? (jsx("div", { className: "ml-s", children: jsx(Text, { font: "font-medium", color: TEXT_COLOR[bgColor], size: logoTitleSizeStyle, children: logo?.title ?? 'Россельхозбанк' }) }))
|
|
1659
|
-
: null] })));
|
|
1660
|
-
|
|
1661
|
-
const checkCaptcha = (body) => doRequest('/sms/checkCaptcha', 'POST', body)
|
|
1662
|
-
.then((res) => res.text())
|
|
1663
|
-
.then((text) => text !== 'ERROR');
|
|
1664
|
-
|
|
1665
|
-
const createCaptcha = (phoneNumber) => doRequest(`/sms/createCaptcha?phoneNumber=${encodeURIComponent(phoneNumber)}`, 'GET').then(async (res) => (res ? res.blob() : new Blob()));
|
|
1666
|
-
|
|
1667
|
-
const CaptchaDialog = JSX(({ phoneNumber, sendCode, onClose }) => {
|
|
1668
|
-
const [captcha, setCaptcha] = useState('');
|
|
1669
|
-
const [code, setCode] = useState('');
|
|
1670
|
-
const [hasError, setHasError] = useState(false);
|
|
1671
|
-
const [isLoading, { setTrue: startLoading, setFalse: endLoading }] = useBool(false);
|
|
1672
|
-
const { closeAll } = useDialogManager();
|
|
1673
|
-
const handleCheckCaptcha = useCallback(async () => {
|
|
1674
|
-
startLoading();
|
|
1675
|
-
const isValidCode = await checkCaptcha({ captchaText: code });
|
|
1676
|
-
if (isValidCode) {
|
|
1677
|
-
onClose?.();
|
|
1678
|
-
sendCode?.();
|
|
1679
|
-
}
|
|
1680
|
-
else {
|
|
1681
|
-
setHasError(true);
|
|
1682
|
-
}
|
|
1683
|
-
endLoading();
|
|
1684
|
-
}, [code, sendCode]);
|
|
1685
|
-
const handleCreateCaptcha = useCallback(() => {
|
|
1686
|
-
(async () => setCaptcha(URL.createObjectURL(await createCaptcha(phoneNumber))))();
|
|
1687
|
-
}, []);
|
|
1688
|
-
useEffect(handleCreateCaptcha, []);
|
|
1689
|
-
return (jsx(Dialog, { 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] }) }));
|
|
1690
|
-
});
|
|
1691
|
-
|
|
1692
|
-
const InputCode = JSX(({ values, setValues, hasError, errorText }) => {
|
|
1693
|
-
const [activeIndex, setActiveIndex] = useState(0);
|
|
1694
|
-
const inputRefs = useRef([]);
|
|
1695
|
-
useEffect(() => {
|
|
1696
|
-
inputRefs.current?.[activeIndex]?.focus();
|
|
1697
|
-
}, [activeIndex]);
|
|
1698
|
-
const handleChange = useCallback((index) => (event) => {
|
|
1699
|
-
const { value } = event.currentTarget;
|
|
1700
|
-
const oneValue = value.slice(0, 1);
|
|
1701
|
-
setValues(values.map((_, i) => (i === index ? oneValue : _)));
|
|
1702
|
-
setActiveIndex(index + 1);
|
|
1703
|
-
}, [values]);
|
|
1704
|
-
const handleKeyDown = useCallback((currentIndex) => (event) => {
|
|
1705
|
-
const { key } = event;
|
|
1706
|
-
if (key === 'Backspace' && !values[currentIndex]) {
|
|
1707
|
-
const previousIndex = currentIndex > 0 ? currentIndex - 1 : values.length - 1;
|
|
1708
|
-
const updatedValues = values.map((value, index) => (index === previousIndex ? '' : value));
|
|
1709
|
-
setValues(updatedValues);
|
|
1710
|
-
setActiveIndex(previousIndex);
|
|
1711
|
-
}
|
|
1712
|
-
}, [values]);
|
|
1713
|
-
const handlePaste = useCallback((event) => {
|
|
1714
|
-
event.preventDefault();
|
|
1715
|
-
const pastedData = event.clipboardData.getData('text');
|
|
1716
|
-
const updatedValues = values.map((_, idx) => (idx < pastedData.length ? pastedData[idx] : _));
|
|
1717
|
-
setValues(updatedValues);
|
|
1718
|
-
setActiveIndex(updatedValues.length - 1);
|
|
1719
|
-
}, [values]);
|
|
1720
|
-
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) => {
|
|
1721
|
-
if (!inputRefs.current) {
|
|
1722
|
-
inputRefs.current = [];
|
|
1723
|
-
}
|
|
1724
|
-
inputRefs.current[index] = ref;
|
|
1725
|
-
}, onFocus: (event) => event.target.select(), onKeyDown: handleKeyDown(index), className: getInputStyle(index, values, hasError) }, index))) }), hasError ? jsx("div", { className: "text-error", children: errorText }) : null] }));
|
|
1726
|
-
});
|
|
1727
|
-
const getInputStyle = (index, values, hasError = false) => {
|
|
1728
|
-
const isInputEmpty = !values[index];
|
|
1729
|
-
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`;
|
|
1730
|
-
};
|
|
1731
|
-
|
|
1732
|
-
const SubmitButton = JSX(({ disabled = false, onClick, text }) => (jsx(Button, { type: "button", onClick: onClick, disabled: disabled, children: jsx(Text, { font: "font-normal", children: text }) })));
|
|
1733
|
-
|
|
1734
|
-
const API$1 = LeadServiceAPI();
|
|
1735
|
-
const checkCode = async (body, isRetail) => {
|
|
1736
|
-
const transformedBody = transformBody(body, isRetail);
|
|
1737
|
-
return isRetail
|
|
1738
|
-
? fetchRetailJSON('/sms/checkCode', 'POST', transformedBody).then(saveToken)
|
|
1739
|
-
: fetchMain(transformedBody).then((res) => {
|
|
1740
|
-
if (res === null) {
|
|
1741
|
-
throw new Error('Неверный код');
|
|
1742
|
-
}
|
|
1743
|
-
});
|
|
1744
|
-
};
|
|
1745
|
-
const saveToken = (data) => {
|
|
1746
|
-
if (data?.access_token && data?.refresh_token) {
|
|
1747
|
-
globalThis.sessionStorage.setItem('accessToken', data.access_token);
|
|
1748
|
-
globalThis.sessionStorage.setItem('refreshToken', data.refresh_token);
|
|
1749
|
-
}
|
|
1750
|
-
};
|
|
1751
|
-
const fetchMain = (body) => API$1.checkCode(body);
|
|
1752
|
-
const transformBody = ({ smsText, smsCodesSetName, body, reqId }, isRetail) => {
|
|
1753
|
-
if (isRetail) {
|
|
1754
|
-
return { smsText, smsCodesSetName };
|
|
1755
|
-
}
|
|
1756
|
-
if (!reqId || !body) {
|
|
1757
|
-
throw new Error('Произошла ошибка, попробуйте позднее');
|
|
1758
|
-
}
|
|
1759
|
-
return { code: smsText, reqId, body };
|
|
1760
|
-
};
|
|
1761
|
-
|
|
1762
|
-
const TIME_TO_RESEND = 180;
|
|
1763
|
-
const useVerifyPhoneDialogSubmit = ({ values, onSuccess, formatData, reqId, isRetail = true, }) => {
|
|
1764
|
-
const sessionStore = useSessionStore();
|
|
1765
|
-
const attempts = sessionStore.smsCode?.attempts || 0;
|
|
1766
|
-
const timer = Math.max(getTimer(sessionStore.smsCode?.sendTime || Date.now()), 0);
|
|
1767
|
-
const [errorText, setErrorText] = useState('');
|
|
1768
|
-
const [isLoading, { setTrue: startLoading, setFalse: endLoading }] = useBool(false);
|
|
1769
|
-
const [timeNextReq, setTimeNextReq] = useState(timer);
|
|
1770
|
-
const resetError = useCallback(() => setErrorText(''), []);
|
|
1771
|
-
const isTimeExpired = Boolean(timeNextReq === 0 && sessionStore.smsCode?.sendTime);
|
|
1772
|
-
const isSubmitButtonDisabled = attempts > 2 || isTimeExpired || !values.every(Boolean);
|
|
1773
|
-
const handleSubmit = useCallback(async () => {
|
|
1774
|
-
try {
|
|
1775
|
-
sessionStore.smsCode = {
|
|
1776
|
-
...sessionStore.smsCode,
|
|
1777
|
-
attempts: attempts + 1,
|
|
1778
|
-
};
|
|
1779
|
-
startLoading();
|
|
1780
|
-
await checkCode({
|
|
1781
|
-
smsText: values.join(''),
|
|
1782
|
-
smsCodesSetName: { key: 'AUTHENTICATION' },
|
|
1783
|
-
body: isRetail ? undefined : formatData,
|
|
1784
|
-
reqId: isRetail ? undefined : reqId,
|
|
1785
|
-
}, isRetail);
|
|
1786
|
-
setTimeNextReq(0);
|
|
1787
|
-
resetError();
|
|
1788
|
-
sessionStore.smsCode = null;
|
|
1789
|
-
await onSuccess?.(values.join(''));
|
|
1790
|
-
}
|
|
1791
|
-
catch {
|
|
1792
|
-
setErrorText(attempts > 1 ? 'Исчерпан лимит ввода смс-кода' : 'Неверный код');
|
|
1793
|
-
}
|
|
1794
|
-
finally {
|
|
1795
|
-
endLoading();
|
|
1796
|
-
}
|
|
1797
|
-
}, [values, attempts]);
|
|
1798
|
-
useEffect(() => {
|
|
1799
|
-
if (isTimeExpired && isRetail) {
|
|
1800
|
-
setErrorText('Код просрочен');
|
|
1801
|
-
}
|
|
1802
|
-
else if (attempts > 2) {
|
|
1803
|
-
setErrorText('Исчерпан лимит ввода смс-кода');
|
|
1804
|
-
}
|
|
1805
|
-
}, [isTimeExpired]);
|
|
1806
|
-
return {
|
|
1807
|
-
handleSubmit,
|
|
1808
|
-
hasError: Boolean(errorText),
|
|
1809
|
-
errorText,
|
|
1810
|
-
isLoading,
|
|
1811
|
-
timeNextReq,
|
|
1812
|
-
isSubmitButtonDisabled,
|
|
1813
|
-
setTimeNextReq,
|
|
1814
|
-
setErrorText,
|
|
1815
|
-
};
|
|
1816
|
-
};
|
|
1817
|
-
const getTimer = (sendTime) => TIME_TO_RESEND - Math.floor((Date.now() - sendTime) / 1000);
|
|
1247
|
+
return [formState, setFormState];
|
|
1248
|
+
}
|
|
1818
1249
|
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
const
|
|
1824
|
-
const
|
|
1825
|
-
const
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1250
|
+
function useForm(initialState, { resetOnSubmit, formValidator, normalizer, onChange, onSubmit } = {}) {
|
|
1251
|
+
const [formState, setFormState] = useNormalizedFormState(initialState, normalizer, onChange);
|
|
1252
|
+
const fieldRefs = useRef(getRefsObject(initialState));
|
|
1253
|
+
const [isDirtyForm, { setTrue: markAsDirty, setFalse: markAsClean }] = useBool(false);
|
|
1254
|
+
const dirtyFieldsMap = useRef({});
|
|
1255
|
+
const [fieldValidatorsMap, { isValid, errors }] = useFormValidator(formState, formValidator);
|
|
1256
|
+
const field = useCallback((fieldName, options = {}) => {
|
|
1257
|
+
const { parse, format, onChange: onFieldChange } = options;
|
|
1258
|
+
const value = formState[fieldName];
|
|
1259
|
+
const isDirty = isDirtyForm || dirtyFieldsMap.current?.[String(fieldName)];
|
|
1260
|
+
const fieldValidator = options?.validator ?? fieldValidatorsMap[fieldName];
|
|
1261
|
+
const fieldErrors = isDirty && fieldValidator ? fieldValidator(value) : [];
|
|
1262
|
+
return {
|
|
1263
|
+
setFieldRef: (_) => {
|
|
1264
|
+
if (fieldRefs.current) {
|
|
1265
|
+
fieldRefs.current[fieldName] = _;
|
|
1266
|
+
}
|
|
1267
|
+
},
|
|
1268
|
+
fieldRef: fieldRefs.current?.[fieldName],
|
|
1269
|
+
value: format ? format(value) : value,
|
|
1270
|
+
isDirty,
|
|
1271
|
+
errors: fieldValidator && fieldErrors,
|
|
1272
|
+
error: fieldErrors[0],
|
|
1273
|
+
onChange: (_) => {
|
|
1274
|
+
dirtyFieldsMap.current ||= {};
|
|
1275
|
+
dirtyFieldsMap.current[String(fieldName)] = true;
|
|
1276
|
+
const fieldVal = parse ? parse(_) : _;
|
|
1277
|
+
onFieldChange?.(fieldVal);
|
|
1278
|
+
setFormState((prev) => ({ ...prev, [fieldName]: fieldVal }));
|
|
1279
|
+
},
|
|
1280
|
+
};
|
|
1281
|
+
}, [formState, isDirtyForm, fieldValidatorsMap, setFormState]);
|
|
1282
|
+
const update = useCallback((_) => {
|
|
1283
|
+
dirtyFieldsMap.current = _;
|
|
1284
|
+
setFormState(_);
|
|
1285
|
+
}, [setFormState]);
|
|
1286
|
+
const reset = useCallback(() => {
|
|
1287
|
+
dirtyFieldsMap.current = {};
|
|
1288
|
+
markAsClean();
|
|
1289
|
+
setFormState(initialState);
|
|
1290
|
+
}, [initialState, setFormState]);
|
|
1291
|
+
const handleSubmit = useCallback((ev) => {
|
|
1292
|
+
ev.preventDefault();
|
|
1293
|
+
if (isValid) {
|
|
1294
|
+
resetOnSubmit && reset();
|
|
1295
|
+
onSubmit?.(formState, ev);
|
|
1852
1296
|
}
|
|
1853
1297
|
else {
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
useEffect(() => {
|
|
1858
|
-
if (!sessionStore.smsCode?.sendTime && isRetail) {
|
|
1859
|
-
handleSendCode();
|
|
1298
|
+
const errorFieldName = getErrorFieldName(formState, fieldValidatorsMap);
|
|
1299
|
+
markAsDirty();
|
|
1300
|
+
field(errorFieldName).fieldRef?.scrollIntoView({ behavior: 'smooth' });
|
|
1860
1301
|
}
|
|
1861
|
-
}, []);
|
|
1862
|
-
return
|
|
1863
|
-
}
|
|
1864
|
-
const
|
|
1865
|
-
const
|
|
1866
|
-
|
|
1867
|
-
|
|
1302
|
+
}, [resetOnSubmit, formState, isValid, reset, onSubmit]);
|
|
1303
|
+
return [formState, { errors, field, update, reset, onSubmit: handleSubmit }];
|
|
1304
|
+
}
|
|
1305
|
+
const getRefsObject = (initialState) => Object.keys(initialState).reduce((acc, key) => ({ ...acc, [key]: null }), {});
|
|
1306
|
+
const getErrorFieldName = (formState, fieldValidatorsMap = {}) => {
|
|
1307
|
+
const [errorFieldName = ''] = Object.entries(formState).find(([fieldName, value]) => {
|
|
1308
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1309
|
+
return fieldValidatorsMap[fieldName]?.(value)?.length;
|
|
1310
|
+
}) ?? [];
|
|
1311
|
+
return errorFieldName;
|
|
1312
|
+
};
|
|
1868
1313
|
|
|
1869
1314
|
const ApplicationFormLayout = JSX((props) => {
|
|
1870
1315
|
const { className, title, children, ...rest } = props;
|
|
1871
1316
|
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] }) }));
|
|
1872
1317
|
});
|
|
1873
1318
|
|
|
1319
|
+
function useDialog(Dialog, initialProps = {}) {
|
|
1320
|
+
const { open, close, ...rest } = useDialogManager();
|
|
1321
|
+
const openDialog = useCallback((props, options = {}) => open({
|
|
1322
|
+
dialog: (jsx(Dialog, { ...initialProps, ...props, onClose: () => {
|
|
1323
|
+
close();
|
|
1324
|
+
props.onClose?.();
|
|
1325
|
+
} })),
|
|
1326
|
+
...options,
|
|
1327
|
+
}), [Dialog, open, close]);
|
|
1328
|
+
return { open: openDialog, close, ...rest };
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1874
1331
|
const getConsentDataProcessing = (inputs) => inputs?.find((_) => _?.name === 'consentDataProcessing');
|
|
1875
1332
|
|
|
1876
1333
|
// TODO Базовая функицональность всех Control - надо вынести и привязать к required флагу
|
|
@@ -1894,6 +1351,12 @@
|
|
|
1894
1351
|
return debouncedCallback;
|
|
1895
1352
|
};
|
|
1896
1353
|
|
|
1354
|
+
const noop = () => {
|
|
1355
|
+
// Do nothing
|
|
1356
|
+
};
|
|
1357
|
+
|
|
1358
|
+
const renderLabel$1 = (label) => label ? (jsx(Text, { size: "text-m", color: "text-primary-text", font: "font-light", children: label })) : null;
|
|
1359
|
+
|
|
1897
1360
|
function useEventListener(target, type, listener, options) {
|
|
1898
1361
|
useEffect(() => {
|
|
1899
1362
|
if (!target || !listener) {
|
|
@@ -1917,6 +1380,30 @@
|
|
|
1917
1380
|
return targetRef;
|
|
1918
1381
|
}
|
|
1919
1382
|
|
|
1383
|
+
const inputValidStyle = 'border border-solid outline-none border-gray hover:border-primary-hover active:border-primary-text focus:border-primary-text rounded';
|
|
1384
|
+
|
|
1385
|
+
const getValidStyle = (valid) => (valid ? inputValidStyle : 'border-error');
|
|
1386
|
+
|
|
1387
|
+
const Input = JSX(
|
|
1388
|
+
// eslint-disable-next-line max-lines-per-function
|
|
1389
|
+
({ key, className, id, name, type = 'text', label, placeholder, value = '', valid = true, pattern, autoFocus = false, isTextarea = false, disabled = false, children, onChange, onFocus, onBlur, }) => {
|
|
1390
|
+
const inputRef = useRef(null);
|
|
1391
|
+
const handleChange = useCallback((e) => {
|
|
1392
|
+
const valueWithoutSpace = (e.target?.value ?? '').trimStart();
|
|
1393
|
+
onChange && onChange(valueWithoutSpace);
|
|
1394
|
+
}, [onChange]);
|
|
1395
|
+
useEffect(() => {
|
|
1396
|
+
if (autoFocus) {
|
|
1397
|
+
inputRef.current?.focus();
|
|
1398
|
+
}
|
|
1399
|
+
}, [autoFocus, inputRef]);
|
|
1400
|
+
const paddingStyle = children ? 'pr-3xl' : '';
|
|
1401
|
+
const validStyle = getValidStyle(valid);
|
|
1402
|
+
const ariaLabel = label ?? name ?? id;
|
|
1403
|
+
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] }));
|
|
1404
|
+
});
|
|
1405
|
+
const defaultStyle$1 = 'w-full border rounded-md text-primary-text outline-none p-m';
|
|
1406
|
+
|
|
1920
1407
|
const InputWrapper = JSX(({ className, label, value = '', error, errors, type, isInteger, placeholder, maxLength, inputRef, isOpen, onOpen, onClose, onChange = noop, ...rest }) => {
|
|
1921
1408
|
const popupRef = useOutsideClick(onClose);
|
|
1922
1409
|
const handleChange = useCallback((v) => {
|
|
@@ -2711,9 +2198,9 @@
|
|
|
2711
2198
|
onChange && onChange(!value);
|
|
2712
2199
|
}, [onChange, disabled, value]);
|
|
2713
2200
|
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" }));
|
|
2714
|
-
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$
|
|
2201
|
+
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$4(text)] }) }));
|
|
2715
2202
|
});
|
|
2716
|
-
const renderText$
|
|
2203
|
+
const renderText$4 = (text) => text ? (jsx("div", { className: "ml-s", children: jsx(Text, { size: "text-l", font: "font-light", children: text }) })) : null;
|
|
2717
2204
|
const getCursorStyle = (disabled = false) => (disabled ? 'cursor-not-allowed' : 'cursor-pointer');
|
|
2718
2205
|
const role = (isRadio = false) => (isRadio ? 'radio' : 'checkbox');
|
|
2719
2206
|
const checkboxStyle = (value = false) => style('rounded border', { 'bg-primary-main': value });
|
|
@@ -3062,6 +2549,39 @@
|
|
|
3062
2549
|
|
|
3063
2550
|
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;
|
|
3064
2551
|
|
|
2552
|
+
const themeStyle$1 = {
|
|
2553
|
+
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'),
|
|
2554
|
+
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'),
|
|
2555
|
+
};
|
|
2556
|
+
const embeddedStyle = style('group/btn-embedded', 'bg-transparent border border-transparent outline-none');
|
|
2557
|
+
const disabledStyle = style('bg-main-gray text-main-disabled cursor-not-allowed');
|
|
2558
|
+
const Button = JSX(({ className, type = 'button', version = 'primary', shape = 'default', embedded, disabled, role, ariaLabel, data, dataTheme, children, wcmsIgnore, onClick = noop, }) => {
|
|
2559
|
+
const handleClick = useCallback(role !== 'tab' ? handlerDecorator(onClick) : onClick, [
|
|
2560
|
+
role,
|
|
2561
|
+
onClick,
|
|
2562
|
+
]);
|
|
2563
|
+
const aspectsAttrs = useMemo(() => getAspectsAttributes(data), [data]);
|
|
2564
|
+
const isRound = shape === 'round';
|
|
2565
|
+
return (jsx("button", { className: style('font-sans flex items-center gap-xs', {
|
|
2566
|
+
[themeStyle$1[version]]: !disabled && !embedded,
|
|
2567
|
+
[embeddedStyle]: embedded,
|
|
2568
|
+
[disabledStyle]: disabled,
|
|
2569
|
+
}, embedded ? 'justify-between' : 'justify-center', embedded || isRound ? 'p-0' : 'px-9 py-4', {
|
|
2570
|
+
'rounded-md': shape === 'default',
|
|
2571
|
+
'rounded-full': isRound,
|
|
2572
|
+
}, 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 }));
|
|
2573
|
+
});
|
|
2574
|
+
|
|
2575
|
+
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" }) })));
|
|
2576
|
+
|
|
2577
|
+
const DIALOG_STYLE = {
|
|
2578
|
+
sm: 'max-w-sm top-1/3',
|
|
2579
|
+
lg: 'max-w-lg',
|
|
2580
|
+
'4xl': 'max-w-4xl',
|
|
2581
|
+
none: 'mt-0',
|
|
2582
|
+
};
|
|
2583
|
+
const Dialog = JSX(({ head, maxWidth = '4xl', children, onClose, onClick }) => (jsxs("div", { className: style('relative bg-white p-lg pb-6xl my-6xl mx-auto rounded-lg w-full', DIALOG_STYLE[maxWidth]), 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 z-10", onClose: onClose }), jsx("div", { className: "container", children: head })] }), jsx("div", { className: "container", children: children })] })));
|
|
2584
|
+
|
|
3065
2585
|
const ResponseTypeDialog = JSX(({ ok, typeForm, onClose }) => {
|
|
3066
2586
|
const statusIcon = ok ? 'ResponseOKIcon' : 'ResponseFailIcon';
|
|
3067
2587
|
const responseOKDescription = typeForm === 'ANTIFRAUD'
|
|
@@ -3146,34 +2666,203 @@
|
|
|
3146
2666
|
return { ...formState, typeForm: { key: typeForm, text: '' } };
|
|
3147
2667
|
};
|
|
3148
2668
|
|
|
3149
|
-
const
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
2669
|
+
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, {
|
|
2670
|
+
'backdrop-blur': blur,
|
|
2671
|
+
}), 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" }) })));
|
|
2672
|
+
|
|
2673
|
+
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] })));
|
|
2674
|
+
|
|
2675
|
+
const themeStyle = {
|
|
2676
|
+
primary: themeStyle$1.primary,
|
|
2677
|
+
secondary: themeStyle$1.secondary,
|
|
2678
|
+
white: 'text-primary-main bg-white hover:text-white hover:bg-primary-hover active:bg-white active:text-primary-main',
|
|
2679
|
+
link: 'text-primary-main',
|
|
2680
|
+
gray: themeStyle$1.secondary,
|
|
2681
|
+
transparent: '',
|
|
2682
|
+
'': '',
|
|
2683
|
+
};
|
|
2684
|
+
const Link = JSX((props) => {
|
|
2685
|
+
const link = useLink();
|
|
2686
|
+
const { className, href, target, text, aboveText, version = 'link', rel, ariaLabel, data, children, onClick, } = link(props);
|
|
2687
|
+
const buttonLike = version !== 'link';
|
|
2688
|
+
return (jsx("a", { className: style('group/btn inline-flex items-center h-fit', 'font-sans no-underline select-none', 'border border-transparent focus:border-primary-text focus:border', 'cursor-pointer', {
|
|
2689
|
+
[themeStyle[version]]: Boolean(version),
|
|
2690
|
+
[aboveText ? 'px-9 py-2.5' : 'px-9 py-4']: buttonLike,
|
|
2691
|
+
'rounded-md': buttonLike,
|
|
2692
|
+
}, className), href: href, target: target, rel: rel, "aria-label": ariaLabel ?? `Ссылка на ${text}`, role: href ? 'link' : 'button', onClick: onClick, ...getAspectsAttributes(data), children: children ?? renderText$3(text, aboveText) }));
|
|
2693
|
+
});
|
|
2694
|
+
const renderText$3 = (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;
|
|
2695
|
+
|
|
2696
|
+
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] })));
|
|
2697
|
+
|
|
2698
|
+
const agreementText = 'Нажимая кнопку, вы подтверждаете согласие с ';
|
|
2699
|
+
const agreementTextPF = 'Нажимая на кнопку, вы подтверждаете, что клиент дал согласие на ';
|
|
2700
|
+
const renderAgreementSubmit = ({ consentDataProcessing, link, button, typeForm, }) => (jsxs("div", { className: "flex col-span-2 gap-xs flex-col w-full items-baseline", children: [consentDataProcessing ? (jsxs("div", { children: [jsxs("div", { className: "flex gap-3 items-center", children: [jsx(Checkbox, { ...consentDataProcessing }), jsx(Footnote, { link: link })] }), renderErrorText(withValidator(consentDataProcessing, agreementValidator).error)] })) : (jsx(Footnote, { text: typeForm === 'PF' ? agreementTextPF : agreementText, link: link })), jsx(SubmitButton$1, { className: "w-full @xl:w-auto", children: button?.text ? button.text : 'Отправить заявку' })] }));
|
|
2701
|
+
|
|
2702
|
+
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" })] })] })] }));
|
|
2703
|
+
|
|
2704
|
+
const useInterval = (handler, period) => {
|
|
2705
|
+
const timer = useRef(null);
|
|
2706
|
+
const stop = useCallback(() => clearInterval(timer.current), []);
|
|
2707
|
+
const start = useCallback(() => {
|
|
2708
|
+
stop();
|
|
2709
|
+
timer.current = setInterval(() => handler(stop), period);
|
|
2710
|
+
}, [handler, period, stop]);
|
|
2711
|
+
useEffect(() => {
|
|
2712
|
+
start();
|
|
2713
|
+
return stop;
|
|
2714
|
+
}, [start, stop]);
|
|
2715
|
+
return { start, stop };
|
|
2716
|
+
};
|
|
2717
|
+
|
|
2718
|
+
function useCountDownTimer({ seconds, period = 1000, onTick, onEnd }) {
|
|
2719
|
+
const counter = useRef(seconds);
|
|
2720
|
+
const handleTick = useCallback((stop) => {
|
|
2721
|
+
counter.current ||= 0;
|
|
2722
|
+
counter.current = Math.max(0, counter.current - 1);
|
|
2723
|
+
try {
|
|
2724
|
+
onTick?.(counter.current);
|
|
2725
|
+
}
|
|
2726
|
+
finally {
|
|
2727
|
+
if (counter.current <= 0) {
|
|
2728
|
+
stop();
|
|
2729
|
+
onEnd?.();
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
}, [onTick, onEnd]);
|
|
2733
|
+
const { start } = useInterval(handleTick, period);
|
|
2734
|
+
return useCallback((_) => {
|
|
2735
|
+
counter.current = _;
|
|
2736
|
+
start();
|
|
2737
|
+
}, []);
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2740
|
+
const InputCode = JSX(({ values, setValues, hasError, errorText }) => {
|
|
2741
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
|
2742
|
+
const inputRefs = useRef([]);
|
|
2743
|
+
useEffect(() => {
|
|
2744
|
+
inputRefs.current?.[activeIndex]?.focus();
|
|
2745
|
+
}, [activeIndex]);
|
|
2746
|
+
const handleChange = useCallback((index) => (event) => {
|
|
2747
|
+
const { value } = event.currentTarget;
|
|
2748
|
+
const oneValue = value.slice(0, 1);
|
|
2749
|
+
setValues(values.map((_, i) => (i === index ? oneValue : _)));
|
|
2750
|
+
setActiveIndex(index + 1);
|
|
2751
|
+
}, [values]);
|
|
2752
|
+
const handleKeyDown = useCallback((currentIndex) => (event) => {
|
|
2753
|
+
const { key } = event;
|
|
2754
|
+
if (key === 'Backspace' && !values[currentIndex]) {
|
|
2755
|
+
const previousIndex = currentIndex > 0 ? currentIndex - 1 : values.length - 1;
|
|
2756
|
+
const updatedValues = values.map((value, index) => (index === previousIndex ? '' : value));
|
|
2757
|
+
setValues(updatedValues);
|
|
2758
|
+
setActiveIndex(previousIndex);
|
|
2759
|
+
}
|
|
2760
|
+
}, [values]);
|
|
2761
|
+
const handlePaste = useCallback((event) => {
|
|
2762
|
+
event.preventDefault();
|
|
2763
|
+
const pastedData = event.clipboardData.getData('text');
|
|
2764
|
+
const updatedValues = values.map((_, idx) => (idx < pastedData.length ? pastedData[idx] : _));
|
|
2765
|
+
setValues(updatedValues);
|
|
2766
|
+
setActiveIndex(updatedValues.length - 1);
|
|
2767
|
+
}, [values]);
|
|
2768
|
+
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) => {
|
|
2769
|
+
if (!inputRefs.current) {
|
|
2770
|
+
inputRefs.current = [];
|
|
2771
|
+
}
|
|
2772
|
+
inputRefs.current[index] = ref;
|
|
2773
|
+
}, onFocus: (event) => event.target.select(), onKeyDown: handleKeyDown(index), className: getInputStyle(index, values, hasError) }, index))) }), hasError ? jsx("div", { className: "text-error", children: errorText }) : null] }));
|
|
2774
|
+
});
|
|
2775
|
+
const getInputStyle = (index, values, hasError = false) => {
|
|
2776
|
+
const isInputEmpty = !values[index];
|
|
2777
|
+
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`;
|
|
2778
|
+
};
|
|
2779
|
+
|
|
2780
|
+
const SubmitButton = JSX(({ disabled = false, onClick, text }) => (jsx(Button, { type: "button", onClick: onClick, disabled: disabled, children: jsx(Text, { font: "font-normal", children: text }) })));
|
|
2781
|
+
|
|
2782
|
+
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 })));
|
|
2783
|
+
|
|
2784
|
+
const Timer = JSX(({ className, seconds }) => (jsx("span", { className: className, children: formatTimer(seconds) })));
|
|
2785
|
+
const formatTimer = (seconds) => {
|
|
2786
|
+
const minutes = Math.floor(seconds / 60);
|
|
2787
|
+
return [minutes, seconds % 60].map((_) => String(_).padStart(2, '0')).join(':');
|
|
3157
2788
|
};
|
|
3158
|
-
const Link = JSX((props) => {
|
|
3159
|
-
const link = useLink();
|
|
3160
|
-
const { className, href, target, text, aboveText, version = 'link', rel, ariaLabel, data, children, onClick, } = link(props);
|
|
3161
|
-
const buttonLike = version !== 'link';
|
|
3162
|
-
return (jsx("a", { className: style('group/btn inline-flex items-center h-fit', 'font-sans no-underline select-none', 'border border-transparent focus:border-primary-text focus:border', 'cursor-pointer', {
|
|
3163
|
-
[themeStyle[version]]: Boolean(version),
|
|
3164
|
-
[aboveText ? 'px-9 py-2.5' : 'px-9 py-4']: buttonLike,
|
|
3165
|
-
'rounded-md': buttonLike,
|
|
3166
|
-
}, className), href: href, target: target, rel: rel, "aria-label": ariaLabel ?? `Ссылка на ${text}`, role: href ? 'link' : 'button', onClick: onClick, ...getAspectsAttributes(data), children: children ?? renderText$2(text, aboveText) }));
|
|
3167
|
-
});
|
|
3168
|
-
const renderText$2 = (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;
|
|
3169
2789
|
|
|
3170
|
-
const
|
|
2790
|
+
const VerifyPhoneDialogLayout = JSX(({ children, isLoading, isSubmitButtonDisabled, timeNextReq, onSubmit, onSendCode, values, onChange, errorText, hasError, phone, onClose, }) => (jsx(Dialog, { maxWidth: "lg", onClose: onClose, children: jsxs("div", { className: "flex flex-col gap-xl items-center rounded-md", children: [renderHeadline(phone), jsx(InputCode, { values: values, setValues: onChange, errorText: errorText, hasError: hasError }), renderText$2(timeNextReq, onSendCode), children, renderNextButton(isSubmitButtonDisabled, onSubmit), isLoading ? jsx(Loader, { blur: false }) : null] }) })));
|
|
2791
|
+
const renderHeadline = (phone) => (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" }));
|
|
2792
|
+
const renderNextButton = (disabled, onClick) => (jsx(SubmitButton, { text: "\u0414\u0430\u043B\u0435\u0435", disabled: disabled, onClick: onClick }));
|
|
2793
|
+
const renderText$2 = (timeNextReq, handleSendCode) => timeNextReq ? (jsxs("div", { className: "flex flex-row text-l font-light text-base gap-2xs", children: [jsx("span", { 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, { 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" }) }));
|
|
3171
2794
|
|
|
3172
|
-
const
|
|
3173
|
-
const
|
|
3174
|
-
const renderAgreementSubmit = ({ consentDataProcessing, link, button, typeForm, }) => (jsxs("div", { className: "flex col-span-2 gap-xs flex-col w-full items-baseline", children: [consentDataProcessing ? (jsxs("div", { children: [jsxs("div", { className: "flex gap-3 items-center", children: [jsx(Checkbox, { ...consentDataProcessing }), jsx(Footnote, { link: link })] }), renderErrorText(withValidator(consentDataProcessing, agreementValidator).error)] })) : (jsx(Footnote, { text: typeForm === 'PF' ? agreementTextPF : agreementText, link: link })), jsx(SubmitButton$1, { className: "w-full @xl:w-auto", children: button?.text ? button.text : 'Отправить заявку' })] }));
|
|
2795
|
+
const TIME_TO_RESEND$2 = 180;
|
|
2796
|
+
const getTimer = (sendTime) => TIME_TO_RESEND$2 - Math.floor((Date.now() - sendTime) / 1000);
|
|
3175
2797
|
|
|
3176
|
-
const
|
|
2798
|
+
const API$2 = LeadServiceAPI();
|
|
2799
|
+
const useVerifyPhoneDialogSubmit$1 = ({ values, onSuccess, formatData, reqId, }) => {
|
|
2800
|
+
const timer = Math.max(getTimer(Date.now()), 0);
|
|
2801
|
+
const [errorText, setErrorText] = useState('');
|
|
2802
|
+
const [isLoading, { setTrue: startLoading, setFalse: endLoading }] = useBool(false);
|
|
2803
|
+
const [timeNextReq, setTimeNextReq] = useState(timer);
|
|
2804
|
+
const resetError = useCallback(() => setErrorText(''), []);
|
|
2805
|
+
const isSubmitButtonDisabled = !values.every(Boolean);
|
|
2806
|
+
const handleSubmit = useCallback(async () => {
|
|
2807
|
+
try {
|
|
2808
|
+
startLoading();
|
|
2809
|
+
const response = await API$2.checkCode({
|
|
2810
|
+
code: values.join(''),
|
|
2811
|
+
body: formatData,
|
|
2812
|
+
reqId,
|
|
2813
|
+
});
|
|
2814
|
+
if (response?.errorDesc) {
|
|
2815
|
+
setErrorText(response?.errorDesc);
|
|
2816
|
+
return;
|
|
2817
|
+
}
|
|
2818
|
+
setTimeNextReq(0);
|
|
2819
|
+
resetError();
|
|
2820
|
+
onSuccess?.(values.join(''));
|
|
2821
|
+
}
|
|
2822
|
+
catch {
|
|
2823
|
+
setErrorText('Неверный код');
|
|
2824
|
+
}
|
|
2825
|
+
finally {
|
|
2826
|
+
endLoading();
|
|
2827
|
+
}
|
|
2828
|
+
}, [values]);
|
|
2829
|
+
return {
|
|
2830
|
+
handleSubmit,
|
|
2831
|
+
hasError: Boolean(errorText),
|
|
2832
|
+
errorText,
|
|
2833
|
+
isLoading,
|
|
2834
|
+
timeNextReq,
|
|
2835
|
+
isSubmitButtonDisabled,
|
|
2836
|
+
setTimeNextReq,
|
|
2837
|
+
setErrorText,
|
|
2838
|
+
};
|
|
2839
|
+
};
|
|
2840
|
+
|
|
2841
|
+
const API$1 = LeadServiceAPI();
|
|
2842
|
+
const CODE_LENGTH$1 = 4;
|
|
2843
|
+
const TIME_TO_RESEND$1 = 180;
|
|
2844
|
+
const VerifyPhoneDialog$1 = JSX(({ phone, onSuccess = noop, onClose = noop, formatData = {}, reqId }) => {
|
|
2845
|
+
const [values, setValues] = useState(Array(CODE_LENGTH$1).fill(''));
|
|
2846
|
+
const [requestId, setRequestId] = useState(reqId);
|
|
2847
|
+
const { handleSubmit, hasError, errorText, isLoading, timeNextReq, isSubmitButtonDisabled, setTimeNextReq, setErrorText, } = useVerifyPhoneDialogSubmit$1({
|
|
2848
|
+
values,
|
|
2849
|
+
onSuccess,
|
|
2850
|
+
formatData,
|
|
2851
|
+
reqId: requestId ?? '',
|
|
2852
|
+
});
|
|
2853
|
+
const phoneNumber = formatPhone(phone);
|
|
2854
|
+
const restartTimer = useCountDownTimer({ seconds: timeNextReq, onTick: setTimeNextReq });
|
|
2855
|
+
const handleSendCode = useCallback(async () => {
|
|
2856
|
+
const response = await API$1.sendCode({ phone: phoneNumber });
|
|
2857
|
+
if (response) {
|
|
2858
|
+
setTimeNextReq(TIME_TO_RESEND$1);
|
|
2859
|
+
restartTimer(TIME_TO_RESEND$1);
|
|
2860
|
+
setErrorText('');
|
|
2861
|
+
setRequestId(String(response));
|
|
2862
|
+
}
|
|
2863
|
+
}, [phoneNumber, restartTimer, onClose]);
|
|
2864
|
+
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 }));
|
|
2865
|
+
});
|
|
3177
2866
|
|
|
3178
2867
|
const API = LeadServiceAPI();
|
|
3179
2868
|
const ApplicationForm = UniBlock(
|
|
@@ -3185,7 +2874,7 @@
|
|
|
3185
2874
|
const aspects = useAspects();
|
|
3186
2875
|
const formValidator = useMemo(() => getFormValidator(inputs), [inputs]);
|
|
3187
2876
|
const responseTypeDialog = useDialog(ResponseTypeDialog);
|
|
3188
|
-
const verifyPhoneDialog = useDialog(VerifyPhoneDialog);
|
|
2877
|
+
const verifyPhoneDialog = useDialog(VerifyPhoneDialog$1);
|
|
3189
2878
|
const handleSubmit = useCallback(async (formData, ev) => {
|
|
3190
2879
|
const formatData = getFormatData({ ...formData, ...additionalParams });
|
|
3191
2880
|
if (endpoint === 'initcorporatelead') {
|
|
@@ -3197,10 +2886,8 @@
|
|
|
3197
2886
|
}
|
|
3198
2887
|
verifyPhoneDialog.open({
|
|
3199
2888
|
phone,
|
|
3200
|
-
withDescription: false,
|
|
3201
2889
|
formatData,
|
|
3202
2890
|
reqId: String(response),
|
|
3203
|
-
isRetail: false,
|
|
3204
2891
|
onSuccess: () => {
|
|
3205
2892
|
verifyPhoneDialog.close();
|
|
3206
2893
|
responseTypeDialog.open({ ok: true, typeForm });
|
|
@@ -3505,6 +3192,42 @@
|
|
|
3505
3192
|
EsiaStatuses["Pending"] = "PENDING";
|
|
3506
3193
|
})(EsiaStatuses || (EsiaStatuses = {}));
|
|
3507
3194
|
|
|
3195
|
+
const getTraceId = () => {
|
|
3196
|
+
const result = new Uint8Array(8);
|
|
3197
|
+
globalThis.crypto.getRandomValues(result);
|
|
3198
|
+
return result.reduce((acc, _) => `${acc}${_.toString(16).padStart(2, '0')}`, '');
|
|
3199
|
+
};
|
|
3200
|
+
|
|
3201
|
+
const fetchRetailJSON = async (url, method, body) => {
|
|
3202
|
+
try {
|
|
3203
|
+
const response = await doRequest(url, method, body);
|
|
3204
|
+
return response.json();
|
|
3205
|
+
}
|
|
3206
|
+
catch (err) {
|
|
3207
|
+
console.error(err);
|
|
3208
|
+
return null;
|
|
3209
|
+
}
|
|
3210
|
+
};
|
|
3211
|
+
async function doRequest(url, method, body) {
|
|
3212
|
+
const traceId = getTraceId();
|
|
3213
|
+
return globalThis?.fetch?.(`${RETAIL_API_BASE_URI}${url}`, {
|
|
3214
|
+
method,
|
|
3215
|
+
headers: {
|
|
3216
|
+
'Content-Type': 'application/json',
|
|
3217
|
+
'X-B3-Sampled': '1',
|
|
3218
|
+
'X-B3-Spanid': traceId,
|
|
3219
|
+
'X-B3-Traceid': traceId,
|
|
3220
|
+
...getAuthorizationHeaders(),
|
|
3221
|
+
},
|
|
3222
|
+
credentials: 'include',
|
|
3223
|
+
body: body ? JSON.stringify(body) : null,
|
|
3224
|
+
});
|
|
3225
|
+
}
|
|
3226
|
+
const getAuthorizationHeaders = () => {
|
|
3227
|
+
const token = sessionStorage.getItem('accessToken');
|
|
3228
|
+
return token ? { Authorization: `Bearer ${token}` } : null;
|
|
3229
|
+
};
|
|
3230
|
+
|
|
3508
3231
|
const getLink = (body) => fetchRetailJSON('/esia/getLink', 'POST', body);
|
|
3509
3232
|
|
|
3510
3233
|
const EsiaLoginBanner = JSX(({ onChangeEsiaStatus, productType }) => {
|
|
@@ -4443,42 +4166,180 @@
|
|
|
4443
4166
|
|
|
4444
4167
|
const API_BASE_URI = '/light-api-cash/v1';
|
|
4445
4168
|
|
|
4446
|
-
const useLeadFormData = (typeField) => {
|
|
4447
|
-
const { data, error } = useAsyncData(`${API_BASE_URI}/dictionary?dictionaryType=${encodeURIComponent(typeField)}`, fetchData);
|
|
4448
|
-
if (data && 'errorMessage' in data) {
|
|
4449
|
-
return { error };
|
|
4450
|
-
}
|
|
4451
|
-
return { data: data, error };
|
|
4452
|
-
};
|
|
4453
|
-
const fetchData = async (url) => {
|
|
4454
|
-
const result = await fetchJSON(url, { method: 'POST' });
|
|
4455
|
-
return result || [];
|
|
4456
|
-
};
|
|
4169
|
+
const useLeadFormData = (typeField) => {
|
|
4170
|
+
const { data, error } = useAsyncData(`${API_BASE_URI}/dictionary?dictionaryType=${encodeURIComponent(typeField)}`, fetchData);
|
|
4171
|
+
if (data && 'errorMessage' in data) {
|
|
4172
|
+
return { error };
|
|
4173
|
+
}
|
|
4174
|
+
return { data: data, error };
|
|
4175
|
+
};
|
|
4176
|
+
const fetchData = async (url) => {
|
|
4177
|
+
const result = await fetchJSON(url, { method: 'POST' });
|
|
4178
|
+
return result || [];
|
|
4179
|
+
};
|
|
4180
|
+
|
|
4181
|
+
const AddressRetailField = JSX(({ field, input }) => {
|
|
4182
|
+
const [offices, setOffices] = useState([]);
|
|
4183
|
+
const { data } = useLeadFormData('REGION_RF');
|
|
4184
|
+
const regionValue = field('regionRetail')?.value || {};
|
|
4185
|
+
const addressField = field(input?.name ?? '');
|
|
4186
|
+
useEffect(() => {
|
|
4187
|
+
(async () => {
|
|
4188
|
+
const officesList = await fetchRegionOffices(regionValue?.key ?? '');
|
|
4189
|
+
setOffices(officesList);
|
|
4190
|
+
})();
|
|
4191
|
+
if (regionValue?.key) {
|
|
4192
|
+
addressField.onChange?.('');
|
|
4193
|
+
}
|
|
4194
|
+
}, [regionValue.key]);
|
|
4195
|
+
const { points } = useOfficesAtmsMapData({
|
|
4196
|
+
data: offices,
|
|
4197
|
+
filtrationState: {},
|
|
4198
|
+
getBalloon: getOfficePoint,
|
|
4199
|
+
});
|
|
4200
|
+
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 = '' }) => ({
|
|
4201
|
+
key: id?.toString() || '',
|
|
4202
|
+
text: address,
|
|
4203
|
+
})), ...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 }) }) })] }));
|
|
4204
|
+
});
|
|
4205
|
+
|
|
4206
|
+
function copy(source, target) {
|
|
4207
|
+
for (const [k, v] of source.entries()) {
|
|
4208
|
+
if (v !== null && v !== undefined) {
|
|
4209
|
+
target.setItem(k, v);
|
|
4210
|
+
}
|
|
4211
|
+
else {
|
|
4212
|
+
target.removeItem(k);
|
|
4213
|
+
}
|
|
4214
|
+
}
|
|
4215
|
+
}
|
|
4216
|
+
|
|
4217
|
+
function replicate(primary, secondary) {
|
|
4218
|
+
copy(primary, secondary);
|
|
4219
|
+
copy(secondary, primary);
|
|
4220
|
+
return primary.bus.watch(({ type, event }) => {
|
|
4221
|
+
if (event !== null && event !== undefined) {
|
|
4222
|
+
secondary.setItem(type, event);
|
|
4223
|
+
}
|
|
4224
|
+
else {
|
|
4225
|
+
secondary.removeItem(type);
|
|
4226
|
+
}
|
|
4227
|
+
});
|
|
4228
|
+
}
|
|
4229
|
+
|
|
4230
|
+
class StorageAdapter {
|
|
4231
|
+
storage;
|
|
4232
|
+
bus;
|
|
4233
|
+
get size() {
|
|
4234
|
+
return this.storage?.length ?? 0;
|
|
4235
|
+
}
|
|
4236
|
+
constructor(storage, bus = new EventBus()) {
|
|
4237
|
+
this.storage = storage;
|
|
4238
|
+
this.bus = bus;
|
|
4239
|
+
}
|
|
4240
|
+
hasItem(key) {
|
|
4241
|
+
return Boolean(this.storage?.getItem(String(key)));
|
|
4242
|
+
}
|
|
4243
|
+
getItem(key) {
|
|
4244
|
+
const _ = this.storage?.getItem(String(key)) ?? null;
|
|
4245
|
+
try {
|
|
4246
|
+
return JSON.parse(String(_));
|
|
4247
|
+
}
|
|
4248
|
+
catch (ex) {
|
|
4249
|
+
return null;
|
|
4250
|
+
}
|
|
4251
|
+
}
|
|
4252
|
+
entries() {
|
|
4253
|
+
return Array.from({ length: this.size }, (_, i) => {
|
|
4254
|
+
const k = String(this.storage?.key(i));
|
|
4255
|
+
return [k, this.getItem(k)];
|
|
4256
|
+
});
|
|
4257
|
+
}
|
|
4258
|
+
setItem(key, value) {
|
|
4259
|
+
if (value !== null) {
|
|
4260
|
+
this.storage?.setItem(String(key), JSON.stringify(value));
|
|
4261
|
+
}
|
|
4262
|
+
else {
|
|
4263
|
+
this.storage?.removeItem(String(key));
|
|
4264
|
+
}
|
|
4265
|
+
this.bus?.subject(key, value);
|
|
4266
|
+
}
|
|
4267
|
+
removeItem(key) {
|
|
4268
|
+
this.storage?.removeItem(String(key));
|
|
4269
|
+
this.bus?.subject(key, null);
|
|
4270
|
+
}
|
|
4271
|
+
}
|
|
4272
|
+
|
|
4273
|
+
class Store {
|
|
4274
|
+
bus;
|
|
4275
|
+
store = new Map();
|
|
4276
|
+
get size() {
|
|
4277
|
+
return this.store.size;
|
|
4278
|
+
}
|
|
4279
|
+
constructor(bus = new EventBus()) {
|
|
4280
|
+
this.bus = bus;
|
|
4281
|
+
}
|
|
4282
|
+
hasItem(key) {
|
|
4283
|
+
return this.store.has(key);
|
|
4284
|
+
}
|
|
4285
|
+
getItem(key) {
|
|
4286
|
+
return this.store.get(key);
|
|
4287
|
+
}
|
|
4288
|
+
entries() {
|
|
4289
|
+
return this.store.entries();
|
|
4290
|
+
}
|
|
4291
|
+
setItem(key, value) {
|
|
4292
|
+
this.store.set(key, value);
|
|
4293
|
+
this.bus.subject(key, value);
|
|
4294
|
+
}
|
|
4295
|
+
removeItem(key) {
|
|
4296
|
+
this.store.delete(key);
|
|
4297
|
+
this.bus.subject(key, null);
|
|
4298
|
+
}
|
|
4299
|
+
}
|
|
4300
|
+
|
|
4301
|
+
function useRerender() {
|
|
4302
|
+
const [, setCount] = useState(0);
|
|
4303
|
+
return useCallback(() => setCount(_ => (_ + 1) % (1 << 16)), []);
|
|
4304
|
+
}
|
|
4457
4305
|
|
|
4458
|
-
const
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4306
|
+
const DEFAULT_METHODS = {};
|
|
4307
|
+
/**
|
|
4308
|
+
* MobX like reactivity (simplified).
|
|
4309
|
+
* Can be used to migrate from Redux/MobX or something else
|
|
4310
|
+
*
|
|
4311
|
+
* @param store
|
|
4312
|
+
* @returns reactive proxy backed by store
|
|
4313
|
+
*/
|
|
4314
|
+
function useStore(store, methods = DEFAULT_METHODS) {
|
|
4315
|
+
const deps = useRef(null);
|
|
4316
|
+
const render = useRerender();
|
|
4317
|
+
useEffect(() => store.bus.watch(ev => {
|
|
4318
|
+
if (deps.current?.has(String(ev.type))) {
|
|
4319
|
+
render();
|
|
4320
|
+
}
|
|
4321
|
+
}), [store, render]);
|
|
4322
|
+
return useMemo(() => new Proxy(methods, {
|
|
4323
|
+
get(_, key) {
|
|
4324
|
+
deps.current ||= new Set();
|
|
4325
|
+
deps.current.add(key);
|
|
4326
|
+
return store.getItem(key);
|
|
4327
|
+
},
|
|
4328
|
+
has(_, key) {
|
|
4329
|
+
deps.current ||= new Set();
|
|
4330
|
+
deps.current.add(key);
|
|
4331
|
+
return store.hasItem(key);
|
|
4332
|
+
},
|
|
4333
|
+
set(_, key, value) {
|
|
4334
|
+
store.setItem(key, value);
|
|
4335
|
+
return true;
|
|
4336
|
+
},
|
|
4337
|
+
deleteProperty(_, key) {
|
|
4338
|
+
store.removeItem(key);
|
|
4339
|
+
return true;
|
|
4340
|
+
}
|
|
4341
|
+
}), [store]);
|
|
4342
|
+
}
|
|
4482
4343
|
|
|
4483
4344
|
const localStore = new Store(); // localStorage cache
|
|
4484
4345
|
replicate(localStore, new StorageAdapter(globalThis?.localStorage));
|
|
@@ -5707,6 +5568,12 @@
|
|
|
5707
5568
|
|
|
5708
5569
|
const renderSubmitButton = (button, isSending = false) => (jsx(SubmitButton$1, { className: "w-full @xl:w-auto", isLoading: isSending, children: button?.text ? button.text : 'Отправить заявку' }));
|
|
5709
5570
|
|
|
5571
|
+
const sessionStore = new Store(); // sessionStorage cache
|
|
5572
|
+
replicate(sessionStore, new StorageAdapter(globalThis?.sessionStorage));
|
|
5573
|
+
function useSessionStore() {
|
|
5574
|
+
return useStore(sessionStore);
|
|
5575
|
+
}
|
|
5576
|
+
|
|
5710
5577
|
const createDraftTask = async (body) => {
|
|
5711
5578
|
const res = await fetchRetailJSON('/user-data/createDraftTask', 'POST', body);
|
|
5712
5579
|
return res || {};
|
|
@@ -5735,6 +5602,171 @@
|
|
|
5735
5602
|
|
|
5736
5603
|
const updateUserTask = (body) => doRequest('/user-data/updateUserTask', 'PUT', body);
|
|
5737
5604
|
|
|
5605
|
+
const sendCode = (body) => doRequest('/sms/sendCode', 'POST', body)
|
|
5606
|
+
.then((res) => res.text())
|
|
5607
|
+
.then((text) => text === 'OK');
|
|
5608
|
+
|
|
5609
|
+
const ICON_SIZE = { width: '103', height: '21' };
|
|
5610
|
+
|
|
5611
|
+
const logoTitleSizeStyle = 'text-s';
|
|
5612
|
+
|
|
5613
|
+
const ICON_VERSION_MAP = {
|
|
5614
|
+
'bg-white': 'color',
|
|
5615
|
+
transparent: 'white',
|
|
5616
|
+
};
|
|
5617
|
+
const SVG_COLOR = {
|
|
5618
|
+
'bg-white': 'text-primary-main',
|
|
5619
|
+
transparent: 'text-white',
|
|
5620
|
+
};
|
|
5621
|
+
const renderImage = (bgColor, image, size) => {
|
|
5622
|
+
const img = image?.src
|
|
5623
|
+
? image
|
|
5624
|
+
: {
|
|
5625
|
+
icon: image?.icon || 'LogoIcon',
|
|
5626
|
+
iconVersion: ICON_VERSION_MAP[bgColor],
|
|
5627
|
+
};
|
|
5628
|
+
return (jsx(Img, { image: img, className: SVG_COLOR[bgColor], width: size?.width, height: size?.height }));
|
|
5629
|
+
};
|
|
5630
|
+
|
|
5631
|
+
const TEXT_COLOR = {
|
|
5632
|
+
'bg-white': 'text-primary-text',
|
|
5633
|
+
transparent: 'text-white',
|
|
5634
|
+
};
|
|
5635
|
+
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
|
|
5636
|
+
? children ?? (jsx("div", { className: "ml-s", children: jsx(Text, { font: "font-medium", color: TEXT_COLOR[bgColor], size: logoTitleSizeStyle, children: logo?.title ?? 'Россельхозбанк' }) }))
|
|
5637
|
+
: null] })));
|
|
5638
|
+
|
|
5639
|
+
const checkCaptcha = (body) => doRequest('/sms/checkCaptcha', 'POST', body)
|
|
5640
|
+
.then((res) => res.text())
|
|
5641
|
+
.then((text) => text !== 'ERROR');
|
|
5642
|
+
|
|
5643
|
+
const createCaptcha = (phoneNumber) => doRequest(`/sms/createCaptcha?phoneNumber=${encodeURIComponent(phoneNumber)}`, 'GET').then(async (res) => (res ? res.blob() : new Blob()));
|
|
5644
|
+
|
|
5645
|
+
const CaptchaDialog = JSX(({ phoneNumber, sendCode, onClose }) => {
|
|
5646
|
+
const [captcha, setCaptcha] = useState('');
|
|
5647
|
+
const [code, setCode] = useState('');
|
|
5648
|
+
const [hasError, setHasError] = useState(false);
|
|
5649
|
+
const [isLoading, { setTrue: startLoading, setFalse: endLoading }] = useBool(false);
|
|
5650
|
+
const { closeAll } = useDialogManager();
|
|
5651
|
+
const handleCheckCaptcha = useCallback(async () => {
|
|
5652
|
+
startLoading();
|
|
5653
|
+
const isValidCode = await checkCaptcha({ captchaText: code });
|
|
5654
|
+
if (isValidCode) {
|
|
5655
|
+
onClose?.();
|
|
5656
|
+
sendCode?.();
|
|
5657
|
+
}
|
|
5658
|
+
else {
|
|
5659
|
+
setHasError(true);
|
|
5660
|
+
}
|
|
5661
|
+
endLoading();
|
|
5662
|
+
}, [code, sendCode]);
|
|
5663
|
+
const handleCreateCaptcha = useCallback(() => {
|
|
5664
|
+
(async () => setCaptcha(URL.createObjectURL(await createCaptcha(phoneNumber))))();
|
|
5665
|
+
}, []);
|
|
5666
|
+
useEffect(handleCreateCaptcha, []);
|
|
5667
|
+
return (jsx(Dialog, { 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] }) }));
|
|
5668
|
+
});
|
|
5669
|
+
|
|
5670
|
+
const checkCode = async (body) => fetchRetailJSON('/sms/checkCode', 'POST', body).then(saveToken);
|
|
5671
|
+
const saveToken = (data) => {
|
|
5672
|
+
if (data?.access_token && data?.refresh_token) {
|
|
5673
|
+
globalThis.sessionStorage.setItem('accessToken', data.access_token);
|
|
5674
|
+
globalThis.sessionStorage.setItem('refreshToken', data.refresh_token);
|
|
5675
|
+
}
|
|
5676
|
+
};
|
|
5677
|
+
|
|
5678
|
+
const TIME_TO_RESEND = 180;
|
|
5679
|
+
const useVerifyPhoneDialogSubmit = ({ values, onSuccess, }) => {
|
|
5680
|
+
const sessionStore = useSessionStore();
|
|
5681
|
+
const attempts = sessionStore.smsCode?.attempts || 0;
|
|
5682
|
+
const timer = Math.max(getTimer(sessionStore.smsCode?.sendTime || Date.now()), 0);
|
|
5683
|
+
const [errorText, setErrorText] = useState('');
|
|
5684
|
+
const [isLoading, { setTrue: startLoading, setFalse: endLoading }] = useBool(false);
|
|
5685
|
+
const [timeNextReq, setTimeNextReq] = useState(timer);
|
|
5686
|
+
const resetError = useCallback(() => setErrorText(''), []);
|
|
5687
|
+
const isTimeExpired = Boolean(timeNextReq === 0 && sessionStore.smsCode?.sendTime);
|
|
5688
|
+
const isSubmitButtonDisabled = attempts > 2 || isTimeExpired || !values.every(Boolean);
|
|
5689
|
+
const handleSubmit = useCallback(async () => {
|
|
5690
|
+
try {
|
|
5691
|
+
sessionStore.smsCode = {
|
|
5692
|
+
...sessionStore.smsCode,
|
|
5693
|
+
attempts: attempts + 1,
|
|
5694
|
+
};
|
|
5695
|
+
startLoading();
|
|
5696
|
+
await checkCode({
|
|
5697
|
+
smsText: values.join(''),
|
|
5698
|
+
smsCodesSetName: { key: 'AUTHENTICATION' },
|
|
5699
|
+
});
|
|
5700
|
+
setTimeNextReq(0);
|
|
5701
|
+
resetError();
|
|
5702
|
+
sessionStore.smsCode = null;
|
|
5703
|
+
onSuccess?.(values.join(''));
|
|
5704
|
+
}
|
|
5705
|
+
catch {
|
|
5706
|
+
setErrorText(attempts > 1 ? 'Исчерпан лимит ввода смс-кода' : 'Неверный код');
|
|
5707
|
+
}
|
|
5708
|
+
finally {
|
|
5709
|
+
endLoading();
|
|
5710
|
+
}
|
|
5711
|
+
}, [values, attempts]);
|
|
5712
|
+
useEffect(() => {
|
|
5713
|
+
if (isTimeExpired) {
|
|
5714
|
+
setErrorText('Код просрочен');
|
|
5715
|
+
}
|
|
5716
|
+
else if (attempts > 2) {
|
|
5717
|
+
setErrorText('Исчерпан лимит ввода смс-кода');
|
|
5718
|
+
}
|
|
5719
|
+
}, [isTimeExpired]);
|
|
5720
|
+
return {
|
|
5721
|
+
handleSubmit,
|
|
5722
|
+
hasError: Boolean(errorText),
|
|
5723
|
+
errorText,
|
|
5724
|
+
isLoading,
|
|
5725
|
+
timeNextReq,
|
|
5726
|
+
isSubmitButtonDisabled,
|
|
5727
|
+
setTimeNextReq,
|
|
5728
|
+
setErrorText,
|
|
5729
|
+
};
|
|
5730
|
+
};
|
|
5731
|
+
|
|
5732
|
+
const CODE_LENGTH = 4;
|
|
5733
|
+
const VerifyPhoneDialog = JSX(({ phone, withDescription = true, consents, onSuccess = noop, onClose = noop }) => {
|
|
5734
|
+
const [values, setValues] = useState(Array(CODE_LENGTH).fill(''));
|
|
5735
|
+
const sessionStore = useSessionStore();
|
|
5736
|
+
const { handleSubmit, hasError, errorText, isLoading, timeNextReq, isSubmitButtonDisabled, setTimeNextReq, setErrorText, } = useVerifyPhoneDialogSubmit({
|
|
5737
|
+
values,
|
|
5738
|
+
onSuccess,
|
|
5739
|
+
});
|
|
5740
|
+
const captchaDialog = useDialog(CaptchaDialog);
|
|
5741
|
+
const phoneNumber = formatPhone(phone);
|
|
5742
|
+
const restartTimer = useCountDownTimer({ seconds: timeNextReq, onTick: setTimeNextReq });
|
|
5743
|
+
const handleSendCode = useCallback(async () => {
|
|
5744
|
+
const response = await sendCode({
|
|
5745
|
+
phoneNumber,
|
|
5746
|
+
smsCodesSetName: { key: 'AUTHENTICATION' },
|
|
5747
|
+
});
|
|
5748
|
+
if (response) {
|
|
5749
|
+
setTimeNextReq(TIME_TO_RESEND);
|
|
5750
|
+
restartTimer(TIME_TO_RESEND);
|
|
5751
|
+
setErrorText('');
|
|
5752
|
+
sessionStore.smsCode = {
|
|
5753
|
+
sendTime: Date.now(),
|
|
5754
|
+
attempts: 0,
|
|
5755
|
+
};
|
|
5756
|
+
}
|
|
5757
|
+
else {
|
|
5758
|
+
captchaDialog.open({ phoneNumber, sendCode: handleSendCode });
|
|
5759
|
+
}
|
|
5760
|
+
}, [phoneNumber, restartTimer, onClose]);
|
|
5761
|
+
useEffect(() => {
|
|
5762
|
+
if (!sessionStore.smsCode?.sendTime) {
|
|
5763
|
+
handleSendCode();
|
|
5764
|
+
}
|
|
5765
|
+
}, []);
|
|
5766
|
+
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, children: renderDescription$2(consents, withDescription) }));
|
|
5767
|
+
});
|
|
5768
|
+
const renderDescription$2 = (consents, isRender = false) => isRender ? (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;
|
|
5769
|
+
|
|
5738
5770
|
const defaultConsentText = {
|
|
5739
5771
|
title: 'Подпишите согласие на запрос в БКИ',
|
|
5740
5772
|
description: 'Согласие на запрос в Бюро кредитных историй (БКИ) ускорит решение по кредиту',
|
|
@@ -10373,7 +10405,7 @@
|
|
|
10373
10405
|
};
|
|
10374
10406
|
const handleInputSell = (setCalcState, currencyRatesSell) => (value, currencyFrom, currencyTo) => {
|
|
10375
10407
|
setCalcState({ inputSell: formatValue(value), selectBuy: currencyTo });
|
|
10376
|
-
const rate = currencyRatesSell.find((_) => _.currency?.currency === currencyTo)?.
|
|
10408
|
+
const rate = currencyRatesSell.find((_) => _.currency?.currency === currencyTo)?.saleExchangeRate ||
|
|
10377
10409
|
currencyRatesSell.find((_) => _.currency?.currency === currencyFrom)?.buyExchangeRate;
|
|
10378
10410
|
if (rate) {
|
|
10379
10411
|
setCalcState({
|
|
@@ -10383,7 +10415,7 @@
|
|
|
10383
10415
|
};
|
|
10384
10416
|
const handleInputBuy = (setCalcState, currencyRatesBuy) => (value, currencyTo, currencyFrom) => {
|
|
10385
10417
|
setCalcState({ inputBuy: formatValue(value), selectSell: currencyFrom });
|
|
10386
|
-
const rate = currencyRatesBuy.find((_) => _.currency?.currency === currencyFrom)?.
|
|
10418
|
+
const rate = currencyRatesBuy.find((_) => _.currency?.currency === currencyFrom)?.buyExchangeRate ||
|
|
10387
10419
|
currencyRatesBuy.find((_) => _.currency?.currency === currencyTo)?.saleExchangeRate;
|
|
10388
10420
|
if (rate) {
|
|
10389
10421
|
setCalcState({
|
|
@@ -11752,7 +11784,7 @@
|
|
|
11752
11784
|
slots: () => [HEADER_SLOT, FOOTER_SLOT, STICKY_FOOTER_SLOT],
|
|
11753
11785
|
});
|
|
11754
11786
|
|
|
11755
|
-
const packageVersion = "0.14.
|
|
11787
|
+
const packageVersion = "0.14.912";
|
|
11756
11788
|
|
|
11757
11789
|
exports.Blocks = Blocks;
|
|
11758
11790
|
exports.ContentPage = ContentPage;
|