Components: move Results from Calculation

This commit is contained in:
Chika 2022-06-29 18:26:43 +03:00
parent 692b298180
commit 90b5f4d3a3
28 changed files with 187 additions and 247 deletions

View File

@ -1,21 +0,0 @@
/* eslint-disable object-curly-newline */
/* eslint-disable import/prefer-default-export */
import type { FormTabRows } from '../../lib/render-rows';
export const id = 'output';
export const title = 'Результаты';
const defaultRowStyle = { gridTemplateColumns: ['1fr', '1fr 1fr'] };
export const rows: FormTabRows = [
[['labelResultTotalGraphwithNDS', 'labelResultPlPrice'], defaultRowStyle],
[['labelResultPriceUpPr', 'labelResultIRRGraphPerc'], defaultRowStyle],
[['labelResultIRRNominalPerc', 'labelResultInsKasko'], defaultRowStyle],
[['labelResultInsOsago', 'labelResultDopProdSum'], defaultRowStyle],
[['labelResultFirstPayment', 'labelResultLastPayment'], defaultRowStyle],
[['labelResultFirstPaymentRiskPolicy', 'labelResultTerm'], defaultRowStyle],
[['labelResultAB_FL', 'labelResultAB_UL'], defaultRowStyle],
[['labelResultBonusMPL', 'labelResultDopMPLLeasing'], defaultRowStyle],
[['labelResultBonusDopProd', 'labelResultBonusSafeFinance'], defaultRowStyle],
];

View File

@ -1,12 +0,0 @@
import renderFormRows from '../../lib/render-rows';
import { id, rows, title } from './config';
function Output() {
return renderFormRows(rows);
}
export default {
id,
title,
Component: Output,
};

View File

