elements: add render props
This commit is contained in:
parent
ffa2731e0e
commit
8f0ac2cf40
@ -48,6 +48,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"newline-before-return": "warn",
|
"newline-before-return": "warn",
|
||||||
"@typescript-eslint/consistent-type-imports": "error"
|
"@typescript-eslint/consistent-type-imports": "error",
|
||||||
|
"react/prop-types": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,24 @@
|
|||||||
/* eslint-disable react/jsx-no-bind */
|
/* eslint-disable react/jsx-no-bind */
|
||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import type { FC } from 'react';
|
||||||
import { useStatus } from 'stores/calculation/statuses/hooks';
|
import { useStatus } from 'stores/calculation/statuses/hooks';
|
||||||
import { getAction } from '../config/map-actions';
|
import type { Elements } from '../config/map-actions';
|
||||||
import type { BuilderProps } from './types';
|
import type { ElementsProps } from '../types/elements-props';
|
||||||
|
|
||||||
export default function buildAction({ elementName, Component, ...props }: BuilderProps) {
|
type BuilderProps = {
|
||||||
const actionName = getAction(elementName);
|
elementName: Elements;
|
||||||
|
actionName: string;
|
||||||
|
};
|
||||||
|
|
||||||
return observer(() => {
|
export default function buildAction(Component: FC<any>, { elementName, actionName }: BuilderProps) {
|
||||||
|
return observer<ElementsProps[typeof elementName]>((props) => {
|
||||||
const status = useStatus(elementName);
|
const status = useStatus(elementName);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Component
|
<Component
|
||||||
status={status}
|
status={status}
|
||||||
{...props}
|
|
||||||
action={() => import(`process/${actionName}`).then((m) => m.default())}
|
action={() => import(`process/${actionName}`).then((m) => m.default())}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,13 +1,21 @@
|
|||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import type { FC } from 'react';
|
||||||
import { useStatus } from 'stores/calculation/statuses/hooks';
|
import { useStatus } from 'stores/calculation/statuses/hooks';
|
||||||
|
import type { ComputedValues } from 'stores/calculation/values/computed';
|
||||||
import { useComputedValue } from 'stores/calculation/values/hooks';
|
import { useComputedValue } from 'stores/calculation/values/hooks';
|
||||||
import { getComputedValueName } from '../config/map-computed';
|
import type { Elements } from '../config/map-computed';
|
||||||
import type { BuilderProps } from './types';
|
import type { ElementsProps } from '../types/elements-props';
|
||||||
|
|
||||||
export default function buildComputedValue({ elementName, Component, ...props }: BuilderProps) {
|
type BuilderProps = {
|
||||||
const computedValueName = getComputedValueName(elementName);
|
elementName: Elements;
|
||||||
|
computedValueName: ComputedValues;
|
||||||
|
};
|
||||||
|
|
||||||
return observer(() => {
|
export default function buildComputedValue(
|
||||||
|
Component: FC<any>,
|
||||||
|
{ elementName, computedValueName }: BuilderProps
|
||||||
|
) {
|
||||||
|
return observer<ElementsProps[typeof elementName]>((props) => {
|
||||||
const computedValue = useComputedValue(computedValueName);
|
const computedValue = useComputedValue(computedValueName);
|
||||||
const status = useStatus(elementName);
|
const status = useStatus(elementName);
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,20 @@
|
|||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import type { FC } from 'react';
|
||||||
import { useOptions } from 'stores/calculation/options/hooks';
|
import { useOptions } from 'stores/calculation/options/hooks';
|
||||||
import { useStatus } from 'stores/calculation/statuses/hooks';
|
import { useStatus } from 'stores/calculation/statuses/hooks';
|
||||||
import { useValidation } from 'stores/calculation/validation/hooks';
|
import { useValidation } from 'stores/calculation/validation/hooks';
|
||||||
import { useSetValue, useValue } from 'stores/calculation/values/hooks';
|
import { useSetValue, useValue } from 'stores/calculation/values/hooks';
|
||||||
import { getValueName } from '../config/map-values';
|
import type { Values } from 'stores/calculation/values/types';
|
||||||
import type { BuilderProps } from './types';
|
import type { Elements } from '../config/map-values';
|
||||||
|
import type { ElementsProps } from '../types/elements-props';
|
||||||
|
|
||||||
export default function buildOptions({ elementName, Component, ...props }: BuilderProps) {
|
type BuilderProps = {
|
||||||
const valueName = getValueName(elementName);
|
elementName: Elements;
|
||||||
|
valueName: Values;
|
||||||
|
};
|
||||||
|
|
||||||
return observer(() => {
|
export default function buildOptions(Component: FC<any>, { elementName, valueName }: BuilderProps) {
|
||||||
|
return observer<ElementsProps[typeof elementName]>((props) => {
|
||||||
const value = useValue(valueName);
|
const value = useValue(valueName);
|
||||||
const setValue = useSetValue(valueName);
|
const setValue = useSetValue(valueName);
|
||||||
const status = useStatus(elementName);
|
const status = useStatus(elementName);
|
||||||
|
|||||||
@ -1,12 +1,20 @@
|
|||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import type { FC } from 'react';
|
||||||
import { useValue } from 'stores/calculation/values/hooks';
|
import { useValue } from 'stores/calculation/values/hooks';
|
||||||
import { getValueName } from '../config/map-values';
|
import type { Values } from 'stores/calculation/values/types';
|
||||||
import type { BuilderProps } from './types';
|
import type { Elements } from '../config/map-values';
|
||||||
|
import type { ElementsProps } from '../types/elements-props';
|
||||||
|
|
||||||
export default function buildReadonly({ elementName, Component, ...props }: BuilderProps) {
|
type BuilderProps = {
|
||||||
const valueName = getValueName(elementName);
|
elementName: Elements;
|
||||||
|
valueName: Values;
|
||||||
|
};
|
||||||
|
|
||||||
return observer(() => {
|
export default function buildReadonly(
|
||||||
|
Component: FC<any>,
|
||||||
|
{ elementName, valueName }: BuilderProps
|
||||||
|
) {
|
||||||
|
return observer<ElementsProps[typeof elementName]>((props) => {
|
||||||
const value = useValue(valueName);
|
const value = useValue(valueName);
|
||||||
|
|
||||||
return <Component value={value} readOnly {...props} />;
|
return <Component value={value} readOnly {...props} />;
|
||||||
|
|||||||
@ -1,14 +1,19 @@
|
|||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import type { FC } from 'react';
|
||||||
import { useStatus } from 'stores/calculation/statuses/hooks';
|
import { useStatus } from 'stores/calculation/statuses/hooks';
|
||||||
import { useValidation } from 'stores/calculation/validation/hooks';
|
import { useValidation } from 'stores/calculation/validation/hooks';
|
||||||
import { useSetValue, useValue } from 'stores/calculation/values/hooks';
|
import { useSetValue, useValue } from 'stores/calculation/values/hooks';
|
||||||
import { getValueName } from '../config/map-values';
|
import type { Values } from 'stores/calculation/values/types';
|
||||||
import type { BuilderProps } from './types';
|
import type { Elements } from '../config/map-values';
|
||||||
|
import type { ElementsProps } from '../types/elements-props';
|
||||||
|
|
||||||
export default function buildValue({ elementName, Component, ...props }: BuilderProps) {
|
type BuilderProps = {
|
||||||
const valueName = getValueName(elementName);
|
elementName: Elements;
|
||||||
|
valueName: Values;
|
||||||
|
};
|
||||||
|
|
||||||
return observer(() => {
|
export default function buildValue(Component: FC<any>, { elementName, valueName }: BuilderProps) {
|
||||||
|
return observer<ElementsProps[typeof elementName]>((props) => {
|
||||||
const value = useValue(valueName);
|
const value = useValue(valueName);
|
||||||
const setValue = useSetValue(valueName);
|
const setValue = useSetValue(valueName);
|
||||||
const status = useStatus(elementName);
|
const status = useStatus(elementName);
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
import type { FC } from 'react';
|
|
||||||
import type { Elements } from '../config/map-values';
|
|
||||||
|
|
||||||
export interface BuilderProps {
|
|
||||||
elementName: Elements;
|
|
||||||
Component: FC<any>;
|
|
||||||
style: React.CSSProperties;
|
|
||||||
}
|
|
||||||
103
Components/Calculation/config/elements-render.tsx
Normal file
103
Components/Calculation/config/elements-render.tsx
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import Link from 'Elements/Link';
|
||||||
|
import Tooltip from 'Elements/Tooltip';
|
||||||
|
import type { FC, ReactNode } from 'react';
|
||||||
|
import { Flex } from 'UIKit/grid';
|
||||||
|
import buildReadonly from '../builders/build-readonly';
|
||||||
|
import type { Elements } from './map-values';
|
||||||
|
|
||||||
|
function Head({ children }: { children: ReactNode }) {
|
||||||
|
return (
|
||||||
|
<Flex
|
||||||
|
flexDirection={['column', 'row']}
|
||||||
|
justifyContent={['', 'space-between']}
|
||||||
|
alignItems={['', 'center']}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type RenderProps = { render: (Title: FC, Element: FC) => JSX.Element };
|
||||||
|
|
||||||
|
const render: Partial<Record<Elements, RenderProps>> = {
|
||||||
|
selectLead: {
|
||||||
|
render: (Title, Element) => {
|
||||||
|
const LinkComponent = buildReadonly(Link, {
|
||||||
|
elementName: 'linkLeadUrl',
|
||||||
|
valueName: 'leadUrl',
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex flexDirection="column">
|
||||||
|
<Head>
|
||||||
|
<Title />
|
||||||
|
<LinkComponent text="Открыть в CRM" />
|
||||||
|
</Head>
|
||||||
|
<Element />
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
selectOpportunity: {
|
||||||
|
render: (Title, Element) => {
|
||||||
|
const LinkComponent = buildReadonly(Link, {
|
||||||
|
elementName: 'linkOpportunityUrl',
|
||||||
|
valueName: 'opportunityUrl',
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex flexDirection="column">
|
||||||
|
<Head>
|
||||||
|
<Title />
|
||||||
|
<LinkComponent text="Открыть в CRM" />
|
||||||
|
</Head>
|
||||||
|
<Element />
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
selectQuote: {
|
||||||
|
render: (Title, Element) => {
|
||||||
|
const LinkComponent = buildReadonly(Link, {
|
||||||
|
elementName: 'linkQuoteUrl',
|
||||||
|
valueName: 'quoteUrl',
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex flexDirection="column">
|
||||||
|
<Head>
|
||||||
|
<Title />
|
||||||
|
<LinkComponent text="Открыть в CRM" />
|
||||||
|
</Head>
|
||||||
|
<Element />
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
tbxVehicleTaxInYear: {
|
||||||
|
render: (Title, Component) => (
|
||||||
|
<Tooltip title="Без учета налога на роскошь" placement="topLeft">
|
||||||
|
<Flex flexDirection="column">
|
||||||
|
<Title />
|
||||||
|
<Component />
|
||||||
|
</Flex>
|
||||||
|
</Tooltip>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
selectHighSeasonStart: {
|
||||||
|
render: (Title, Component) => (
|
||||||
|
<Tooltip title="С какого платежа начинается полный высокий сезон" placement="topLeft">
|
||||||
|
<Flex flexDirection="column">
|
||||||
|
<Title />
|
||||||
|
<Component />
|
||||||
|
</Flex>
|
||||||
|
</Tooltip>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default render;
|
||||||
@ -148,6 +148,9 @@ const elementsToValues = wrapElementsMap({
|
|||||||
|
|
||||||
/** Link Elements */
|
/** Link Elements */
|
||||||
linkDownloadKp: 'kpUrl',
|
linkDownloadKp: 'kpUrl',
|
||||||
|
linkLeadUrl: 'leadUrl',
|
||||||
|
linkOpportunityUrl: 'opportunityUrl',
|
||||||
|
linkQuoteUrl: 'quoteUrl',
|
||||||
});
|
});
|
||||||
|
|
||||||
type ElementsValues = typeof elementsToValues;
|
type ElementsValues = typeof elementsToValues;
|
||||||
|
|||||||
@ -162,4 +162,7 @@ export interface ElementsProps {
|
|||||||
|
|
||||||
/** Link Elements */
|
/** Link Elements */
|
||||||
linkDownloadKp: LinkProps;
|
linkDownloadKp: LinkProps;
|
||||||
|
linkLeadUrl: LinkProps;
|
||||||
|
linkOpportunityUrl: LinkProps;
|
||||||
|
linkQuoteUrl: LinkProps;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,12 +3,12 @@ import type { BaseButtonProps } from 'antd/lib/button/button';
|
|||||||
import { throttle } from 'lodash';
|
import { throttle } from 'lodash';
|
||||||
import type { BaseElementProps } from './types';
|
import type { BaseElementProps } from './types';
|
||||||
|
|
||||||
type ElementProps = BaseElementProps<never> & {
|
type ElementProps = {
|
||||||
action: () => void;
|
action: () => void;
|
||||||
text: string;
|
text: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Button({ status, action, text }: ElementProps) {
|
export default function Button({ status, action, text }: BaseElementProps<never> & ElementProps) {
|
||||||
const throttledAction = throttle(action, 1200, {
|
const throttledAction = throttle(action, 1200, {
|
||||||
trailing: false,
|
trailing: false,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import type { BaseElementProps } from './types';
|
|||||||
|
|
||||||
const { Item: FormItem } = Form;
|
const { Item: FormItem } = Form;
|
||||||
|
|
||||||
type ElementProps = BaseElementProps<boolean> & {
|
type ElementProps = {
|
||||||
text: string;
|
text: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ export default function Checkbox({
|
|||||||
help,
|
help,
|
||||||
text,
|
text,
|
||||||
...props
|
...props
|
||||||
}: ElementProps) {
|
}: BaseElementProps<boolean> & ElementProps) {
|
||||||
function handleChange(e: CheckboxChangeEvent) {
|
function handleChange(e: CheckboxChangeEvent) {
|
||||||
setValue(e.target.checked);
|
setValue(e.target.checked);
|
||||||
}
|
}
|
||||||
@ -36,6 +36,6 @@ export default function Checkbox({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckboxProps = AntCheckboxProps & Pick<ElementProps, 'text'>;
|
type CheckboxProps = AntCheckboxProps & ElementProps;
|
||||||
|
|
||||||
export type { CheckboxProps };
|
export type { CheckboxProps };
|
||||||
|
|||||||
@ -3,11 +3,16 @@ import { Button as AntButton } from 'antd';
|
|||||||
import type { BaseButtonProps } from 'antd/lib/button/button';
|
import type { BaseButtonProps } from 'antd/lib/button/button';
|
||||||
import type { BaseElementProps } from './types';
|
import type { BaseElementProps } from './types';
|
||||||
|
|
||||||
type ElementProps = BaseElementProps<string> & {
|
type ElementProps = {
|
||||||
text: string;
|
text: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Link({ value, status, text, ...props }: ElementProps) {
|
export default function Link({
|
||||||
|
value,
|
||||||
|
status,
|
||||||
|
text,
|
||||||
|
...props
|
||||||
|
}: BaseElementProps<string> & ElementProps) {
|
||||||
return (
|
return (
|
||||||
<AntButton
|
<AntButton
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
@ -23,6 +28,6 @@ export default function Link({ value, status, text, ...props }: ElementProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type LinkProps = BaseButtonProps & Pick<ElementProps, 'text'>;
|
type LinkProps = BaseButtonProps & ElementProps;
|
||||||
|
|
||||||
export type { LinkProps };
|
export type { LinkProps };
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import type { BaseElementProps, BaseOption } from './types';
|
|||||||
|
|
||||||
const { Item: FormItem } = Form;
|
const { Item: FormItem } = Form;
|
||||||
|
|
||||||
type ElementProps = BaseElementProps<string | null> & {
|
type ElementProps = {
|
||||||
options: BaseOption[];
|
options: BaseOption[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ export default function Select({
|
|||||||
isValid,
|
isValid,
|
||||||
help,
|
help,
|
||||||
...props
|
...props
|
||||||
}: ElementProps) {
|
}: BaseElementProps<string | null> & ElementProps) {
|
||||||
const optionsWithNull = useMemo(
|
const optionsWithNull = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
|
|||||||
3
Elements/Tooltip.js
Normal file
3
Elements/Tooltip.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { Tooltip } from 'antd';
|
||||||
|
|
||||||
|
export default Tooltip;
|
||||||
Loading…
x
Reference in New Issue
Block a user