@redneckz/wildless-cms-uni-blocks 0.2.77 → 0.2.81
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 +5 -82
- package/bundle/bundle.umd.js +35 -0
- package/bundle/bundle.umd.min.js +1 -1
- package/dist/ProjectSettings.d.ts +1 -0
- package/dist/ProjectSettings.js.map +1 -1
- package/dist/components/Accordion/Accordion.d.ts +5 -0
- package/dist/components/Accordion/Accordion.js +10 -0
- package/dist/components/Accordion/Accordion.js.map +1 -0
- package/dist/components/Accordion/AccordionBlocks.d.ts +4 -0
- package/dist/components/Accordion/AccordionBlocks.js +7 -0
- package/dist/components/Accordion/AccordionBlocks.js.map +1 -0
- package/dist/components/Accordion/AccordionContent.d.ts +14 -0
- package/dist/components/Accordion/AccordionContent.js +2 -0
- package/dist/components/Accordion/AccordionContent.js.map +1 -0
- package/dist/components/Accordion/AccordionItem.d.ts +5 -0
- package/dist/components/Accordion/AccordionItem.js +35 -0
- package/dist/components/Accordion/AccordionItem.js.map +1 -0
- package/dist/components/Blocks.d.ts +1 -0
- package/dist/components/Blocks.js +2 -0
- package/dist/components/Blocks.js.map +1 -1
- package/dist/components/CreditCalculator/CreditCalculator.d.ts +2 -1
- package/dist/components/CreditCalculator/CreditCalculator.js +39 -15
- package/dist/components/CreditCalculator/CreditCalculator.js.map +1 -1
- package/dist/components/CreditCalculator/CreditCalculatorContent.d.ts +15 -0
- package/dist/components/CreditCalculator/CreditCalculatorContent.js +2 -0
- package/dist/components/CreditCalculator/CreditCalculatorContent.js.map +1 -0
- package/dist/components/CreditCalculator/constants.d.ts +7 -0
- package/dist/components/CreditCalculator/constants.js +10 -0
- package/dist/components/CreditCalculator/constants.js.map +1 -0
- package/dist/components/CreditCalculator/getCalculatorParams.d.ts +7 -0
- package/dist/components/CreditCalculator/getCalculatorParams.js +11 -0
- package/dist/components/CreditCalculator/getCalculatorParams.js.map +1 -0
- package/dist/components/CreditCalculator/getCreditRate.d.ts +7 -0
- package/dist/components/CreditCalculator/getCreditRate.js +13 -0
- package/dist/components/CreditCalculator/getCreditRate.js.map +1 -0
- package/dist/components/CreditCalculator/getCreditTermYears.d.ts +1 -0
- package/dist/components/CreditCalculator/getCreditTermYears.js +15 -0
- package/dist/components/CreditCalculator/getCreditTermYears.js.map +1 -0
- package/dist/components/CreditCalculator/getMonthlyPayment.d.ts +11 -0
- package/dist/components/CreditCalculator/getMonthlyPayment.js +19 -0
- package/dist/components/CreditCalculator/getMonthlyPayment.js.map +1 -0
- package/dist/content-page-repository/ContentPageRepository.d.ts +3 -0
- package/dist/content-page-repository/ContentPageRepository.js +14 -0
- package/dist/content-page-repository/ContentPageRepository.js.map +1 -1
- package/dist/hooks/useCreditCalculatorData.d.ts +3 -0
- package/dist/hooks/useCreditCalculatorData.js +15 -0
- package/dist/hooks/useCreditCalculatorData.js.map +1 -0
- package/dist/ui-kit/Icon/IconProps.d.ts +4 -1
- package/dist/ui-kit/Icon/IconProps.js +3 -0
- package/dist/ui-kit/Icon/IconProps.js.map +1 -1
- package/dist/ui-kit/InputRange/InputRange.js +3 -2
- package/dist/ui-kit/InputRange/InputRange.js.map +1 -1
- package/dist/utils/addSpacesBetweenNumbers.d.ts +1 -0
- package/dist/utils/addSpacesBetweenNumbers.js +5 -0
- package/dist/utils/addSpacesBetweenNumbers.js.map +1 -0
- package/lib/ProjectSettings.d.ts +1 -0
- package/lib/ProjectSettings.js.map +1 -1
- package/lib/common.css +1 -1
- package/lib/components/Accordion/Accordion.d.ts +5 -0
- package/lib/components/Accordion/Accordion.fixture.d.ts +4 -0
- package/lib/components/Accordion/Accordion.js +8 -0
- package/lib/components/Accordion/Accordion.js.map +1 -0
- package/lib/components/Accordion/AccordionBlocks.d.ts +4 -0
- package/lib/components/Accordion/AccordionBlocks.js +6 -0
- package/lib/components/Accordion/AccordionBlocks.js.map +1 -0
- package/lib/components/Accordion/AccordionContent.d.ts +14 -0
- package/lib/components/Accordion/AccordionContent.js +2 -0
- package/lib/components/Accordion/AccordionContent.js.map +1 -0
- package/lib/components/Accordion/AccordionItem.d.ts +5 -0
- package/lib/components/Accordion/AccordionItem.js +30 -0
- package/lib/components/Accordion/AccordionItem.js.map +1 -0
- package/lib/components/BenefitsBlock/BenefitsBlock.fixture.d.ts +2 -0
- package/lib/components/Blocks.d.ts +1 -0
- package/lib/components/Blocks.js +2 -0
- package/lib/components/Blocks.js.map +1 -1
- package/lib/components/ComparisonTable/ComparisonTable.fixture.d.ts +8 -0
- package/lib/components/ContentPage/ContentPage.fixture.d.ts +6 -0
- package/lib/components/CreditCalculator/CreditCalculator.d.ts +2 -1
- package/lib/components/CreditCalculator/CreditCalculator.fixture.d.ts +2 -0
- package/lib/components/CreditCalculator/CreditCalculator.js +39 -15
- package/lib/components/CreditCalculator/CreditCalculator.js.map +1 -1
- package/lib/components/CreditCalculator/CreditCalculatorContent.d.ts +15 -0
- package/lib/components/CreditCalculator/CreditCalculatorContent.js +2 -0
- package/lib/components/CreditCalculator/CreditCalculatorContent.js.map +1 -0
- package/lib/components/CreditCalculator/constants.d.ts +7 -0
- package/lib/components/CreditCalculator/constants.js +8 -0
- package/lib/components/CreditCalculator/constants.js.map +1 -0
- package/lib/components/CreditCalculator/getCalculatorParams.d.ts +7 -0
- package/lib/components/CreditCalculator/getCalculatorParams.js +8 -0
- package/lib/components/CreditCalculator/getCalculatorParams.js.map +1 -0
- package/lib/components/CreditCalculator/getCreditRate.d.ts +7 -0
- package/lib/components/CreditCalculator/getCreditRate.js +10 -0
- package/lib/components/CreditCalculator/getCreditRate.js.map +1 -0
- package/lib/components/CreditCalculator/getCreditTermYears.d.ts +1 -0
- package/lib/components/CreditCalculator/getCreditTermYears.js +12 -0
- package/lib/components/CreditCalculator/getCreditTermYears.js.map +1 -0
- package/lib/components/CreditCalculator/getMonthlyPayment.d.ts +11 -0
- package/lib/components/CreditCalculator/getMonthlyPayment.js +16 -0
- package/lib/components/CreditCalculator/getMonthlyPayment.js.map +1 -0
- package/lib/components/ExchangeRateTile/ExchangeRateTile.fixture.d.ts +4 -0
- package/lib/components/Footer/Footer.fixture.d.ts +2 -0
- package/lib/components/Gallery/Gallery.fixture.d.ts +9 -0
- package/lib/components/Header/Header.fixture.d.ts +2 -0
- package/lib/components/LikeControl/LikeControl.fixture.d.ts +2 -0
- package/lib/components/MiniGallery/MiniGallery.fixture.d.ts +5 -0
- package/lib/components/MobileAppTile/MobileAppTile.fixture.d.ts +4 -0
- package/lib/components/Placeholder/Placeholder.fixture.d.ts +2 -0
- package/lib/components/ProductBlock/ProductBlock.fixture.d.ts +5 -0
- package/lib/components/ProductGallery/ProductGallery.fixture.d.ts +2 -0
- package/lib/components/ProductTile/ProductTile.fixture.d.ts +7 -0
- package/lib/components/PromoTile/PromoTile.fixture.d.ts +4 -0
- package/lib/components/StepsBlock/StepsBlock.fixture.d.ts +2 -0
- package/lib/components/TextBlock/TextBlock.fixture.d.ts +2 -0
- package/lib/components/Tile/Tile.fixture.d.ts +8 -0
- package/lib/content-page-repository/ContentPageRepository.d.ts +3 -0
- package/lib/content-page-repository/ContentPageRepository.js +14 -0
- package/lib/content-page-repository/ContentPageRepository.js.map +1 -1
- package/lib/cosmos.decorator.d.ts +4 -0
- package/lib/hooks/useCreditCalculatorData.d.ts +3 -0
- package/lib/hooks/useCreditCalculatorData.js +12 -0
- package/lib/hooks/useCreditCalculatorData.js.map +1 -0
- package/lib/setup-fixture.d.ts +3 -0
- package/lib/ui-kit/BlockItem/BlockItem.fixture.d.ts +3 -0
- package/lib/ui-kit/Button/Button.fixture.d.ts +13 -0
- package/lib/ui-kit/Button/LikeButton.fixture.d.ts +5 -0
- package/lib/ui-kit/HeaderItem/HeaderItem.fixture.d.ts +6 -0
- package/lib/ui-kit/Icon/Icon.fixture.d.ts +5 -0
- package/lib/ui-kit/Icon/IconProps.d.ts +4 -1
- package/lib/ui-kit/Icon/IconProps.js +3 -0
- package/lib/ui-kit/Icon/IconProps.js.map +1 -1
- package/lib/ui-kit/InputRange/InputRange.js +3 -2
- package/lib/ui-kit/InputRange/InputRange.js.map +1 -1
- package/lib/ui-kit/Logo/Logo.fixture.d.ts +3 -0
- package/lib/ui-kit/TopItem/TopItem.fixture.d.ts +6 -0
- package/lib/utils/addSpacesBetweenNumbers.d.ts +1 -0
- package/lib/utils/addSpacesBetweenNumbers.js +2 -0
- package/lib/utils/addSpacesBetweenNumbers.js.map +1 -0
- package/package.json +5 -4
- package/src/ProjectSettings.ts +1 -0
- package/src/components/Accordion/Accordion.fixture.tsx +62 -0
- package/src/components/Accordion/Accordion.tsx +22 -0
- package/src/components/Accordion/AccordionBlocks.tsx +7 -0
- package/src/components/Accordion/AccordionContent.ts +18 -0
- package/src/components/Accordion/AccordionItem.tsx +68 -0
- package/src/components/Blocks.ts +2 -0
- package/src/components/ContentPage/ContentPage.page.json +78 -0
- package/src/components/CreditCalculator/CreditCalculator.fixture.tsx +1 -1
- package/src/components/CreditCalculator/CreditCalculator.tsx +134 -85
- package/src/components/CreditCalculator/CreditCalculatorContent.ts +17 -0
- package/src/components/CreditCalculator/constants.ts +8 -0
- package/src/components/CreditCalculator/getCalculatorParams.ts +16 -0
- package/src/components/CreditCalculator/getCreditRate.ts +18 -0
- package/src/components/CreditCalculator/getCreditTermYears.spec.ts +10 -0
- package/src/components/CreditCalculator/getCreditTermYears.ts +15 -0
- package/src/components/CreditCalculator/getMonthlyPayment.ts +32 -0
- package/src/content-page-repository/ContentPageRepository.ts +17 -0
- package/src/hooks/useCreditCalculatorData.ts +23 -0
- package/src/icons/DocIcon.svg +5 -0
- package/src/icons/MinusIcon.svg +1 -0
- package/src/icons/PlusIcon.svg +1 -0
- package/src/ui-kit/Icon/IconProps.ts +3 -0
- package/src/ui-kit/InputRange/InputRange.tsx +3 -2
- package/src/utils/addSpacesBetweenNumbers.ts +2 -0
|
@@ -1,106 +1,155 @@
|
|
|
1
1
|
import { JSX } from '@redneckz/uni-jsx';
|
|
2
|
+
import { useCreditCalculatorData } from '../../hooks/useCreditCalculatorData';
|
|
2
3
|
import { UniBlockProps } from '../../types';
|
|
3
4
|
import { Button } from '../../ui-kit/Button/Button';
|
|
4
5
|
import { Checkbox } from '../../ui-kit/Checkbox/Checkbox';
|
|
5
6
|
import { InputRange } from '../../ui-kit/InputRange/InputRange';
|
|
7
|
+
import { addSpacesBetweenNumbers } from '../../utils/addSpacesBetweenNumbers';
|
|
6
8
|
import { clamp } from '../../utils/clamp';
|
|
9
|
+
import {
|
|
10
|
+
DEFAULT_MAX_MONTHS,
|
|
11
|
+
DEFAULT_MIN_MONTHS,
|
|
12
|
+
DEFAULT_MONTHS,
|
|
13
|
+
DEFAULT_SUM,
|
|
14
|
+
MONTHS_IN_YEAR,
|
|
15
|
+
} from './constants';
|
|
16
|
+
import { CreditCalculatorContent } from './CreditCalculatorContent';
|
|
17
|
+
import { getCalculatorParams } from './getCalculatorParams';
|
|
18
|
+
import { getCreditRate } from './getCreditRate';
|
|
19
|
+
import { getCreditTermYears } from './getCreditTermYears';
|
|
20
|
+
import { getMonthlyPayment } from './getMonthlyPayment';
|
|
7
21
|
|
|
8
|
-
export interface CreditCalculatorProps extends UniBlockProps {}
|
|
22
|
+
export interface CreditCalculatorProps extends CreditCalculatorContent, UniBlockProps {}
|
|
23
|
+
|
|
24
|
+
const STEP_MONEY = 1000;
|
|
25
|
+
const STEP_MONTHS = 1;
|
|
26
|
+
const DEFAULT_PAYMENT_TYPE = 'annuity';
|
|
9
27
|
|
|
10
28
|
const borderStyle = 'border-solid border-3 border-primary-main rounded-md';
|
|
11
29
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const
|
|
30
|
+
export const CreditCalculator = JSX<CreditCalculatorProps>(
|
|
31
|
+
({ context, className, directoryName }) => {
|
|
32
|
+
const [moneyValue, setMoneyValue] = context.useState<number | undefined>(undefined);
|
|
33
|
+
const [monthsValue, setMonthsValue] = context.useState<number | undefined>(undefined);
|
|
34
|
+
const [isAnnuityChecked, setIsAnnuityChecked] = context.useState(true);
|
|
35
|
+
const [isInsuranceChecked, setIsInsuranceChecked] = context.useState(true);
|
|
15
36
|
|
|
16
|
-
const
|
|
37
|
+
const tableRows = useCreditCalculatorData(context.useAsyncData, directoryName).rows;
|
|
17
38
|
|
|
18
|
-
const
|
|
19
|
-
const MAX_MONTHS = 84;
|
|
20
|
-
const STEP_MONTHS = 1;
|
|
39
|
+
const calculatorParams = getCalculatorParams({ tableRows, isAnnuity: isAnnuityChecked });
|
|
21
40
|
|
|
22
|
-
const
|
|
41
|
+
const defaultSum =
|
|
42
|
+
calculatorParams.maxSum && calculatorParams.minSum
|
|
43
|
+
? (calculatorParams.maxSum - calculatorParams.minSum) / 2
|
|
44
|
+
: DEFAULT_SUM;
|
|
23
45
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const [isInsuranceChecked, setIsInsuranceChecked] = context.useState(true);
|
|
46
|
+
const defaultMonths =
|
|
47
|
+
calculatorParams.maxMonths && calculatorParams.minMonths
|
|
48
|
+
? Math.round((calculatorParams.maxMonths - calculatorParams.minMonths) / 2)
|
|
49
|
+
: DEFAULT_MONTHS;
|
|
29
50
|
|
|
30
|
-
|
|
31
|
-
setMonthsValue(clamp(value * MONTHS_IN_YEAR, MIN_MONTHS, MAX_MONTHS));
|
|
32
|
-
};
|
|
51
|
+
const rate = getCreditRate({ calculatorParams, isInsurance: isInsuranceChecked });
|
|
33
52
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
const montlyPayment = getMonthlyPayment({
|
|
54
|
+
calculatorParams,
|
|
55
|
+
paymentType: DEFAULT_PAYMENT_TYPE,
|
|
56
|
+
rate,
|
|
57
|
+
sum: moneyValue || defaultSum,
|
|
58
|
+
months: monthsValue || defaultMonths,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const creditTermYears = getCreditTermYears(
|
|
62
|
+
calculatorParams.minMonths || DEFAULT_MIN_MONTHS,
|
|
63
|
+
calculatorParams.maxMonths || DEFAULT_MAX_MONTHS,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
function handleButtonClick(value: number) {
|
|
67
|
+
setMonthsValue(
|
|
68
|
+
clamp(
|
|
69
|
+
value * MONTHS_IN_YEAR,
|
|
70
|
+
calculatorParams?.minMonths || DEFAULT_MIN_MONTHS,
|
|
71
|
+
calculatorParams?.maxMonths || DEFAULT_MAX_MONTHS,
|
|
72
|
+
),
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<section className={`font-sans text-primary-text bg-white p-4 ${className}`}>
|
|
78
|
+
<div className={`box-border p-12 flex flex-col justify-between ${borderStyle}`}>
|
|
79
|
+
<div className="flex justify-between">
|
|
80
|
+
<div className="grow mr-11">
|
|
81
|
+
<InputRange
|
|
82
|
+
title="Желаемая сумма кредита, ₽"
|
|
83
|
+
items={[
|
|
84
|
+
`От ${addSpacesBetweenNumbers(Number(calculatorParams.minSum))} рублей`,
|
|
85
|
+
`До ${addSpacesBetweenNumbers(Number(calculatorParams.maxSum))} рублей`,
|
|
86
|
+
]}
|
|
87
|
+
min={calculatorParams?.minSum}
|
|
88
|
+
max={calculatorParams?.maxSum}
|
|
89
|
+
step={STEP_MONEY}
|
|
90
|
+
value={moneyValue || defaultSum}
|
|
91
|
+
onChange={setMoneyValue}
|
|
92
|
+
/>
|
|
93
|
+
<InputRange
|
|
94
|
+
title="Срок кредита, месяцев"
|
|
95
|
+
items={['Или выберите из предложенных вариантов ниже']}
|
|
96
|
+
min={calculatorParams?.minMonths}
|
|
97
|
+
max={calculatorParams?.maxMonths}
|
|
98
|
+
step={STEP_MONTHS}
|
|
99
|
+
value={monthsValue || defaultMonths}
|
|
100
|
+
onChange={setMonthsValue}
|
|
101
|
+
/>
|
|
102
|
+
<div className="flex mb-7">
|
|
103
|
+
{creditTermYears.map((number, i) => renderButton(number, i, handleButtonClick))}
|
|
104
|
+
</div>
|
|
105
|
+
<Checkbox
|
|
106
|
+
text="Получаю пенсию на карту Россельхозбанка"
|
|
107
|
+
checked={isAnnuityChecked}
|
|
108
|
+
onChange={setIsAnnuityChecked}
|
|
109
|
+
/>
|
|
110
|
+
<Checkbox
|
|
111
|
+
className="mb-4"
|
|
112
|
+
text="Комплексная страховая защита"
|
|
113
|
+
checked={isInsuranceChecked}
|
|
114
|
+
onChange={setIsInsuranceChecked}
|
|
115
|
+
/>
|
|
116
|
+
</div>
|
|
117
|
+
<div className="p-9 bg-primary-main rounded-md text-white">
|
|
118
|
+
<div className="text-base mb-5">Наше предложение</div>
|
|
119
|
+
<div className="text-sm opacity-60">Ежемесячный платёж</div>
|
|
120
|
+
<div className="text-lg mb-3">
|
|
121
|
+
{addSpacesBetweenNumbers(Math.round(montlyPayment))} ₽
|
|
122
|
+
</div>
|
|
123
|
+
<div className="text-sm opacity-60">Ставка</div>
|
|
124
|
+
<div className="text-lg">{rate} %</div>
|
|
59
125
|
</div>
|
|
60
|
-
<Checkbox
|
|
61
|
-
text="Получаю пенсию на карту Россельхозбанка"
|
|
62
|
-
checked={isAnnuityChecked}
|
|
63
|
-
onChange={setIsAnnuityChecked}
|
|
64
|
-
/>
|
|
65
|
-
<Checkbox
|
|
66
|
-
className="mb-4"
|
|
67
|
-
text="Комплексная страховая защита"
|
|
68
|
-
checked={isInsuranceChecked}
|
|
69
|
-
onChange={setIsInsuranceChecked}
|
|
70
|
-
/>
|
|
71
|
-
</div>
|
|
72
|
-
<div className="p-9 bg-primary-main rounded-md text-white">
|
|
73
|
-
<div className="text-base mb-5">Наше предложение</div>
|
|
74
|
-
<div className="text-sm opacity-60">Ежемесячный платёж</div>
|
|
75
|
-
<div className="text-lg mb-3">26 827 ₽</div>
|
|
76
|
-
<div className="text-sm opacity-60">Ставка</div>
|
|
77
|
-
<div className="text-lg">16,9 %</div>
|
|
78
126
|
</div>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
127
|
+
<div className="flex items-center">
|
|
128
|
+
<Button className="mr-3" text="Отправить заявку" version="primary" href="#" />
|
|
129
|
+
<div
|
|
130
|
+
className="w-80 text-xxs leading-4 text-secondary-text"
|
|
131
|
+
aria-label="Соглашение на обработку персональных данных"
|
|
132
|
+
>
|
|
133
|
+
Отправляя заявку, вы соглашаетесь на обработку персональных данных соответственно
|
|
134
|
+
требованиям ФЗ «О персональных данных»
|
|
135
|
+
</div>
|
|
88
136
|
</div>
|
|
89
137
|
</div>
|
|
90
|
-
</
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
const renderButton = (number: number, i: number, handleClick: (number: number) => void) => (
|
|
96
|
-
<div
|
|
97
|
-
key={String(i)}
|
|
98
|
-
className="bg-secondary-light rounded-3xl h-10 w-[75px] box-border mr-2 flex items-center justify-center cursor-pointer"
|
|
99
|
-
role="button"
|
|
100
|
-
onClick={() => handleClick(number)}
|
|
101
|
-
>
|
|
102
|
-
<span className="font-medium text-sm">
|
|
103
|
-
{number} {number > 4 ? 'лет' : 'года'}
|
|
104
|
-
</span>
|
|
105
|
-
</div>
|
|
138
|
+
</section>
|
|
139
|
+
);
|
|
140
|
+
},
|
|
106
141
|
);
|
|
142
|
+
|
|
143
|
+
function renderButton(number: number, i: number, handleClick: (number: number) => void) {
|
|
144
|
+
return (
|
|
145
|
+
<button
|
|
146
|
+
key={String(i)}
|
|
147
|
+
className="bg-secondary-light rounded-3xl h-10 w-[75px] box-border mr-2 flex items-center justify-center cursor-pointer border-none"
|
|
148
|
+
onClick={() => handleClick(number)}
|
|
149
|
+
>
|
|
150
|
+
<span className="font-semibold text-sm">
|
|
151
|
+
{number} {number === 1 ? 'год' : number > 4 ? 'лет' : 'года'}
|
|
152
|
+
</span>
|
|
153
|
+
</button>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface CalculatorParams {
|
|
2
|
+
isAnnuity?: boolean;
|
|
3
|
+
minSum?: number;
|
|
4
|
+
maxSum?: number;
|
|
5
|
+
minMonths?: number;
|
|
6
|
+
maxMonths?: number;
|
|
7
|
+
rateWithInsurance?: number;
|
|
8
|
+
rateWithoutInsurance?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface CreditCalculatorData {
|
|
12
|
+
rows?: CalculatorParams[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface CreditCalculatorContent {
|
|
16
|
+
directoryName?: string;
|
|
17
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const DEFAULT_MIN_SUM = 30000;
|
|
2
|
+
export const DEFAULT_MAX_SUM = 3000000;
|
|
3
|
+
export const DEFAULT_SUM = (DEFAULT_MAX_SUM - DEFAULT_MIN_SUM) / 2;
|
|
4
|
+
export const DEFAULT_MIN_MONTHS = 1;
|
|
5
|
+
export const DEFAULT_MAX_MONTHS = 84;
|
|
6
|
+
export const DEFAULT_MONTHS = Math.round((DEFAULT_MAX_MONTHS - DEFAULT_MIN_MONTHS) / 2);
|
|
7
|
+
|
|
8
|
+
export const MONTHS_IN_YEAR = 12;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CalculatorParams } from './CreditCalculatorContent';
|
|
2
|
+
|
|
3
|
+
interface GetCalculatorParamsParams {
|
|
4
|
+
tableRows?: CalculatorParams[];
|
|
5
|
+
isAnnuity?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const getCalculatorParams = (params: GetCalculatorParamsParams) => {
|
|
9
|
+
const { tableRows, isAnnuity = false } = params;
|
|
10
|
+
|
|
11
|
+
if (!tableRows) return {};
|
|
12
|
+
|
|
13
|
+
const calculatorParams = tableRows.find((row) => row.isAnnuity === isAnnuity);
|
|
14
|
+
|
|
15
|
+
return calculatorParams || {};
|
|
16
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CalculatorParams } from './CreditCalculatorContent';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_RATE = 5;
|
|
4
|
+
|
|
5
|
+
interface GetCreditRateParams {
|
|
6
|
+
calculatorParams?: CalculatorParams;
|
|
7
|
+
isInsurance: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const getCreditRate = (params: GetCreditRateParams) => {
|
|
11
|
+
const { calculatorParams, isInsurance } = params;
|
|
12
|
+
|
|
13
|
+
if (!calculatorParams) return DEFAULT_RATE;
|
|
14
|
+
|
|
15
|
+
return isInsurance
|
|
16
|
+
? calculatorParams?.rateWithInsurance || DEFAULT_RATE
|
|
17
|
+
: calculatorParams?.rateWithoutInsurance || DEFAULT_RATE;
|
|
18
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getCreditTermYears } from './getCreditTermYears';
|
|
2
|
+
|
|
3
|
+
describe('getCreditTermYears', () => {
|
|
4
|
+
it('should return array starts from min year plus one and ends with max year', () => {
|
|
5
|
+
const minMonths = 12;
|
|
6
|
+
const maxMonths = 96;
|
|
7
|
+
const items = [2, 3, 4, 5, 6, 8];
|
|
8
|
+
expect(getCreditTermYears(minMonths, maxMonths)).toEqual(items);
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { MONTHS_IN_YEAR } from './constants';
|
|
2
|
+
|
|
3
|
+
const MAX_YEARS_LENGTH = 5;
|
|
4
|
+
|
|
5
|
+
export const getCreditTermYears = (minMonths: number, maxMonths: number) => {
|
|
6
|
+
const totalYears = Math.ceil((maxMonths - minMonths) / 12);
|
|
7
|
+
const firstYear = Math.floor(minMonths / MONTHS_IN_YEAR) + 1;
|
|
8
|
+
|
|
9
|
+
const result = new Array(Math.min(totalYears - 1, MAX_YEARS_LENGTH))
|
|
10
|
+
.fill(0)
|
|
11
|
+
.map((_, i) => firstYear + i);
|
|
12
|
+
|
|
13
|
+
const maxYear = totalYears + firstYear - 1;
|
|
14
|
+
return result.concat(maxYear);
|
|
15
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { clamp } from '../../utils/clamp';
|
|
2
|
+
import { DEFAULT_MAX_SUM, DEFAULT_MIN_SUM, MONTHS_IN_YEAR } from './constants';
|
|
3
|
+
import { CalculatorParams } from './CreditCalculatorContent';
|
|
4
|
+
|
|
5
|
+
type PaymentType = 'annuity' | 'differentiated';
|
|
6
|
+
|
|
7
|
+
interface GetMonthlyPaymentParams {
|
|
8
|
+
calculatorParams?: CalculatorParams;
|
|
9
|
+
paymentType: PaymentType;
|
|
10
|
+
rate: number;
|
|
11
|
+
sum: number;
|
|
12
|
+
months: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const getMonthlyPayment = (params: GetMonthlyPaymentParams) => {
|
|
16
|
+
const { calculatorParams, paymentType, rate, sum, months } = params;
|
|
17
|
+
|
|
18
|
+
if (!calculatorParams) return 0;
|
|
19
|
+
|
|
20
|
+
const finalSum = clamp(
|
|
21
|
+
sum,
|
|
22
|
+
calculatorParams.minSum || DEFAULT_MIN_SUM,
|
|
23
|
+
calculatorParams.maxSum || DEFAULT_MAX_SUM,
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
if (paymentType === 'annuity') {
|
|
27
|
+
const annuityCoef = Number(rate) / (MONTHS_IN_YEAR * 100);
|
|
28
|
+
return finalSum * (annuityCoef + annuityCoef / (Math.pow(1 + annuityCoef, months) - 1));
|
|
29
|
+
} else {
|
|
30
|
+
return finalSum / months + finalSum * (Number(rate) / 12);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -5,6 +5,7 @@ import type { ContentPageDef } from '../types';
|
|
|
5
5
|
import type { TransformationOptions } from './TransformationOptions';
|
|
6
6
|
import { transformContentPage } from './transformContentPage';
|
|
7
7
|
|
|
8
|
+
const INDEX_PAGE_SLUG = 'index';
|
|
8
9
|
const find = util.promisify(glob);
|
|
9
10
|
|
|
10
11
|
export function ContentPageRepository({
|
|
@@ -16,6 +17,11 @@ export function ContentPageRepository({
|
|
|
16
17
|
return await Promise.all(pagePaths.map(readPage));
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
async function getSecondaryContentPages() {
|
|
21
|
+
const pages = await getAllContentPages();
|
|
22
|
+
return pages.filter((content) => content.slug !== INDEX_PAGE_SLUG);
|
|
23
|
+
}
|
|
24
|
+
|
|
19
25
|
async function getContentPageBySlug(slug: string): Promise<ContentPageDef | undefined> {
|
|
20
26
|
const pages = await getAllContentPages();
|
|
21
27
|
return pages.find((content) => content.slug === slug);
|
|
@@ -26,6 +32,14 @@ export function ContentPageRepository({
|
|
|
26
32
|
return page && toMobilePage(page);
|
|
27
33
|
}
|
|
28
34
|
|
|
35
|
+
async function getIndexPage() {
|
|
36
|
+
return await getContentPageBySlug(INDEX_PAGE_SLUG);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function getIndexMobilePage() {
|
|
40
|
+
return await getMobilePageBySlug(INDEX_PAGE_SLUG);
|
|
41
|
+
}
|
|
42
|
+
|
|
29
43
|
const cache: Record<string, ContentPageDef> = {};
|
|
30
44
|
async function readPage(filePath: string): Promise<ContentPageDef> {
|
|
31
45
|
if (!(filePath in cache)) {
|
|
@@ -41,5 +55,8 @@ export function ContentPageRepository({
|
|
|
41
55
|
getAllContentPages,
|
|
42
56
|
getContentPageBySlug,
|
|
43
57
|
getMobilePageBySlug,
|
|
58
|
+
getSecondaryContentPages,
|
|
59
|
+
getIndexPage,
|
|
60
|
+
getIndexMobilePage,
|
|
44
61
|
};
|
|
45
62
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AsyncDataHook } from '../components/ContentPage/ContentPageContext';
|
|
2
|
+
import { CreditCalculatorData } from '../components/CreditCalculator/CreditCalculatorContent';
|
|
3
|
+
|
|
4
|
+
export function useCreditCalculatorData(
|
|
5
|
+
useAsyncData: AsyncDataHook,
|
|
6
|
+
directoryName: string | undefined,
|
|
7
|
+
): CreditCalculatorData {
|
|
8
|
+
const { data } = useAsyncData(creditCalculatorUrl(directoryName), () =>
|
|
9
|
+
fetchCreditCalculatorData(directoryName),
|
|
10
|
+
);
|
|
11
|
+
return data || {};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function fetchCreditCalculatorData(
|
|
15
|
+
directoryName: string | undefined,
|
|
16
|
+
): Promise<CreditCalculatorData> {
|
|
17
|
+
const response = await fetch(creditCalculatorUrl(directoryName));
|
|
18
|
+
return await response.json();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function creditCalculatorUrl(directoryName: string | undefined) {
|
|
22
|
+
return `/wcms-resources/${directoryName || 'credit-calculator-data'}.json`;
|
|
23
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.809 2.759A2.813 2.813 0 0 1 11.742 2h5.524C18.776 2 20 3.16 20 4.59v13.82c0 1.43-1.224 2.59-2.734 2.59H6.734C5.224 21 4 19.84 4 18.41v-5.95c0-.477.408-.864.911-.864.504 0 .912.387.912.864v5.95c0 .476.408.863.911.863h10.532c.503 0 .911-.387.911-.864V4.591c0-.477-.408-.864-.911-.864h-5.367v4.03c0 .955-.816 1.728-1.823 1.728H4.911c-.368 0-.7-.21-.842-.533a.83.83 0 0 1 .198-.941l5.542-5.252Zm.267 2.19L7.112 7.758h2.964v-2.81Z" fill="#1C1C1C" />
|
|
3
|
+
<rect x="8" y="12" width="8" height="2" rx="1" fill="#42AB44" />
|
|
4
|
+
<rect x="8" y="15" width="5" height="2" rx="1" fill="#42AB44" />
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 12h5M4 12h7" stroke="#42AB44" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 18V6M15 12h5M4 12h7M12 20V4" stroke="#42AB44" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { JSX } from '@redneckz/uni-jsx';
|
|
2
|
+
import { addSpacesBetweenNumbers } from '../../utils/addSpacesBetweenNumbers';
|
|
2
3
|
import type { InputRangeProps } from './InputRangeProps';
|
|
3
4
|
|
|
4
5
|
export const InputRange = JSX<InputRangeProps>(
|
|
@@ -11,7 +12,7 @@ export const InputRange = JSX<InputRangeProps>(
|
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
const inputStyle = {
|
|
14
|
-
backgroundSize: `${(value * 100) / max -
|
|
15
|
+
backgroundSize: `${(((value - min) * 100) / (max - min)).toFixed(2)}% 100%`,
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
const handleBlur = () => {
|
|
@@ -33,7 +34,7 @@ export const InputRange = JSX<InputRangeProps>(
|
|
|
33
34
|
className={`m-0 font-sans text-sm w-full h-12 border-2 border-solid border-main-divider rounded-md outline-none p-0 pl-4 m-0 box-border text-primary-text ${
|
|
34
35
|
title ? 'pt-4' : ''
|
|
35
36
|
}`}
|
|
36
|
-
value={
|
|
37
|
+
value={addSpacesBetweenNumbers(value)}
|
|
37
38
|
onChange={(e) => handleChange(e.target.value)}
|
|
38
39
|
onBlur={handleBlur}
|
|
39
40
|
/>
|