partial success!

This commit is contained in:
Владислав Чикалкин 2020-08-27 14:03:39 +03:00
parent 4745d0cfd6
commit 0a7a543934
20 changed files with 2986 additions and 1354 deletions

View File

@ -0,0 +1,26 @@
import { TitledInput } from "client/Elements/Input";
import { testEffectForPrice, testEffectForOne } from "client/Effects";
export default [
{
title: "FirstSection",
elements: [
{
name: "tbxPrice",
title: "Цена",
Component: TitledInput,
// getValue: undefined,
sourceValueName: "price",
Effects: [testEffectForPrice],
},
{
name: "tbxOne",
title: "One",
Component: TitledInput,
// getValue: undefined,
sourceValueName: "one",
Effects: [testEffectForOne],
},
],
},
];

View File

@ -1,73 +1,22 @@
import Background from "client/Elements/Background";
import { useStores } from "client/hooks/useStores";
import Elements from "core/config/elements";
import { useObserver } from "mobx-react";
import React from "react";
function buildElement(
elementName,
Element,
title,
sourceValueName,
getValue,
action,
actionAsync,
valuesStore
) {
if (sourceValueName) {
return (
<Element
title={title}
value={valuesStore.getValue(sourceValueName)}
onChange={(e) => {
valuesStore.setValue(sourceValueName, e.target.value);
}}
/>
);
}
if (getValue) {
return (
<Element
title={title}
value={getValue(valuesStore)}
onChange={(e) => {
valuesStore.setValue(sourceValueName, e.target.value);
}}
/>
);
}
}
import Sections from "./Sections";
import buildElement from "client/hocs/buildElement";
const Calculation = () => {
const {
calculationStore: { valuesStore, statusStore },
} = useStores();
return useObserver(() => (
return (
<Background>
{Object.keys(Elements).map((elementName) => {
const { Element, title, sourceValueName, getValue } = Elements[
elementName
];
return buildElement(
elementName,
Element,
title,
sourceValueName,
getValue,
undefined,
undefined,
valuesStore
);
})}
{Sections.map(({ title, elements }, i) => (
<div key={i}>
<p>{title}</p>
{elements.map((element, ie) => {
const Element = buildElement(element);
return <Element />;
})}
</div>
))}
</Background>
));
};
const styles = {
root: {},
contentWrapper: { flex: 2 },
resultsWrapper: { flex: 1 },
);
};
// export default observer(Calculation);

View File

@ -0,0 +1,20 @@
import CalculationStore from "client/stores/CalculationStore";
import { TEffect } from "core/types/effect";
export const testEffectForPrice: TEffect = async (
calculationStore: CalculationStore
) => {
const price = calculationStore.getValue("price");
if (price > 5000) {
calculationStore.setValue("one", 500);
}
};
export const testEffectForOne: TEffect = async (
calculationStore: CalculationStore
) => {
const one = calculationStore.getValue("one");
if (one > 1000) {
calculationStore.setValue("price", 100500);
}
};

View File

