Calculation: fix elements-render & builders types

This commit is contained in:
Chika 2022-06-23 11:39:02 +03:00
parent a6dac59364
commit 1295b94b25
12 changed files with 121 additions and 104 deletions

View File

@ -33,7 +33,7 @@
],
"import/extensions": "off",
"object-curly-newline": [
"error",
"warn",
{
"ObjectExpression": "always",
"ObjectPattern": { "multiline": true },

View File

@ -1,20 +1,19 @@
/* eslint-disable react/jsx-no-bind */
import { observer } from 'mobx-react-lite';
import type { FC } from 'react';
import type { ComponentType } from 'react';
import { useStatus } from 'stores/calculation/statuses/hooks';
import type { Elements } from '../config/map/actions';
import type { ElementsProps } from '../types/elements-props';
type BuilderProps = {
elementName: Elements;
valueName: string;
};
export default function buildAction(
Component: FC<any>,
export default function buildAction<T>(
Component: ComponentType<T>,
{ elementName, valueName: actionName }: BuilderProps
) {
return observer<ElementsProps[typeof elementName]>((props) => {
return observer((props: T) => {
const status = useStatus(elementName);
return (

View File

@ -1,21 +1,20 @@
import { observer } from 'mobx-react-lite';
import type { FC } from 'react';
import type { ComponentType } from 'react';
import { useStatus } from 'stores/calculation/statuses/hooks';
import type { ComputedValues } from 'stores/calculation/values/computed';
import { useComputedValue } from 'stores/calculation/values/hooks';
import type { Elements } from '../config/map/computed';
import type { ElementsProps } from '../types/elements-props';
type BuilderProps = {
elementName: Elements;
valueName: ComputedValues;
};
export default function buildComputedValue(
Component: FC<any>,
export default function buildComputedValue<T>(
Component: ComponentType<T>,
{ elementName, valueName: computedValueName }: BuilderProps
) {
return observer<ElementsProps[typeof elementName]>((props) => {
return observer((props: T) => {
const computedValue = useComputedValue(computedValueName);
const status = useStatus(elementName);

View File

@ -1,11 +1,10 @@
import { observer } from 'mobx-react-lite';
import type { FC } from 'react';
import type { ComponentType } from 'react';
import { useOptions } from 'stores/calculation/options/hooks';
import { useStatus } from 'stores/calculation/statuses/hooks';
import { useValidation } from 'stores/calculation/validation/hooks';
import type { Values } from 'stores/calculation/values/types';
import type { Elements } from '../config/map/values';
import type { ElementsProps } from '../types/elements-props';
import { useStoreValue } from './hooks';
type BuilderProps = {
@ -13,8 +12,11 @@ type BuilderProps = {
valueName: Values;
};
export default function buildOptions(Component: FC<any>, { elementName, valueName }: BuilderProps) {
return observer<ElementsProps[typeof elementName]>((props) => {
export default function buildOptions<T>(
Component: ComponentType<T>,
{ elementName, valueName }: BuilderProps
) {
return observer((props: T) => {
const [value, setValue] = useStoreValue(valueName);
const status = useStatus(elementName);
const { isValid, help } = useValidation(elementName);

View File

@ -1,19 +1,14 @@
import { observer } from 'mobx-react-lite';
import type { FC } from 'react';
import type { ComponentType } from 'react';
import { useValue } from 'stores/calculation/values/hooks';
import type { Values } from 'stores/calculation/values/types';
import type { ElementsProps } from '../types/elements-props';
type BuilderProps = {
elementName: keyof ElementsProps;
valueName: Values;
};
export default function buildReadonly(
Component: FC<any>,
{ elementName, valueName }: BuilderProps
) {
return observer<ElementsProps[typeof elementName]>((props) => {
export default function buildReadonly<T>(Component: ComponentType<T>, { valueName }: BuilderProps) {
return observer((props: T) => {
const [value] = useValue(valueName);
return <Component value={value} readOnly {...props} />;

View File

@ -1,10 +1,9 @@
import { observer } from 'mobx-react-lite';
import type { FC } from 'react';
import type { ComponentType } from 'react';
import { useStatus } from 'stores/calculation/statuses/hooks';
import { useValidation } from 'stores/calculation/validation/hooks';
import type { Values } from 'stores/calculation/values/types';
import type { Elements } from '../config/map/values';
import type { ElementsProps } from '../types/elements-props';
import { useStoreValue } from './hooks';
export type BuilderProps = {
@ -12,8 +11,11 @@ export type BuilderProps = {
valueName: Values;
};
export default function buildValue(Component: FC<any>, { elementName, valueName }: BuilderProps) {
return observer<ElementsProps[typeof elementName]>((props) => {
export default function buildValue<T>(
Component: ComponentType<T>,
{ elementName, valueName }: BuilderProps
) {
return observer((props: T) => {
const [value, setValue] = useStoreValue(valueName);
const status = useStatus(elementName);
const { isValid, help } = useValidation(elementName);

View File

@ -3,9 +3,12 @@ import buildComputed from '../builders/build-computed';
import buildOptions from '../builders/build-options';
import buildReadonly from '../builders/build-readonly';
import buildValue from '../builders/build-value';
import type components from './elements-components';
const builders: Record<keyof typeof components, any> = {
function wrapElementsBuilders<C, T extends Record<string, C>>(arg: T) {
return arg;
}
const builders = wrapElementsBuilders({
cbxRecalcWithRevision: buildValue,
tbxLeaseObjectPrice: buildValue,
tbxLeaseObjectPriceWthtVAT: buildValue,
@ -154,6 +157,6 @@ const builders: Record<keyof typeof components, any> = {
labelResultBonusDopProd: buildReadonly,
labelResultBonusSafeFinance: buildReadonly,
labelResultFirstPaymentRiskPolicy: buildReadonly,
};
});
export default builders;

View File

@ -0,0 +1,7 @@
/* eslint-disable object-curly-newline */
import type map from '../map';
import overrideRender from './override';
import render from './render';
import type { RenderProps } from './types';
export default Object.assign(render, overrideRender) as Record<keyof typeof map, RenderProps>;

View File

@ -0,0 +1,36 @@
import type { ReactNode } from 'react';
import styled from 'styled-components';
import { Flex } from 'UIKit/grid';
import { min } from 'UIKit/mq';
const ElementTitle = styled.h5`
color: rgba(0, 0, 0, 0.75);
font-weight: 600;
font-size: 13px;
line-height: 1.5;
margin: 0 8px 3px 0;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
${min('laptop')} {
font-size: 14px;
}
`;
export function Head({ title, addon }: { title: string; addon?: ReactNode }) {
return (
<Flex
flexDirection={['column', 'row']}
justifyContent={['', 'space-between']}
alignItems={['', 'center']}
>
<ElementTitle>{title}</ElementTitle>
{addon}
</Flex>
);
}
export function Container({ children }: { children: ReactNode }) {
return <Flex flexDirection="column">{children}</Flex>;
}

View File

@ -1,81 +1,22 @@
/* eslint-disable object-curly-newline */
import Link from 'Elements/Link';
import Tooltip from 'Elements/Tooltip';
import type { ReactNode } from 'react';
import styled from 'styled-components';
import { Flex } from 'UIKit/grid';
import { min } from 'UIKit/mq';
import buildReadonly from '../builders/build-readonly';
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 type { ComponentProps } from 'react';
import buildReadonly from '../../builders/build-readonly';
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';
import type { RenderProps } from './types';
const ElementTitle = styled.h5`
color: rgba(0, 0, 0, 0.75);
font-weight: 600;
font-size: 13px;
line-height: 1.5;
margin: 0 8px 3px 0;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
${min('laptop')} {
font-size: 14px;
}
`;
function Head({ title, addon }: { title: string; addon?: ReactNode }) {
return (
<Flex
flexDirection={['column', 'row']}
justifyContent={['', 'space-between']}
alignItems={['', 'center']}
>
<ElementTitle>{title}</ElementTitle>
{addon}
</Flex>
);
}
function Container({ children }: { children: ReactNode }) {
return <Flex flexDirection="column">{children}</Flex>;
}
type RenderProps = { render: () => JSX.Element };
const renderElements = (Object.keys(map) as (keyof typeof map)[]).reduce((acc, elementName) => {
const title = titles[elementName];
const valueName = map[elementName];
const Component = components[elementName];
const props = elementsProps[elementName];
const builder = builders[elementName];
const Element = builder(Component, {
elementName,
valueName,
});
acc[elementName] = {
render: () => (
<Container key={elementName}>
<Head title={title} />
<Element {...props} />
</Container>
),
};
return acc;
}, {} as Record<keyof typeof map, RenderProps>);
const defaultLinkProps = {
const defaultLinkProps: ComponentProps<typeof Link> = {
text: 'Открыть в CRM',
type: 'link',
};
const overrideRenderElements: Partial<Record<keyof typeof map, RenderProps>> = {
const overrideRender: Partial<Record<keyof typeof map, RenderProps>> = {
selectLead: {
render: () => {
const title = titles.selectLead;
@ -90,7 +31,6 @@ const overrideRenderElements: Partial<Record<keyof typeof map, RenderProps>> = {
});
const LinkComponent = buildReadonly(Link, {
elementName: 'linkLeadUrl',
valueName: 'leadUrl',
});
@ -117,7 +57,6 @@ const overrideRenderElements: Partial<Record<keyof typeof map, RenderProps>> = {
});
const LinkComponent = buildReadonly(Link, {
elementName: 'linkOpportunityUrl',
valueName: 'opportunityUrl',
});
@ -144,7 +83,6 @@ const overrideRenderElements: Partial<Record<keyof typeof map, RenderProps>> = {
});
const LinkComponent = buildReadonly(Link, {
elementName: 'linkQuoteUrl',
valueName: 'quoteUrl',
});
@ -206,4 +144,4 @@ const overrideRenderElements: Partial<Record<keyof typeof map, RenderProps>> = {
},
};
export default Object.assign(renderElements, overrideRenderElements);
export default overrideRender;

View File

@ -0,0 +1,33 @@
/* eslint-disable object-curly-newline */
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];
const valueName = map[elementName];
const Component = components[elementName];
const props = elementsProps[elementName];
const builder = builders[elementName];
const Element = builder(Component, {
elementName,
valueName,
});
acc[elementName] = {
render: () => (
<Container key={elementName}>
<Head title={title} />
<Element {...props} />
</Container>
),
};
return acc;
}, {});
export default render;

View File

@ -0,0 +1,3 @@
import type { FC } from 'react';
export type RenderProps = { render: FC };