@redneckz/wildless-cms-uni-blocks 0.14.246 → 0.14.248
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/blocks.schema.json +1 -1
- package/bundle/bundle.umd.js +1197 -1159
- package/bundle/bundle.umd.min.js +1 -1
- package/bundle/components/BankAccountFiltration/BankAccountFiltration.d.ts +6 -0
- package/bundle/components/BankAccountFiltration/BankAccountFiltrationContent.d.ts +21 -0
- package/bundle/components/Carousel/Carousel.d.ts +2 -1
- package/bundle/components/CarouselLinks/CarouselLinks.d.ts +2 -1
- package/bundle/ui-kit/BaseFiltration/BaseFiltrationContent.d.ts +4 -0
- package/{lib/ui-kit/BaseFiltration/renderFiltrationForm.d.ts → bundle/ui-kit/BaseFiltration/FiltrationForm.d.ts} +4 -6
- package/dist/components/BankAccountFiltration/BankAccountFiltration.d.ts +6 -0
- package/dist/components/BankAccountFiltration/BankAccountFiltration.js +50 -0
- package/dist/components/BankAccountFiltration/BankAccountFiltration.js.map +1 -0
- package/dist/components/BankAccountFiltration/BankAccountFiltrationContent.d.ts +21 -0
- package/dist/components/BankAccountFiltration/BankAccountFiltrationContent.js +2 -0
- package/dist/components/BankAccountFiltration/BankAccountFiltrationContent.js.map +1 -0
- package/dist/components/Blocks.js +2 -0
- package/dist/components/Blocks.js.map +1 -1
- package/dist/components/Carousel/Carousel.d.ts +2 -1
- package/dist/components/CarouselLinks/CarouselLinks.d.ts +2 -1
- package/dist/components/DepositFiltration/DepositFiltration.js +5 -6
- package/dist/components/DepositFiltration/DepositFiltration.js.map +1 -1
- package/dist/components/MortgageFiltration/MortgageFiltration.js +2 -2
- package/dist/components/MortgageFiltration/MortgageFiltration.js.map +1 -1
- package/dist/ui-kit/BaseFiltration/BaseFiltrationContent.d.ts +4 -0
- package/{bundle/ui-kit/BaseFiltration/renderFiltrationForm.d.ts → dist/ui-kit/BaseFiltration/FiltrationForm.d.ts} +4 -7
- package/dist/ui-kit/BaseFiltration/FiltrationForm.js +28 -0
- package/dist/ui-kit/BaseFiltration/FiltrationForm.js.map +1 -0
- package/lib/common.css +1 -1
- package/lib/components/BankAccountFiltration/BankAccountFiltration.d.ts +6 -0
- package/lib/components/BankAccountFiltration/BankAccountFiltration.fixture.d.ts +6 -0
- package/lib/components/BankAccountFiltration/BankAccountFiltration.js +48 -0
- package/lib/components/BankAccountFiltration/BankAccountFiltration.js.map +1 -0
- package/lib/components/BankAccountFiltration/BankAccountFiltrationContent.d.ts +21 -0
- package/lib/components/BankAccountFiltration/BankAccountFiltrationContent.js +2 -0
- package/lib/components/BankAccountFiltration/BankAccountFiltrationContent.js.map +1 -0
- package/lib/components/Blocks.js +2 -0
- package/lib/components/Blocks.js.map +1 -1
- package/lib/components/Carousel/Carousel.d.ts +2 -1
- package/lib/components/CarouselLinks/CarouselLinks.d.ts +2 -1
- package/lib/components/DepositFiltration/DepositFiltration.js +5 -6
- package/lib/components/DepositFiltration/DepositFiltration.js.map +1 -1
- package/lib/components/MortgageFiltration/MortgageFiltration.js +2 -2
- package/lib/components/MortgageFiltration/MortgageFiltration.js.map +1 -1
- package/lib/ui-kit/BaseFiltration/BaseFiltrationContent.d.ts +4 -0
- package/{dist/ui-kit/BaseFiltration/renderFiltrationForm.d.ts → lib/ui-kit/BaseFiltration/FiltrationForm.d.ts} +4 -7
- package/lib/ui-kit/BaseFiltration/FiltrationForm.js +26 -0
- package/lib/ui-kit/BaseFiltration/FiltrationForm.js.map +1 -0
- package/mobile/bundle/bundle.umd.js +15 -12
- package/mobile/bundle/bundle.umd.min.js +1 -1
- package/mobile/bundle/components/BankAccountFiltration/BankAccountFiltration.d.ts +6 -0
- package/mobile/bundle/components/BankAccountFiltration/BankAccountFiltrationContent.d.ts +21 -0
- package/mobile/bundle/components/Carousel/Carousel.d.ts +2 -1
- package/mobile/bundle/components/CarouselLinks/CarouselLinks.d.ts +2 -1
- package/mobile/bundle/ui-kit/BaseFiltration/BaseFiltrationContent.d.ts +4 -0
- package/mobile/bundle/ui-kit/BaseFiltration/{renderFiltrationForm.d.ts → FiltrationForm.d.ts} +4 -7
- package/mobile/dist/components/BankAccountFiltration/BankAccountFiltration.d.ts +6 -0
- package/mobile/dist/components/BankAccountFiltration/BankAccountFiltration.js +50 -0
- package/mobile/dist/components/BankAccountFiltration/BankAccountFiltration.js.map +1 -0
- package/mobile/dist/components/BankAccountFiltration/BankAccountFiltrationContent.d.ts +21 -0
- package/mobile/dist/components/BankAccountFiltration/BankAccountFiltrationContent.js +2 -0
- package/mobile/dist/components/BankAccountFiltration/BankAccountFiltrationContent.js.map +1 -0
- package/mobile/dist/components/Carousel/Carousel.d.ts +2 -1
- package/mobile/dist/components/CarouselLinks/CarouselLinks.d.ts +2 -1
- package/mobile/dist/components/DepositFiltration/DepositFiltration.js +5 -6
- package/mobile/dist/components/DepositFiltration/DepositFiltration.js.map +1 -1
- package/mobile/dist/components/MortgageFiltration/MortgageFiltration.js +2 -2
- package/mobile/dist/components/MortgageFiltration/MortgageFiltration.js.map +1 -1
- package/mobile/dist/ui-kit/BaseFiltration/BaseFiltrationContent.d.ts +4 -0
- package/mobile/dist/ui-kit/BaseFiltration/FiltrationForm.d.ts +12 -0
- package/mobile/dist/ui-kit/BaseFiltration/FiltrationForm.js +28 -0
- package/mobile/dist/ui-kit/BaseFiltration/FiltrationForm.js.map +1 -0
- package/mobile/lib/common.css +1 -1
- package/mobile/lib/components/BankAccountFiltration/BankAccountFiltration.d.ts +6 -0
- package/mobile/lib/components/BankAccountFiltration/BankAccountFiltration.js +48 -0
- package/mobile/lib/components/BankAccountFiltration/BankAccountFiltration.js.map +1 -0
- package/mobile/lib/components/BankAccountFiltration/BankAccountFiltrationContent.d.ts +21 -0
- package/mobile/lib/components/BankAccountFiltration/BankAccountFiltrationContent.js +2 -0
- package/mobile/lib/components/BankAccountFiltration/BankAccountFiltrationContent.js.map +1 -0
- package/mobile/lib/components/Carousel/Carousel.d.ts +2 -1
- package/mobile/lib/components/CarouselLinks/CarouselLinks.d.ts +2 -1
- package/mobile/lib/components/DepositFiltration/DepositFiltration.js +5 -6
- package/mobile/lib/components/DepositFiltration/DepositFiltration.js.map +1 -1
- package/mobile/lib/components/MortgageFiltration/MortgageFiltration.js +2 -2
- package/mobile/lib/components/MortgageFiltration/MortgageFiltration.js.map +1 -1
- package/mobile/lib/ui-kit/BaseFiltration/BaseFiltrationContent.d.ts +4 -0
- package/mobile/lib/ui-kit/BaseFiltration/FiltrationForm.d.ts +12 -0
- package/mobile/lib/ui-kit/BaseFiltration/FiltrationForm.js +26 -0
- package/mobile/lib/ui-kit/BaseFiltration/FiltrationForm.js.map +1 -0
- package/mobile/src/components/BankAccountFiltration/BankAccountFiltration.example.json +64 -0
- package/mobile/src/components/BankAccountFiltration/BankAccountFiltration.tsx +109 -0
- package/mobile/src/components/BankAccountFiltration/BankAccountFiltration.ui.json +1 -0
- package/mobile/src/components/BankAccountFiltration/BankAccountFiltrationContent.ts +27 -0
- package/mobile/src/components/Carousel/Carousel.tsx +1 -1
- package/mobile/src/components/CarouselLinks/CarouselLinks.tsx +1 -1
- package/mobile/src/components/DepositFiltration/DepositFiltration.tsx +25 -22
- package/mobile/src/components/MortgageFiltration/MortgageFiltration.tsx +7 -2
- package/mobile/src/ui-kit/BaseFiltration/BaseFiltrationContent.ts +4 -0
- package/mobile/src/ui-kit/BaseFiltration/{renderFiltrationForm.tsx → FiltrationForm.tsx} +31 -26
- package/package.json +1 -1
- package/src/components/BankAccountFiltration/BankAccountFiltration.example.json +64 -0
- package/src/components/BankAccountFiltration/BankAccountFiltration.fixture.tsx +141 -0
- package/src/components/BankAccountFiltration/BankAccountFiltration.tsx +109 -0
- package/src/components/BankAccountFiltration/BankAccountFiltration.ui.json +1 -0
- package/src/components/BankAccountFiltration/BankAccountFiltrationContent.ts +27 -0
- package/src/components/Blocks.ts +2 -0
- package/src/components/Carousel/Carousel.tsx +1 -1
- package/src/components/CarouselLinks/CarouselLinks.tsx +1 -1
- package/src/components/DepositFiltration/DepositFiltration.tsx +25 -22
- package/src/components/MortgageFiltration/MortgageFiltration.tsx +7 -2
- package/src/ui-kit/BaseFiltration/BaseFiltrationContent.ts +4 -0
- package/src/ui-kit/BaseFiltration/{renderFiltrationForm.tsx → FiltrationForm.tsx} +31 -26
- package/dist/ui-kit/BaseFiltration/renderFiltrationForm.js +0 -23
- package/dist/ui-kit/BaseFiltration/renderFiltrationForm.js.map +0 -1
- package/lib/ui-kit/BaseFiltration/renderFiltrationForm.js +0 -20
- package/lib/ui-kit/BaseFiltration/renderFiltrationForm.js.map +0 -1
- package/mobile/dist/ui-kit/BaseFiltration/renderFiltrationForm.d.ts +0 -15
- package/mobile/dist/ui-kit/BaseFiltration/renderFiltrationForm.js +0 -23
- package/mobile/dist/ui-kit/BaseFiltration/renderFiltrationForm.js.map +0 -1
- package/mobile/lib/ui-kit/BaseFiltration/renderFiltrationForm.d.ts +0 -15
- package/mobile/lib/ui-kit/BaseFiltration/renderFiltrationForm.js +0 -20
- package/mobile/lib/ui-kit/BaseFiltration/renderFiltrationForm.js.map +0 -1
package/bundle/bundle.umd.js
CHANGED
|
@@ -1849,60 +1849,109 @@
|
|
|
1849
1849
|
.filter((input) => !input?.condition ||
|
|
1850
1850
|
input?.condition.values.find((_) => _ === data?.[input?.condition?.name]));
|
|
1851
1851
|
|
|
1852
|
-
|
|
1853
|
-
const AlignStyles = 'text-center';
|
|
1852
|
+
const joinList = (sep) => (list) => list.reduce((acc, el, i) => (acc.length ? acc.concat({ ...sep, key: `sep-${i}` }, el) : [el]), []);
|
|
1854
1853
|
|
|
1855
|
-
const
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
}
|
|
1854
|
+
const SlideCheckboxGroup = JSX(({ value, onChange, items = [], multiple }) => {
|
|
1855
|
+
const handleChange = (newValue) => {
|
|
1856
|
+
if (!onChange) {
|
|
1857
|
+
return;
|
|
1858
|
+
}
|
|
1859
|
+
const hasAlready = value?.includes(newValue);
|
|
1860
|
+
if (multiple) {
|
|
1861
|
+
onChange(hasAlready ? (value || []).filter((v) => v !== newValue) : [...(value || []), newValue]);
|
|
1862
|
+
}
|
|
1863
|
+
else {
|
|
1864
|
+
onChange(hasAlready ? [] : [newValue]);
|
|
1865
|
+
}
|
|
1866
|
+
};
|
|
1867
|
+
return items.map((item) => (jsx(SlideCheckbox, { text: item?.title, value: [value].flatMap((_) => _).includes(item.value), onChange: () => handleChange(item.value), type: multiple ? 'checkbox' : 'radio' }, item.value)));
|
|
1867
1868
|
});
|
|
1868
1869
|
|
|
1869
|
-
const
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1870
|
+
const FiltrationForm = JSX(({ children, filtrationSchema, resetButton, field, reset }) => (jsxs("form", { className: "flex flex-col @4xl:flex-row justify-between bg-white p-4xl gap-s @4xl:gap-0", children: [jsxs("div", { className: "flex flex-col @4xl:flex-row gap-xl", children: [children, joinList(jsx("div", { className: "h-full w-px bg-gray" }))(
|
|
1871
|
+
// TS can't correctly refine array's type after filter
|
|
1872
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1873
|
+
Object.entries(filtrationSchema).map(renderFormItem(field)).filter(Boolean))] }), resetButton ? (jsx("div", { children: jsx(Button, { type: "reset", className: "w-full @4xl:w-56 @4xl:ml-s", onClick: reset, children: resetButton?.text }) })) : null] })));
|
|
1874
|
+
const renderFormItem = (field) => ([key, item]) => {
|
|
1875
|
+
const type = item?.type;
|
|
1876
|
+
switch (type) {
|
|
1877
|
+
case 'array':
|
|
1878
|
+
return renderArrayFormItem(key, field)(item);
|
|
1879
|
+
default:
|
|
1880
|
+
return null;
|
|
1881
|
+
}
|
|
1882
|
+
};
|
|
1883
|
+
const renderArrayFormItem = (key, field) => (item) => item?.ui !== 'dropdown' ? renderCheckboxes(key, field)(item) : null;
|
|
1884
|
+
const renderCheckboxes = (key, field) => (item) => {
|
|
1885
|
+
const options = item?.items?.enum?.map((e, i) => ({ value: e, title: item?.items?.enumNames?.[i] || '' })) ||
|
|
1886
|
+
[];
|
|
1887
|
+
return (jsxs("div", { className: "flex-1", children: [item?.title ? (jsx("div", { className: "mb-m", children: jsx(Text, { size: "text-m", font: "font-medium", color: "text-primary-text", children: item.title }) })) : null, jsx(SlideCheckboxGroup, { items: options, multiple: !item?.single, ...field(key) })] }, key));
|
|
1888
|
+
};
|
|
1873
1889
|
|
|
1874
|
-
|
|
1890
|
+
function zip(firstCol, ...restCols) {
|
|
1891
|
+
return firstCol.map((firstEl, rowIndex) => [firstEl, ...restCols.map((col) => col[rowIndex])]);
|
|
1892
|
+
}
|
|
1875
1893
|
|
|
1876
|
-
const
|
|
1894
|
+
const isEmpty = (v) => v === null ||
|
|
1895
|
+
v === undefined ||
|
|
1896
|
+
v === '' ||
|
|
1897
|
+
(Array.isArray(v) && v.length === 0) ||
|
|
1898
|
+
(typeof v === 'object' && Object.keys(v).length === 0);
|
|
1877
1899
|
|
|
1878
|
-
const
|
|
1879
|
-
const
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1900
|
+
const isSingularFieldMatch = (key, pattern) => (target) => isEmpty(pattern[key]) || isEmpty(target[key]) || pattern[key] === target[key];
|
|
1901
|
+
const isMultipleFieldMatch = (key, pattern) => (target) => isEmpty(pattern[key]) ||
|
|
1902
|
+
isEmpty(target[key]) ||
|
|
1903
|
+
pattern[key]?.every((_) => target[key]?.includes(_));
|
|
1904
|
+
const isNumberFieldMatch = (key, pattern) => (target) => isEmpty(pattern[key]) ||
|
|
1905
|
+
isEmpty(target[key]) ||
|
|
1906
|
+
naturalNumber(pattern[key]) <= naturalNumber(target[key]);
|
|
1907
|
+
const isMultipleNumberFieldMatch = (key, pattern) => (target) => isEmpty(pattern[key]) || isEmpty(target[key]) || target[key]?.includes(pattern[key]);
|
|
1908
|
+
const isValueInRange = (key, pattern) => (target) => isEmpty(pattern[key]) ||
|
|
1909
|
+
isEmpty(target[key]) ||
|
|
1910
|
+
(naturalNumber(pattern[key]?.min) >= naturalNumber(target[key]?.min) &&
|
|
1911
|
+
naturalNumber(pattern[key]?.min) <= naturalNumber(target[key]?.max));
|
|
1912
|
+
const targetMatchPattern = (pattern, target) => Object.entries(pattern)
|
|
1913
|
+
.map(([key, subPattern]) => {
|
|
1914
|
+
if (typeof subPattern === 'number') {
|
|
1915
|
+
return Array.isArray(target[key])
|
|
1916
|
+
? isMultipleNumberFieldMatch(key, pattern)
|
|
1917
|
+
: isNumberFieldMatch(key, pattern);
|
|
1889
1918
|
}
|
|
1890
|
-
|
|
1919
|
+
if (typeof subPattern === 'object' && 'min' in subPattern && 'max' in subPattern) {
|
|
1920
|
+
return isValueInRange(key, pattern);
|
|
1921
|
+
}
|
|
1922
|
+
return Array.isArray(subPattern)
|
|
1923
|
+
? isMultipleFieldMatch(key, pattern)
|
|
1924
|
+
: isSingularFieldMatch(key, pattern);
|
|
1925
|
+
})
|
|
1926
|
+
.every((predicate) => predicate(target));
|
|
1927
|
+
const naturalNumber = (n) => Number(n || 0);
|
|
1891
1928
|
|
|
1892
|
-
const
|
|
1893
|
-
|
|
1894
|
-
|
|
1929
|
+
const filterBlocks = (blocksWithProps, filtrationState) => (normalize = identity) => blocksWithProps
|
|
1930
|
+
?.filter(([, content]) => targetMatchPattern(filtrationState, normalize(content) || {}))
|
|
1931
|
+
.map(([block]) => block);
|
|
1895
1932
|
|
|
1896
|
-
const
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1933
|
+
const useFiltrationForm = (initialFormState, { block, page, normalize = identity, }) => {
|
|
1934
|
+
const blocks = block?.blocks || [];
|
|
1935
|
+
const [filtrationState, { field, reset, update: replaceFiltrationState }] = useForm(initialFormState);
|
|
1936
|
+
const blocksWithProps = useMemo(() => zip(blocks, blocks.map((b) => resolveBlockProps(b.content, page?.fallback))), [blocks, page?.fallback]);
|
|
1937
|
+
const blocksToRender = filtrationState === initialFormState
|
|
1938
|
+
? blocks
|
|
1939
|
+
: filterBlocks(blocksWithProps, filtrationState)(normalize);
|
|
1940
|
+
return [
|
|
1941
|
+
filtrationState,
|
|
1942
|
+
{ blocksToRender, blocksWithProps },
|
|
1943
|
+
{ field, reset, update: replaceFiltrationState },
|
|
1944
|
+
];
|
|
1900
1945
|
};
|
|
1901
1946
|
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
});
|
|
1947
|
+
/** @deprecated */
|
|
1948
|
+
const AlignStyles = 'text-center';
|
|
1949
|
+
|
|
1950
|
+
const NotFound = JSX(({ title, description }) => (jsxs("div", { className: "bg-white p-6xl py-20 flex gap-s flex-col @xl:items-center", children: [jsx(Img, { image: { icon: 'MagnifierIcon', iconVersion: 'normal' }, width: "120", height: "120" }), jsx(Headline, { title: title, description: description, headlineVersion: "S", isEmbedded: true, align: AlignStyles })] })));
|
|
1951
|
+
|
|
1952
|
+
const getBorderStyle = (showBorder = false) => showBorder
|
|
1953
|
+
? 'border border-solid border-gray group-data-secondary:border-white/50 group-data-gray:border-main-divider'
|
|
1954
|
+
: '';
|
|
1906
1955
|
|
|
1907
1956
|
const useCarouselControls = (props, initialIndex = 0) => {
|
|
1908
1957
|
const { itemCount, visibleItemCount } = props;
|
|
@@ -1926,211 +1975,119 @@
|
|
|
1926
1975
|
];
|
|
1927
1976
|
};
|
|
1928
1977
|
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
: 'bg-white text-primary-text hover:text-primary-main', className || ''), disabled: disabled, ...rest, children: jsx(Img, { className: "w-4 h-4 min-w-4 min-h-4 rounded-full box-border", image: { icon: 'ArrowLeftIcon', iconVersion: 'black' }, imageClassName: "group-hover/btn:text-primary-main", width: "16", height: "16" }) })));
|
|
1933
|
-
/** @deprecated */
|
|
1934
|
-
const ScrollLeftButton = JSX((props) => (jsx(ArrowButton, { ...props, ariaLabel: "\u041F\u0440\u043E\u043B\u0438\u0441\u0442\u0430\u0442\u044C \u0432\u043B\u0435\u0432\u043E", "data-block-control": "scroll-left" })));
|
|
1935
|
-
/** @deprecated */
|
|
1936
|
-
const ScrollRightButton = JSX((props) => (jsx(ArrowButton, { ...props, className: `${props.className || ''} rotate-180`, ariaLabel: "\u041F\u0440\u043E\u043B\u0438\u0441\u0442\u0430\u0442\u044C \u0432\u043F\u0440\u0430\u0432\u043E", "data-block-control": "scroll-right" })));
|
|
1937
|
-
|
|
1938
|
-
/** @deprecated */
|
|
1939
|
-
function renderArrows({ dec, inc, canDec, canInc, btnClass, className = '', }) {
|
|
1940
|
-
const isVisible = canDec || canInc;
|
|
1941
|
-
if (!isVisible) {
|
|
1942
|
-
return null;
|
|
1978
|
+
const mapChildren = (mapper) => (children) => {
|
|
1979
|
+
if (children === null || children === undefined) {
|
|
1980
|
+
return children;
|
|
1943
1981
|
}
|
|
1944
|
-
return (
|
|
1945
|
-
}
|
|
1946
|
-
|
|
1947
|
-
const calculatorValueBlockStyle = 'flex justify-between @xl:flex-col';
|
|
1948
|
-
const CalculatorValueBlock = JSX(({ className, title, value, fractionDigits, fixed, prefix, postfix }) => (jsxs("div", { className: style(calculatorValueBlockStyle, className), children: [title ? (jsx(Text, { size: "text-l", font: "font-light", color: "text-secondary-text", children: title })) : null, value ? (jsx("div", { children: jsx(Text, { size: "text-h3", children: [prefix, toLocalNumberFormat(fractionDigits, { fixed })(value), postfix]
|
|
1949
|
-
.filter(Boolean)
|
|
1950
|
-
.join(' ') }) })) : (jsx("div", { children: jsx(Text, { size: "text-h3", children: "-" }) }))] })));
|
|
1951
|
-
|
|
1952
|
-
const DEFAULT_MIN_SUM$1 = 10000;
|
|
1953
|
-
const DEFAULT_MAX_SUM$1 = 5000000;
|
|
1954
|
-
const CREDIT_DEFAULT_SUM = 200000;
|
|
1955
|
-
const REFINANCING_DEFAULT_SUM = 700000;
|
|
1956
|
-
const REFINANCING_DEFAULT_MAX_SUM = 3000000;
|
|
1957
|
-
const REFINANCING_OLD_MIN_SUM = 0;
|
|
1958
|
-
const REFINANCING_OLD_DEFAULT_SUM = 0;
|
|
1959
|
-
const REFINANCING_OLD_MAX_SUM = 2500000;
|
|
1960
|
-
const REFINANCING_EXTRA_MIN_SUM = 0;
|
|
1961
|
-
const REFINANCING_EXTRA_MAX_SUM = 500000;
|
|
1962
|
-
const DEPOSIT_DEFAULT_SUM = 20000;
|
|
1963
|
-
const DEFAULT_MIN_MONTHS = 1;
|
|
1964
|
-
const DEFAULT_REFINANCING_MIN_MONTHS = 13;
|
|
1965
|
-
const DEFAULT_REFINANCING_MONTHS = 48;
|
|
1966
|
-
const DEFAULT_MAX_MONTHS = 60;
|
|
1967
|
-
const DEFAULT_MONTHS = Math.round((DEFAULT_MAX_MONTHS - DEFAULT_MIN_MONTHS) / 2);
|
|
1968
|
-
const BUSINESS_DEFAULT_SUM = 100000;
|
|
1969
|
-
const BUSINESS_MIN_DAYS = 1;
|
|
1970
|
-
const BUSINESS_MAX_DAYS = 1095;
|
|
1971
|
-
const BUSINESS_RATE_MIN_DAYS = 30; // порог количества дней, при которых ставка не доступна
|
|
1972
|
-
const BUSINESS_OPERATING_MIN_DAYS = 90;
|
|
1973
|
-
const BUSINESS_OPERATING_MAX_DAYS = 730;
|
|
1974
|
-
const BUSINESS_DEFAULT_DAYS = 60;
|
|
1975
|
-
const MONTHS_IN_YEAR = 12;
|
|
1976
|
-
const MONTHLY_INTEREST_RATE = MONTHS_IN_YEAR * 100;
|
|
1977
|
-
const DEFAULT_CREDIT_CALCULATOR_PARAMS = {
|
|
1978
|
-
minSum: DEFAULT_MIN_SUM$1,
|
|
1979
|
-
maxSum: DEFAULT_MAX_SUM$1,
|
|
1980
|
-
minMonths: DEFAULT_MIN_MONTHS,
|
|
1981
|
-
maxMonths: DEFAULT_MAX_MONTHS,
|
|
1982
|
-
rate: 0,
|
|
1983
|
-
isSalaryClient: false,
|
|
1984
|
-
isPensionClient: false,
|
|
1985
|
-
isStateEmployee: false,
|
|
1986
|
-
isInsurance: true,
|
|
1987
|
-
};
|
|
1988
|
-
const DEFAULT_REFINANCING_CALCULATOR_PARAMS = {
|
|
1989
|
-
minSum: DEFAULT_MIN_SUM$1,
|
|
1990
|
-
maxSum: REFINANCING_DEFAULT_MAX_SUM,
|
|
1991
|
-
minSumOld: REFINANCING_OLD_MIN_SUM,
|
|
1992
|
-
maxSumOld: REFINANCING_OLD_MAX_SUM,
|
|
1993
|
-
minSumExtra: REFINANCING_EXTRA_MIN_SUM,
|
|
1994
|
-
maxSumExtra: REFINANCING_EXTRA_MAX_SUM,
|
|
1995
|
-
minMonths: DEFAULT_REFINANCING_MIN_MONTHS,
|
|
1996
|
-
maxMonths: DEFAULT_MAX_MONTHS,
|
|
1997
|
-
rate: 0,
|
|
1998
|
-
isExtraMoney: false,
|
|
1999
|
-
isSalaryClient: false,
|
|
2000
|
-
isInsurance: true,
|
|
2001
|
-
};
|
|
2002
|
-
const DEFAULT_TRAVEL_MIN_SUM = 6000;
|
|
2003
|
-
const DEFAULT_REST_MIN_SUM = 6000;
|
|
2004
|
-
const DEFAULT_BONUS_CALCULATOR_PARAMS = {
|
|
2005
|
-
minSumTravel: 6000,
|
|
2006
|
-
maxSumTravel: 200000,
|
|
2007
|
-
minSumOther: 6000,
|
|
2008
|
-
maxSumOther: 200000,
|
|
2009
|
-
maxBonus: 5000,
|
|
2010
|
-
prefMonthsNum: 2,
|
|
2011
|
-
prefTravelBonusRate: 0.015,
|
|
2012
|
-
prefRestBonusRate: 0.01,
|
|
2013
|
-
travelBonusRate: 0.015,
|
|
2014
|
-
restBonusRate: 0.01,
|
|
2015
|
-
};
|
|
2016
|
-
const DEFAULT_DEPOSIT_CALCULATOR_PARAMS = {
|
|
2017
|
-
minSum: 50000,
|
|
2018
|
-
maxSum: 100000001,
|
|
2019
|
-
minMonths: 2,
|
|
2020
|
-
maxMonths: 10,
|
|
2021
|
-
rate: 0,
|
|
2022
|
-
isMonthlyInterestPayment: true,
|
|
2023
|
-
isRemoteRegistration: true,
|
|
2024
|
-
};
|
|
2025
|
-
const DEFAULT_BUSINESS_DEPOSIT_CALCULATOR_PARAMS = {
|
|
2026
|
-
minSum: 1000,
|
|
2027
|
-
maxSum: 100000001,
|
|
2028
|
-
minDays: BUSINESS_MIN_DAYS,
|
|
2029
|
-
maxDays: BUSINESS_MAX_DAYS,
|
|
2030
|
-
rate: 0,
|
|
2031
|
-
isMonthlyInterestPayment: true,
|
|
2032
|
-
isReplenished: false,
|
|
2033
|
-
isPartialWithdrawal: false,
|
|
2034
|
-
depositeName: "Депозит 'Стабильный'",
|
|
1982
|
+
return Array.isArray(children) ? children.map(mapper) : mapper(children, 0);
|
|
2035
1983
|
};
|
|
2036
1984
|
|
|
2037
|
-
const
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
1985
|
+
const HEADER_HEIGHT = 170;
|
|
1986
|
+
const FOOTER_HEIGHT = 48;
|
|
1987
|
+
const BLOCKS_GAP = 4;
|
|
1988
|
+
const PAGE_PADDINGS_X = 20;
|
|
1989
|
+
const DEFAULT_HEIGHT = 866;
|
|
1990
|
+
const getContainerHeight = (minHeight) => ({
|
|
1991
|
+
height: `calc(100vh - ${HEADER_HEIGHT + FOOTER_HEIGHT + BLOCKS_GAP + PAGE_PADDINGS_X}px)`,
|
|
1992
|
+
minHeight: `${minHeight || DEFAULT_HEIGHT}px`,
|
|
1993
|
+
});
|
|
2045
1994
|
|
|
2046
|
-
const
|
|
2047
|
-
|
|
2048
|
-
const
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
`От ${toLocalNumberFormat(2)(rest.min || 0)} ₽`,
|
|
2069
|
-
`До ${toLocalNumberFormat(2)(rest.max || 0)} ₽`,
|
|
2070
|
-
];
|
|
2071
|
-
return jsx(InputRange, { items: isShowItems ? items : [], step: step, ...rest });
|
|
1995
|
+
const SENSITIVITY_SCALE = 10;
|
|
1996
|
+
function useIntersectionObserver(observerCallback, { sensitivity, rootRef } = {}) {
|
|
1997
|
+
const ref = useRef(null);
|
|
1998
|
+
const observerOptions = useMemo(() => ({ threshold: sensitivityToThreshold(sensitivity), root: rootRef?.current }), [sensitivity, rootRef?.current]);
|
|
1999
|
+
useEffect(() => {
|
|
2000
|
+
if (!ref.current) {
|
|
2001
|
+
return undefined;
|
|
2002
|
+
}
|
|
2003
|
+
const intersectionObserver = new IntersectionObserver(observerCallback, observerOptions);
|
|
2004
|
+
intersectionObserver.observe(ref.current);
|
|
2005
|
+
return () => {
|
|
2006
|
+
intersectionObserver.disconnect();
|
|
2007
|
+
};
|
|
2008
|
+
}, [observerCallback, observerOptions]);
|
|
2009
|
+
return ref;
|
|
2010
|
+
}
|
|
2011
|
+
function sensitivityToThreshold(sensitivity = 0) {
|
|
2012
|
+
const thresholdsCount = Math.round(sensitivity * SENSITIVITY_SCALE);
|
|
2013
|
+
return Array.from({ length: thresholdsCount })
|
|
2014
|
+
.fill(0)
|
|
2015
|
+
.map((_, thi) => Math.min(thi / thresholdsCount), 1)
|
|
2016
|
+
.concat(1);
|
|
2072
2017
|
}
|
|
2073
2018
|
|
|
2074
|
-
const
|
|
2075
|
-
const
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
min: minSumTravel,
|
|
2083
|
-
max: maxSumTravel,
|
|
2084
|
-
step: 500,
|
|
2085
|
-
isShowItems: false,
|
|
2086
|
-
...field('travelExpenseValue'),
|
|
2087
|
-
}), renderWantedSumInput({
|
|
2088
|
-
title: 'Сумма покупок в остальных категориях, ₽',
|
|
2089
|
-
min: minSumOther,
|
|
2090
|
-
max: maxSumOther,
|
|
2091
|
-
step: 500,
|
|
2092
|
-
isShowItems: false,
|
|
2093
|
-
...field('restExpenseValue'),
|
|
2094
|
-
})] }), monthBonus >= 0
|
|
2095
|
-
? renderRate({
|
|
2096
|
-
title: 'Баллов за месяц',
|
|
2097
|
-
rate: monthBonus,
|
|
2098
|
-
fractionDigits: 0,
|
|
2099
|
-
isUnknownRateShown: false,
|
|
2100
|
-
unit: '',
|
|
2101
|
-
})
|
|
2102
|
-
: null, jsxs("div", { className: "flex flex-col gap-y-xl @xl:w-96", children: [yearBonus >= 0 ? jsx(CalculatorValueBlock, { title: "\u0411\u0430\u043B\u043B\u043E\u0432 \u0437\u0430 \u0433\u043E\u0434", value: yearBonus }) : null, renderButtonsSection(buttons, { isVertical: true }), renderFootnote(footnote)] })] }));
|
|
2019
|
+
const SwipeListItem = JSX(({ className, style: inlineStyle, idx, activeIndex, observerOptions, children, onIntersection, }) => {
|
|
2020
|
+
const observerCallback = useCallback((entries) => {
|
|
2021
|
+
if (entries.length && onIntersection) {
|
|
2022
|
+
onIntersection(idx || 0, entries[entries.length - 1]);
|
|
2023
|
+
}
|
|
2024
|
+
}, [onIntersection, idx]);
|
|
2025
|
+
const ref = useIntersectionObserver(observerCallback, observerOptions);
|
|
2026
|
+
return (jsx("div", { className: style('inline-block snap-always box-border', className), style: inlineStyle, "aria-current": Boolean(idx === activeIndex), ref: ref, role: "listitem", children: children }));
|
|
2103
2027
|
});
|
|
2104
2028
|
|
|
2105
|
-
const
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2029
|
+
const childStyleMap = ['min-w-full', '@lg:min-w-[50%]', '@lg:min-w-[33.3%]', '@lg:min-w-[25%]'];
|
|
2030
|
+
const SwipeListContainer = JSX(({ className, itemClassName, containerRef, activeIndex, visibleItemCount = 0, gap = 0, padding = 0, listType = 'horizontal-list', snapAlign = 'snap-center', minHeight, children, onVisibleItemsChange, onVisibleIndicesChange, }) => {
|
|
2031
|
+
const observerOptions = {
|
|
2032
|
+
sensitivity: 1,
|
|
2033
|
+
rootRef: containerRef,
|
|
2034
|
+
};
|
|
2035
|
+
const itemsVisibilityListRef = useRef([]);
|
|
2036
|
+
const handleIntersection = useCallback((idx, entry) => {
|
|
2037
|
+
const itemsVisibilityList = [...(itemsVisibilityListRef.current || [])];
|
|
2038
|
+
itemsVisibilityList[idx] = entry;
|
|
2039
|
+
itemsVisibilityListRef.current = itemsVisibilityList;
|
|
2040
|
+
onVisibleItemsChange && onVisibleItemsChange(itemsVisibilityList);
|
|
2041
|
+
onVisibleIndicesChange && onVisibleIndicesChange(getVisibleIndices(itemsVisibilityList));
|
|
2042
|
+
}, [onVisibleItemsChange, onVisibleIndicesChange]);
|
|
2043
|
+
const additionPadding = visibleItemCount > 0 ? gap * Number(visibleItemCount) - 1 : 0;
|
|
2044
|
+
const isVerticalList = listType === 'vertical-list';
|
|
2045
|
+
const isHorizontalList = listType === 'horizontal-list';
|
|
2046
|
+
const containerStyle = {
|
|
2047
|
+
...(isHorizontalList ? getContainerOffset(padding, additionPadding) : {}),
|
|
2048
|
+
...(isVerticalList ? getContainerHeight(minHeight) : {}),
|
|
2049
|
+
gap: `${gap}px`,
|
|
2050
|
+
};
|
|
2051
|
+
return (jsx("div", { className: style('box-border overflow-auto no-scrollbar', listType, className), style: containerStyle, ref: containerRef, role: "list", children: mapChildren((child, idx) => (jsx(SwipeListItem, { className: style(snapAlign, visibleItemCount ? childStyleMap[visibleItemCount - 1] : '', isVerticalList ? 'h-full' : '', itemClassName), style: isHorizontalList ? getContainerOffset(padding / 4) : {}, activeIndex: activeIndex, idx: idx, observerOptions: observerOptions, onIntersection: handleIntersection, children: child }, String(idx))))(children) }));
|
|
2052
|
+
});
|
|
2053
|
+
// Styles used to compensate outer container padding to get rid of clipping effect
|
|
2054
|
+
const getContainerOffset = (padding, additionalPadding = 0) => ({
|
|
2055
|
+
marginLeft: `${-padding}px`,
|
|
2056
|
+
marginRight: `${-padding}px`,
|
|
2057
|
+
paddingLeft: `${padding}px`,
|
|
2058
|
+
paddingRight: `${padding + additionalPadding}px`,
|
|
2059
|
+
});
|
|
2060
|
+
const getVisibleIndices = (itemsVisibilityList) => itemsVisibilityList
|
|
2061
|
+
.map((_, i) => [_, i])
|
|
2062
|
+
.filter(([_]) => _ && _.intersectionRatio >= 0.9)
|
|
2063
|
+
.map(([, i]) => i);
|
|
2117
2064
|
|
|
2118
|
-
const
|
|
2119
|
-
horizontal: '
|
|
2120
|
-
vertical: 'flex-col
|
|
2065
|
+
const containerStyles = {
|
|
2066
|
+
'horizontal-list': 'mx-auto mt-lg w-fit',
|
|
2067
|
+
'vertical-list': 'absolute flex-col justify-center h-full top-0 left-4',
|
|
2121
2068
|
};
|
|
2122
|
-
const
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
const
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2069
|
+
const activeDotStyles = {
|
|
2070
|
+
'horizontal-list': 'w-6',
|
|
2071
|
+
'vertical-list': 'h-6',
|
|
2072
|
+
};
|
|
2073
|
+
const dotStyle = 'cursor-pointer rounded-full transition-width duration-300 bg-primary-main group-data-secondary:bg-white group-data-transparent:bg-white';
|
|
2074
|
+
const inactiveDotStyle = 'w-2 h-2 opacity-30';
|
|
2075
|
+
const SwipeListControlDots = JSX(({ className = '', containerRef, activeIndex, dotCount = 0, listType = 'horizontal-list', version, }) => {
|
|
2076
|
+
const handleClick = (idx) => {
|
|
2077
|
+
if (idx !== activeIndex && containerRef?.current) {
|
|
2078
|
+
containerRef.current.children[idx]?.scrollIntoView({
|
|
2079
|
+
behavior: 'smooth',
|
|
2080
|
+
block: 'nearest',
|
|
2081
|
+
});
|
|
2082
|
+
}
|
|
2083
|
+
};
|
|
2084
|
+
return dotCount ? (jsx("div", { className: style('flex gap-xs', containerStyles[listType], version ? 'group' : '', className), "data-ver": version, children: Array.from({ length: dotCount })
|
|
2085
|
+
.fill(null)
|
|
2086
|
+
.map((_, idx) => (jsx("div", { className: `${dotStyle} ${idx === activeIndex ? activeDotStyles[listType] : inactiveDotStyle}`, role: "button", "aria-hidden": true, onClick: () => handleClick(idx) }, String(idx)))) })) : null;
|
|
2132
2087
|
});
|
|
2133
2088
|
|
|
2089
|
+
const areArraysEqual = (as, bs) => as === bs || Boolean(as && bs && as?.length === bs?.length && as.every((_, i) => _ === bs[i]));
|
|
2090
|
+
|
|
2134
2091
|
const defaultDiscriminator = (_) => _;
|
|
2135
2092
|
const maxBy = (discriminator = defaultDiscriminator) => (list) => list.reduceRight((a, b) => (discriminator(a) > discriminator(b) ? a : b));
|
|
2136
2093
|
const max = maxBy();
|
|
@@ -2138,906 +2095,1080 @@
|
|
|
2138
2095
|
const minBy = (discriminator = defaultDiscriminator) => maxBy((_) => -discriminator(_));
|
|
2139
2096
|
const min = minBy();
|
|
2140
2097
|
|
|
2141
|
-
const
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
[maxKey]: limitParams[maxKey],
|
|
2145
|
-
}
|
|
2146
|
-
: getRangeByKeys([minKey, maxKey], rateRows);
|
|
2147
|
-
const getRangeByKeys = ([minKey, maxKey], rows = []) => ({
|
|
2148
|
-
[minKey]: rows.length
|
|
2149
|
-
? min(rows.filter((row) => typeof row[minKey] === 'number').map((row) => row[minKey]))
|
|
2150
|
-
: 0,
|
|
2151
|
-
[maxKey]: rows.length
|
|
2152
|
-
? max(rows.filter((row) => typeof row[minKey] === 'number').map((row) => row[maxKey]))
|
|
2153
|
-
: 0,
|
|
2154
|
-
});
|
|
2155
|
-
const checkRangeByKeys = (value, [minKey, maxKey], sourceBookRow) => value >= sourceBookRow[minKey] && value <= sourceBookRow[maxKey];
|
|
2156
|
-
|
|
2157
|
-
const DEPOSIT_RATES_SERVICE_MAP = {
|
|
2158
|
-
UL: 'businessdepositrates',
|
|
2159
|
-
IP: 'selfemployeddepositrates',
|
|
2098
|
+
const getItemWidth = (container) => (itemCount) => container.scrollWidth / itemCount;
|
|
2099
|
+
const scrollBy = (container) => (itemCount, delta) => {
|
|
2100
|
+
container.scrollBy({ left: delta * getItemWidth(container)(itemCount), behavior: 'smooth' });
|
|
2160
2101
|
};
|
|
2161
|
-
function useBusinessDepositRates(rateParams) {
|
|
2162
|
-
const serviceName = rateParams?.rateType ? DEPOSIT_RATES_SERVICE_MAP[rateParams?.rateType] : '';
|
|
2163
|
-
const { data } = useAsyncData(serviceName ? `/api/v1/depositrates/${serviceName}` : null, fetchJSONUnsafe);
|
|
2164
|
-
return Array.isArray(data) ? data : [];
|
|
2165
|
-
}
|
|
2166
2102
|
|
|
2167
|
-
const
|
|
2168
|
-
|
|
2169
|
-
const isOperatingDeposit = isReplenished || isPartialWithdrawal;
|
|
2170
|
-
const isDisabledOperatingDeposit = daysValue < BUSINESS_OPERATING_MIN_DAYS || daysValue > BUSINESS_OPERATING_MAX_DAYS;
|
|
2171
|
-
const rateRows = useBusinessDepositRates(rateParams);
|
|
2172
|
-
if (daysValue <= BUSINESS_RATE_MIN_DAYS) {
|
|
2173
|
-
return {
|
|
2174
|
-
...DEFAULT_BUSINESS_DEPOSIT_CALCULATOR_PARAMS,
|
|
2175
|
-
...userInputParams,
|
|
2176
|
-
isDisabledOperatingDeposit,
|
|
2177
|
-
isUnavailableByTerm: true,
|
|
2178
|
-
};
|
|
2179
|
-
}
|
|
2180
|
-
const businessDepositCalculatorSourceBookParams = rateRows?.find((_) => {
|
|
2181
|
-
return (isMonthlyInterestPayment === _.isMonthlyInterestPayment &&
|
|
2182
|
-
checkIsOperatingDeposit(isOperatingDeposit, _) &&
|
|
2183
|
-
checkRangeByKeys(moneyValue, ['minSum', 'maxSum'], _) &&
|
|
2184
|
-
checkRangeByKeys(daysValue, ['minDays', 'maxDays'], _));
|
|
2185
|
-
}) || DEFAULT_BUSINESS_DEPOSIT_CALCULATOR_PARAMS;
|
|
2186
|
-
const { rate } = businessDepositCalculatorSourceBookParams;
|
|
2187
|
-
const income = getDepositIncome$1(rate, userInputParams);
|
|
2188
|
-
const finalSum = moneyValue + income;
|
|
2189
|
-
const sourceBookRows = rateRows || [DEFAULT_BUSINESS_DEPOSIT_CALCULATOR_PARAMS];
|
|
2190
|
-
return {
|
|
2191
|
-
...businessDepositCalculatorSourceBookParams,
|
|
2192
|
-
...getRangeByKeys(['minSum', 'maxSum'], sourceBookRows),
|
|
2193
|
-
...getRangeByKeys(['minDays', 'maxDays'], sourceBookRows),
|
|
2194
|
-
...userInputParams,
|
|
2195
|
-
isDisabledOperatingDeposit,
|
|
2196
|
-
income,
|
|
2197
|
-
finalSum,
|
|
2198
|
-
};
|
|
2103
|
+
const scrollToEnd = (container) => {
|
|
2104
|
+
container.scrollTo({ left: container.scrollWidth, behavior: 'smooth' });
|
|
2199
2105
|
};
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
:
|
|
2203
|
-
const getDepositIncome$1 = (rate, userInputParams) => {
|
|
2204
|
-
const { isMonthlyInterestPayment, moneyValue, daysValue } = userInputParams;
|
|
2205
|
-
/*
|
|
2206
|
-
Приблизительный расчёт, не учитывающий разницу в количестве дней в месяцах. Месяц принят за 30 дней, год за 365 дней.
|
|
2207
|
-
*/
|
|
2208
|
-
if (isMonthlyInterestPayment) {
|
|
2209
|
-
return Math.round(moneyValue * Math.pow((1200 + rate) / 1200, daysValue / 30) - moneyValue);
|
|
2210
|
-
}
|
|
2211
|
-
else {
|
|
2212
|
-
return Math.round((moneyValue * rate * daysValue) / 365 / 100);
|
|
2213
|
-
}
|
|
2106
|
+
|
|
2107
|
+
const scrollToStart = (container) => {
|
|
2108
|
+
container.scrollTo({ left: 0, behavior: 'smooth' });
|
|
2214
2109
|
};
|
|
2215
2110
|
|
|
2216
|
-
const
|
|
2217
|
-
const
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
}
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
viewSettingFieldKey: 'isShowInsurance',
|
|
2272
|
-
});
|
|
2273
|
-
const checkRowParam$1 = ({ row, userInputParams, paramsViewSettings, fieldKey, viewSettingFieldKey, }) => {
|
|
2274
|
-
const isExclude = paramsViewSettings ? !paramsViewSettings[viewSettingFieldKey] : false;
|
|
2275
|
-
return isExclude || userInputParams[fieldKey] === row[fieldKey];
|
|
2111
|
+
const useSwipeListScroll = ({ itemCount, onVisibleIndicesChange, }) => {
|
|
2112
|
+
const containerRef = useRef(null);
|
|
2113
|
+
const [visibleIndices, setVisibleIndices] = useState([]);
|
|
2114
|
+
const handleVisibleIndicesChange = useCallback((indices) => {
|
|
2115
|
+
setVisibleIndices((prevIndices) => areArraysEqual(prevIndices, indices) ? prevIndices : indices);
|
|
2116
|
+
onVisibleIndicesChange && onVisibleIndicesChange(indices);
|
|
2117
|
+
}, [itemCount]);
|
|
2118
|
+
const [minIndex, maxIndex] = visibleIndices.length
|
|
2119
|
+
? [minBy()(visibleIndices), maxBy()(visibleIndices)]
|
|
2120
|
+
: [-1, -1];
|
|
2121
|
+
const canScrollLeft = minIndex > 0;
|
|
2122
|
+
const canScrollRight = maxIndex < itemCount - 1;
|
|
2123
|
+
const scrollLeft = useCallback(() => {
|
|
2124
|
+
if (!containerRef.current) {
|
|
2125
|
+
return;
|
|
2126
|
+
}
|
|
2127
|
+
if (canScrollLeft) {
|
|
2128
|
+
scrollBy(containerRef.current)(itemCount, -1);
|
|
2129
|
+
}
|
|
2130
|
+
else {
|
|
2131
|
+
scrollToEnd(containerRef.current);
|
|
2132
|
+
}
|
|
2133
|
+
}, [itemCount, canScrollLeft]);
|
|
2134
|
+
const scrollRight = useCallback(() => {
|
|
2135
|
+
if (!containerRef.current) {
|
|
2136
|
+
return;
|
|
2137
|
+
}
|
|
2138
|
+
if (canScrollRight) {
|
|
2139
|
+
scrollBy(containerRef.current)(itemCount, 1);
|
|
2140
|
+
}
|
|
2141
|
+
else {
|
|
2142
|
+
scrollToStart(containerRef.current);
|
|
2143
|
+
}
|
|
2144
|
+
}, [itemCount, canScrollRight]);
|
|
2145
|
+
const scrollTo = useCallback((idx, options = {
|
|
2146
|
+
behavior: 'smooth',
|
|
2147
|
+
block: 'nearest',
|
|
2148
|
+
inline: 'center',
|
|
2149
|
+
}) => {
|
|
2150
|
+
if (containerRef?.current) {
|
|
2151
|
+
containerRef.current.children[idx]?.scrollIntoView(options);
|
|
2152
|
+
}
|
|
2153
|
+
}, [containerRef]);
|
|
2154
|
+
return [
|
|
2155
|
+
containerRef,
|
|
2156
|
+
{
|
|
2157
|
+
scrollLeft,
|
|
2158
|
+
scrollRight,
|
|
2159
|
+
scrollTo,
|
|
2160
|
+
canScrollLeft,
|
|
2161
|
+
canScrollRight,
|
|
2162
|
+
visibleIndicesRange: [minIndex, maxIndex],
|
|
2163
|
+
handleVisibleIndicesChange,
|
|
2164
|
+
},
|
|
2165
|
+
];
|
|
2276
2166
|
};
|
|
2277
2167
|
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
userInputParams,
|
|
2287
|
-
paramsViewSettings,
|
|
2288
|
-
}) &&
|
|
2289
|
-
checkRangeByKeys(moneyValue, ['minSum', 'maxSum'], row) &&
|
|
2290
|
-
checkRangeByKeys(monthsValue, ['minMonths', 'maxMonths'], row)) || DEFAULT_CREDIT_CALCULATOR_PARAMS;
|
|
2168
|
+
/** @deprecated */
|
|
2169
|
+
const ArrowButton = JSX(({ className, disabled, ...rest }) => (jsx(LinkButton, { rounded: true, className: style('group/btn w-12 h-12 min-h-12 max-h-12 flex items-center justify-center shadow-main-black', disabled
|
|
2170
|
+
? 'bg-secondary-light text-secondary-text'
|
|
2171
|
+
: 'bg-white text-primary-text hover:text-primary-main', className || ''), disabled: disabled, ...rest, children: jsx(Img, { className: "w-4 h-4 min-w-4 min-h-4 rounded-full box-border", image: { icon: 'ArrowLeftIcon', iconVersion: 'black' }, imageClassName: "group-hover/btn:text-primary-main", width: "16", height: "16" }) })));
|
|
2172
|
+
/** @deprecated */
|
|
2173
|
+
const ScrollLeftButton = JSX((props) => (jsx(ArrowButton, { ...props, ariaLabel: "\u041F\u0440\u043E\u043B\u0438\u0441\u0442\u0430\u0442\u044C \u0432\u043B\u0435\u0432\u043E", "data-block-control": "scroll-left" })));
|
|
2174
|
+
/** @deprecated */
|
|
2175
|
+
const ScrollRightButton = JSX((props) => (jsx(ArrowButton, { ...props, className: `${props.className || ''} rotate-180`, ariaLabel: "\u041F\u0440\u043E\u043B\u0438\u0441\u0442\u0430\u0442\u044C \u0432\u043F\u0440\u0430\u0432\u043E", "data-block-control": "scroll-right" })));
|
|
2291
2176
|
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
const
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
else if (isAnnuity) {
|
|
2302
|
-
const i = rate / MONTHLY_INTEREST_RATE; // Используется значение ставки в процентах
|
|
2303
|
-
if (moneyExtra) {
|
|
2304
|
-
return (moneyValue + moneyExtra) * (i + i / (Math.pow(1 + i, monthsValue) - 1));
|
|
2177
|
+
const scrollButtonStyle$1 = 'absolute top-[calc(50%-24px)] z-40';
|
|
2178
|
+
const blurBaseStyle = 'absolute top-0 bottom-0 z-40 hidden @lg:block w-20 pointer-events-none';
|
|
2179
|
+
const CarouselScrollButtons = JSX(({ scroll, activeIndex, itemCount, arrowsPadded, hasEdgeBlocks, onScrollLeft, onScrollRight, }) => {
|
|
2180
|
+
const { canScrollLeft, canScrollRight, scrollLeft, scrollRight } = scroll;
|
|
2181
|
+
const canMoveLeft = hasEdgeBlocks ? activeIndex > 0 : canScrollLeft;
|
|
2182
|
+
const canMoveRight = hasEdgeBlocks ? activeIndex < itemCount - 1 : canScrollRight;
|
|
2183
|
+
const handleScrollLeft = useCallback(() => {
|
|
2184
|
+
if (!hasEdgeBlocks) {
|
|
2185
|
+
scrollLeft();
|
|
2305
2186
|
}
|
|
2306
2187
|
else {
|
|
2307
|
-
|
|
2188
|
+
canScrollLeft && activeIndex !== itemCount - 1 && scrollLeft();
|
|
2189
|
+
onScrollLeft();
|
|
2308
2190
|
}
|
|
2309
|
-
}
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2191
|
+
}, [scrollLeft, onScrollLeft, hasEdgeBlocks, canScrollLeft, activeIndex, itemCount]);
|
|
2192
|
+
const handleScrollRight = useCallback(() => {
|
|
2193
|
+
if (!hasEdgeBlocks) {
|
|
2194
|
+
scrollRight();
|
|
2195
|
+
}
|
|
2196
|
+
else {
|
|
2197
|
+
canScrollRight && activeIndex !== 0 && scrollRight();
|
|
2198
|
+
onScrollRight();
|
|
2199
|
+
}
|
|
2200
|
+
}, [scrollRight, onScrollRight, hasEdgeBlocks, canScrollLeft, activeIndex, itemCount]);
|
|
2201
|
+
return (jsxs("div", { className: "m:hidden block", children: [renderBlur(scroll), canMoveLeft ? (jsx(ScrollLeftButton, { className: style(scrollButtonStyle$1, arrowsPadded ? 'left-1 m:left-8' : 'left-0'), onClick: handleScrollLeft })) : null, canMoveRight ? (jsx(ScrollRightButton, { className: style(scrollButtonStyle$1, arrowsPadded ? 'right-1 m:right-8' : 'right-0'), onClick: handleScrollRight })) : null] }));
|
|
2202
|
+
});
|
|
2203
|
+
const renderBlur = (scroll) => (jsxs("div", { children: [scroll.canScrollLeft ? (jsx("div", { className: style(blurBaseStyle, 'left-0 bg-opacity-from-white group-data-secondary:bg-none') })) : null, scroll.canScrollRight ? (jsx("div", { className: style(blurBaseStyle, 'right-0 bg-opacity-to-white group-data-secondary:bg-none') })) : null] }));
|
|
2314
2204
|
|
|
2315
|
-
const
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
const
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2205
|
+
const ITEMS_GAP = 16;
|
|
2206
|
+
|
|
2207
|
+
const renderCardHighlight = ({ className, text = 'ХИТ' } = {}) => (jsxs("div", { className: style('w-14 h-14 bg-white flex flex-col items-center justify-center rounded-md shadow-main-black', className), children: [jsx(Icon, { iconVersion: "black", name: "HeartIcon", width: "24", height: "24" }), jsx(Paragraph, { size: "text-s", font: "font-normal", align: "text-center", color: "text-primary-text", children: text })] }));
|
|
2208
|
+
|
|
2209
|
+
const cardBaseStyle = 'relative h-full';
|
|
2210
|
+
const CARD_SIZE_MAP = {
|
|
2211
|
+
small: 'sm:min-w-64',
|
|
2212
|
+
normal: 'sm:min-w-96',
|
|
2213
|
+
big: 'sm:min-w-[515px]',
|
|
2214
|
+
};
|
|
2215
|
+
const renderCarouselCards = ({ noCardBorder, activeIndex, cardSize = 'normal', ...rest }) => {
|
|
2216
|
+
const { blocks: childBlocks } = rest.block || {};
|
|
2217
|
+
const someCardsHighlighted = childBlocks?.some(isCardHighlighted);
|
|
2218
|
+
return renderChildren({
|
|
2219
|
+
...rest,
|
|
2220
|
+
renderProps: (block, options, blockIndex) => (jsxs("div", { className: cardWrapperStyle(block, { someCardsHighlighted }), children: [renderBlock$1(block, options, {
|
|
2221
|
+
className: cardStyle(block, {
|
|
2222
|
+
someCardsHighlighted,
|
|
2223
|
+
showBorder: !noCardBorder,
|
|
2224
|
+
cardSize,
|
|
2225
|
+
}),
|
|
2226
|
+
blockIndex,
|
|
2227
|
+
isActive: blockIndex === activeIndex,
|
|
2228
|
+
}), isCardHighlighted(block)
|
|
2229
|
+
? renderCardHighlight({ className: 'absolute top-0 -right-4 z-40' })
|
|
2230
|
+
: null] }, String(blockIndex))),
|
|
2332
2231
|
});
|
|
2333
|
-
const { rate } = creditCalculatorRateParams;
|
|
2334
|
-
const monthlyPayment = getMonthlyPayment(rate, userInputParams);
|
|
2335
|
-
return {
|
|
2336
|
-
...creditCalculatorRateParams,
|
|
2337
|
-
...userInputParams,
|
|
2338
|
-
minSum,
|
|
2339
|
-
maxSum,
|
|
2340
|
-
minMonths,
|
|
2341
|
-
maxMonths,
|
|
2342
|
-
moneyValue,
|
|
2343
|
-
monthsValue,
|
|
2344
|
-
monthlyPayment,
|
|
2345
|
-
};
|
|
2346
2232
|
};
|
|
2233
|
+
const cardWrapperStyle = (_, { someCardsHighlighted }) => style(cardBaseStyle, someCardsHighlighted && (isCardHighlighted(_) ? 'pt-3xl' : 'pt-3xl sm:pt-16'));
|
|
2234
|
+
const cardStyle = (_, { someCardsHighlighted, showBorder, cardSize = 'normal', }) => style(cardBaseStyle, 'min-w-80', CARD_SIZE_MAP[cardSize], // TODO fix для RecommendationCard
|
|
2235
|
+
someCardsHighlighted && (isCardHighlighted(_) ? 'pt-3xl sm:pt-16' : 'pt-3xl'), getBorderStyle(showBorder), showBorder && 'h-full');
|
|
2236
|
+
const isCardHighlighted = (_) => _?.content && 'isHighlighting' in _.content && _.content.isHighlighting;
|
|
2347
2237
|
|
|
2348
|
-
const
|
|
2349
|
-
const renderMonthsInput = ({ min = 0, max = 0, availableMonths, ...rest }) => (jsx(InputRange, { items: [`От ${monthText(min)}`, `До ${monthText(max)}`], step: STEP_MONTHS, ...(availableMonths?.length ? { list: availableMonths } : { min, max }), ...rest }));
|
|
2350
|
-
const monthText = (month) => `${month} ${Number(month) % 10 === 1 ? 'месяца' : 'месяцев'}`;
|
|
2351
|
-
|
|
2352
|
-
const renderPaymentType = (props) => renderBinaryRadioButtonGroup({
|
|
2353
|
-
...props,
|
|
2354
|
-
radioGroupClassName: 'sm:flex-col',
|
|
2355
|
-
items: [
|
|
2356
|
-
{ id: 'annuity', text: 'Аннуитетный' },
|
|
2357
|
-
{ id: 'differential', text: 'Дифференцированный' },
|
|
2358
|
-
],
|
|
2359
|
-
});
|
|
2238
|
+
const VISIBLE_ITEM_COUNT = 1;
|
|
2360
2239
|
|
|
2361
|
-
const
|
|
2362
|
-
const
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
const
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2240
|
+
const Carousel = UniBlock(({ className, itemCount, visibleItemCount = VISIBLE_ITEM_COUNT, noCardBorder, isAlignCenter, arrowsPadded = true, isGap = true, isEmbedded = false, cardSize = 'normal', ...rest }) => {
|
|
2241
|
+
const { blocks: childBlocks = [] } = rest.block || {};
|
|
2242
|
+
const count = itemCount || childBlocks?.length;
|
|
2243
|
+
const [activeIndex, { inc: increaseActiveIndex, dec: decreaseActiveIndex }] = useCarouselControls({
|
|
2244
|
+
itemCount: count,
|
|
2245
|
+
visibleItemCount,
|
|
2246
|
+
}, Math.floor(visibleItemCount / 2));
|
|
2247
|
+
const [containerRef, scroll] = useSwipeListScroll({ itemCount: count });
|
|
2248
|
+
const [dotsActiveIndex] = scroll.visibleIndicesRange;
|
|
2249
|
+
// TODO Remove
|
|
2250
|
+
const isBankHistoryCarousel = childBlocks && childBlocks[0]?.type === 'CarouselBankHistoryCard';
|
|
2251
|
+
return (jsxs(BlockWrapper, { className: style(isEmbedded ? '@container-normal' : '', className), defaultPadding: "p-6xl", ...rest, children: [jsxs("div", { className: style(isAlignCenter ? 'flex justify-center' : '', 'relative max-w-full'), children: [jsx(SwipeListContainer, { containerRef: containerRef, visibleItemCount: visibleItemCount, snapAlign: "snap-start", gap: isGap ? ITEMS_GAP : undefined, onVisibleIndicesChange: scroll.handleVisibleIndicesChange, children: renderCarouselCards({ noCardBorder, activeIndex, cardSize, ...rest }) }), jsx(CarouselScrollButtons, { scroll: scroll, arrowsPadded: arrowsPadded, onScrollLeft: decreaseActiveIndex, onScrollRight: increaseActiveIndex, hasEdgeBlocks: isBankHistoryCarousel, activeIndex: activeIndex, itemCount: count })] }), jsx(SwipeListControlDots, { className: "@5xl:hidden", containerRef: containerRef, activeIndex: dotsActiveIndex, dotCount: count, listType: "horizontal-list" })] }));
|
|
2252
|
+
}, {
|
|
2253
|
+
childrenTypes: [
|
|
2254
|
+
'CarouselCard',
|
|
2255
|
+
'CarouselBankHistoryCard',
|
|
2256
|
+
'CarouselCatalogCard',
|
|
2257
|
+
'CarouselRecommendationCard',
|
|
2258
|
+
'CarouselTariffsCard',
|
|
2259
|
+
'RichTextBlock',
|
|
2260
|
+
'ProductBlock',
|
|
2261
|
+
],
|
|
2262
|
+
childSchema: () => ({
|
|
2263
|
+
isHighlighting: {
|
|
2264
|
+
title: 'Выделить карточку',
|
|
2265
|
+
type: 'boolean',
|
|
2266
|
+
},
|
|
2267
|
+
}),
|
|
2268
|
+
});
|
|
2269
|
+
|
|
2270
|
+
const EMPTY_SCHEMA = {};
|
|
2271
|
+
const initialFiltrationState$3 = {};
|
|
2272
|
+
const BankAccountFiltration = UniBlock(({ className, filtrationSchema = EMPTY_SCHEMA, resetButton, notFound, ...rest }) => {
|
|
2273
|
+
const [, { blocksToRender }, { field, reset }] = useFiltrationForm(initialFiltrationState$3, {
|
|
2274
|
+
block: rest.block,
|
|
2275
|
+
page: rest.options?.page,
|
|
2377
2276
|
});
|
|
2378
|
-
const
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
})
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
...field('monthsValue'),
|
|
2400
|
-
value: calculatorParams.monthsValue,
|
|
2401
|
-
}), renderCreditParamsForm$1({ ...calculatorParams, ...paramsViewSettings }, field), jsx("div", { className: "sm:hidden", children: paymentTypeElement })] }), rateChildren: renderRate({
|
|
2402
|
-
rate: calculatorParams.rate,
|
|
2403
|
-
}), resultChildren: jsxs("div", { children: [jsx(CalculatorValueBlock, { title: "\u0415\u0436\u0435\u043C\u0435\u0441\u044F\u0447\u043D\u044B\u0439 \u043F\u043B\u0430\u0442\u0451\u0436", value: calculatorParams.monthlyPayment, postfix: "\u20BD" }), jsx("div", { className: "hidden sm:block mb-lg", children: paymentTypeElement }), renderButtonsSection(buttons, { isVertical: true }), renderFootnote(footnote)] }) }));
|
|
2277
|
+
const selectArrProps = Object.entries(filtrationSchema)
|
|
2278
|
+
// Only StringArray
|
|
2279
|
+
.filter(([, schema]) => schema.type === 'array' && schema.ui === 'dropdown')
|
|
2280
|
+
.map(([name, schema]) => ({
|
|
2281
|
+
className: 'w-64',
|
|
2282
|
+
label: schema.title,
|
|
2283
|
+
options: stringArrayToOptions(schema),
|
|
2284
|
+
...field(name, {
|
|
2285
|
+
parse: ({ key }) => [key],
|
|
2286
|
+
format: ([value] = []) => stringArrayToOptions(schema).find((_) => _.key === value) || { key: '' },
|
|
2287
|
+
}),
|
|
2288
|
+
}));
|
|
2289
|
+
const Selects = selectArrProps.map((props, i) => jsx(Select, { ...props }, String(i)));
|
|
2290
|
+
return (jsxs(BlockWrapper, { className: style(className), defaultPadding: "p-0", version: "transparent", ...rest, children: [jsx(FiltrationForm, { filtrationSchema: filtrationSchema, field: field, reset: reset, children: jsxs("div", { children: [Selects, jsx("div", { children: jsx(Button, { type: "reset", className: "mt-lg w-64", onClick: reset, version: resetButton?.version, children: resetButton?.text }) })] }) }), jsx("div", { className: style(blocksToRender?.length ? 'hidden' : 'block'), children: notFound ? jsx(NotFound, { ...notFound }) : null }), jsx(Carousel, { padding: "p-0", isEmbedded: true, itemCount: blocksToRender?.length, visibleItemCount: 0, isAlignCenter: true, isGap: false, children: renderBlocksList(blocksToRender, {
|
|
2291
|
+
...rest.options,
|
|
2292
|
+
parent: rest.block,
|
|
2293
|
+
renderProps: (block, options, i) => (jsx("div", { className: style('relative min-w-80', getBorderStyle(true)), children: renderBlock$1(block, options) }, String(i))),
|
|
2294
|
+
}) })] }));
|
|
2295
|
+
}, {
|
|
2296
|
+
childrenTypes: ['CarouselTariffsCard'],
|
|
2297
|
+
childSchema: (content) => content?.filtrationSchema || {},
|
|
2404
2298
|
});
|
|
2405
|
-
const
|
|
2299
|
+
const stringArrayToOptions = (stringEnum) => zip(stringEnum.items?.enum || [], stringEnum.items?.enumNames || []).map(([key, text]) => ({
|
|
2300
|
+
key,
|
|
2301
|
+
text,
|
|
2302
|
+
}));
|
|
2406
2303
|
|
|
2407
|
-
const
|
|
2304
|
+
const iconBgStyles = {
|
|
2305
|
+
'': 'bg-main-divider group-data-secondary:bg-white/30',
|
|
2306
|
+
primary: 'bg-main-divider',
|
|
2307
|
+
secondary: 'bg-secondary-light',
|
|
2308
|
+
opacity: 'bg-white/30',
|
|
2309
|
+
};
|
|
2310
|
+
const RoundedIcon = JSX(({ className, defaultIconSize = 44, iconBgVersion = 'primary', size, icon, ...rest }) => {
|
|
2311
|
+
const widthAndHeight = String(size?.width || defaultIconSize);
|
|
2312
|
+
return icon ? (jsx("div", { style: {
|
|
2313
|
+
width: `${widthAndHeight}px`,
|
|
2314
|
+
height: `${widthAndHeight}px`,
|
|
2315
|
+
}, className: style('rounded-icon object-fit flex justify-center items-center', iconBgStyles[iconBgVersion], className), children: jsx(Icon, { ...rest, width: "54%", height: "54%", name: icon }) })) : null;
|
|
2316
|
+
});
|
|
2408
2317
|
|
|
2409
|
-
const
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2318
|
+
const defaultIconSize = 44;
|
|
2319
|
+
|
|
2320
|
+
const BenefitsBlock = JSX(({ className = '', title, benefitList, ...rest }) => (jsxs(BlockWrapper, { className: className, defaultPadding: "p-6xl", ...rest, children: [title ? jsx(Heading, { headingType: "h3", as: "h2", className: AlignStyles, title: title }) : null, benefitList?.length ? (jsx("div", { className: "flex flex-col @md:flex-row flex-wrap w-full @md:justify-center mt-xl gap-5xl", role: "list", children: benefitList.map(renderBenefit) })) : null] })));
|
|
2321
|
+
const renderBenefit = ({ label, description, items, icon, iconBgVersion, isDotted = false }, i) => (jsxs("div", { className: "flex gap-m items-center @md:basis-1/2 @md:max-w-[500px]", role: "listitem", children: [icon?.icon ? (jsx(RoundedIcon, { className: "shrink-0", defaultIconSize: defaultIconSize, iconBgVersion: iconBgVersion || '', ...icon })) : null, icon?.src ? jsx(Img, { className: "shrink-0", image: icon }) : null, label ? (jsxs("div", { className: "@sm:h-full space-y-xs", children: [jsx(Heading, { headingType: "h6", children: label }), jsx(Text, { size: "text-l", color: "text-secondary-text group-data-secondary:text-white/80", font: "font-light", children: description }), jsx(List, { dotClassName: "bg-secondary-text", listItemSize: "S", items: items, isDotted: isDotted })] })) : null] }, String(i)));
|
|
2322
|
+
|
|
2323
|
+
const bonusBenefitStyles = 'items-center';
|
|
2324
|
+
|
|
2325
|
+
const renderBonusBenefit = (cardTextAlign) => ({ icon, title, description }, i) => (jsxs("div", { className: style('flex flex-col gap-1', bonusBenefitStyles, !description && !title ? 'justify-center' : ''), children: [title ? (jsx(Text, { size: "text-h6", font: "font-normal", align: cardTextAlign, children: title })) : null, icon ? jsx(Img, { image: icon, height: "180", className: "w-auto mx-auto" }) : null, description ? (jsx(Text, { size: "text-h6", font: "font-normal", align: cardTextAlign, children: description })) : null] }, String(i)));
|
|
2326
|
+
|
|
2327
|
+
const renderBonusBenefits = (bonusBenefits, columnsCount, cardTextAlign) => (jsx("div", { className: `grid gap-2xs ${getElementsColsValue(columnsCount)}`, children: bonusBenefits.map(renderBonusBenefit(cardTextAlign)) }));
|
|
2328
|
+
const getElementsColsValue = (colValue) => {
|
|
2329
|
+
switch (colValue) {
|
|
2330
|
+
case '3':
|
|
2331
|
+
return 'grid-cols-3';
|
|
2332
|
+
case '4':
|
|
2333
|
+
return 'grid-cols-4';
|
|
2334
|
+
case '5':
|
|
2335
|
+
return 'grid-cols-5';
|
|
2336
|
+
default:
|
|
2337
|
+
return 'grid-cols-5';
|
|
2422
2338
|
}
|
|
2423
|
-
return result;
|
|
2424
2339
|
};
|
|
2425
2340
|
|
|
2426
|
-
const
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
row,
|
|
2435
|
-
userInputParams,
|
|
2436
|
-
paramKey: 'isMonthlyInterestPayment',
|
|
2437
|
-
isExclude: isExcludeMonthlyInterestPayment,
|
|
2438
|
-
}) &&
|
|
2439
|
-
checkRowByParam({
|
|
2440
|
-
row,
|
|
2441
|
-
userInputParams,
|
|
2442
|
-
paramKey: 'isRemoteRegistration',
|
|
2443
|
-
isExclude: isExcludeRemoteRegistration,
|
|
2444
|
-
}) &&
|
|
2445
|
-
checkRangeByKeys(moneyValue, ['minSum', 'maxSum'], row) &&
|
|
2446
|
-
checkRangeByKeys(monthsValue || defaultMonth, ['minMonths', 'maxMonths'], row)) || DEFAULT_DEPOSIT_CALCULATOR_PARAMS;
|
|
2447
|
-
const { rate } = depositCalculatorSourceBookParams;
|
|
2448
|
-
const income = getDepositIncome(rate, userInputParams);
|
|
2449
|
-
const finalSum = moneyValue + income;
|
|
2450
|
-
const sourceBookRows = calcSource?.rateRows || [DEFAULT_DEPOSIT_CALCULATOR_PARAMS];
|
|
2451
|
-
return {
|
|
2452
|
-
...depositCalculatorSourceBookParams,
|
|
2453
|
-
...getRangeByKeys(['minSum', 'maxSum'], sourceBookRows),
|
|
2454
|
-
...getRangeByKeys(['minMonths', 'maxMonths'], sourceBookRows),
|
|
2455
|
-
availableMonths: mergeIntervals(sourceBookRows.map((row) => [row['minMonths'], row['maxMonths']])).flatMap(([start, end]) => arrayByRange(start, end)),
|
|
2456
|
-
...userInputParams,
|
|
2457
|
-
defaultMonth,
|
|
2458
|
-
income,
|
|
2459
|
-
finalSum,
|
|
2460
|
-
};
|
|
2461
|
-
};
|
|
2462
|
-
const getDepositIncome = (rate, userInputParams) => {
|
|
2463
|
-
const { isMonthlyInterestPayment, moneyValue, monthsValue } = userInputParams;
|
|
2464
|
-
if (isMonthlyInterestPayment) {
|
|
2465
|
-
return Math.round(moneyValue * Math.pow((1200 + rate) / 1200, monthsValue) - moneyValue);
|
|
2466
|
-
}
|
|
2467
|
-
else {
|
|
2468
|
-
/*
|
|
2469
|
-
Приблизительный расчёт, не учитывающий разницу в количестве дней в месяцах. Месяц принят за 30 дней, год за 365 дней.
|
|
2470
|
-
*/
|
|
2471
|
-
return Math.round((moneyValue * rate * 30 * monthsValue) / 365 / 100);
|
|
2472
|
-
}
|
|
2341
|
+
const BonusBenefitsBlock = JSX(({ bonusBenefits, cardTextAlign = 'text-center', className = '', columnsCount = '4', subtitle, title, ...rest }) => (jsxs(BlockWrapper, { className: style('space-y-3xl', className), defaultPadding: "p-6xl", ...rest, children: [jsx(Headline, { defaultPadding: "", title: title, description: subtitle, headlineVersion: "M" }), bonusBenefits?.length
|
|
2342
|
+
? renderBonusBenefits(bonusBenefits, columnsCount, cardTextAlign)
|
|
2343
|
+
: null] })));
|
|
2344
|
+
|
|
2345
|
+
const AlignJustifyStyle = {
|
|
2346
|
+
start: 'justify-start',
|
|
2347
|
+
center: 'justify-center',
|
|
2348
|
+
end: 'justify-end',
|
|
2473
2349
|
};
|
|
2474
|
-
const checkRowByParam = ({ row, userInputParams, paramKey, isExclude }) => isExclude || userInputParams[paramKey] === row[paramKey];
|
|
2475
|
-
const getMiddleMonth = (minMonths, maxMonths) => minMonths + Math.round((maxMonths - minMonths) / 2);
|
|
2476
2350
|
|
|
2477
|
-
const
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
{ id: 'remote', text: 'Дистанционно' },
|
|
2481
|
-
{ id: 'office', text: 'Офис Банка' },
|
|
2482
|
-
],
|
|
2351
|
+
const ButtonsBlock = JSX(({ buttons, className = '', align, ...rest }) => {
|
|
2352
|
+
const alignStyle = align ? style('flex', AlignJustifyStyle[align]) : '';
|
|
2353
|
+
return (jsx(BlockWrapper, { className: style('!bg-transparent', alignStyle, className), defaultPadding: "p-0", ...rest, children: renderButtonsSection(buttons) }));
|
|
2483
2354
|
});
|
|
2484
2355
|
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
const
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
const calculatorParams = getDepositCalculatorParams(userInputParams, calcSource, paramsViewSettings);
|
|
2494
|
-
const { defaultMonth, rate, income, finalSum } = calculatorParams;
|
|
2495
|
-
const { onChange: setMonthsValue } = field('monthsValue');
|
|
2496
|
-
const { onChange: setMoneyValue } = field('moneyValue');
|
|
2497
|
-
useEffect(() => {
|
|
2498
|
-
!userInputParams.monthsValue && setMonthsValue && setMonthsValue(defaultMonth);
|
|
2499
|
-
}, [defaultMonth]);
|
|
2500
|
-
useEffect(() => {
|
|
2501
|
-
setMoneyValue &&
|
|
2502
|
-
setMoneyValue(clamp(userInputParams.moneyValue, calculatorParams.minSum, calculatorParams.maxSum));
|
|
2503
|
-
}, [calculatorParams.minSum, calculatorParams.maxSum]);
|
|
2504
|
-
return (jsx(CalculatorFormLayout, { className: className, inputChildren: jsxs("div", { children: [renderWantedSumInput({
|
|
2505
|
-
title: 'Сумма, ₽',
|
|
2506
|
-
min: calculatorParams.minSum,
|
|
2507
|
-
max: calculatorParams.maxSum,
|
|
2508
|
-
...field('moneyValue'),
|
|
2509
|
-
value: calculatorParams.moneyValue,
|
|
2510
|
-
}), renderMonthsInput({
|
|
2511
|
-
title: 'Срок, месяцев',
|
|
2512
|
-
min: calculatorParams.minMonths,
|
|
2513
|
-
max: calculatorParams.maxMonths,
|
|
2514
|
-
availableMonths: calculatorParams.availableMonths,
|
|
2515
|
-
...field('monthsValue'),
|
|
2516
|
-
value: calculatorParams.monthsValue,
|
|
2517
|
-
}), renderDepositParamsForm({ ...calculatorParams, ...paramsViewSettings }, field)] }), rateChildren: renderRate({
|
|
2518
|
-
rate,
|
|
2519
|
-
}), resultChildren: jsxs("div", { children: [jsx(CalculatorValueBlock, { title: "\u0414\u043E\u0445\u043E\u0434 \u0432 \u043A\u043E\u043D\u0446\u0435 \u0441\u0440\u043E\u043A\u0430", value: income, postfix: "\u20BD", prefix: "+" }), jsx(CalculatorValueBlock, { title: "\u0421\u0443\u043C\u043C\u0430 \u0432 \u043A\u043E\u043D\u0446\u0435 \u0441\u0440\u043E\u043A\u0430", value: finalSum, postfix: "\u20BD" }), renderButtonsSection(buttons, { isVertical: true }), renderFootnote(footnote)] }) }));
|
|
2520
|
-
});
|
|
2521
|
-
const renderDepositParamsForm = (params, field) => (jsxs("div", { className: "flex flex-col gap-y-2xl", children: [params.isShowMonthlyInterestPayment
|
|
2522
|
-
? renderInterestPayment({
|
|
2523
|
-
title: 'Выплата процентов',
|
|
2524
|
-
...field('isMonthlyInterestPayment'),
|
|
2525
|
-
value: params.isMonthlyInterestPayment,
|
|
2526
|
-
})
|
|
2527
|
-
: null, params.isShowRemoteRegistration
|
|
2528
|
-
? renderRegistrationType({
|
|
2529
|
-
title: 'Оформление',
|
|
2530
|
-
...field('isRemoteRegistration'),
|
|
2531
|
-
value: params.isRemoteRegistration,
|
|
2532
|
-
})
|
|
2533
|
-
: null] }));
|
|
2356
|
+
/** @deprecated */
|
|
2357
|
+
function renderArrows({ dec, inc, canDec, canInc, btnClass, className = '', }) {
|
|
2358
|
+
const isVisible = canDec || canInc;
|
|
2359
|
+
if (!isVisible) {
|
|
2360
|
+
return null;
|
|
2361
|
+
}
|
|
2362
|
+
return (jsxs("div", { children: [canDec ? (jsx(ArrowButton, { className: style('absolute z-40', btnClass[0], className), onClick: dec, ariaLabel: "\u041F\u0440\u043E\u043B\u0438\u0441\u0442\u0430\u0442\u044C \u0432\u043B\u0435\u0432\u043E", "data-block-control": "scroll-left", disabled: !canDec })) : null, canInc ? (jsx(ArrowButton, { className: style('absolute z-40 rotate-180', btnClass[1], className), onClick: inc, ariaLabel: "\u041F\u0440\u043E\u043B\u0438\u0441\u0442\u0430\u0442\u044C \u0432\u043F\u0440\u0430\u0432\u043E", "data-block-control": "scroll-right", disabled: !canInc })) : null] }));
|
|
2363
|
+
}
|
|
2534
2364
|
|
|
2535
|
-
const
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
}) &&
|
|
2540
|
-
checkRowParam({
|
|
2541
|
-
...props,
|
|
2542
|
-
fieldKey: 'isInsurance',
|
|
2543
|
-
viewSettingFieldKey: 'isShowInsurance',
|
|
2544
|
-
});
|
|
2545
|
-
const checkRowParam = ({ row, userInputParams, paramsViewSettings, fieldKey, viewSettingFieldKey, }) => {
|
|
2546
|
-
const isExclude = paramsViewSettings ? !paramsViewSettings[viewSettingFieldKey] : false;
|
|
2547
|
-
return isExclude || userInputParams[fieldKey] === row[fieldKey];
|
|
2548
|
-
};
|
|
2365
|
+
const calculatorValueBlockStyle = 'flex justify-between @xl:flex-col';
|
|
2366
|
+
const CalculatorValueBlock = JSX(({ className, title, value, fractionDigits, fixed, prefix, postfix }) => (jsxs("div", { className: style(calculatorValueBlockStyle, className), children: [title ? (jsx(Text, { size: "text-l", font: "font-light", color: "text-secondary-text", children: title })) : null, value ? (jsx("div", { children: jsx(Text, { size: "text-h3", children: [prefix, toLocalNumberFormat(fractionDigits, { fixed })(value), postfix]
|
|
2367
|
+
.filter(Boolean)
|
|
2368
|
+
.join(' ') }) })) : (jsx("div", { children: jsx(Text, { size: "text-h3", children: "-" }) }))] })));
|
|
2549
2369
|
|
|
2550
|
-
const
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2370
|
+
const DEFAULT_MIN_SUM$1 = 10000;
|
|
2371
|
+
const DEFAULT_MAX_SUM$1 = 5000000;
|
|
2372
|
+
const CREDIT_DEFAULT_SUM = 200000;
|
|
2373
|
+
const REFINANCING_DEFAULT_SUM = 700000;
|
|
2374
|
+
const REFINANCING_DEFAULT_MAX_SUM = 3000000;
|
|
2375
|
+
const REFINANCING_OLD_MIN_SUM = 0;
|
|
2376
|
+
const REFINANCING_OLD_DEFAULT_SUM = 0;
|
|
2377
|
+
const REFINANCING_OLD_MAX_SUM = 2500000;
|
|
2378
|
+
const REFINANCING_EXTRA_MIN_SUM = 0;
|
|
2379
|
+
const REFINANCING_EXTRA_MAX_SUM = 500000;
|
|
2380
|
+
const DEPOSIT_DEFAULT_SUM = 20000;
|
|
2381
|
+
const DEFAULT_MIN_MONTHS = 1;
|
|
2382
|
+
const DEFAULT_REFINANCING_MIN_MONTHS = 13;
|
|
2383
|
+
const DEFAULT_REFINANCING_MONTHS = 48;
|
|
2384
|
+
const DEFAULT_MAX_MONTHS = 60;
|
|
2385
|
+
const DEFAULT_MONTHS = Math.round((DEFAULT_MAX_MONTHS - DEFAULT_MIN_MONTHS) / 2);
|
|
2386
|
+
const BUSINESS_DEFAULT_SUM = 100000;
|
|
2387
|
+
const BUSINESS_MIN_DAYS = 1;
|
|
2388
|
+
const BUSINESS_MAX_DAYS = 1095;
|
|
2389
|
+
const BUSINESS_RATE_MIN_DAYS = 30; // порог количества дней, при которых ставка не доступна
|
|
2390
|
+
const BUSINESS_OPERATING_MIN_DAYS = 90;
|
|
2391
|
+
const BUSINESS_OPERATING_MAX_DAYS = 730;
|
|
2392
|
+
const BUSINESS_DEFAULT_DAYS = 60;
|
|
2393
|
+
const MONTHS_IN_YEAR = 12;
|
|
2394
|
+
const MONTHLY_INTEREST_RATE = MONTHS_IN_YEAR * 100;
|
|
2395
|
+
const DEFAULT_CREDIT_CALCULATOR_PARAMS = {
|
|
2396
|
+
minSum: DEFAULT_MIN_SUM$1,
|
|
2397
|
+
maxSum: DEFAULT_MAX_SUM$1,
|
|
2398
|
+
minMonths: DEFAULT_MIN_MONTHS,
|
|
2399
|
+
maxMonths: DEFAULT_MAX_MONTHS,
|
|
2400
|
+
rate: 0,
|
|
2401
|
+
isSalaryClient: false,
|
|
2402
|
+
isPensionClient: false,
|
|
2403
|
+
isStateEmployee: false,
|
|
2404
|
+
isInsurance: true,
|
|
2405
|
+
};
|
|
2406
|
+
const DEFAULT_REFINANCING_CALCULATOR_PARAMS = {
|
|
2407
|
+
minSum: DEFAULT_MIN_SUM$1,
|
|
2408
|
+
maxSum: REFINANCING_DEFAULT_MAX_SUM,
|
|
2409
|
+
minSumOld: REFINANCING_OLD_MIN_SUM,
|
|
2410
|
+
maxSumOld: REFINANCING_OLD_MAX_SUM,
|
|
2411
|
+
minSumExtra: REFINANCING_EXTRA_MIN_SUM,
|
|
2412
|
+
maxSumExtra: REFINANCING_EXTRA_MAX_SUM,
|
|
2413
|
+
minMonths: DEFAULT_REFINANCING_MIN_MONTHS,
|
|
2414
|
+
maxMonths: DEFAULT_MAX_MONTHS,
|
|
2415
|
+
rate: 0,
|
|
2416
|
+
isExtraMoney: false,
|
|
2417
|
+
isSalaryClient: false,
|
|
2418
|
+
isInsurance: true,
|
|
2419
|
+
};
|
|
2420
|
+
const DEFAULT_TRAVEL_MIN_SUM = 6000;
|
|
2421
|
+
const DEFAULT_REST_MIN_SUM = 6000;
|
|
2422
|
+
const DEFAULT_BONUS_CALCULATOR_PARAMS = {
|
|
2423
|
+
minSumTravel: 6000,
|
|
2424
|
+
maxSumTravel: 200000,
|
|
2425
|
+
minSumOther: 6000,
|
|
2426
|
+
maxSumOther: 200000,
|
|
2427
|
+
maxBonus: 5000,
|
|
2428
|
+
prefMonthsNum: 2,
|
|
2429
|
+
prefTravelBonusRate: 0.015,
|
|
2430
|
+
prefRestBonusRate: 0.01,
|
|
2431
|
+
travelBonusRate: 0.015,
|
|
2432
|
+
restBonusRate: 0.01,
|
|
2433
|
+
};
|
|
2434
|
+
const DEFAULT_DEPOSIT_CALCULATOR_PARAMS = {
|
|
2435
|
+
minSum: 50000,
|
|
2436
|
+
maxSum: 100000001,
|
|
2437
|
+
minMonths: 2,
|
|
2438
|
+
maxMonths: 10,
|
|
2439
|
+
rate: 0,
|
|
2440
|
+
isMonthlyInterestPayment: true,
|
|
2441
|
+
isRemoteRegistration: true,
|
|
2442
|
+
};
|
|
2443
|
+
const DEFAULT_BUSINESS_DEPOSIT_CALCULATOR_PARAMS = {
|
|
2444
|
+
minSum: 1000,
|
|
2445
|
+
maxSum: 100000001,
|
|
2446
|
+
minDays: BUSINESS_MIN_DAYS,
|
|
2447
|
+
maxDays: BUSINESS_MAX_DAYS,
|
|
2448
|
+
rate: 0,
|
|
2449
|
+
isMonthlyInterestPayment: true,
|
|
2450
|
+
isReplenished: false,
|
|
2451
|
+
isPartialWithdrawal: false,
|
|
2452
|
+
depositeName: "Депозит 'Стабильный'",
|
|
2453
|
+
};
|
|
2555
2454
|
|
|
2556
|
-
const
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
checkRangeByKeys(monthsValue, ['minMonths', 'maxMonths'], row)) || DEFAULT_REFINANCING_CALCULATOR_PARAMS;
|
|
2455
|
+
const getBonus = (params, bonusTravelValue, bonusOtherValue) => {
|
|
2456
|
+
const { maxBonus = 5000, prefMonthsNum = DEFAULT_BONUS_CALCULATOR_PARAMS.prefMonthsNum, prefTravelBonusRate = DEFAULT_BONUS_CALCULATOR_PARAMS.prefTravelBonusRate, prefRestBonusRate = 0.01, travelBonusRate = 0.015, restBonusRate = 0.01, } = params;
|
|
2457
|
+
const prefBonus = Math.min(Math.round(prefTravelBonusRate * bonusTravelValue) +
|
|
2458
|
+
Math.round(prefRestBonusRate * bonusOtherValue), maxBonus);
|
|
2459
|
+
const bonus = Math.min(Math.round(travelBonusRate * bonusTravelValue) + Math.round(restBonusRate * bonusOtherValue), maxBonus);
|
|
2460
|
+
const yearBonus = prefBonus * prefMonthsNum + bonus * (MONTHS_IN_YEAR - prefMonthsNum);
|
|
2461
|
+
return [prefBonus, yearBonus];
|
|
2462
|
+
};
|
|
2565
2463
|
|
|
2566
|
-
const
|
|
2567
|
-
const {
|
|
2568
|
-
const
|
|
2569
|
-
const limitRows = calcSource?.limitRows || [];
|
|
2570
|
-
const sourceBookLimitParams = getRefinancingCalculatorLimitParams({
|
|
2571
|
-
limitRows,
|
|
2572
|
-
userInputParams,
|
|
2573
|
-
paramsViewSettings,
|
|
2574
|
-
});
|
|
2575
|
-
const { minSum, maxSum } = getLimitRangeByKeys(['minSum', 'maxSum'], sourceBookLimitParams, rateRows);
|
|
2576
|
-
const { minMonths, maxMonths } = getLimitRangeByKeys(['minMonths', 'maxMonths'], sourceBookLimitParams, rateRows);
|
|
2577
|
-
const refinancingCalculatorSourceBookRateParams = getRefinancingCalculatorRateParams({
|
|
2578
|
-
rateRows,
|
|
2579
|
-
userInputParams,
|
|
2580
|
-
paramsViewSettings,
|
|
2581
|
-
moneyValue,
|
|
2582
|
-
monthsValue,
|
|
2583
|
-
oldMonthlyPayment,
|
|
2584
|
-
moneyExtra,
|
|
2585
|
-
});
|
|
2586
|
-
const { rate } = refinancingCalculatorSourceBookRateParams;
|
|
2587
|
-
const monthlyPayment = getMonthlyPayment(rate, userInputParams);
|
|
2588
|
-
const benefit = userInputParams.oldMonthlyPayment - monthlyPayment;
|
|
2464
|
+
const getBonusCalculatorParams = (userInputParams, calcSource) => {
|
|
2465
|
+
const { travelExpenseValue, restExpenseValue } = userInputParams;
|
|
2466
|
+
const [monthBonus, yearBonus] = getBonus(calcSource || DEFAULT_BONUS_CALCULATOR_PARAMS, travelExpenseValue, restExpenseValue);
|
|
2589
2467
|
return {
|
|
2590
|
-
...
|
|
2468
|
+
...calcSource,
|
|
2591
2469
|
...userInputParams,
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
minMonths,
|
|
2595
|
-
maxMonths,
|
|
2596
|
-
moneyValue,
|
|
2597
|
-
monthsValue,
|
|
2598
|
-
oldMonthlyPayment,
|
|
2599
|
-
moneyExtra,
|
|
2600
|
-
monthlyPayment,
|
|
2601
|
-
benefit,
|
|
2470
|
+
monthBonus,
|
|
2471
|
+
yearBonus,
|
|
2602
2472
|
};
|
|
2603
2473
|
};
|
|
2604
2474
|
|
|
2605
|
-
const
|
|
2475
|
+
const renderFootnote = (text) => text ? (jsx(Paragraph, { size: "text-s", font: "font-light", color: "text-secondary-text", children: text })) : null;
|
|
2476
|
+
|
|
2477
|
+
const Rate = JSX(({ rate = 0, title = 'Ставка', unit, fractionDigits = 2, depositeName, isShowDepositeName }) => (jsxs("div", { children: [jsx(Text, { size: "text-l", font: "font-light", color: "text-secondary-text", children: title }), jsxs("div", { className: "relative", children: [jsxs("div", { className: "flex justify-start gradient-color-text", children: [jsx("span", { className: "font-mohave text-title-huge pr-xl -mt-m tracking-[-15px]", children: toLocalNumberFormat(fractionDigits, { fixed: true })(rate) }), unit ? jsx("span", { className: "text-7xl", children: unit }) : null] }), depositeName && isShowDepositeName ? (jsx("div", { className: "absolute bottom-2 w-full text-left whitespace-nowrap", children: depositeName })) : null] })] })));
|
|
2478
|
+
|
|
2479
|
+
const UnknownRate = JSX(({ title = 'Ставка', isUnavailableByTerm = false }) => (jsxs("div", { className: "space-y-s", children: [jsx(Text, { size: "text-l", font: "font-light", color: "text-secondary-text", children: title }), jsx(Icon, { className: "w-10 h-10 @5xl:h-auto @5xl:w-40", name: "PercentIcon" }), jsx("div", { className: "w-64", children: isUnavailableByTerm ? (jsxs(Paragraph, { size: "text-xl", font: "font-light", color: "text-primary-text", children: ["\u041F\u0440\u043E\u0446\u0435\u043D\u0442\u043D\u0430\u044F \u0441\u0442\u0430\u0432\u043A\u0430 \u0434\u043B\u044F \u0441\u0440\u043E\u043A\u0430 ", jsx("strong", { children: "1-30 \u0434\u043D\u0435\u0439" }), " \u0443\u0441\u0442\u0430\u043D\u0430\u0432\u043B\u0438\u0432\u0430\u0435\u0442\u0441\u044F \u043F\u0440\u0438 \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0438 \u0432 \u0411\u0430\u043D\u043A"] })) : (jsx(Paragraph, { size: "text-xl", font: "font-light", color: "text-primary-text", children: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\u0440\u0443\u0433\u0443\u044E \u0441\u0443\u043C\u043C\u0443 \u0438\u043B\u0438 \u0441\u0440\u043E\u043A" })) })] })));
|
|
2480
|
+
|
|
2481
|
+
const renderRate = ({ title = 'Ставка', rate = 0, unit = '%', fractionDigits = 2, isUnknownRateShown = true, ...rest }) => isUnknownRateShown && rate === 0 ? (jsx(UnknownRate, { title: title, ...rest })) : (jsxs("div", { children: [jsx("div", { className: "hidden @xl:block", children: jsx(Rate, { title: title, rate: rate, unit: unit, fractionDigits: fractionDigits, ...rest }) }), jsx("div", { className: "@xl:hidden", children: jsx(CalculatorValueBlock, { title: title, value: rate, postfix: unit, fractionDigits: fractionDigits, fixed: true, ...rest }) })] }));
|
|
2482
|
+
|
|
2483
|
+
const DEFAULT_MONEY_STEP = 1000;
|
|
2484
|
+
function renderWantedSumInput({ isShowItems = true, step = DEFAULT_MONEY_STEP, ...rest }) {
|
|
2485
|
+
const items = [
|
|
2486
|
+
`От ${toLocalNumberFormat(2)(rest.min || 0)} ₽`,
|
|
2487
|
+
`До ${toLocalNumberFormat(2)(rest.max || 0)} ₽`,
|
|
2488
|
+
];
|
|
2489
|
+
return jsx(InputRange, { items: isShowItems ? items : [], step: step, ...rest });
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2492
|
+
const BonusCalculatorForm = JSX(({ className = '', calcSource, buttons, footnote }) => {
|
|
2606
2493
|
const [userInputParams, { field }] = useForm({
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
isSalaryClient: false,
|
|
2610
|
-
isExtraMoney: false,
|
|
2611
|
-
moneyValue: REFINANCING_DEFAULT_SUM,
|
|
2612
|
-
oldMonthlyPayment: REFINANCING_OLD_DEFAULT_SUM,
|
|
2613
|
-
monthsValue: DEFAULT_REFINANCING_MONTHS,
|
|
2614
|
-
moneyExtra: REFINANCING_OLD_DEFAULT_SUM,
|
|
2615
|
-
});
|
|
2616
|
-
const calculatorParams = getRefinancingCalculatorParams(userInputParams, calcSource, paramsViewSettings);
|
|
2617
|
-
const paymentTypeElement = renderPaymentType({
|
|
2618
|
-
title: '',
|
|
2619
|
-
mobileTitle: 'Тип платежа',
|
|
2620
|
-
orientation: 'vertical',
|
|
2621
|
-
...field('isAnnuity'),
|
|
2494
|
+
travelExpenseValue: DEFAULT_TRAVEL_MIN_SUM,
|
|
2495
|
+
restExpenseValue: DEFAULT_REST_MIN_SUM,
|
|
2622
2496
|
});
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
...field('moneyValue'),
|
|
2629
|
-
value: calculatorParams.moneyValue,
|
|
2630
|
-
}), renderWantedSumInput({
|
|
2631
|
-
title: 'Ежемесячный платёж в других банках, ₽',
|
|
2632
|
-
step: 500,
|
|
2633
|
-
min: calculatorParams.minSumOld,
|
|
2634
|
-
max: calculatorParams.maxSumOld,
|
|
2635
|
-
...field('oldMonthlyPayment'),
|
|
2636
|
-
value: calculatorParams.oldMonthlyPayment,
|
|
2637
|
-
}), renderMonthsInput({
|
|
2638
|
-
title: 'Новый срок кредита, месяцев',
|
|
2639
|
-
min: calculatorParams.minMonths,
|
|
2640
|
-
max: calculatorParams.maxMonths,
|
|
2641
|
-
...field('monthsValue'),
|
|
2642
|
-
value: calculatorParams.monthsValue,
|
|
2643
|
-
}), renderCreditParamsForm({ ...calculatorParams, ...paramsViewSettings }, field), calculatorParams.isExtraMoney
|
|
2644
|
-
? renderWantedSumInput({
|
|
2645
|
-
title: 'Дополнительная сумма, ₽ ',
|
|
2497
|
+
const { minSumTravel, maxSumTravel, minSumOther, maxSumOther, monthBonus, yearBonus } = getBonusCalculatorParams(userInputParams, calcSource);
|
|
2498
|
+
return (jsxs("section", { className: style('flex flex-col justify-between @5xl:flex-row gap-y-4xl', className), children: [jsxs("div", { className: "flex flex-col @xl:max-w-md gap-2xl border-b border-b-main-divider @xl:border-none pb-3xl @xl:pb-0", children: [renderWantedSumInput({
|
|
2499
|
+
title: 'Сумма покупок в категории путешествия, ₽',
|
|
2500
|
+
min: minSumTravel,
|
|
2501
|
+
max: maxSumTravel,
|
|
2646
2502
|
step: 500,
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2503
|
+
isShowItems: false,
|
|
2504
|
+
...field('travelExpenseValue'),
|
|
2505
|
+
}), renderWantedSumInput({
|
|
2506
|
+
title: 'Сумма покупок в остальных категориях, ₽',
|
|
2507
|
+
min: minSumOther,
|
|
2508
|
+
max: maxSumOther,
|
|
2509
|
+
step: 500,
|
|
2510
|
+
isShowItems: false,
|
|
2511
|
+
...field('restExpenseValue'),
|
|
2512
|
+
})] }), monthBonus >= 0
|
|
2513
|
+
? renderRate({
|
|
2514
|
+
title: 'Баллов за месяц',
|
|
2515
|
+
rate: monthBonus,
|
|
2516
|
+
fractionDigits: 0,
|
|
2517
|
+
isUnknownRateShown: false,
|
|
2518
|
+
unit: '',
|
|
2519
|
+
})
|
|
2520
|
+
: null, jsxs("div", { className: "flex flex-col gap-y-xl @xl:w-96", children: [yearBonus >= 0 ? jsx(CalculatorValueBlock, { title: "\u0411\u0430\u043B\u043B\u043E\u0432 \u0437\u0430 \u0433\u043E\u0434", value: yearBonus }) : null, renderButtonsSection(buttons, { isVertical: true }), renderFootnote(footnote)] })] }));
|
|
2656
2521
|
});
|
|
2657
|
-
const renderCreditParamsForm = (params, field) => (jsxs("div", { className: "space-y-lg sm:space-y-s", children: [params.isShowSalaryClient ? (jsx(Checkbox, { text: "\u041F\u043E\u043B\u0443\u0447\u0430\u044E \u0437\u0430\u0440\u043F\u043B\u0430\u0442\u0443 \u043D\u0430 \u0441\u0447\u0451\u0442 \u0432 \u0420\u043E\u0441\u0441\u0435\u043B\u044C\u0445\u043E\u0437\u0431\u0430\u043D\u043A\u0435", ...field('isSalaryClient'), value: params.isSalaryClient })) : null, params.isShowInsurance ? (jsx(Checkbox, { text: "\u041A\u043E\u043C\u043F\u043B\u0435\u043A\u0441\u043D\u0430\u044F \u0441\u0442\u0440\u0430\u0445\u043E\u0432\u0430\u044F \u0437\u0430\u0449\u0438\u0442\u0430", ...field('isInsurance'), value: params.isInsurance })) : null, jsx(Checkbox, { text: "\u041F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0443\u044E \u0441\u0443\u043C\u043C\u0443", ...field('isExtraMoney'), value: params.isExtraMoney })] }));
|
|
2658
|
-
|
|
2659
|
-
const EmbeddableCalcBlocks = {
|
|
2660
|
-
CreditCalculatorForm,
|
|
2661
|
-
DepositCalculatorForm,
|
|
2662
|
-
BusinessDepositCalculatorForm,
|
|
2663
|
-
BonusCalculatorForm,
|
|
2664
|
-
RefinancingCalculatorForm,
|
|
2665
|
-
};
|
|
2666
2522
|
|
|
2667
|
-
const
|
|
2668
|
-
const type = block?.calcType;
|
|
2669
|
-
if (!type || !(type in EmbeddableCalcBlocks)) {
|
|
2670
|
-
return null;
|
|
2671
|
-
}
|
|
2672
|
-
const EmbeddedBlock = EmbeddableCalcBlocks[type];
|
|
2673
|
-
return (jsx("section", { className: "box-border relative bg-white flex shrink-0 self-start basis-full", role: "listitem", children: jsxs("div", { className: "box-border p-4xl w-full space-y-xl", children: [block?.title ? jsx(Heading, { className: "text-center", title: block.title }) : null, jsx(EmbeddedBlock, { ...block })] }) }, String(i)));
|
|
2674
|
-
};
|
|
2523
|
+
const CalculatorFormLayout = JSX(({ className, inputChildren, rateChildren, resultChildren }) => (jsxs("section", { className: style('flex flex-col justify-between @5xl:flex-row gap-m', className), children: [jsx("div", { className: "flex flex-col gap-y-m sm:max-w-md gap-2xl", children: inputChildren }), jsx("div", { className: "border-b border-main-divider md:hidden" }), rateChildren, jsx("div", { className: "flex flex-col gap-2xl sm:w-96 max-w-full", children: resultChildren })] })));
|
|
2675
2524
|
|
|
2676
|
-
const
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
const [activeIndex, controls] = useCarouselControls({
|
|
2683
|
-
itemCount: calculatorTabs?.length,
|
|
2684
|
-
visibleItemCount: COLUMNS_FOR_SCROLL,
|
|
2685
|
-
});
|
|
2686
|
-
return (jsxs(BlockWrapper, { className: style('box-border overflow-hidden relative', className), defaultPadding: "p-0", ...rest, children: [jsxs("div", { className: "bg-white", children: [tabsNav.length > 1
|
|
2687
|
-
? renderTabs$1({
|
|
2688
|
-
activeIndex,
|
|
2689
|
-
tabsNav,
|
|
2690
|
-
tabAlign,
|
|
2691
|
-
slideIndexShift,
|
|
2692
|
-
onClick: handleSlideIndexShift,
|
|
2693
|
-
})
|
|
2694
|
-
: null, renderArrows({
|
|
2695
|
-
...controls,
|
|
2696
|
-
btnClass: ['left-3', 'right-3'],
|
|
2697
|
-
className: 'top-10',
|
|
2698
|
-
})] }), jsx("div", { className: "flex", style: { transform: `translateX(-${slideIndexShift}00%)` }, role: "list", children: calculatorBlocks?.length ? calculatorBlocks.map(renderCalculatorBlock) : null })] }));
|
|
2699
|
-
});
|
|
2700
|
-
function renderNavButton$3({ tab, i, isActive, onClick }) {
|
|
2701
|
-
const btnClassName = isActive
|
|
2702
|
-
? 'w-96 p-m border-none bg-primary-main text-white'
|
|
2703
|
-
: `w-96 p-s ease-in duration-300 bg-white text-primary-text`;
|
|
2704
|
-
const btnTitleClassName = isActive ? 'text-xl mb-xs' : `text-l mb-2xs`;
|
|
2705
|
-
const btnDescClassName = isActive
|
|
2706
|
-
? 'text-l font-light text-white'
|
|
2707
|
-
: `text-m font-light text-secondary-text`;
|
|
2708
|
-
const iconClassName = isActive ? '' : `text-primary-main`;
|
|
2709
|
-
const iconVersion = tab?.icon?.iconVersion;
|
|
2710
|
-
const activeIconStyle = isActive ? 'white' : 'normal';
|
|
2711
|
-
return (jsxs("button", { type: "button", onClick: onClick, "aria-label": tab?.title, className: style('box-border relative border border-gray cursor-pointer text-left border-b-0 flex space-x-m min-h-20', btnClassName), children: [jsx(Img, { className: style('h-6 w-6 min-w-6 min-h-6', iconClassName), image: {
|
|
2712
|
-
...tab?.icon,
|
|
2713
|
-
iconVersion: iconVersion ?? activeIconStyle,
|
|
2714
|
-
}, width: "24", height: "24" }), jsxs("div", { className: "border-0", children: [jsx("div", { className: btnTitleClassName, children: tab?.title }), jsx("div", { className: btnDescClassName, children: tab.description })] })] }, String(i)));
|
|
2715
|
-
}
|
|
2716
|
-
function renderTabs$1({ activeIndex, tabsNav, tabAlign, slideIndexShift, onClick }) {
|
|
2717
|
-
const CARD_SHIFT = 388;
|
|
2718
|
-
const alignStyle = tabAlign ? AlignJustifyStyle[tabAlign] : '';
|
|
2719
|
-
return (jsxs("div", { children: [jsx("div", { style: { transform: `translateX(-${activeIndex * CARD_SHIFT}px)` }, className: "flex flex-col justify-end items-center h-32 pt-4xl box-border duration-1000", children: jsx("div", { className: style('w-full flex flex-nowrap items-end gap-xs', alignStyle), children: tabsNav.map((tab, i) => renderNavButton$3({
|
|
2720
|
-
tab,
|
|
2721
|
-
i,
|
|
2722
|
-
isActive: Boolean(i === slideIndexShift),
|
|
2723
|
-
onClick: () => onClick(i),
|
|
2724
|
-
})) }) }), jsx("div", { className: "w-full h-2 bg-primary-main" })] }));
|
|
2725
|
-
}
|
|
2726
|
-
|
|
2727
|
-
const NumberInput = JSX((props) => {
|
|
2728
|
-
const { onChange, min, max, defaultValue = '0', fractionDigits = 0, ...inputProps } = props;
|
|
2729
|
-
const normalizedProps = useNormalizedInput(props, {
|
|
2730
|
-
normalize: (_ = defaultValue) => min && max ? String(clamp(Number(sanitizeNumberStr(_)), min, max)) : sanitizeNumberStr(_),
|
|
2731
|
-
format: toLocalNumberFormat(fractionDigits),
|
|
2732
|
-
});
|
|
2733
|
-
const handleChange = useCallback((_) => onChange && onChange(sanitizeNumberStr(_)), [onChange]);
|
|
2734
|
-
return jsx(Input, { onChange: handleChange, ...inputProps, ...normalizedProps });
|
|
2735
|
-
});
|
|
2736
|
-
const sanitizeNumberStr = (_ = '') => _.replaceAll(',', '.')
|
|
2737
|
-
.replace(/[^\d.]/g, '')
|
|
2738
|
-
.replace(/([^.]*\.[^.]*)\./, '$1');
|
|
2525
|
+
const getMoneyDefaultValue = (defaultParams, defaultMoney = 0) => defaultParams?.sum ? defaultParams.sum : defaultMoney;
|
|
2526
|
+
const getMonthsDefaultValue = (defaultParams, defaultMonth = 0) => defaultParams?.period &&
|
|
2527
|
+
defaultParams.period >= DEFAULT_MIN_MONTHS &&
|
|
2528
|
+
defaultParams.period <= DEFAULT_MAX_MONTHS
|
|
2529
|
+
? defaultParams.period
|
|
2530
|
+
: defaultMonth;
|
|
2739
2531
|
|
|
2740
|
-
const
|
|
2532
|
+
const STEP_DAYS = 1;
|
|
2533
|
+
const renderDaysInput = (props) => (jsx(InputRange, { items: [`От ${daysText(props.min || 0)}`, `До ${daysText(props.max || 0)}`], step: STEP_DAYS, ...props }));
|
|
2534
|
+
const daysText = (days) => `${days} ${Number(days) % 10 === 1 ? 'дня' : 'дней'}`;
|
|
2741
2535
|
|
|
2742
|
-
const
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
const MAX_AMOUNT = 300000;
|
|
2746
|
-
const MIN_AMOUNT = 1;
|
|
2747
|
-
const FORM_URL_MAP = {
|
|
2748
|
-
private: 'https://old.rshb.ru/p2p/',
|
|
2749
|
-
business: 'https://old.rshb.ru/smallbusiness/p2p/',
|
|
2750
|
-
};
|
|
2751
|
-
const INITIAL_FORM_STATE = {
|
|
2752
|
-
amount: 1500,
|
|
2536
|
+
const orientationStyleMap = {
|
|
2537
|
+
horizontal: 'gap-5xl',
|
|
2538
|
+
vertical: 'flex-col gap-s',
|
|
2753
2539
|
};
|
|
2754
|
-
const
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2540
|
+
const RadioButtonGroup = JSX(({ items, checkedItem, className, onChange: onChangeCheckedItem, orientation = 'horizontal', }) => (jsx("div", { className: style(`flex ${orientationStyleMap[orientation]}`, className), role: "radiogroup", children: items?.map(({ id, text }) => (jsx(Checkbox, { isRadio: true, text: text, value: checkedItem === id, onChange: () => onChangeCheckedItem && onChangeCheckedItem(id) }, String(id)))) })));
|
|
2541
|
+
|
|
2542
|
+
const renderBinaryRadioButtonGroup = ({ items, title, mobileTitle = title, orientation = 'horizontal', value, radioGroupClassName, onChange, }) => (jsxs("div", { className: "space-y-s", children: [title ? (jsx("div", { className: "hidden @5xl:block", children: jsx(Text, { color: "text-secondary-text", font: "font-light", children: title }) })) : null, mobileTitle ? (jsx("div", { className: "@5xl:hidden", children: jsx(Text, { color: "text-secondary-text", font: "font-light", children: mobileTitle }) })) : null, jsx(RadioButtonGroup, { orientation: orientation, items: items, checkedItem: items[value ? 0 : 1].id, className: style('flex-col sm:flex-row', radioGroupClassName), onChange: (_) => onChange && onChange(_ === items[0].id) })] }));
|
|
2543
|
+
|
|
2544
|
+
const renderInterestPayment = (props) => renderBinaryRadioButtonGroup({
|
|
2545
|
+
...props,
|
|
2546
|
+
items: [
|
|
2547
|
+
{ id: 'everyMonth', text: 'Ежемесячно' },
|
|
2548
|
+
{ id: 'atEndTerm', text: 'В конце срока' },
|
|
2549
|
+
],
|
|
2761
2550
|
});
|
|
2762
2551
|
|
|
2763
|
-
const
|
|
2764
|
-
|
|
2765
|
-
|
|
2552
|
+
const getLimitRangeByKeys = ([minKey, maxKey], limitParams, rateRows = []) => limitParams && limitParams[minKey] && limitParams[maxKey]
|
|
2553
|
+
? {
|
|
2554
|
+
[minKey]: limitParams[minKey],
|
|
2555
|
+
[maxKey]: limitParams[maxKey],
|
|
2766
2556
|
}
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
const getContainerHeight = (minHeight) => ({
|
|
2776
|
-
height: `calc(100vh - ${HEADER_HEIGHT + FOOTER_HEIGHT + BLOCKS_GAP + PAGE_PADDINGS_X}px)`,
|
|
2777
|
-
minHeight: `${minHeight || DEFAULT_HEIGHT}px`,
|
|
2557
|
+
: getRangeByKeys([minKey, maxKey], rateRows);
|
|
2558
|
+
const getRangeByKeys = ([minKey, maxKey], rows = []) => ({
|
|
2559
|
+
[minKey]: rows.length
|
|
2560
|
+
? min(rows.filter((row) => typeof row[minKey] === 'number').map((row) => row[minKey]))
|
|
2561
|
+
: 0,
|
|
2562
|
+
[maxKey]: rows.length
|
|
2563
|
+
? max(rows.filter((row) => typeof row[minKey] === 'number').map((row) => row[maxKey]))
|
|
2564
|
+
: 0,
|
|
2778
2565
|
});
|
|
2566
|
+
const checkRangeByKeys = (value, [minKey, maxKey], sourceBookRow) => value >= sourceBookRow[minKey] && value <= sourceBookRow[maxKey];
|
|
2779
2567
|
|
|
2780
|
-
const
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
const intersectionObserver = new IntersectionObserver(observerCallback, observerOptions);
|
|
2789
|
-
intersectionObserver.observe(ref.current);
|
|
2790
|
-
return () => {
|
|
2791
|
-
intersectionObserver.disconnect();
|
|
2792
|
-
};
|
|
2793
|
-
}, [observerCallback, observerOptions]);
|
|
2794
|
-
return ref;
|
|
2795
|
-
}
|
|
2796
|
-
function sensitivityToThreshold(sensitivity = 0) {
|
|
2797
|
-
const thresholdsCount = Math.round(sensitivity * SENSITIVITY_SCALE);
|
|
2798
|
-
return Array.from({ length: thresholdsCount })
|
|
2799
|
-
.fill(0)
|
|
2800
|
-
.map((_, thi) => Math.min(thi / thresholdsCount), 1)
|
|
2801
|
-
.concat(1);
|
|
2568
|
+
const DEPOSIT_RATES_SERVICE_MAP = {
|
|
2569
|
+
UL: 'businessdepositrates',
|
|
2570
|
+
IP: 'selfemployeddepositrates',
|
|
2571
|
+
};
|
|
2572
|
+
function useBusinessDepositRates(rateParams) {
|
|
2573
|
+
const serviceName = rateParams?.rateType ? DEPOSIT_RATES_SERVICE_MAP[rateParams?.rateType] : '';
|
|
2574
|
+
const { data } = useAsyncData(serviceName ? `/api/v1/depositrates/${serviceName}` : null, fetchJSONUnsafe);
|
|
2575
|
+
return Array.isArray(data) ? data : [];
|
|
2802
2576
|
}
|
|
2803
2577
|
|
|
2804
|
-
const
|
|
2805
|
-
const
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2578
|
+
const useBusinessDepositCalculatorParams = (userInputParams, rateParams) => {
|
|
2579
|
+
const { daysValue, moneyValue, isPartialWithdrawal, isReplenished, isMonthlyInterestPayment } = userInputParams;
|
|
2580
|
+
const isOperatingDeposit = isReplenished || isPartialWithdrawal;
|
|
2581
|
+
const isDisabledOperatingDeposit = daysValue < BUSINESS_OPERATING_MIN_DAYS || daysValue > BUSINESS_OPERATING_MAX_DAYS;
|
|
2582
|
+
const rateRows = useBusinessDepositRates(rateParams);
|
|
2583
|
+
if (daysValue <= BUSINESS_RATE_MIN_DAYS) {
|
|
2584
|
+
return {
|
|
2585
|
+
...DEFAULT_BUSINESS_DEPOSIT_CALCULATOR_PARAMS,
|
|
2586
|
+
...userInputParams,
|
|
2587
|
+
isDisabledOperatingDeposit,
|
|
2588
|
+
isUnavailableByTerm: true,
|
|
2589
|
+
};
|
|
2590
|
+
}
|
|
2591
|
+
const businessDepositCalculatorSourceBookParams = rateRows?.find((_) => {
|
|
2592
|
+
return (isMonthlyInterestPayment === _.isMonthlyInterestPayment &&
|
|
2593
|
+
checkIsOperatingDeposit(isOperatingDeposit, _) &&
|
|
2594
|
+
checkRangeByKeys(moneyValue, ['minSum', 'maxSum'], _) &&
|
|
2595
|
+
checkRangeByKeys(daysValue, ['minDays', 'maxDays'], _));
|
|
2596
|
+
}) || DEFAULT_BUSINESS_DEPOSIT_CALCULATOR_PARAMS;
|
|
2597
|
+
const { rate } = businessDepositCalculatorSourceBookParams;
|
|
2598
|
+
const income = getDepositIncome$1(rate, userInputParams);
|
|
2599
|
+
const finalSum = moneyValue + income;
|
|
2600
|
+
const sourceBookRows = rateRows || [DEFAULT_BUSINESS_DEPOSIT_CALCULATOR_PARAMS];
|
|
2601
|
+
return {
|
|
2602
|
+
...businessDepositCalculatorSourceBookParams,
|
|
2603
|
+
...getRangeByKeys(['minSum', 'maxSum'], sourceBookRows),
|
|
2604
|
+
...getRangeByKeys(['minDays', 'maxDays'], sourceBookRows),
|
|
2605
|
+
...userInputParams,
|
|
2606
|
+
isDisabledOperatingDeposit,
|
|
2607
|
+
income,
|
|
2608
|
+
finalSum,
|
|
2835
2609
|
};
|
|
2836
|
-
return (jsx("div", { className: style('box-border overflow-auto no-scrollbar', listType, className), style: containerStyle, ref: containerRef, role: "list", children: mapChildren((child, idx) => (jsx(SwipeListItem, { className: style(snapAlign, visibleItemCount ? childStyleMap[visibleItemCount - 1] : '', isVerticalList ? 'h-full' : '', itemClassName), style: isHorizontalList ? getContainerOffset(padding / 4) : {}, activeIndex: activeIndex, idx: idx, observerOptions: observerOptions, onIntersection: handleIntersection, children: child }, String(idx))))(children) }));
|
|
2837
|
-
});
|
|
2838
|
-
// Styles used to compensate outer container padding to get rid of clipping effect
|
|
2839
|
-
const getContainerOffset = (padding, additionalPadding = 0) => ({
|
|
2840
|
-
marginLeft: `${-padding}px`,
|
|
2841
|
-
marginRight: `${-padding}px`,
|
|
2842
|
-
paddingLeft: `${padding}px`,
|
|
2843
|
-
paddingRight: `${padding + additionalPadding}px`,
|
|
2844
|
-
});
|
|
2845
|
-
const getVisibleIndices = (itemsVisibilityList) => itemsVisibilityList
|
|
2846
|
-
.map((_, i) => [_, i])
|
|
2847
|
-
.filter(([_]) => _ && _.intersectionRatio >= 0.9)
|
|
2848
|
-
.map(([, i]) => i);
|
|
2849
|
-
|
|
2850
|
-
const containerStyles = {
|
|
2851
|
-
'horizontal-list': 'mx-auto mt-lg w-fit',
|
|
2852
|
-
'vertical-list': 'absolute flex-col justify-center h-full top-0 left-4',
|
|
2853
2610
|
};
|
|
2854
|
-
const
|
|
2855
|
-
|
|
2856
|
-
|
|
2611
|
+
const checkIsOperatingDeposit = (isOperatingDeposit, sourceBookRow) => isOperatingDeposit
|
|
2612
|
+
? sourceBookRow.isReplenished && sourceBookRow.isPartialWithdrawal
|
|
2613
|
+
: !sourceBookRow.isReplenished && !sourceBookRow.isPartialWithdrawal;
|
|
2614
|
+
const getDepositIncome$1 = (rate, userInputParams) => {
|
|
2615
|
+
const { isMonthlyInterestPayment, moneyValue, daysValue } = userInputParams;
|
|
2616
|
+
/*
|
|
2617
|
+
Приблизительный расчёт, не учитывающий разницу в количестве дней в месяцах. Месяц принят за 30 дней, год за 365 дней.
|
|
2618
|
+
*/
|
|
2619
|
+
if (isMonthlyInterestPayment) {
|
|
2620
|
+
return Math.round(moneyValue * Math.pow((1200 + rate) / 1200, daysValue / 30) - moneyValue);
|
|
2621
|
+
}
|
|
2622
|
+
else {
|
|
2623
|
+
return Math.round((moneyValue * rate * daysValue) / 365 / 100);
|
|
2624
|
+
}
|
|
2857
2625
|
};
|
|
2858
|
-
const dotStyle = 'cursor-pointer rounded-full transition-width duration-300 bg-primary-main group-data-secondary:bg-white group-data-transparent:bg-white';
|
|
2859
|
-
const inactiveDotStyle = 'w-2 h-2 opacity-30';
|
|
2860
|
-
const SwipeListControlDots = JSX(({ className = '', containerRef, activeIndex, dotCount = 0, listType = 'horizontal-list', version, }) => {
|
|
2861
|
-
const handleClick = (idx) => {
|
|
2862
|
-
if (idx !== activeIndex && containerRef?.current) {
|
|
2863
|
-
containerRef.current.children[idx]?.scrollIntoView({
|
|
2864
|
-
behavior: 'smooth',
|
|
2865
|
-
block: 'nearest',
|
|
2866
|
-
});
|
|
2867
|
-
}
|
|
2868
|
-
};
|
|
2869
|
-
return dotCount ? (jsx("div", { className: style('flex gap-xs', containerStyles[listType], version ? 'group' : '', className), "data-ver": version, children: Array.from({ length: dotCount })
|
|
2870
|
-
.fill(null)
|
|
2871
|
-
.map((_, idx) => (jsx("div", { className: `${dotStyle} ${idx === activeIndex ? activeDotStyles[listType] : inactiveDotStyle}`, role: "button", "aria-hidden": true, onClick: () => handleClick(idx) }, String(idx)))) })) : null;
|
|
2872
|
-
});
|
|
2873
2626
|
|
|
2874
|
-
const
|
|
2627
|
+
const BusinessDepositCalculatorForm = JSX(({ className = '', buttons, footnote, bottomFootnote, isShowDepositeName, defaultParams, rateParams, }) => {
|
|
2628
|
+
const [userInputParams, { field }] = useForm({
|
|
2629
|
+
moneyValue: getMoneyDefaultValue(defaultParams, BUSINESS_DEFAULT_SUM),
|
|
2630
|
+
daysValue: getMonthsDefaultValue(defaultParams, BUSINESS_DEFAULT_DAYS),
|
|
2631
|
+
isReplenished: Boolean(defaultParams?.isReplenished),
|
|
2632
|
+
isPartialWithdrawal: Boolean(defaultParams?.isPartialWithdrawal),
|
|
2633
|
+
isMonthlyInterestPayment: Boolean(defaultParams?.isMonthlyInterestPayment),
|
|
2634
|
+
});
|
|
2635
|
+
const calculatorParams = useBusinessDepositCalculatorParams(userInputParams, rateParams);
|
|
2636
|
+
const { income, finalSum, rate, isUnavailableByTerm, depositeName } = calculatorParams;
|
|
2637
|
+
return (jsx(CalculatorFormLayout, { className: className, inputChildren: jsxs("div", { children: [renderWantedSumInput({
|
|
2638
|
+
title: 'Сумма, ₽',
|
|
2639
|
+
min: calculatorParams.minSum,
|
|
2640
|
+
max: calculatorParams.maxSum,
|
|
2641
|
+
...field('moneyValue'),
|
|
2642
|
+
value: calculatorParams.moneyValue,
|
|
2643
|
+
}), renderDaysInput({
|
|
2644
|
+
title: 'Срок, дней',
|
|
2645
|
+
min: calculatorParams.minDays,
|
|
2646
|
+
max: calculatorParams.maxDays,
|
|
2647
|
+
...field('daysValue'),
|
|
2648
|
+
value: calculatorParams.daysValue,
|
|
2649
|
+
}), jsxs("div", { className: "flex flex-col sm:flex-row gap-y-4 gap-x-14", children: [renderBusinessDepositParamsForm(calculatorParams, field), renderInterestPayment({
|
|
2650
|
+
title: 'Выплата процентов',
|
|
2651
|
+
orientation: 'vertical',
|
|
2652
|
+
...field('isMonthlyInterestPayment'),
|
|
2653
|
+
radioGroupClassName: 'sm:flex-col',
|
|
2654
|
+
})] })] }), rateChildren: renderRate({
|
|
2655
|
+
rate,
|
|
2656
|
+
depositeName,
|
|
2657
|
+
isShowDepositeName,
|
|
2658
|
+
isUnavailableByTerm,
|
|
2659
|
+
}), resultChildren: jsxs("div", { children: [renderDepositResults(finalSum, income), renderButtonsSection(buttons, { isVertical: true }), renderFootnote(footnote), renderFootnote(bottomFootnote)] }) }));
|
|
2660
|
+
});
|
|
2661
|
+
const renderBusinessDepositParamsForm = (calculatorParams, field) => (jsxs("div", { className: "space-y-s", children: [jsx(Text, { color: "text-secondary-text", font: "font-light", children: "\u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B" }), jsxs("div", { className: "flex flex-col gap-y-xl sm:gap-y-s", children: [jsx(Checkbox, { text: "\u041F\u043E\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435", disabled: calculatorParams.isDisabledOperatingDeposit, ...field('isReplenished'), value: calculatorParams.isReplenished }), jsx(Checkbox, { disabled: calculatorParams.isDisabledOperatingDeposit, text: "\u0427\u0430\u0441\u0442\u0438\u0447\u043D\u043E\u0435 \u0441\u043D\u044F\u0442\u0438\u0435", ...field('isPartialWithdrawal'), value: calculatorParams.isPartialWithdrawal })] })] }));
|
|
2662
|
+
const renderDepositResults = (finalSum, income) => (jsxs("div", { className: "flex flex-col gap-2xl sm:gap-0 mb-lg", children: [jsx(CalculatorValueBlock, { title: "\u0414\u043E\u0445\u043E\u0434 \u0432 \u043A\u043E\u043D\u0446\u0435 \u0441\u0440\u043E\u043A\u0430", value: income, postfix: "\u20BD", prefix: "+" }), jsx(CalculatorValueBlock, { title: "\u0421\u0443\u043C\u043C\u0430 \u0432 \u043A\u043E\u043D\u0446\u0435 \u0441\u0440\u043E\u043A\u0430", value: finalSum, postfix: "\u20BD" })] }));
|
|
2875
2663
|
|
|
2876
|
-
const
|
|
2877
|
-
|
|
2878
|
-
|
|
2664
|
+
const checkCreditSourceBookRowCommonParams = (props) => checkRowParam$1({
|
|
2665
|
+
...props,
|
|
2666
|
+
fieldKey: 'isSalaryClient',
|
|
2667
|
+
viewSettingFieldKey: 'isShowSalaryClient',
|
|
2668
|
+
}) &&
|
|
2669
|
+
checkRowParam$1({
|
|
2670
|
+
...props,
|
|
2671
|
+
fieldKey: 'isStateEmployee',
|
|
2672
|
+
viewSettingFieldKey: 'isShowStateEmployee',
|
|
2673
|
+
}) &&
|
|
2674
|
+
checkRowParam$1({
|
|
2675
|
+
...props,
|
|
2676
|
+
fieldKey: 'isPensionClient',
|
|
2677
|
+
viewSettingFieldKey: 'isShowPensionClient',
|
|
2678
|
+
}) &&
|
|
2679
|
+
checkRowParam$1({
|
|
2680
|
+
...props,
|
|
2681
|
+
fieldKey: 'isInsurance',
|
|
2682
|
+
viewSettingFieldKey: 'isShowInsurance',
|
|
2683
|
+
});
|
|
2684
|
+
const checkRowParam$1 = ({ row, userInputParams, paramsViewSettings, fieldKey, viewSettingFieldKey, }) => {
|
|
2685
|
+
const isExclude = paramsViewSettings ? !paramsViewSettings[viewSettingFieldKey] : false;
|
|
2686
|
+
return isExclude || userInputParams[fieldKey] === row[fieldKey];
|
|
2879
2687
|
};
|
|
2880
2688
|
|
|
2881
|
-
const
|
|
2882
|
-
|
|
2883
|
-
|
|
2689
|
+
const getCreditCalculatorLimitParams = ({ limitRows, userInputParams, paramsViewSettings, }) => limitRows?.find((row) => checkCreditSourceBookRowCommonParams({
|
|
2690
|
+
row,
|
|
2691
|
+
userInputParams,
|
|
2692
|
+
paramsViewSettings,
|
|
2693
|
+
}));
|
|
2884
2694
|
|
|
2885
|
-
const
|
|
2886
|
-
|
|
2887
|
-
|
|
2695
|
+
const getCreditCalculatorRateParams = ({ rateRows = [], userInputParams, paramsViewSettings, moneyValue, monthsValue, }) => rateRows?.find((row) => checkCreditSourceBookRowCommonParams({
|
|
2696
|
+
row,
|
|
2697
|
+
userInputParams,
|
|
2698
|
+
paramsViewSettings,
|
|
2699
|
+
}) &&
|
|
2700
|
+
checkRangeByKeys(moneyValue, ['minSum', 'maxSum'], row) &&
|
|
2701
|
+
checkRangeByKeys(monthsValue, ['minMonths', 'maxMonths'], row)) || DEFAULT_CREDIT_CALCULATOR_PARAMS;
|
|
2888
2702
|
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
if (!containerRef.current) {
|
|
2903
|
-
return;
|
|
2904
|
-
}
|
|
2905
|
-
if (canScrollLeft) {
|
|
2906
|
-
scrollBy(containerRef.current)(itemCount, -1);
|
|
2703
|
+
/**
|
|
2704
|
+
* Формулы расчёта аннуитетных и дифференцированных платежей:
|
|
2705
|
+
* https://finuslugi.ru/potrebitelskie_kredity/stat_annuitetnye_i_differentsirovannye_platezhi
|
|
2706
|
+
*/
|
|
2707
|
+
const getMonthlyPayment = (rate, params) => {
|
|
2708
|
+
const { isAnnuity, moneyValue, monthsValue, moneyExtra } = params;
|
|
2709
|
+
if (rate === 0) {
|
|
2710
|
+
return 0;
|
|
2711
|
+
}
|
|
2712
|
+
else if (isAnnuity) {
|
|
2713
|
+
const i = rate / MONTHLY_INTEREST_RATE; // Используется значение ставки в процентах
|
|
2714
|
+
if (moneyExtra) {
|
|
2715
|
+
return (moneyValue + moneyExtra) * (i + i / (Math.pow(1 + i, monthsValue) - 1));
|
|
2907
2716
|
}
|
|
2908
2717
|
else {
|
|
2909
|
-
|
|
2910
|
-
}
|
|
2911
|
-
}, [itemCount, canScrollLeft]);
|
|
2912
|
-
const scrollRight = useCallback(() => {
|
|
2913
|
-
if (!containerRef.current) {
|
|
2914
|
-
return;
|
|
2718
|
+
return moneyValue * (i + i / (Math.pow(1 + i, monthsValue) - 1));
|
|
2915
2719
|
}
|
|
2916
|
-
|
|
2917
|
-
|
|
2720
|
+
}
|
|
2721
|
+
else {
|
|
2722
|
+
return Math.round(moneyValue / monthsValue) + moneyValue * (rate / (MONTHS_IN_YEAR * 100)); // Используется значение ставки (rate) в процентах, делённое на сто.
|
|
2723
|
+
}
|
|
2724
|
+
};
|
|
2725
|
+
|
|
2726
|
+
const getCreditCalculatorParams = (userInputParams, calcSource, paramsViewSettings) => {
|
|
2727
|
+
const { moneyValue, monthsValue } = userInputParams;
|
|
2728
|
+
const rateRows = calcSource?.rateRows || [DEFAULT_CREDIT_CALCULATOR_PARAMS];
|
|
2729
|
+
const limitRows = calcSource?.limitRows || [];
|
|
2730
|
+
const creditCalculatorSourceBookLimitParams = getCreditCalculatorLimitParams({
|
|
2731
|
+
limitRows,
|
|
2732
|
+
userInputParams,
|
|
2733
|
+
paramsViewSettings,
|
|
2734
|
+
});
|
|
2735
|
+
const { minSum, maxSum } = getLimitRangeByKeys(['minSum', 'maxSum'], creditCalculatorSourceBookLimitParams, rateRows);
|
|
2736
|
+
const { minMonths, maxMonths } = getLimitRangeByKeys(['minMonths', 'maxMonths'], creditCalculatorSourceBookLimitParams, rateRows);
|
|
2737
|
+
const creditCalculatorRateParams = getCreditCalculatorRateParams({
|
|
2738
|
+
rateRows,
|
|
2739
|
+
userInputParams,
|
|
2740
|
+
paramsViewSettings,
|
|
2741
|
+
moneyValue,
|
|
2742
|
+
monthsValue,
|
|
2743
|
+
});
|
|
2744
|
+
const { rate } = creditCalculatorRateParams;
|
|
2745
|
+
const monthlyPayment = getMonthlyPayment(rate, userInputParams);
|
|
2746
|
+
return {
|
|
2747
|
+
...creditCalculatorRateParams,
|
|
2748
|
+
...userInputParams,
|
|
2749
|
+
minSum,
|
|
2750
|
+
maxSum,
|
|
2751
|
+
minMonths,
|
|
2752
|
+
maxMonths,
|
|
2753
|
+
moneyValue,
|
|
2754
|
+
monthsValue,
|
|
2755
|
+
monthlyPayment,
|
|
2756
|
+
};
|
|
2757
|
+
};
|
|
2758
|
+
|
|
2759
|
+
const STEP_MONTHS = 1;
|
|
2760
|
+
const renderMonthsInput = ({ min = 0, max = 0, availableMonths, ...rest }) => (jsx(InputRange, { items: [`От ${monthText(min)}`, `До ${monthText(max)}`], step: STEP_MONTHS, ...(availableMonths?.length ? { list: availableMonths } : { min, max }), ...rest }));
|
|
2761
|
+
const monthText = (month) => `${month} ${Number(month) % 10 === 1 ? 'месяца' : 'месяцев'}`;
|
|
2762
|
+
|
|
2763
|
+
const renderPaymentType = (props) => renderBinaryRadioButtonGroup({
|
|
2764
|
+
...props,
|
|
2765
|
+
radioGroupClassName: 'sm:flex-col',
|
|
2766
|
+
items: [
|
|
2767
|
+
{ id: 'annuity', text: 'Аннуитетный' },
|
|
2768
|
+
{ id: 'differential', text: 'Дифференцированный' },
|
|
2769
|
+
],
|
|
2770
|
+
});
|
|
2771
|
+
|
|
2772
|
+
const CreditCalculatorForm = JSX(({ className, calcSource, buttons, footnote, paramsViewSettings, defaultParams }) => {
|
|
2773
|
+
const [userInputParams, { field }] = useForm({
|
|
2774
|
+
moneyValue: getMoneyDefaultValue(defaultParams, CREDIT_DEFAULT_SUM),
|
|
2775
|
+
monthsValue: getMonthsDefaultValue(defaultParams, DEFAULT_MONTHS),
|
|
2776
|
+
isAnnuity: Boolean(defaultParams?.isAnnuity),
|
|
2777
|
+
isInsurance: Boolean(defaultParams?.isEnableInsurance),
|
|
2778
|
+
isSalaryClient: Boolean(defaultParams?.isEnableSalaryClient),
|
|
2779
|
+
isPensionClient: Boolean(defaultParams?.isEnablePensionClient),
|
|
2780
|
+
isStateEmployee: Boolean(defaultParams?.isEnableStateEmployee),
|
|
2781
|
+
});
|
|
2782
|
+
const calculatorParams = getCreditCalculatorParams(userInputParams, calcSource, paramsViewSettings);
|
|
2783
|
+
const paymentTypeElement = renderPaymentType({
|
|
2784
|
+
title: '',
|
|
2785
|
+
mobileTitle: 'Тип платежа',
|
|
2786
|
+
orientation: 'vertical',
|
|
2787
|
+
...field('isAnnuity'),
|
|
2788
|
+
});
|
|
2789
|
+
const { onChange: setMoneyValue } = field('moneyValue');
|
|
2790
|
+
const { onChange: setMonthsValue } = field('monthsValue');
|
|
2791
|
+
useEffect(() => {
|
|
2792
|
+
setMoneyValue &&
|
|
2793
|
+
setMoneyValue(clamp(userInputParams.moneyValue, calculatorParams.minSum, calculatorParams.maxSum));
|
|
2794
|
+
}, [calculatorParams.minSum, calculatorParams.maxSum]);
|
|
2795
|
+
useEffect(() => {
|
|
2796
|
+
setMonthsValue &&
|
|
2797
|
+
setMonthsValue(clamp(userInputParams.monthsValue, calculatorParams.minMonths, calculatorParams.maxMonths));
|
|
2798
|
+
}, [calculatorParams.minMonths, calculatorParams.maxMonths]);
|
|
2799
|
+
return (jsx(CalculatorFormLayout, { className: className, inputChildren: jsxs("div", { children: [renderWantedSumInput({
|
|
2800
|
+
title: 'Сумма кредита, ₽',
|
|
2801
|
+
step: 500,
|
|
2802
|
+
min: calculatorParams.minSum,
|
|
2803
|
+
max: calculatorParams.maxSum,
|
|
2804
|
+
...field('moneyValue'),
|
|
2805
|
+
value: calculatorParams.moneyValue,
|
|
2806
|
+
}), renderMonthsInput({
|
|
2807
|
+
title: 'Срок кредита, месяцев',
|
|
2808
|
+
min: calculatorParams.minMonths,
|
|
2809
|
+
max: calculatorParams.maxMonths,
|
|
2810
|
+
...field('monthsValue'),
|
|
2811
|
+
value: calculatorParams.monthsValue,
|
|
2812
|
+
}), renderCreditParamsForm$1({ ...calculatorParams, ...paramsViewSettings }, field), jsx("div", { className: "sm:hidden", children: paymentTypeElement })] }), rateChildren: renderRate({
|
|
2813
|
+
rate: calculatorParams.rate,
|
|
2814
|
+
}), resultChildren: jsxs("div", { children: [jsx(CalculatorValueBlock, { title: "\u0415\u0436\u0435\u043C\u0435\u0441\u044F\u0447\u043D\u044B\u0439 \u043F\u043B\u0430\u0442\u0451\u0436", value: calculatorParams.monthlyPayment, postfix: "\u20BD" }), jsx("div", { className: "hidden sm:block mb-lg", children: paymentTypeElement }), renderButtonsSection(buttons, { isVertical: true }), renderFootnote(footnote)] }) }));
|
|
2815
|
+
});
|
|
2816
|
+
const renderCreditParamsForm$1 = (params, field) => (jsxs("div", { className: "flex flex-col gap-y-2xl", children: [params.isShowSalaryClient ? (jsx(Checkbox, { text: `Получаю зарплату на счёт\nв Россельхозбанке`, ...field('isSalaryClient'), value: params.isSalaryClient, className: "whitespace-pre-line sm:whitespace-normal" })) : null, params.isShowStateEmployee ? (jsx(Checkbox, { text: "\u0420\u0430\u0431\u043E\u0442\u0430\u044E \u0432 \u0431\u044E\u0434\u0436\u0435\u0442\u043D\u043E\u0439 \u043E\u0440\u0433\u0430\u043D\u0438\u0437\u0430\u0446\u0438\u0438", ...field('isStateEmployee'), value: params.isStateEmployee })) : null, params.isShowPensionClient ? (jsx(Checkbox, { text: "\u041F\u043E\u043B\u0443\u0447\u0430\u044E \u043F\u0435\u043D\u0441\u0438\u044E \u043D\u0430 \u043A\u0430\u0440\u0442\u0443 \u0420\u043E\u0441\u0441\u0435\u043B\u044C\u0445\u043E\u0437\u0431\u0430\u043D\u043A\u0430", ...field('isPensionClient'), value: params.isPensionClient })) : null, params.isShowInsurance ? (jsx(Checkbox, { text: "\u041A\u043E\u043C\u043F\u043B\u0435\u043A\u0441\u043D\u0430\u044F \u0441\u0442\u0440\u0430\u0445\u043E\u0432\u0430\u044F \u0437\u0430\u0449\u0438\u0442\u0430", ...field('isInsurance'), value: params.isInsurance })) : null] }));
|
|
2817
|
+
|
|
2818
|
+
const arrayByRange = (start, stop, step = 1) => Array.from({ length: Math.abs(stop - start) / step + 1 }, (value, index) => stop >= start ? start + index * step : start - index * step);
|
|
2819
|
+
|
|
2820
|
+
const mergeIntervals = (intervals) => {
|
|
2821
|
+
const result = [...intervals];
|
|
2822
|
+
result.sort(([a], [c]) => a - c);
|
|
2823
|
+
let i = 1;
|
|
2824
|
+
while (i < result.length) {
|
|
2825
|
+
const [a, b] = result[i - 1];
|
|
2826
|
+
const [c, d] = result[i];
|
|
2827
|
+
if (b >= c) {
|
|
2828
|
+
result.splice(i - 1, 2, [a, Math.max(b, d)]);
|
|
2918
2829
|
}
|
|
2919
2830
|
else {
|
|
2920
|
-
|
|
2921
|
-
}
|
|
2922
|
-
}, [itemCount, canScrollRight]);
|
|
2923
|
-
const scrollTo = useCallback((idx, options = {
|
|
2924
|
-
behavior: 'smooth',
|
|
2925
|
-
block: 'nearest',
|
|
2926
|
-
inline: 'center',
|
|
2927
|
-
}) => {
|
|
2928
|
-
if (containerRef?.current) {
|
|
2929
|
-
containerRef.current.children[idx]?.scrollIntoView(options);
|
|
2831
|
+
i++;
|
|
2930
2832
|
}
|
|
2931
|
-
}
|
|
2932
|
-
return
|
|
2933
|
-
containerRef,
|
|
2934
|
-
{
|
|
2935
|
-
scrollLeft,
|
|
2936
|
-
scrollRight,
|
|
2937
|
-
scrollTo,
|
|
2938
|
-
canScrollLeft,
|
|
2939
|
-
canScrollRight,
|
|
2940
|
-
visibleIndicesRange: [minIndex, maxIndex],
|
|
2941
|
-
handleVisibleIndicesChange,
|
|
2942
|
-
},
|
|
2943
|
-
];
|
|
2833
|
+
}
|
|
2834
|
+
return result;
|
|
2944
2835
|
};
|
|
2945
2836
|
|
|
2946
|
-
const
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
const
|
|
2952
|
-
const
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
}
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2837
|
+
const getDepositCalculatorParams = (userInputParams, calcSource, paramsViewSettings) => {
|
|
2838
|
+
const { moneyValue, monthsValue } = userInputParams;
|
|
2839
|
+
const defaultMonth = calcSource?.rateRows?.[0]
|
|
2840
|
+
? getMiddleMonth(calcSource.rateRows[0].minMonths, calcSource.rateRows[0].maxMonths)
|
|
2841
|
+
: 0;
|
|
2842
|
+
const isExcludeMonthlyInterestPayment = !paramsViewSettings?.isShowMonthlyInterestPayment;
|
|
2843
|
+
const isExcludeRemoteRegistration = !paramsViewSettings?.isShowRemoteRegistration;
|
|
2844
|
+
const depositCalculatorSourceBookParams = calcSource?.rateRows?.find((row) => checkRowByParam({
|
|
2845
|
+
row,
|
|
2846
|
+
userInputParams,
|
|
2847
|
+
paramKey: 'isMonthlyInterestPayment',
|
|
2848
|
+
isExclude: isExcludeMonthlyInterestPayment,
|
|
2849
|
+
}) &&
|
|
2850
|
+
checkRowByParam({
|
|
2851
|
+
row,
|
|
2852
|
+
userInputParams,
|
|
2853
|
+
paramKey: 'isRemoteRegistration',
|
|
2854
|
+
isExclude: isExcludeRemoteRegistration,
|
|
2855
|
+
}) &&
|
|
2856
|
+
checkRangeByKeys(moneyValue, ['minSum', 'maxSum'], row) &&
|
|
2857
|
+
checkRangeByKeys(monthsValue || defaultMonth, ['minMonths', 'maxMonths'], row)) || DEFAULT_DEPOSIT_CALCULATOR_PARAMS;
|
|
2858
|
+
const { rate } = depositCalculatorSourceBookParams;
|
|
2859
|
+
const income = getDepositIncome(rate, userInputParams);
|
|
2860
|
+
const finalSum = moneyValue + income;
|
|
2861
|
+
const sourceBookRows = calcSource?.rateRows || [DEFAULT_DEPOSIT_CALCULATOR_PARAMS];
|
|
2862
|
+
return {
|
|
2863
|
+
...depositCalculatorSourceBookParams,
|
|
2864
|
+
...getRangeByKeys(['minSum', 'maxSum'], sourceBookRows),
|
|
2865
|
+
...getRangeByKeys(['minMonths', 'maxMonths'], sourceBookRows),
|
|
2866
|
+
availableMonths: mergeIntervals(sourceBookRows.map((row) => [row['minMonths'], row['maxMonths']])).flatMap(([start, end]) => arrayByRange(start, end)),
|
|
2867
|
+
...userInputParams,
|
|
2868
|
+
defaultMonth,
|
|
2869
|
+
income,
|
|
2870
|
+
finalSum,
|
|
2871
|
+
};
|
|
2872
|
+
};
|
|
2873
|
+
const getDepositIncome = (rate, userInputParams) => {
|
|
2874
|
+
const { isMonthlyInterestPayment, moneyValue, monthsValue } = userInputParams;
|
|
2875
|
+
if (isMonthlyInterestPayment) {
|
|
2876
|
+
return Math.round(moneyValue * Math.pow((1200 + rate) / 1200, monthsValue) - moneyValue);
|
|
2877
|
+
}
|
|
2878
|
+
else {
|
|
2879
|
+
/*
|
|
2880
|
+
Приблизительный расчёт, не учитывающий разницу в количестве дней в месяцах. Месяц принят за 30 дней, год за 365 дней.
|
|
2881
|
+
*/
|
|
2882
|
+
return Math.round((moneyValue * rate * 30 * monthsValue) / 365 / 100);
|
|
2883
|
+
}
|
|
2884
|
+
};
|
|
2885
|
+
const checkRowByParam = ({ row, userInputParams, paramKey, isExclude }) => isExclude || userInputParams[paramKey] === row[paramKey];
|
|
2886
|
+
const getMiddleMonth = (minMonths, maxMonths) => minMonths + Math.round((maxMonths - minMonths) / 2);
|
|
2887
|
+
|
|
2888
|
+
const renderRegistrationType = (props) => renderBinaryRadioButtonGroup({
|
|
2889
|
+
...props,
|
|
2890
|
+
items: [
|
|
2891
|
+
{ id: 'remote', text: 'Дистанционно' },
|
|
2892
|
+
{ id: 'office', text: 'Офис Банка' },
|
|
2893
|
+
],
|
|
2894
|
+
});
|
|
2895
|
+
|
|
2896
|
+
const DepositCalculatorForm = JSX((props) => {
|
|
2897
|
+
const { className, calcSource, buttons, footnote, paramsViewSettings, defaultParams } = props;
|
|
2898
|
+
const [userInputParams, { field }] = useForm({
|
|
2899
|
+
moneyValue: getMoneyDefaultValue(defaultParams, DEPOSIT_DEFAULT_SUM),
|
|
2900
|
+
monthsValue: getMonthsDefaultValue(defaultParams),
|
|
2901
|
+
isMonthlyInterestPayment: Boolean(defaultParams?.isMonthlyInterestPayment),
|
|
2902
|
+
isRemoteRegistration: Boolean(defaultParams?.isRemoteRegistration),
|
|
2903
|
+
});
|
|
2904
|
+
const calculatorParams = getDepositCalculatorParams(userInputParams, calcSource, paramsViewSettings);
|
|
2905
|
+
const { defaultMonth, rate, income, finalSum } = calculatorParams;
|
|
2906
|
+
const { onChange: setMonthsValue } = field('monthsValue');
|
|
2907
|
+
const { onChange: setMoneyValue } = field('moneyValue');
|
|
2908
|
+
useEffect(() => {
|
|
2909
|
+
!userInputParams.monthsValue && setMonthsValue && setMonthsValue(defaultMonth);
|
|
2910
|
+
}, [defaultMonth]);
|
|
2911
|
+
useEffect(() => {
|
|
2912
|
+
setMoneyValue &&
|
|
2913
|
+
setMoneyValue(clamp(userInputParams.moneyValue, calculatorParams.minSum, calculatorParams.maxSum));
|
|
2914
|
+
}, [calculatorParams.minSum, calculatorParams.maxSum]);
|
|
2915
|
+
return (jsx(CalculatorFormLayout, { className: className, inputChildren: jsxs("div", { children: [renderWantedSumInput({
|
|
2916
|
+
title: 'Сумма, ₽',
|
|
2917
|
+
min: calculatorParams.minSum,
|
|
2918
|
+
max: calculatorParams.maxSum,
|
|
2919
|
+
...field('moneyValue'),
|
|
2920
|
+
value: calculatorParams.moneyValue,
|
|
2921
|
+
}), renderMonthsInput({
|
|
2922
|
+
title: 'Срок, месяцев',
|
|
2923
|
+
min: calculatorParams.minMonths,
|
|
2924
|
+
max: calculatorParams.maxMonths,
|
|
2925
|
+
availableMonths: calculatorParams.availableMonths,
|
|
2926
|
+
...field('monthsValue'),
|
|
2927
|
+
value: calculatorParams.monthsValue,
|
|
2928
|
+
}), renderDepositParamsForm({ ...calculatorParams, ...paramsViewSettings }, field)] }), rateChildren: renderRate({
|
|
2929
|
+
rate,
|
|
2930
|
+
}), resultChildren: jsxs("div", { children: [jsx(CalculatorValueBlock, { title: "\u0414\u043E\u0445\u043E\u0434 \u0432 \u043A\u043E\u043D\u0446\u0435 \u0441\u0440\u043E\u043A\u0430", value: income, postfix: "\u20BD", prefix: "+" }), jsx(CalculatorValueBlock, { title: "\u0421\u0443\u043C\u043C\u0430 \u0432 \u043A\u043E\u043D\u0446\u0435 \u0441\u0440\u043E\u043A\u0430", value: finalSum, postfix: "\u20BD" }), renderButtonsSection(buttons, { isVertical: true }), renderFootnote(footnote)] }) }));
|
|
2931
|
+
});
|
|
2932
|
+
const renderDepositParamsForm = (params, field) => (jsxs("div", { className: "flex flex-col gap-y-2xl", children: [params.isShowMonthlyInterestPayment
|
|
2933
|
+
? renderInterestPayment({
|
|
2934
|
+
title: 'Выплата процентов',
|
|
2935
|
+
...field('isMonthlyInterestPayment'),
|
|
2936
|
+
value: params.isMonthlyInterestPayment,
|
|
2937
|
+
})
|
|
2938
|
+
: null, params.isShowRemoteRegistration
|
|
2939
|
+
? renderRegistrationType({
|
|
2940
|
+
title: 'Оформление',
|
|
2941
|
+
...field('isRemoteRegistration'),
|
|
2942
|
+
value: params.isRemoteRegistration,
|
|
2943
|
+
})
|
|
2944
|
+
: null] }));
|
|
2945
|
+
|
|
2946
|
+
const checkRefinancingSourceBookRowCommonParams = (props) => checkRowParam({
|
|
2947
|
+
...props,
|
|
2948
|
+
fieldKey: 'isSalaryClient',
|
|
2949
|
+
viewSettingFieldKey: 'isShowSalaryClient',
|
|
2950
|
+
}) &&
|
|
2951
|
+
checkRowParam({
|
|
2952
|
+
...props,
|
|
2953
|
+
fieldKey: 'isInsurance',
|
|
2954
|
+
viewSettingFieldKey: 'isShowInsurance',
|
|
2955
|
+
});
|
|
2956
|
+
const checkRowParam = ({ row, userInputParams, paramsViewSettings, fieldKey, viewSettingFieldKey, }) => {
|
|
2957
|
+
const isExclude = paramsViewSettings ? !paramsViewSettings[viewSettingFieldKey] : false;
|
|
2958
|
+
return isExclude || userInputParams[fieldKey] === row[fieldKey];
|
|
2959
|
+
};
|
|
2960
|
+
|
|
2961
|
+
const getRefinancingCalculatorLimitParams = ({ limitRows, userInputParams, paramsViewSettings, }) => limitRows?.find((row) => checkRefinancingSourceBookRowCommonParams({
|
|
2962
|
+
row,
|
|
2963
|
+
userInputParams,
|
|
2964
|
+
paramsViewSettings,
|
|
2965
|
+
}));
|
|
2966
|
+
|
|
2967
|
+
const getRefinancingCalculatorRateParams = ({ rateRows = [], userInputParams, paramsViewSettings, moneyValue, monthsValue, oldMonthlyPayment, moneyExtra, }) => rateRows?.find((row) => checkRefinancingSourceBookRowCommonParams({
|
|
2968
|
+
row,
|
|
2969
|
+
userInputParams,
|
|
2970
|
+
paramsViewSettings,
|
|
2971
|
+
}) &&
|
|
2972
|
+
checkRangeByKeys(moneyValue + moneyExtra, ['minSum', 'maxSum'], row) &&
|
|
2973
|
+
checkRangeByKeys(oldMonthlyPayment, ['minSumOld', 'maxSumOld'], row) &&
|
|
2974
|
+
checkRangeByKeys(moneyExtra, ['minSumExtra', 'maxSumExtra'], row) &&
|
|
2975
|
+
checkRangeByKeys(monthsValue, ['minMonths', 'maxMonths'], row)) || DEFAULT_REFINANCING_CALCULATOR_PARAMS;
|
|
2976
|
+
|
|
2977
|
+
const getRefinancingCalculatorParams = (userInputParams, calcSource, paramsViewSettings) => {
|
|
2978
|
+
const { moneyValue, monthsValue, oldMonthlyPayment, moneyExtra } = userInputParams;
|
|
2979
|
+
const rateRows = calcSource?.rateRows || [DEFAULT_REFINANCING_CALCULATOR_PARAMS];
|
|
2980
|
+
const limitRows = calcSource?.limitRows || [];
|
|
2981
|
+
const sourceBookLimitParams = getRefinancingCalculatorLimitParams({
|
|
2982
|
+
limitRows,
|
|
2983
|
+
userInputParams,
|
|
2984
|
+
paramsViewSettings,
|
|
2985
|
+
});
|
|
2986
|
+
const { minSum, maxSum } = getLimitRangeByKeys(['minSum', 'maxSum'], sourceBookLimitParams, rateRows);
|
|
2987
|
+
const { minMonths, maxMonths } = getLimitRangeByKeys(['minMonths', 'maxMonths'], sourceBookLimitParams, rateRows);
|
|
2988
|
+
const refinancingCalculatorSourceBookRateParams = getRefinancingCalculatorRateParams({
|
|
2989
|
+
rateRows,
|
|
2990
|
+
userInputParams,
|
|
2991
|
+
paramsViewSettings,
|
|
2992
|
+
moneyValue,
|
|
2993
|
+
monthsValue,
|
|
2994
|
+
oldMonthlyPayment,
|
|
2995
|
+
moneyExtra,
|
|
2996
|
+
});
|
|
2997
|
+
const { rate } = refinancingCalculatorSourceBookRateParams;
|
|
2998
|
+
const monthlyPayment = getMonthlyPayment(rate, userInputParams);
|
|
2999
|
+
const benefit = userInputParams.oldMonthlyPayment - monthlyPayment;
|
|
3000
|
+
return {
|
|
3001
|
+
...refinancingCalculatorSourceBookRateParams,
|
|
3002
|
+
...userInputParams,
|
|
3003
|
+
minSum,
|
|
3004
|
+
maxSum,
|
|
3005
|
+
minMonths,
|
|
3006
|
+
maxMonths,
|
|
3007
|
+
moneyValue,
|
|
3008
|
+
monthsValue,
|
|
3009
|
+
oldMonthlyPayment,
|
|
3010
|
+
moneyExtra,
|
|
3011
|
+
monthlyPayment,
|
|
3012
|
+
benefit,
|
|
3013
|
+
};
|
|
3014
|
+
};
|
|
3015
|
+
|
|
3016
|
+
const RefinancingCalculatorForm = JSX(({ className, calcSource, buttons, footnote, paramsViewSettings }) => {
|
|
3017
|
+
const [userInputParams, { field }] = useForm({
|
|
3018
|
+
isAnnuity: true,
|
|
3019
|
+
isInsurance: true,
|
|
3020
|
+
isSalaryClient: false,
|
|
3021
|
+
isExtraMoney: false,
|
|
3022
|
+
moneyValue: REFINANCING_DEFAULT_SUM,
|
|
3023
|
+
oldMonthlyPayment: REFINANCING_OLD_DEFAULT_SUM,
|
|
3024
|
+
monthsValue: DEFAULT_REFINANCING_MONTHS,
|
|
3025
|
+
moneyExtra: REFINANCING_OLD_DEFAULT_SUM,
|
|
3026
|
+
});
|
|
3027
|
+
const calculatorParams = getRefinancingCalculatorParams(userInputParams, calcSource, paramsViewSettings);
|
|
3028
|
+
const paymentTypeElement = renderPaymentType({
|
|
3029
|
+
title: '',
|
|
3030
|
+
mobileTitle: 'Тип платежа',
|
|
3031
|
+
orientation: 'vertical',
|
|
3032
|
+
...field('isAnnuity'),
|
|
3033
|
+
});
|
|
3034
|
+
return (jsx(CalculatorFormLayout, { className: className, inputChildren: jsxs("div", { children: [renderWantedSumInput({
|
|
3035
|
+
title: 'Остаток долга в других банках, ₽ ',
|
|
3036
|
+
step: 500,
|
|
3037
|
+
min: calculatorParams.minSum,
|
|
3038
|
+
max: calculatorParams.maxSum - calculatorParams.maxSumExtra,
|
|
3039
|
+
...field('moneyValue'),
|
|
3040
|
+
value: calculatorParams.moneyValue,
|
|
3041
|
+
}), renderWantedSumInput({
|
|
3042
|
+
title: 'Ежемесячный платёж в других банках, ₽',
|
|
3043
|
+
step: 500,
|
|
3044
|
+
min: calculatorParams.minSumOld,
|
|
3045
|
+
max: calculatorParams.maxSumOld,
|
|
3046
|
+
...field('oldMonthlyPayment'),
|
|
3047
|
+
value: calculatorParams.oldMonthlyPayment,
|
|
3048
|
+
}), renderMonthsInput({
|
|
3049
|
+
title: 'Новый срок кредита, месяцев',
|
|
3050
|
+
min: calculatorParams.minMonths,
|
|
3051
|
+
max: calculatorParams.maxMonths,
|
|
3052
|
+
...field('monthsValue'),
|
|
3053
|
+
value: calculatorParams.monthsValue,
|
|
3054
|
+
}), renderCreditParamsForm({ ...calculatorParams, ...paramsViewSettings }, field), calculatorParams.isExtraMoney
|
|
3055
|
+
? renderWantedSumInput({
|
|
3056
|
+
title: 'Дополнительная сумма, ₽ ',
|
|
3057
|
+
step: 500,
|
|
3058
|
+
min: calculatorParams.minSumExtra,
|
|
3059
|
+
max: calculatorParams.maxSumExtra,
|
|
3060
|
+
...field('moneyExtra'),
|
|
3061
|
+
value: calculatorParams.moneyExtra,
|
|
3062
|
+
})
|
|
3063
|
+
: null, jsx("div", { className: "sm:hidden pt-1 pb-4 border-b border-main-divider", children: paymentTypeElement })] }), rateChildren: renderRate({
|
|
3064
|
+
rate: calculatorParams.rate,
|
|
3065
|
+
fractionDigits: 1,
|
|
3066
|
+
}), resultChildren: jsxs("div", { children: [jsx(CalculatorValueBlock, { title: "\u0415\u0436\u0435\u043C\u0435\u0441\u044F\u0447\u043D\u044B\u0439 \u043F\u043B\u0430\u0442\u0451\u0436", value: calculatorParams.monthlyPayment, postfix: "\u20BD" }), calculatorParams.benefit > 0 ? (jsx(CalculatorValueBlock, { title: 'Выгода в месяц', value: calculatorParams.benefit, postfix: "\u20BD" })) : null, jsx("div", { className: "hidden sm:block mb-lg", children: paymentTypeElement }), renderButtonsSection(buttons, { isVertical: true }), renderFootnote(footnote)] }) }));
|
|
2971
3067
|
});
|
|
2972
|
-
const
|
|
3068
|
+
const renderCreditParamsForm = (params, field) => (jsxs("div", { className: "space-y-lg sm:space-y-s", children: [params.isShowSalaryClient ? (jsx(Checkbox, { text: "\u041F\u043E\u043B\u0443\u0447\u0430\u044E \u0437\u0430\u0440\u043F\u043B\u0430\u0442\u0443 \u043D\u0430 \u0441\u0447\u0451\u0442 \u0432 \u0420\u043E\u0441\u0441\u0435\u043B\u044C\u0445\u043E\u0437\u0431\u0430\u043D\u043A\u0435", ...field('isSalaryClient'), value: params.isSalaryClient })) : null, params.isShowInsurance ? (jsx(Checkbox, { text: "\u041A\u043E\u043C\u043F\u043B\u0435\u043A\u0441\u043D\u0430\u044F \u0441\u0442\u0440\u0430\u0445\u043E\u0432\u0430\u044F \u0437\u0430\u0449\u0438\u0442\u0430", ...field('isInsurance'), value: params.isInsurance })) : null, jsx(Checkbox, { text: "\u041F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0443\u044E \u0441\u0443\u043C\u043C\u0443", ...field('isExtraMoney'), value: params.isExtraMoney })] }));
|
|
2973
3069
|
|
|
2974
|
-
const
|
|
3070
|
+
const EmbeddableCalcBlocks = {
|
|
3071
|
+
CreditCalculatorForm,
|
|
3072
|
+
DepositCalculatorForm,
|
|
3073
|
+
BusinessDepositCalculatorForm,
|
|
3074
|
+
BonusCalculatorForm,
|
|
3075
|
+
RefinancingCalculatorForm,
|
|
3076
|
+
};
|
|
2975
3077
|
|
|
2976
|
-
const
|
|
2977
|
-
|
|
2978
|
-
|
|
3078
|
+
const renderCalculatorBlock = (block, i) => {
|
|
3079
|
+
const type = block?.calcType;
|
|
3080
|
+
if (!type || !(type in EmbeddableCalcBlocks)) {
|
|
3081
|
+
return null;
|
|
3082
|
+
}
|
|
3083
|
+
const EmbeddedBlock = EmbeddableCalcBlocks[type];
|
|
3084
|
+
return (jsx("section", { className: "box-border relative bg-white flex shrink-0 self-start basis-full", role: "listitem", children: jsxs("div", { className: "box-border p-4xl w-full space-y-xl", children: [block?.title ? jsx(Heading, { className: "text-center", title: block.title }) : null, jsx(EmbeddedBlock, { ...block })] }) }, String(i)));
|
|
3085
|
+
};
|
|
2979
3086
|
|
|
2980
|
-
const
|
|
3087
|
+
const Calculator = UniBlock(({ className = '', tabAlign, calculatorTabs = [], ...rest }) => {
|
|
3088
|
+
const tabsNav = calculatorTabs.map((_) => _.nav || {});
|
|
3089
|
+
const calculatorBlocks = calculatorTabs.map(({ calculatorBlock }) => calculatorBlock || {});
|
|
3090
|
+
const [slideIndexShift, setSlideIndexShift] = useState(0);
|
|
3091
|
+
const handleSlideIndexShift = useCallback((_) => setSlideIndexShift(_), []);
|
|
3092
|
+
const COLUMNS_FOR_SCROLL = 3;
|
|
3093
|
+
const [activeIndex, controls] = useCarouselControls({
|
|
3094
|
+
itemCount: calculatorTabs?.length,
|
|
3095
|
+
visibleItemCount: COLUMNS_FOR_SCROLL,
|
|
3096
|
+
});
|
|
3097
|
+
return (jsxs(BlockWrapper, { className: style('box-border overflow-hidden relative', className), defaultPadding: "p-0", ...rest, children: [jsxs("div", { className: "bg-white", children: [tabsNav.length > 1
|
|
3098
|
+
? renderTabs$1({
|
|
3099
|
+
activeIndex,
|
|
3100
|
+
tabsNav,
|
|
3101
|
+
tabAlign,
|
|
3102
|
+
slideIndexShift,
|
|
3103
|
+
onClick: handleSlideIndexShift,
|
|
3104
|
+
})
|
|
3105
|
+
: null, renderArrows({
|
|
3106
|
+
...controls,
|
|
3107
|
+
btnClass: ['left-3', 'right-3'],
|
|
3108
|
+
className: 'top-10',
|
|
3109
|
+
})] }), jsx("div", { className: "flex", style: { transform: `translateX(-${slideIndexShift}00%)` }, role: "list", children: calculatorBlocks?.length ? calculatorBlocks.map(renderCalculatorBlock) : null })] }));
|
|
3110
|
+
});
|
|
3111
|
+
function renderNavButton$3({ tab, i, isActive, onClick }) {
|
|
3112
|
+
const btnClassName = isActive
|
|
3113
|
+
? 'w-96 p-m border-none bg-primary-main text-white'
|
|
3114
|
+
: `w-96 p-s ease-in duration-300 bg-white text-primary-text`;
|
|
3115
|
+
const btnTitleClassName = isActive ? 'text-xl mb-xs' : `text-l mb-2xs`;
|
|
3116
|
+
const btnDescClassName = isActive
|
|
3117
|
+
? 'text-l font-light text-white'
|
|
3118
|
+
: `text-m font-light text-secondary-text`;
|
|
3119
|
+
const iconClassName = isActive ? '' : `text-primary-main`;
|
|
3120
|
+
const iconVersion = tab?.icon?.iconVersion;
|
|
3121
|
+
const activeIconStyle = isActive ? 'white' : 'normal';
|
|
3122
|
+
return (jsxs("button", { type: "button", onClick: onClick, "aria-label": tab?.title, className: style('box-border relative border border-gray cursor-pointer text-left border-b-0 flex space-x-m min-h-20', btnClassName), children: [jsx(Img, { className: style('h-6 w-6 min-w-6 min-h-6', iconClassName), image: {
|
|
3123
|
+
...tab?.icon,
|
|
3124
|
+
iconVersion: iconVersion ?? activeIconStyle,
|
|
3125
|
+
}, width: "24", height: "24" }), jsxs("div", { className: "border-0", children: [jsx("div", { className: btnTitleClassName, children: tab?.title }), jsx("div", { className: btnDescClassName, children: tab.description })] })] }, String(i)));
|
|
3126
|
+
}
|
|
3127
|
+
function renderTabs$1({ activeIndex, tabsNav, tabAlign, slideIndexShift, onClick }) {
|
|
3128
|
+
const CARD_SHIFT = 388;
|
|
3129
|
+
const alignStyle = tabAlign ? AlignJustifyStyle[tabAlign] : '';
|
|
3130
|
+
return (jsxs("div", { children: [jsx("div", { style: { transform: `translateX(-${activeIndex * CARD_SHIFT}px)` }, className: "flex flex-col justify-end items-center h-32 pt-4xl box-border duration-1000", children: jsx("div", { className: style('w-full flex flex-nowrap items-end gap-xs', alignStyle), children: tabsNav.map((tab, i) => renderNavButton$3({
|
|
3131
|
+
tab,
|
|
3132
|
+
i,
|
|
3133
|
+
isActive: Boolean(i === slideIndexShift),
|
|
3134
|
+
onClick: () => onClick(i),
|
|
3135
|
+
})) }) }), jsx("div", { className: "w-full h-2 bg-primary-main" })] }));
|
|
3136
|
+
}
|
|
2981
3137
|
|
|
2982
|
-
const
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
};
|
|
2988
|
-
const renderCarouselCards = ({ noCardBorder, activeIndex, cardSize = 'normal', ...rest }) => {
|
|
2989
|
-
const { blocks: childBlocks } = rest.block || {};
|
|
2990
|
-
const someCardsHighlighted = childBlocks?.some(isCardHighlighted);
|
|
2991
|
-
return renderChildren({
|
|
2992
|
-
...rest,
|
|
2993
|
-
renderProps: (block, options, blockIndex) => (jsxs("div", { className: cardWrapperStyle(block, { someCardsHighlighted }), children: [renderBlock$1(block, options, {
|
|
2994
|
-
className: cardStyle(block, {
|
|
2995
|
-
someCardsHighlighted,
|
|
2996
|
-
showBorder: !noCardBorder,
|
|
2997
|
-
cardSize,
|
|
2998
|
-
}),
|
|
2999
|
-
blockIndex,
|
|
3000
|
-
isActive: blockIndex === activeIndex,
|
|
3001
|
-
}), isCardHighlighted(block)
|
|
3002
|
-
? renderCardHighlight({ className: 'absolute top-0 -right-4 z-40' })
|
|
3003
|
-
: null] }, String(blockIndex))),
|
|
3138
|
+
const NumberInput = JSX((props) => {
|
|
3139
|
+
const { onChange, min, max, defaultValue = '0', fractionDigits = 0, ...inputProps } = props;
|
|
3140
|
+
const normalizedProps = useNormalizedInput(props, {
|
|
3141
|
+
normalize: (_ = defaultValue) => min && max ? String(clamp(Number(sanitizeNumberStr(_)), min, max)) : sanitizeNumberStr(_),
|
|
3142
|
+
format: toLocalNumberFormat(fractionDigits),
|
|
3004
3143
|
});
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3144
|
+
const handleChange = useCallback((_) => onChange && onChange(sanitizeNumberStr(_)), [onChange]);
|
|
3145
|
+
return jsx(Input, { onChange: handleChange, ...inputProps, ...normalizedProps });
|
|
3146
|
+
});
|
|
3147
|
+
const sanitizeNumberStr = (_ = '') => _.replaceAll(',', '.')
|
|
3148
|
+
.replace(/[^\d.]/g, '')
|
|
3149
|
+
.replace(/([^.]*\.[^.]*)\./, '$1');
|
|
3010
3150
|
|
|
3011
|
-
const
|
|
3151
|
+
const CurrencyInput = JSX((props) => (jsx(NumberInput, { ...props, fractionDigits: 2, children: jsx("div", { className: "absolute right-4 bottom-4", children: jsx(Text, { size: "text-xl", font: "font-light", children: "\u20BD" }) }) })));
|
|
3012
3152
|
|
|
3013
|
-
const
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
'RichTextBlock',
|
|
3033
|
-
'ProductBlock',
|
|
3034
|
-
],
|
|
3035
|
-
childSchema: () => ({
|
|
3036
|
-
isHighlighting: {
|
|
3037
|
-
title: 'Выделить карточку',
|
|
3038
|
-
type: 'boolean',
|
|
3039
|
-
},
|
|
3040
|
-
}),
|
|
3153
|
+
const DEFAULT_TITLE = 'Укажите сумму перевода';
|
|
3154
|
+
const DEFAULT_LABEL = 'Сумма перевода';
|
|
3155
|
+
const DEFAULT_PLACEHOLDER = '1500';
|
|
3156
|
+
const MAX_AMOUNT = 300000;
|
|
3157
|
+
const MIN_AMOUNT = 1;
|
|
3158
|
+
const FORM_URL_MAP = {
|
|
3159
|
+
private: 'https://old.rshb.ru/p2p/',
|
|
3160
|
+
business: 'https://old.rshb.ru/smallbusiness/p2p/',
|
|
3161
|
+
};
|
|
3162
|
+
const INITIAL_FORM_STATE = {
|
|
3163
|
+
amount: 1500,
|
|
3164
|
+
};
|
|
3165
|
+
const CardTransfer = JSX(({ className = '', title = DEFAULT_TITLE, label = DEFAULT_LABEL, placeholder = DEFAULT_PLACEHOLDER, button, formType = 'private', ...rest }) => {
|
|
3166
|
+
const [{ amount }, { field }] = useForm(INITIAL_FORM_STATE);
|
|
3167
|
+
const [isDisabled, setDisabled] = useState(false);
|
|
3168
|
+
useEffect(() => {
|
|
3169
|
+
setDisabled(amount <= 0);
|
|
3170
|
+
}, [amount]);
|
|
3171
|
+
return (jsxs(BlockWrapper, { className: style('flex flex-col items-center', className), defaultPadding: "p-6xl", ...rest, children: [title ? (jsx(Heading, { className: "pb-lg xl:pb-4xl self-start xl:self-center", headingType: "h3", title: title })) : null, jsxs("form", { className: "w-full xl:max-w-[468px]", method: "POST", action: FORM_URL_MAP[formType], children: [jsx(CurrencyInput, { valid: !isDisabled, placeholder: placeholder, label: label, max: MAX_AMOUNT, min: MIN_AMOUNT, ...field('amount', { parse: Number, format: String }) }), jsx("input", { type: "hidden", name: "amount", value: amount }), button?.text ? (jsx(Button, { className: "w-full mt-lg", type: "submit", disabled: isDisabled, children: button.text })) : null] })] }));
|
|
3041
3172
|
});
|
|
3042
3173
|
|
|
3043
3174
|
const CarouselBankHistoryCard = JSX(({ className, title, description, blockIndex = 0, isActive, ...rest }) => (jsx(BlockWrapper, { className: style('relative flex h-[485px]', isActive ? 'w-[440px] z-10' : 'w-[340px]', className), defaultPadding: "p-0", ...rest, children: jsx("div", { className: style('basis-full self-center', getBackColor(blockIndex)), children: isActive ? (jsx(Headline, { headlineVersion: "M", title: title, description: description, padding: "p-3xl", align: "text-left", className: "h-96 text-white shadow-dark-blue" })) : (jsx("div", { className: "h-[300px] flex justify-center items-center font-mohave text-title-large", children: jsx("span", { className: getTextColor(blockIndex), children: title }) })) }) })));
|
|
@@ -3322,8 +3453,6 @@
|
|
|
3322
3453
|
return (jsx(DefaultFoldButton, { icon: icons[Number(isUnfolded)], label: labels[Number(isUnfolded)], onClick: onToggle }));
|
|
3323
3454
|
};
|
|
3324
3455
|
|
|
3325
|
-
const NotFound = JSX(({ title, description }) => (jsxs("div", { className: "bg-white p-6xl py-20 flex gap-s flex-col @xl:items-center", children: [jsx(Img, { image: { icon: 'MagnifierIcon', iconVersion: 'normal' }, width: "120", height: "120" }), jsx(Headline, { title: title, description: description, headlineVersion: "S", isEmbedded: true, align: AlignStyles })] })));
|
|
3326
|
-
|
|
3327
3456
|
const ICONS$1 = ['ArrowDownIcon', 'ArrowUpIcon'];
|
|
3328
3457
|
const resultsGridStyle = 'space-y-px lg:space-y-0 lg:grid lg:grid-cols-12 gap-2xs border-box';
|
|
3329
3458
|
const BaseFiltrationInner = JSX(({ label = '', blocksToRender = [], topItemsCount = 0, block, notFound, ...rest }) => {
|
|
@@ -3335,95 +3464,6 @@
|
|
|
3335
3464
|
}, renderFoldButton: ({ isUnfolded, onToggle }) => (jsx(DefaultFoldButton, { className: style(topItemsCount < 1 ? 'hidden' : ''), disabled: !hiddenBlocks?.length, label: label, icon: ICONS$1[Number(isUnfolded)], dataTheme: rest.options?.page?.colorPalette, onClick: onToggle })) })] })] }));
|
|
3336
3465
|
});
|
|
3337
3466
|
|
|
3338
|
-
const SlideCheckboxGroup = JSX(({ value, onChange, items = [], multiple }) => {
|
|
3339
|
-
const handleChange = (newValue) => {
|
|
3340
|
-
if (!onChange) {
|
|
3341
|
-
return;
|
|
3342
|
-
}
|
|
3343
|
-
const hasAlready = value?.includes(newValue);
|
|
3344
|
-
if (multiple) {
|
|
3345
|
-
onChange(hasAlready ? (value || []).filter((v) => v !== newValue) : [...(value || []), newValue]);
|
|
3346
|
-
}
|
|
3347
|
-
else {
|
|
3348
|
-
onChange(hasAlready ? [] : [newValue]);
|
|
3349
|
-
}
|
|
3350
|
-
};
|
|
3351
|
-
return items.map((item) => (jsx(SlideCheckbox, { text: item?.title, value: [value].flatMap((_) => _).includes(item.value), onChange: () => handleChange(item.value), type: multiple ? 'checkbox' : 'radio' }, item.value)));
|
|
3352
|
-
});
|
|
3353
|
-
|
|
3354
|
-
const renderFiltrationForm$1 = ({ field, reset, filtrationSchema, resetButton, children, }) => (jsxs("form", { className: "flex flex-col @4xl:flex-row justify-between bg-white p-4xl gap-s @4xl:gap-0", children: [jsxs("div", { className: "flex flex-col @4xl:flex-row gap-5xl", children: [children, Object.entries(filtrationSchema).map(renderFormItem(field))] }), resetButton ? (jsx("div", { children: jsx(Button, { type: "reset", className: "w-full @4xl:w-72 @4xl:ml-s", onClick: reset, children: resetButton?.text }) })) : null] }));
|
|
3355
|
-
const renderFormItem = (field) => ([key, item]) => {
|
|
3356
|
-
const type = item?.type;
|
|
3357
|
-
switch (type) {
|
|
3358
|
-
case 'array':
|
|
3359
|
-
return renderCheckboxes(key, field)(item);
|
|
3360
|
-
default:
|
|
3361
|
-
return null;
|
|
3362
|
-
}
|
|
3363
|
-
};
|
|
3364
|
-
const renderCheckboxes = (key, field) => (item) => {
|
|
3365
|
-
const options = item?.items?.enum?.map((e, i) => ({ value: e, title: item?.items?.enumNames?.[i] || '' })) ||
|
|
3366
|
-
[];
|
|
3367
|
-
return (jsxs("div", { children: [item?.title ? (jsx("div", { className: "mb-m", children: jsx(Text, { size: "text-m", font: "font-light", color: "text-secondary-text", children: item.title }) })) : null, jsx(SlideCheckboxGroup, { items: options, multiple: !item?.single, ...field(key) })] }, key));
|
|
3368
|
-
};
|
|
3369
|
-
|
|
3370
|
-
function zip(firstCol, ...restCols) {
|
|
3371
|
-
return firstCol.map((firstEl, rowIndex) => [firstEl, ...restCols.map((col) => col[rowIndex])]);
|
|
3372
|
-
}
|
|
3373
|
-
|
|
3374
|
-
const isEmpty = (v) => v === null ||
|
|
3375
|
-
v === undefined ||
|
|
3376
|
-
v === '' ||
|
|
3377
|
-
(Array.isArray(v) && v.length === 0) ||
|
|
3378
|
-
(typeof v === 'object' && Object.keys(v).length === 0);
|
|
3379
|
-
|
|
3380
|
-
const isSingularFieldMatch = (key, pattern) => (target) => isEmpty(pattern[key]) || isEmpty(target[key]) || pattern[key] === target[key];
|
|
3381
|
-
const isMultipleFieldMatch = (key, pattern) => (target) => isEmpty(pattern[key]) ||
|
|
3382
|
-
isEmpty(target[key]) ||
|
|
3383
|
-
pattern[key]?.every((_) => target[key]?.includes(_));
|
|
3384
|
-
const isNumberFieldMatch = (key, pattern) => (target) => isEmpty(pattern[key]) ||
|
|
3385
|
-
isEmpty(target[key]) ||
|
|
3386
|
-
naturalNumber(pattern[key]) <= naturalNumber(target[key]);
|
|
3387
|
-
const isMultipleNumberFieldMatch = (key, pattern) => (target) => isEmpty(pattern[key]) || isEmpty(target[key]) || target[key]?.includes(pattern[key]);
|
|
3388
|
-
const isValueInRange = (key, pattern) => (target) => isEmpty(pattern[key]) ||
|
|
3389
|
-
isEmpty(target[key]) ||
|
|
3390
|
-
(naturalNumber(pattern[key]?.min) >= naturalNumber(target[key]?.min) &&
|
|
3391
|
-
naturalNumber(pattern[key]?.min) <= naturalNumber(target[key]?.max));
|
|
3392
|
-
const targetMatchPattern = (pattern, target) => Object.entries(pattern)
|
|
3393
|
-
.map(([key, subPattern]) => {
|
|
3394
|
-
if (typeof subPattern === 'number') {
|
|
3395
|
-
return Array.isArray(target[key])
|
|
3396
|
-
? isMultipleNumberFieldMatch(key, pattern)
|
|
3397
|
-
: isNumberFieldMatch(key, pattern);
|
|
3398
|
-
}
|
|
3399
|
-
if (typeof subPattern === 'object' && 'min' in subPattern && 'max' in subPattern) {
|
|
3400
|
-
return isValueInRange(key, pattern);
|
|
3401
|
-
}
|
|
3402
|
-
return Array.isArray(subPattern)
|
|
3403
|
-
? isMultipleFieldMatch(key, pattern)
|
|
3404
|
-
: isSingularFieldMatch(key, pattern);
|
|
3405
|
-
})
|
|
3406
|
-
.every((predicate) => predicate(target));
|
|
3407
|
-
const naturalNumber = (n) => Number(n || 0);
|
|
3408
|
-
|
|
3409
|
-
const filterBlocks = (blocksWithProps, filtrationState) => (normalize = identity) => blocksWithProps
|
|
3410
|
-
?.filter(([, content]) => targetMatchPattern(filtrationState, normalize(content) || {}))
|
|
3411
|
-
.map(([block]) => block);
|
|
3412
|
-
|
|
3413
|
-
const useFiltrationForm = (initialFormState, { block, page, normalize = identity, }) => {
|
|
3414
|
-
const blocks = block?.blocks || [];
|
|
3415
|
-
const [filtrationState, { field, reset, update: replaceFiltrationState }] = useForm(initialFormState);
|
|
3416
|
-
const blocksWithProps = useMemo(() => zip(blocks, blocks.map((b) => resolveBlockProps(b.content, page?.fallback))), [blocks, page?.fallback]);
|
|
3417
|
-
const blocksToRender = filtrationState === initialFormState
|
|
3418
|
-
? blocks
|
|
3419
|
-
: filterBlocks(blocksWithProps, filtrationState)(normalize);
|
|
3420
|
-
return [
|
|
3421
|
-
filtrationState,
|
|
3422
|
-
{ blocksToRender, blocksWithProps },
|
|
3423
|
-
{ field, reset, update: replaceFiltrationState },
|
|
3424
|
-
];
|
|
3425
|
-
};
|
|
3426
|
-
|
|
3427
3467
|
const isRateRow = (rateRow) => {
|
|
3428
3468
|
return typeof rateRow?.minMonths === 'number' && typeof rateRow?.maxMonths === 'number';
|
|
3429
3469
|
};
|
|
@@ -3447,11 +3487,10 @@
|
|
|
3447
3487
|
});
|
|
3448
3488
|
const rateRows = blocksWithProps.map(([, _]) => _?.paramsSource?.rateRows);
|
|
3449
3489
|
const months = getMonths(rateRows);
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
return (jsxs(BlockWrapper, { className: style('space-y-2xs', className), defaultPadding: "p-0", version: "transparent", ...rest, children: [renderFiltrationForm$1({ field, reset, filtrationSchema, resetButton, children: Inputs }), jsx(BaseFiltrationInner, { blocksToRender: blocksToRender, ...rest })] }));
|
|
3490
|
+
return (jsxs(BlockWrapper, { className: style('space-y-2xs', className), defaultPadding: "p-0", version: "transparent", ...rest, children: [jsx(FiltrationForm, { filtrationSchema: filtrationSchema, resetButton: resetButton, field: field, reset: reset, children: jsxs("div", { className: "@4xl:max-w-xs", children: [jsx(CurrencyInput, { label: sumInput?.title, min: DEFAULT_MIN_SUM, max: DEFAULT_MAX_SUM, ...field('sum', {
|
|
3491
|
+
parse: (min) => ({ min: Number(min), max: DEFAULT_MAX_SUM }),
|
|
3492
|
+
format: ({ min }) => String(min),
|
|
3493
|
+
}) }), jsx(InputRange, { title: periodInput?.title, items: ['От 3 мес', 'До 5 лет'], list: months, ...field('period') })] }) }), jsx(BaseFiltrationInner, { blocksToRender: blocksToRender, ...rest })] }));
|
|
3455
3494
|
}, {
|
|
3456
3495
|
childrenTypes: ['ProductBlock'],
|
|
3457
3496
|
childSchema: (content) => ({
|
|
@@ -4429,8 +4468,6 @@
|
|
|
4429
4468
|
return (jsx("button", { type: "button", onClick: onClick, "aria-label": title, className: `box-border px-m py-s text-m font-light ${btnClassName}`, children: title }, String(i)));
|
|
4430
4469
|
}
|
|
4431
4470
|
|
|
4432
|
-
const joinList = (sep) => (list) => list.reduce((acc, el, i) => (acc.length ? acc.concat({ ...sep, key: `sep-${i}` }, el) : [el]), []);
|
|
4433
|
-
|
|
4434
4471
|
const investmentCellColorMap = {
|
|
4435
4472
|
yellow: 'bg-yellow',
|
|
4436
4473
|
green: 'bg-green',
|
|
@@ -4637,7 +4674,7 @@
|
|
|
4637
4674
|
blocks: rest.block?.blocks,
|
|
4638
4675
|
onFiltrationStateChange: handleFiltrationStateChange,
|
|
4639
4676
|
});
|
|
4640
|
-
return (jsxs(BlockWrapper, { className: style('space-y-2xs', className), defaultPadding: "p-0", version: "transparent", ...rest, children: [jsx(TabsControl, { ...tabsControlProps }),
|
|
4677
|
+
return (jsxs(BlockWrapper, { className: style('space-y-2xs', className), defaultPadding: "p-0", version: "transparent", ...rest, children: [jsx(TabsControl, { ...tabsControlProps }), jsx(FiltrationForm, { filtrationSchema: filtrationSchema, resetButton: resetButton, field: field, reset: reset }), jsx(BaseFiltrationInner, { blocksToRender: blocksToRender, ...rest })] }));
|
|
4641
4678
|
}, {
|
|
4642
4679
|
childrenTypes: ['ProductBlock'],
|
|
4643
4680
|
childSchema: (content) => content?.filtrationSchema || {},
|
|
@@ -5788,6 +5825,7 @@
|
|
|
5788
5825
|
AdTile,
|
|
5789
5826
|
ApplicationForm,
|
|
5790
5827
|
ApplicationFormCustom,
|
|
5828
|
+
BankAccountFiltration,
|
|
5791
5829
|
BenefitsBlock,
|
|
5792
5830
|
BonusBenefitsBlock,
|
|
5793
5831
|
ButtonsBlock,
|
|
@@ -6049,7 +6087,7 @@
|
|
|
6049
6087
|
slots: () => [HEADER_SLOT, FOOTER_SLOT, STICKY_FOOTER_SLOT],
|
|
6050
6088
|
});
|
|
6051
6089
|
|
|
6052
|
-
const packageVersion = "0.14.
|
|
6090
|
+
const packageVersion = "0.14.247";
|
|
6053
6091
|
|
|
6054
6092
|
exports.Blocks = Blocks;
|
|
6055
6093
|
exports.ContentPage = ContentPage;
|