elements: add render props
This commit is contained in:
parent
ffa2731e0e
commit
8f0ac2cf40
@ -48,6 +48,7 @@
|
||||
}
|
||||
],
|
||||
"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 */
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import type { FC } from 'react';
|
||||
import { useStatus } from 'stores/calculation/statuses/hooks';
|
||||
import { getAction } from '../config/map-actions';
|
||||
import type { BuilderProps } from './types';
|
||||
import type { Elements } from '../config/map-actions';
|
||||
import type { ElementsProps } from '../types/elements-props';
|
||||
|
||||
export default function buildAction({ elementName, Component, ...props }: BuilderProps) {
|
||||
const actionName = getAction(elementName);
|
||||
type BuilderProps = {
|
||||
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);
|
||||
|
||||
return (
|
||||
<Component
|
||||
status={status}
|
||||
{...props}
|
||||
action={() => import(`process/${actionName}`).then((m) => m.default())}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@ -1,13 +1,21 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import type { FC } 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 { getComputedValueName } from '../config/map-computed';
|
||||
import type { BuilderProps } from './types';
|
||||
import type { Elements } from '../config/map-computed';
|
||||
import type { ElementsProps } from '../types/elements-props';
|
||||
|
||||
export default function buildComputedValue({ elementName, Component, ...props }: BuilderProps) {
|
||||
const computedValueName = getComputedValueName(elementName);
|
||||
type BuilderProps = {
|
||||
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 status = useStatus(elementName);
|
||||
|
||||
|
||||
@ -1,15 +1,20 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import type { FC } from 'react';
|
||||
import { useOptions } from 'stores/calculation/options/hooks';
|
||||
import { useStatus } from 'stores/calculation/statuses/hooks';
|
||||
import { useValidation } from 'stores/calculation/validation/hooks';
|
||||
import { useSetValue, useValue } from 'stores/calculation/values/hooks';
|
||||
import { getValueName } from '../config/map-values';
|
||||
import type { BuilderProps } from './types';
|
||||
import type { Values } from 'stores/calculation/values/types';
|
||||
import type { Elements } from '../config/map-values';
|
||||
import type { ElementsProps } from '../types/elements-props';
|
||||
|
||||
export default function buildOptions({ elementName, Component, ...props }: BuilderProps) {
|
||||
const valueName = getValueName(elementName);
|
||||
type BuilderProps = {
|
||||
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 setValue = useSetValue(valueName);
|
||||
const status = useStatus(elementName);
|
||||
|
||||
@ -1,12 +1,20 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import type { FC } from 'react';
|
||||
import { useValue } from 'stores/calculation/values/hooks';
|
||||
import { getValueName } from '../config/map-values';
|
||||
import type { BuilderProps } from './types';
|
||||
import type { Values } from 'stores/calculation/values/types';
|
||||
import type { Elements } from '../config/map-values';
|
||||
import type { ElementsProps } from '../types/elements-props';
|
||||
|
||||
export default function buildReadonly({ elementName, Component, ...props }: BuilderProps) {
|
||||
const valueName = getValueName(elementName);
|
||||
type BuilderProps = {
|
||||
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);
|
||||
|
||||
return <Component value={value} readOnly {...props} />;
|
||||
|
||||
@ -1,14 +1,19 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import type { FC } from 'react';
|
||||
import { useStatus } from 'stores/calculation/statuses/hooks';
|
||||
import { useValidation } from 'stores/calculation/validation/hooks';
|
||||
import { useSetValue, useValue } from 'stores/calculation/values/hooks';
|
||||
import { getValueName } from '../config/map-values';
|
||||
import type { BuilderProps } from './types';
|
||||
import type { Values } from 'stores/calculation/values/types';
|
||||
import type { Elements } from '../config/map-values';
|
||||
import type { ElementsProps } from '../types/elements-props';
|
||||
|
||||
export default function buildValue({ elementName, Component, ...props }: BuilderProps) {
|
||||
const valueName = getValueName(elementName);
|
||||
type BuilderProps = {
|
||||
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 setValue = useSetValue(valueName);
|
||||
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 */
|
||||
linkDownloadKp: 'kpUrl',
|
||||
linkLeadUrl: 'leadUrl',
|
||||
linkOpportunityUrl: 'opportunityUrl',
|
||||
linkQuoteUrl: 'quoteUrl',
|
||||
});
|
||||
|
||||
type ElementsValues = typeof elementsToValues;
|
||||
|
||||
@ -162,4 +162,7 @@ export interface ElementsProps {
|
||||
|
||||
/** Link Elements */
|
||||
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 type { BaseElementProps } from './types';
|
||||
|
||||
type ElementProps = BaseElementProps<never> & {
|
||||
type ElementProps = {
|
||||
action: () => void;
|
||||
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, {
|
||||
trailing: false,
|
||||
});
|
||||
|
||||
@ -5,7 +5,7 @@ import type { BaseElementProps } from './types';
|
||||
|
||||
const { Item: FormItem } = Form;
|
||||
|
||||
type ElementProps = BaseElementProps<boolean> & {
|
||||
type ElementProps = {
|
||||
text: string;
|
||||
};
|
||||
|
||||
@ -17,7 +17,7 @@ export default function Checkbox({
|
||||
help,
|
||||
text,
|
||||
...props
|
||||
}: ElementProps) {
|
||||
}: BaseElementProps<boolean> & ElementProps) {
|
||||
function handleChange(e: CheckboxChangeEvent) {
|
||||
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 };
|
||||
|
||||
@ -3,11 +3,16 @@ import { Button as AntButton } from 'antd';
|
||||
import type { BaseButtonProps } from 'antd/lib/button/button';
|
||||
import type { BaseElementProps } from './types';
|
||||
|
||||
type ElementProps = BaseElementProps<string> & {
|
||||
type ElementProps = {
|
||||
text: string;
|
||||
};
|
||||
|
||||
export default function Link({ value, status, text, ...props }: ElementProps) {
|
||||
export default function Link({
|
||||
value,
|
||||
status,
|
||||
text,
|
||||
...props
|
||||
}: BaseElementProps<string> & ElementProps) {
|
||||
return (
|
||||
<AntButton
|
||||
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 };
|
||||
|
||||
@ -5,7 +5,7 @@ import type { BaseElementProps, BaseOption } from './types';
|
||||
|
||||
const { Item: FormItem } = Form;
|
||||
|
||||
type ElementProps = BaseElementProps<string | null> & {
|
||||
type ElementProps = {
|
||||
options: BaseOption[];
|
||||
};
|
||||
|
||||
@ -17,7 +17,7 @@ export default function Select({
|
||||
isValid,
|
||||
help,
|
||||
...props
|
||||
}: ElementProps) {
|
||||
}: BaseElementProps<string | null> & ElementProps) {
|
||||
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