@ -1,7 +1,6 @@
import buildAction from '../builders/build-action';
import buildComputed from '../builders/build-computed';
import buildOptions from '../builders/build-options';
import buildReadonly from '../builders/build-readonly';
import buildValue from '../builders/build-value';
function wrapElementsBuilders<C, T extends Record<string, C>>(arg: T) {
@ -138,25 +137,6 @@ const builders = wrapElementsBuilders({
labelRegistrationDescription: buildComputed,
btnCreateKP: buildAction,
btnCalculate: buildAction,
labelResultTotalGraphwithNDS: buildReadonly,
labelResultPlPrice: buildReadonly,
labelResultPriceUpPr: buildReadonly,
labelResultIRRGraphPerc: buildReadonly,
labelResultIRRNominalPerc: buildReadonly,
labelResultInsKasko: buildReadonly,
labelResultInsOsago: buildReadonly,
labelResultDopProdSum: buildReadonly,
labelResultFirstPayment: buildReadonly,
labelResultLastPayment: buildReadonly,
labelResultTerm: buildReadonly,
labelResultAB_FL: buildReadonly,
labelResultAB_UL: buildReadonly,
labelResultBonusMPL: buildReadonly,
labelResultDopMPLLeasing: buildReadonly,
labelResultBonusDopProd: buildReadonly,
labelResultBonusSafeFinance: buildReadonly,
labelResultFirstPaymentRiskPolicy: buildReadonly,
});
export default builders;

View File

@ -148,26 +148,6 @@ const components = wrapComponentsMap({
labelIrrInfo: Text,
labelRegistrationDescription: Text,
/** Result Elements */
labelResultTotalGraphwithNDS: Text,
labelResultPlPrice: Text,
labelResultPriceUpPr: Text,
labelResultIRRGraphPerc: Text,
labelResultIRRNominalPerc: Text,
labelResultInsKasko: Text,
labelResultInsOsago: Text,
labelResultDopProdSum: Text,
labelResultFirstPayment: Text,
labelResultLastPayment: Text,
labelResultTerm: Text,
labelResultAB_FL: Text,
labelResultAB_UL: Text,
labelResultBonusMPL: Text,
labelResultDopMPLLeasing: Text,
labelResultBonusDopProd: Text,
labelResultBonusSafeFinance: Text,
labelResultFirstPaymentRiskPolicy: Text,
/** Button Elements */
btnCreateKP: Button,
btnCalculate: Button,

View File

@ -1,9 +1,7 @@
import { MAX_FRANCHISE } from 'constants/values';
import DownloadOutlined from 'Elements/icons/DownloadOutlined';
import date from 'tools/date';
import { formatMoney, formatNumber } from 'tools/format';
import { pipe } from 'tools/function';
import { round } from 'tools/number';
import { formatNumber } from 'tools/format';
import type { ElementsProps } from './elements-components';
const props: Partial<ElementsProps> = {
@ -368,47 +366,4 @@ const props: Partial<ElementsProps> = {
},
};
const moneyResultElementsProps = Object.fromEntries(
(
[
'labelResultTotalGraphwithNDS',
'labelResultPlPrice',
'labelResultInsKasko',
'labelResultInsOsago',
'labelResultDopProdSum',
'labelResultFirstPayment',
'labelResultLastPayment',
'labelResultAB_FL',
'labelResultAB_UL',
'labelResultBonusMPL',
'labelResultDopMPLLeasing',
'labelResultBonusDopProd',
'labelSubsidySum',
'labelResultBonusSafeFinance',
] as (keyof ElementsProps)[]
).map((a) => [
a,
{
middleware: (value: number) => pipe(round, formatMoney)(value),
},
])
);
const numberResultElementsProps = Object.fromEntries(
(
[
'labelResultPriceUpPr',
'labelResultIRRGraphPerc',
'labelResultIRRNominalPerc',
'labelResultTerm',
'labelResultFirstPaymentRiskPolicy',
] as (keyof ElementsProps)[]
).map((a) => [
a,
{
middleware: (value: number) => pipe(round)(value),
},
])
);
export default Object.assign(props, moneyResultElementsProps, numberResultElementsProps);
export default props;

View File

@ -1,4 +1,5 @@
/* eslint-disable object-curly-newline */
import { Container, Head } from 'Components/Layout/Element';
import Link from 'Elements/Link';
import Tooltip from 'Elements/Tooltip';
import type { ComponentProps } from 'react';
@ -8,7 +9,6 @@ import components from '../elements-components';
import elementsProps from '../elements-props';
import titles from '../elements-titles';
import map from '../map';
import { Container, Head } from './layout';
import type { RenderProps } from './types';
const defaultLinkProps: ComponentProps<typeof Link> = {

View File

@ -1,10 +1,10 @@
/* eslint-disable object-curly-newline */
import { Container, Head } from 'Components/Layout/Element';
import builders from '../elements-builders';
import components from '../elements-components';
import elementsProps from '../elements-props';
import titles from '../elements-titles';
import map from '../map';
import { Container, Head } from './layout';
const render = Object.keys(map).reduce((acc, elementName) => {
const title = titles[elementName];

View File

@ -124,26 +124,6 @@ const titles: Record<ValuesElements | ComputedElements | ActionElements, string>
tbxLeaseObjectPriceWthtVAT: 'Стоимость ПЛ без НДС',
tbxVATInLeaseObjectPrice: 'НДС в стоимости ПЛ',
/** Result Elements */
labelResultTotalGraphwithNDS: 'Итого по графику, с НДС',
labelResultPlPrice: 'Стоимость ПЛ с НДС',
labelResultPriceUpPr: 'Удорожание, год',
labelResultIRRGraphPerc: 'IRR по графику клиента, %',
labelResultIRRNominalPerc: 'IRR (номинал), %',
labelResultInsKasko: 'КАСКО, НС, ДГО в графике',
labelResultInsOsago: 'ОСАГО в графике',
labelResultDopProdSum: 'Общая сумма доп.продуктов',
labelResultFirstPayment: 'Первый платеж',
labelResultLastPayment: 'Последний платеж',
labelResultTerm: 'Срок, мес.',
labelResultAB_FL: 'АВ ФЛ, без НДФЛ.',
labelResultAB_UL: 'АВ ЮЛ, с НДС.',
labelResultBonusMPL: 'Бонус МПЛ за лизинг, без НДФЛ',
labelResultDopMPLLeasing: 'Доп.бонус МПЛ за лизинг, без НДФЛ',
labelResultBonusDopProd: 'Бонус МПЛ за доп.продукты, без НДФЛ',
labelResultBonusSafeFinance: 'Бонус за Safe Finance без НДФЛ',
labelResultFirstPaymentRiskPolicy: 'Первый платеж по риск политике, %',
/** Link Elements */
linkDownloadKp: '',

View File

@ -126,26 +126,6 @@ const elementsToValues = wrapElementsMap({
selectFuelCard: 'fuelCard',
tbxMinPriceChange: 'minPriceChange',
/** Result Elements */
labelResultTotalGraphwithNDS: 'resultTotalGraphwithNDS',
labelResultPlPrice: 'resultPlPrice',
labelResultPriceUpPr: 'resultPriceUpPr',
labelResultIRRGraphPerc: 'resultIRRGraphPerc',
labelResultIRRNominalPerc: 'resultIRRNominalPerc',
labelResultInsKasko: 'resultInsKasko',
labelResultInsOsago: 'resultInsOsago',
labelResultDopProdSum: 'resultDopProdSum',
labelResultFirstPayment: 'resultFirstPayment',
labelResultLastPayment: 'resultLastPayment',
labelResultTerm: 'resultTerm',
labelResultAB_FL: 'resultAB_FL',
labelResultAB_UL: 'resultAB_UL',
labelResultBonusMPL: 'resultBonusMPL',
labelResultDopMPLLeasing: 'resultDopMPLLeasing',
labelResultBonusDopProd: 'resultBonusDopProd',
labelResultBonusSafeFinance: 'resultBonusSafeFinance',
labelResultFirstPaymentRiskPolicy: 'resultFirstPaymentRiskPolicy',
/** Link Elements */
linkDownloadKp: 'kpUrl',
});

View File

@ -1,3 +1,2 @@
export { default as Form } from './Form';
export { default as Results } from './Results';
export { default as Settings } from './Settings';

View File

@ -0,0 +1,64 @@
/* eslint-disable object-curly-newline */
import type { Values } from 'stores/results/types';
import { formatMoney, formatPercent } from 'tools/format';
import { pipe } from 'tools/function';
import { round } from 'tools/number';
export const id = 'output';
export const title = 'Результаты';
export const titles: Record<Values, string> = {
resultTotalGraphwithNDS: 'Итого по графику, с НДС',
resultPlPrice: 'Стоимость ПЛ с НДС',
resultPriceUpPr: 'Удорожание, год',
resultIRRGraphPerc: 'IRR по графику клиента, %',
resultIRRNominalPerc: 'IRR (номинал), %',
resultInsKasko: 'КАСКО, НС, ДГО в графике',
resultInsOsago: 'ОСАГО в графике',
resultDopProdSum: 'Общая сумма доп.продуктов',
resultFirstPayment: 'Первый платеж',
resultLastPayment: 'Последний платеж',
resultTerm: 'Срок, мес.',
resultAB_FL: 'АВ ФЛ, без НДФЛ.',
resultAB_UL: 'АВ ЮЛ, с НДС.',
resultBonusMPL: 'Бонус МПЛ за лизинг, без НДФЛ',
resultDopMPLLeasing: 'Доп.бонус МПЛ за лизинг, без НДФЛ',
resultBonusDopProd: 'Бонус МПЛ за доп.продукты, без НДФЛ',
resultBonusSafeFinance: 'Бонус за Safe Finance без НДФЛ',
resultFirstPaymentRiskPolicy: 'Первый платеж по риск политике, %',
};
const moneyFormatters = Object.fromEntries(
(
[
'resultTotalGraphwithNDS',
'resultPlPrice',
'resultInsKasko',
'resultInsOsago',
'resultDopProdSum',
'resultFirstPayment',
'resultLastPayment',
'resultAB_FL',
'resultAB_UL',
'resultBonusMPL',
'resultDopMPLLeasing',
'resultBonusDopProd',
'labelSubsidySum',
'resultBonusSafeFinance',
'resultPriceUpPr',
] as Values[]
).map((a) => [a, (value: number) => pipe(round, formatMoney)(value)])
);
const percentFormatters = Object.fromEntries(
(['resultIRRGraphPerc', 'resultIRRNominalPerc', 'resultFirstPaymentRiskPolicy'] as Values[]).map(
(a) => [a, (value: number) => pipe(round, formatPercent)(value)]
)
);
const defaultFormatters = {
resultTerm: (value: number) => value,
};
export const formatters = Object.assign(moneyFormatters, percentFormatters, defaultFormatters);

View File

@ -0,0 +1,46 @@
import { Container, Head } from 'Components/Layout/Element';
import Text from 'Elements/Text';
import { toJS } from 'mobx';
import { observer } from 'mobx-react-lite';
import { useStore } from 'stores/hooks';
import styled from 'styled-components';
import { Box } from 'UIKit/grid';
import { min } from 'UIKit/mq';
import { formatters, id, title, titles } from './config';
const Grid = styled(Box)`
display: grid;
grid-template-columns: 1fr;
${min('laptop')} {
grid-template-columns: 1fr 1fr;
}
`;
const Output = observer(() => {
const { $results } = useStore();
const values = toJS($results.output);
return (
<Grid>
{Object.keys(values).map((valueName) => {
const formatter = formatters[valueName];
const storeValue = values[valueName];
const value = formatter(storeValue);
return (
<Container key={valueName}>
<Head title={titles[valueName]} />
<Text>{value}</Text>
</Container>
);
})}
</Grid>
);
});
export default {
id,
title,
Component: Output,
};

View File

@ -3,7 +3,7 @@ import { observer } from 'mobx-react-lite';
import { useStore } from 'stores/hooks';
import styled from 'styled-components';
import { Box, Flex } from 'UIKit/grid';
import titles from '../config/elements-titles';
import titles from '../Calculation/config/elements-titles';
const Bold = styled.span`
font-weight: bold;

View File

@ -1,6 +1,5 @@
import type { FC } from 'react';
import type { FC, ReactNode } from 'react';
import styled from 'styled-components';
import type { BaseElementProps } from './types';
const Span = styled.span`
margin-bottom: 18px;
@ -8,9 +7,10 @@ const Span = styled.span`
`;
type TextProps = {
middleware: (value: any) => string;
value: any;
children: ReactNode;
};
export default (function Text({ value, ...props }: BaseElementProps<string> & TextProps) {
return <Span {...props}>{value}</Span>;
export default (function Text({ value, ...props }: TextProps) {
return <Span {...props}>{value || props.children}</Span>;
} as FC<TextProps>);

View File

@ -491,24 +491,6 @@ const defaultOptions: CalculationOptions = {
labelSubsidySum: [],
selectFuelCard: [],
tbxMinPriceChange: [],
labelResultTotalGraphwithNDS: [],
labelResultPlPrice: [],
labelResultPriceUpPr: [],
labelResultIRRGraphPerc: [],
labelResultIRRNominalPerc: [],
labelResultInsKasko: [],
labelResultInsOsago: [],
labelResultDopProdSum: [],
labelResultFirstPayment: [],
labelResultLastPayment: [],
labelResultTerm: [],
labelResultAB_FL: [],
labelResultAB_UL: [],
labelResultBonusMPL: [],
labelResultDopMPLLeasing: [],
labelResultBonusDopProd: [],
labelResultBonusSafeFinance: [],
labelResultFirstPaymentRiskPolicy: [],
linkDownloadKp: [],
};

View File

@ -121,24 +121,6 @@ const defaultStatuses: CalculationStatuses = {
labelSubsidySum: 'Default',
selectFuelCard: 'Default',
tbxMinPriceChange: 'Default',
labelResultTotalGraphwithNDS: 'Default',
labelResultPlPrice: 'Default',
labelResultPriceUpPr: 'Default',
labelResultIRRGraphPerc: 'Default',
labelResultIRRNominalPerc: 'Default',
labelResultInsKasko: 'Default',
labelResultInsOsago: 'Default',
labelResultDopProdSum: 'Default',
labelResultFirstPayment: 'Default',
labelResultLastPayment: 'Default',
labelResultTerm: 'Default',
labelResultAB_FL: 'Default',
labelResultAB_UL: 'Default',
labelResultBonusMPL: 'Default',
labelResultDopMPLLeasing: 'Default',
labelResultBonusDopProd: 'Default',
labelResultBonusSafeFinance: 'Default',
labelResultFirstPaymentRiskPolicy: 'Default',
linkDownloadKp: 'Default',
};

View File

@ -123,24 +123,6 @@ const defaultValues: CalculationValues = {
subsidy: null,
subsidySum: 0,
fuelCard: null,
resultTotalGraphwithNDS: 0,
resultPlPrice: 0,
resultPriceUpPr: 0,
resultIRRGraphPerc: 0,
resultIRRNominalPerc: 0,
resultInsKasko: 0,
resultInsOsago: 0,
resultDopProdSum: 0,
resultFirstPayment: 0,
resultLastPayment: 0,
resultTerm: 0,
resultAB_FL: 0,
resultAB_UL: 0,
resultBonusMPL: 0,
resultDopMPLLeasing: 0,
resultBonusDopProd: 0,
resultBonusSafeFinance: 0,
resultFirstPaymentRiskPolicy: 0,
kpUrl: null,
leadUrl: null,
opportunityUrl: null,

View File

@ -1,5 +1,6 @@
import initializeApollo from 'apollo/client';
import * as Calculation from 'Components/Calculation';
import Results from 'Components/Results';
import type { GetServerSideProps } from 'next';
import Head from 'next/head';
import { fetchUser } from 'services/user';
@ -37,7 +38,7 @@ function Home() {
</Head>
<Calculation.Form />
<Calculation.Settings />
<Calculation.Results />
<Results />
</Grid>
);
}

View File

@ -217,26 +217,6 @@ export type CalculationValues = {
VATInLeaseObjectPrice: number;
engineHours: number;
/** Result Values */
resultTotalGraphwithNDS: number;
resultPlPrice: number;
resultPriceUpPr: number;
resultIRRGraphPerc: number;
resultIRRNominalPerc: number;
resultInsKasko: number;
resultInsOsago: number;
resultDopProdSum: number;
resultFirstPayment: number;
resultLastPayment: number;
resultTerm: number;
resultAB_FL: number;
resultAB_UL: number;
resultBonusMPL: number;
resultDopMPLLeasing: number;
resultBonusDopProd: number;
resultBonusSafeFinance: number;
resultFirstPaymentRiskPolicy: number;
/** Link Values */
kpUrl: string | null;
leadUrl: string | null;

View File

@ -0,0 +1,24 @@
/* eslint-disable import/prefer-default-export */
import type { OutputValues } from './types';
export const defaultOutputValues: OutputValues = {
resultTotalGraphwithNDS: 0,
resultPlPrice: 0,
resultPriceUpPr: 0,
resultIRRGraphPerc: 0,
resultIRRNominalPerc: 0,
resultInsKasko: 0,
resultInsOsago: 0,
resultDopProdSum: 0,
resultFirstPayment: 0,
resultLastPayment: 0,
resultTerm: 0,
resultAB_FL: 0,
resultAB_UL: 0,
resultBonusMPL: 0,
resultDopMPLLeasing: 0,
resultBonusDopProd: 0,
resultBonusSafeFinance: 0,
resultFirstPaymentRiskPolicy: 0,
};

View File

@ -1,15 +1,19 @@
import type { Payment } from 'Components/Calculation/Results/PaymentsTable/types';
import type { Payment } from 'Components/Results/PaymentsTable/types';
import type { IObservableArray } from 'mobx';
import { makeAutoObservable, observable } from 'mobx';
import type RootStore from 'stores/root';
import { defaultOutputValues } from './default-values';
import type { OutputValues } from './types';
export default class Results {
root: RootStore;
payments: IObservableArray<Payment>;
output: OutputValues;
constructor(rootStore: RootStore) {
this.payments = observable<Payment>([]);
this.output = defaultOutputValues;
makeAutoObservable(this);
this.root = rootStore;
@ -19,7 +23,12 @@ export default class Results {
this.payments.replace(payments);
};
setOutput = (output: OutputValues) => {
this.output = output;
};
clear = () => {
this.payments.clear();
this.output = defaultOutputValues;
};
}

22
stores/results/types.ts Normal file
View File

@ -0,0 +1,22 @@
export type OutputValues = {
resultTotalGraphwithNDS: number;
resultPlPrice: number;
resultPriceUpPr: number;
resultIRRGraphPerc: number;
resultIRRNominalPerc: number;
resultInsKasko: number;
resultInsOsago: number;
resultDopProdSum: number;
resultFirstPayment: number;
resultLastPayment: number;
resultTerm: number;
resultAB_FL: number;
resultAB_UL: number;
resultBonusMPL: number;
resultDopMPLLeasing: number;
resultBonusDopProd: number;
resultBonusSafeFinance: number;
resultFirstPaymentRiskPolicy: number;
};
export type Values = keyof OutputValues;

View File

@ -1,10 +1,17 @@
export function formatMoney(n = 0.0, currency = 'RUB') {
export function formatMoney(n = 0, currency = 'RUB') {
return Intl.NumberFormat('ru', {
style: 'currency',
currency,
}).format(n);
}
export function formatNumber(n = 0.0) {
export function formatNumber(n = 0) {
return Intl.NumberFormat('ru').format(n);
}
export function formatPercent(n = 0) {
return Intl.NumberFormat('ru', {
style: 'percent',
maximumFractionDigits: 2,
}).format(n);
}