@ -1,6 +1,7 @@
import React from "react";
import styled from "styled-components";
import { Flex } from "client/UIKit/grid";
import { IElementProps } from "core/types/elements";
export const TextInput = styled.input`
width: 200px;
@ -11,11 +12,16 @@ const Title = styled.div`
`;
export const TitledInput = (props) => {
const { title } = props;
const { title, value, onChange } = props;
return (
<Flex flexDirection="column" mx="10px" my="5px">
{title && <Title>{title}</Title>}
<TextInput {...props} />
<TextInput
onChange={(e) => {
onChange(e);
}}
value={value}
/>
</Flex>
);
};

View File

@ -0,0 +1,18 @@
import React from "react";
import styled from "styled-components";
const Select = (props) => {
const { options } = props;
if (!options || options.length === 0) {
return null;
}
return (
<select {...props}>
{options.map(({ value, text }) => (
<option value={value}>{text}</option>
))}
</select>
);
};
export { Select };

View File

@ -3,8 +3,8 @@ import RootStore from "client/stores";
export const StoreContext = createContext();
const rootStore = new RootStore();
export const StoreProvider = ({ children }) => (
<StoreContext.Provider value={new RootStore()}>
{children}
</StoreContext.Provider>
<StoreContext.Provider value={rootStore}>{children}</StoreContext.Provider>
);

View File

@ -0,0 +1,47 @@
import { withStore } from "client/hocs/withStore";
import CalculationStore from "client/stores/CalculationStore";
import CommonStore from "client/stores/CommonStore";
import { SourceValueNames } from "core/types/values";
import { useObserver } from "mobx-react";
import React, { ComponentType } from "react";
import { useStores } from "client/hooks/useStores";
type TElementBuilder = <P extends unknown>(data: {
name: string;
title: string;
Component: ComponentType<P>;
sourceValueName: SourceValueNames;
getValue: () => any;
Effects: Promise<void>[];
calculationStore: CalculationStore;
commonStore: CommonStore;
}) => (props: P) => JSX.Element;
const buildElement: TElementBuilder = ({
name,
title,
Component,
sourceValueName,
getValue,
Effects,
calculationStore,
commonStore,
}) => (props) => {
const { calculationStore } = useStores();
return useObserver(() => (
<Component
{...props}
title={title}
value={calculationStore.getValue(sourceValueName)}
onChange={(e: any) => {
calculationStore.setValue(sourceValueName, e.target.value);
var effect = Effects[0];
//@ts-ignore
effect(calculationStore);
}}
/>
));
};
export default buildElement;

View File

@ -1,6 +1,7 @@
import React, { ComponentType } from "react";
// import hoistNonReactStatics from "hoist-non-react-statics";
import { useStores } from "../hooks/useStores";
import { useObserver } from "mobx-react";
export type TWithStoreHOC = <P extends unknown>(
Component: ComponentType<P>
@ -8,9 +9,9 @@ export type TWithStoreHOC = <P extends unknown>(
export const withStore: TWithStoreHOC = (WrappedComponent) => (props) => {
const ComponentWithStore = () => {
const store = useStores();
const stores = useStores();
return <WrappedComponent {...props} store={store} />;
return <WrappedComponent {...props} stores={stores} />;
};
ComponentWithStore.defaultProps = { ...WrappedComponent.defaultProps };

View File

@ -0,0 +1,24 @@
import initialStatuses from "core/config/initialStatuses";
import initialValues from "core/config/initialValues";
import { SourceValueNames } from "core/types/values";
import { action, observable } from "mobx";
import { Status } from "core/types/elements";
class CalculationStore {
values = observable(initialValues);
statuses = observable(initialStatuses);
getValue = (sourceValueName: SourceValueNames) =>
this.values[sourceValueName];
setValue = action((sourceValueName: SourceValueNames, newValue: any) => {
this.values[sourceValueName] = newValue;
// TODO: Run effect here
});
getStatus = (elementName: string) => this.statuses[elementName];
setStatus = action((elementName: string, status: Status) => {
this.statuses[elementName] = status;
});
}
export default CalculationStore;

View File

@ -1,13 +0,0 @@
import { action, observable } from "mobx";
import { Status } from "core/types/elements";
import initialStatuses from "core/config/initialStatuses";
class StatusStore {
statuses = observable(initialStatuses);
setStatus = action((elementName: string, status: Status) => {
this.statuses[elementName] = status;
});
}
export default StatusStore;

View File

@ -1,17 +0,0 @@
import initialValues from "core/config/initialValues";
import { SourceValuesNames } from "core/types/values";
import { action, observable } from "mobx";
class ValuesStore {
values = observable(initialValues);
setValue = action((sourceValueName: SourceValuesNames, newValue: any) => {
//@ts-ignore
this.values[sourceValueName] = newValue;
});
getValue = (sourceValueName: SourceValuesNames) =>
this.values[sourceValueName];
}
export default ValuesStore;

View File

@ -1,16 +1,3 @@
import Elements from "core/config/elements";
import { action, observable } from "mobx";
import StatusStore from "./StatusStore";
import ValuesStore from "./ValuesStore";
class CalculationStore {
statusStore: StatusStore;
valuesStore: ValuesStore;
constructor() {
this.statusStore = new StatusStore();
this.valuesStore = new ValuesStore();
}
}
import CalculationStore from "./CalculationStore";
export default CalculationStore;

View File

@ -1 +1,3 @@
export default {};
class CommonStore {}
export default CommonStore;

View File

@ -1,10 +1,13 @@
import CalculationStore from "./CalculationStore";
import CommonStore from "client/stores/CommonStore";
class RootStore {
calculationStore: CalculationStore;
commonStore: CommonStore;
constructor() {
this.calculationStore = new CalculationStore();
this.commonStore = new CommonStore();
}
}

View File

@ -1,35 +0,0 @@
import { IElement } from "core/types/elements";
import React from "react";
import { TitledInput } from "client/Elements/Input";
const elements: {
[element: string]: IElement;
} = {
tbx1: {
// title: "Такса",
Element: (props: any) => <TitledInput {...props} />,
sourceValueName: "tax",
},
tbx2: {
Element: (props: any) => <TitledInput {...props} />,
sourceValueName: "price",
},
tbx3: {
Element: (props: any) => <TitledInput {...props} />,
getValue: (valuesStore) => {
const { tax, price } = valuesStore.values;
if (tax && price) {
{
if (typeof tax === "string" && typeof price === "string") {
return parseInt(tax) + parseInt(price);
}
}
}
},
// getStatus:(elementName,statusesStore)=>{
// }
},
};
export default elements;

View File

@ -2,8 +2,6 @@ import { ValuesMap } from "core/types/values";
const initialValues: ValuesMap = {
price: 10000,
tax: 151515,
test: 999999,
};
export default initialValues;

3
src/core/types/effect.ts Normal file
View File

@ -0,0 +1,3 @@
import CalculationStore from "client/stores/CalculationStore";
export type TEffect = (calculationStore: CalculationStore) => Promise<void>;

View File

@ -1,52 +1,7 @@
import { ReactNode } from "react";
import ValuesStore from "client/stores/CalculationStore/ValuesStore";
import StatusStore from "client/stores/CalculationStore/StatusStore";
import { Value, SourceValuesNames } from "./values";
type Action = { (): void };
type Trigger = { (): Action[] };
import CalculationStore from "client/stores/CalculationStore";
import { SourceValueNames } from "core/types/values";
export enum Status {
Default,
Disabled,
Hidden,
Fetching,
}
export interface IBaseElement {
title?: string;
Element: React.Component | ReactNode | JSX.IntrinsicElements | JSX.Element;
getInitialValue?: () => Value;
getInitialStatus?: () => Status | undefined;
getStatus?: (
elementName: string,
statusStore: StatusStore
) => Status | undefined;
}
export interface IBindedElement extends IBaseElement {
sourceValueName?: SourceValuesNames;
}
export interface IComputedElement extends IBaseElement {
getValue?: (valuesStore: ValuesStore) => Value;
getValueAsync?: (
elementName: string,
valuesStore: ValuesStore
) => Promise<Value>;
}
export interface ITriggerElement extends IComputedElement, IBindedElement {
action?: (
e: React.ChangeEvent,
valuesStore: ValuesStore,
statusStore: StatusStore
) => void;
actionAsync?: (
e: React.ChangeEvent,
valuesStore: ValuesStore,
statusStore: StatusStore
) => Promise<void>;
}
export type IElement = IBindedElement & IComputedElement & ITriggerElement;

View File

@ -1,6 +1,5 @@
export type SourceValuesNames = "price" | "tax" | "test";
export type SourceValueNames = "one" | "two" | "three" | "price";
export type Value = string | number | boolean | undefined;
export type ValuesMap = {
[sourceValueName in SourceValuesNames]?: Value;
[valueName in SourceValueNames]?: any;
};

3959
yarn.lock

File diff suppressed because it is too large Load Diff