prepare frontend for /unlimited page
This commit is contained in:
parent
c347095ded
commit
8268ba3c26
@ -21,8 +21,7 @@ export default function buildAction<T>(
|
||||
return (
|
||||
<Component
|
||||
action={() =>
|
||||
import(`process/${processName}/action`).then((module) => module.action(context))
|
||||
}
|
||||
import(`process/${processName}/action`).then((module) => module.action(context))}
|
||||
status={status}
|
||||
{...props}
|
||||
/>
|
||||
|
||||
@ -19,13 +19,13 @@ export default function buildOptions<T>(
|
||||
return observer((props: T) => {
|
||||
const [value, setValue] = useStoreValue(valueName);
|
||||
const status = useStatus(elementName);
|
||||
const { isValid, help } = useValidation(elementName);
|
||||
const { validateStatus, help } = useValidation(elementName);
|
||||
const options = useOptions(elementName);
|
||||
|
||||
return (
|
||||
<Component
|
||||
help={help}
|
||||
isValid={isValid}
|
||||
validateStatus={validateStatus}
|
||||
options={options}
|
||||
setValue={setValue}
|
||||
status={status}
|
||||
|
||||
@ -18,12 +18,12 @@ export default function buildValue<T>(
|
||||
return observer((props: T) => {
|
||||
const [value, setValue] = useStoreValue(valueName);
|
||||
const status = useStatus(elementName);
|
||||
const { isValid, help } = useValidation(elementName);
|
||||
const { validateStatus, help } = useValidation(elementName);
|
||||
|
||||
return (
|
||||
<Component
|
||||
help={help}
|
||||
isValid={isValid}
|
||||
validateStatus={validateStatus}
|
||||
setValue={setValue}
|
||||
status={status}
|
||||
value={value}
|
||||
|
||||
@ -23,41 +23,57 @@ const AlertWrapper = styled(Box)`
|
||||
margin: 0 0 5px 0;
|
||||
`;
|
||||
|
||||
function getElementsErrors($calculation) {
|
||||
function getElementsErrors({ $calculation, $process }) {
|
||||
return Object.values($calculation.$validation).map((validation) => {
|
||||
const elementErrors = validation.getErrors();
|
||||
const elementTitle = validation.params.err_title;
|
||||
|
||||
return elementErrors.map(({ key, message }) => (
|
||||
<AlertWrapper>
|
||||
<Alert key={key} type="error" showIcon message={Message(elementTitle, message)} />
|
||||
<Alert
|
||||
key={key}
|
||||
type={$process.has('Unlimited') ? 'warning' : 'error'}
|
||||
showIcon
|
||||
message={Message(elementTitle, message)}
|
||||
/>
|
||||
</AlertWrapper>
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
function getPaymentsTableErrors($tables) {
|
||||
function getPaymentsTableErrors({ $tables, $process }) {
|
||||
const { payments } = $tables;
|
||||
const errors = payments.validation.getErrors();
|
||||
const title = payments.validation.params.err_title;
|
||||
|
||||
return errors.map(({ key, message }) => (
|
||||
<Alert key={key} type="error" showIcon message={Message(title, message)} />
|
||||
<Alert
|
||||
key={key}
|
||||
type={$process.has('Unlimited') ? 'warning' : 'error'}
|
||||
showIcon
|
||||
message={Message(title, message)}
|
||||
/>
|
||||
));
|
||||
}
|
||||
|
||||
function getInsuranceTableErrors($tables) {
|
||||
function getInsuranceTableErrors({ $tables, $process }) {
|
||||
const { insurance } = $tables;
|
||||
const errors = insurance.validation.getErrors();
|
||||
const title = insurance.validation.params.err_title;
|
||||
|
||||
return errors.map(({ key, message }) => (
|
||||
<Alert key={key} type="error" showIcon message={Message(title, message)} />
|
||||
<Alert
|
||||
key={key}
|
||||
type={$process.has('Unlimited') ? 'warning' : 'error'}
|
||||
showIcon
|
||||
message={Message(title, message)}
|
||||
/>
|
||||
));
|
||||
}
|
||||
|
||||
const Errors = observer(() => {
|
||||
const { $calculation, $tables } = useStore();
|
||||
const store = useStore();
|
||||
const { $calculation, $tables } = store;
|
||||
|
||||
const hasElementsErrors = Object.values($calculation.$validation).some(
|
||||
(validation) => validation.hasErrors
|
||||
@ -69,9 +85,9 @@ const Errors = observer(() => {
|
||||
return <Alert type="success" showIcon message="Ошибок нет 🙂" />;
|
||||
}
|
||||
|
||||
const elementsErrors = getElementsErrors($calculation);
|
||||
const paymentsErrors = getPaymentsTableErrors($tables);
|
||||
const insuranceErrors = getInsuranceTableErrors($tables);
|
||||
const elementsErrors = getElementsErrors(store);
|
||||
const paymentsErrors = getPaymentsTableErrors(store);
|
||||
const insuranceErrors = getInsuranceTableErrors(store);
|
||||
|
||||
const errors = [...elementsErrors, ...paymentsErrors, ...insuranceErrors];
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import type { ProcessContext } from '@/process/types';
|
||||
import ValidationHelper from '@/stores/validation/helper';
|
||||
import { reaction } from 'mobx';
|
||||
import { uid } from 'radash';
|
||||
import { makeDisposable } from 'tools';
|
||||
import type { BaseOption } from 'ui/elements/types';
|
||||
|
||||
function hasInvalidValueOrOptions(value: unknown, options: Array<BaseOption<unknown>>) {
|
||||
@ -16,34 +17,38 @@ function hasInvalidValueOrOptions(value: unknown, options: Array<BaseOption<unkn
|
||||
}
|
||||
|
||||
export default function reactions({ store }: ProcessContext) {
|
||||
const { $calculation, $tables } = store;
|
||||
const { $calculation, $tables, $process } = store;
|
||||
|
||||
reaction(
|
||||
() => {
|
||||
const hasElementsErrors = Object.values($calculation.$validation).some(
|
||||
(validation) => validation.hasErrors
|
||||
);
|
||||
makeDisposable(
|
||||
() =>
|
||||
reaction(
|
||||
() => {
|
||||
const hasElementsErrors = Object.values($calculation.$validation).some(
|
||||
(validation) => validation.hasErrors
|
||||
);
|
||||
|
||||
const hasPaymentsErrors = $tables.payments.validation.hasErrors;
|
||||
const hasInsuranceErrors = $tables.insurance.validation.hasErrors;
|
||||
const hasFingapErrors = $tables.fingap.validation.hasErrors;
|
||||
const hasPaymentsErrors = $tables.payments.validation.hasErrors;
|
||||
const hasInsuranceErrors = $tables.insurance.validation.hasErrors;
|
||||
const hasFingapErrors = $tables.fingap.validation.hasErrors;
|
||||
|
||||
return hasElementsErrors || hasPaymentsErrors || hasInsuranceErrors || hasFingapErrors;
|
||||
},
|
||||
(hasErrors) => {
|
||||
if (hasErrors) {
|
||||
$calculation.$status.setStatus('btnCalculate', 'Disabled');
|
||||
$calculation.$status.setStatus('btnCreateKP', 'Disabled');
|
||||
$calculation.$status.setStatus('btnCreateKPMini', 'Disabled');
|
||||
} else {
|
||||
$calculation.$status.setStatus('btnCalculate', 'Default');
|
||||
$calculation.$status.setStatus('btnCreateKP', 'Default');
|
||||
$calculation.$status.setStatus('btnCreateKPMini', 'Default');
|
||||
}
|
||||
},
|
||||
{
|
||||
fireImmediately: true,
|
||||
}
|
||||
return hasElementsErrors || hasPaymentsErrors || hasInsuranceErrors || hasFingapErrors;
|
||||
},
|
||||
(hasErrors) => {
|
||||
if (hasErrors) {
|
||||
$calculation.$status.setStatus('btnCalculate', 'Disabled');
|
||||
$calculation.$status.setStatus('btnCreateKP', 'Disabled');
|
||||
$calculation.$status.setStatus('btnCreateKPMini', 'Disabled');
|
||||
} else {
|
||||
$calculation.$status.setStatus('btnCalculate', 'Default');
|
||||
$calculation.$status.setStatus('btnCreateKP', 'Default');
|
||||
$calculation.$status.setStatus('btnCreateKPMini', 'Default');
|
||||
}
|
||||
},
|
||||
{
|
||||
fireImmediately: true,
|
||||
}
|
||||
),
|
||||
() => $process.has('Unlimited')
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import Validation from '../validation';
|
||||
import type { ValidationParams } from '../validation/types';
|
||||
import OptionsStore from './options';
|
||||
import StatusStore from './statuses';
|
||||
@ -6,17 +7,18 @@ import titles from '@/Components/Calculation/config/elements-titles';
|
||||
import type * as Values from '@/Components/Calculation/config/map/values';
|
||||
import { getValueName } from '@/Components/Calculation/config/map/values';
|
||||
import type RootStore from '@/stores/root';
|
||||
import Validation from '@/stores/validation';
|
||||
import { observable } from 'mobx';
|
||||
import type { BaseOption } from 'ui/elements/types';
|
||||
|
||||
export default class CalculationStore {
|
||||
private root: RootStore;
|
||||
public $values: ValuesStore;
|
||||
public $status: StatusStore;
|
||||
public $options: OptionsStore;
|
||||
public $validation: Partial<Record<Values.Elements, Validation>>;
|
||||
|
||||
constructor(rootStore: RootStore) {
|
||||
this.root = rootStore;
|
||||
this.$values = new ValuesStore(rootStore);
|
||||
this.$status = new StatusStore(rootStore);
|
||||
this.$options = new OptionsStore(rootStore);
|
||||
@ -24,10 +26,13 @@ export default class CalculationStore {
|
||||
}
|
||||
|
||||
private createElementValidation = <E extends Values.Elements>(elementName: E) => {
|
||||
this.$validation[elementName] = new Validation({
|
||||
err_key: elementName,
|
||||
err_title: titles[elementName],
|
||||
});
|
||||
this.$validation[elementName] = new Validation(
|
||||
{
|
||||
err_key: elementName,
|
||||
err_title: titles[elementName],
|
||||
},
|
||||
this.root
|
||||
);
|
||||
};
|
||||
|
||||
public element = <E extends Values.Elements>(elementName: E) => ({
|
||||
|
||||
@ -21,6 +21,8 @@ export default class StatusStore {
|
||||
};
|
||||
|
||||
public getStatus(elementName: ElementsActions | ElementsValues) {
|
||||
if (this.root.$process.has('Unlimited')) return 'Default';
|
||||
|
||||
return this.overrided[elementName] || this.statuses[elementName];
|
||||
}
|
||||
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
import { useStore } from '@/stores/hooks';
|
||||
|
||||
export function useValidation(elementName) {
|
||||
const { $calculation } = useStore();
|
||||
const { $calculation, $process } = useStore();
|
||||
const hasErrors = $calculation.$validation?.[elementName]?.hasErrors;
|
||||
if (hasErrors) {
|
||||
return {
|
||||
help: 'Некорректные данные',
|
||||
isValid: false,
|
||||
validateStatus: $process.has('Unlimited') ? 'warning' : 'error',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
isValid: true,
|
||||
validateStatus: '',
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { ObservableSet } from 'mobx';
|
||||
import { observable } from 'mobx';
|
||||
|
||||
export type Process = 'ELT' | 'LoadKP';
|
||||
export type Process = 'ELT' | 'LoadKP' | 'Unlimited';
|
||||
export type ProcessStore = ObservableSet<Process>;
|
||||
|
||||
export default function createProcessStore() {
|
||||
|
||||
@ -15,10 +15,13 @@ export default class FinGAPTable {
|
||||
this.selectedKeys = new Set();
|
||||
this.risks = observable<FinGAP.Risk>([]);
|
||||
|
||||
this.validation = new Validation({
|
||||
err_key: 'ERR_FINGAP_TABLE',
|
||||
err_title: 'Таблица рисков Safe Finance',
|
||||
});
|
||||
this.validation = new Validation(
|
||||
{
|
||||
err_key: 'ERR_FINGAP_TABLE',
|
||||
err_title: 'Таблица рисков Safe Finance',
|
||||
},
|
||||
rootStore
|
||||
);
|
||||
|
||||
makeAutoObservable(this);
|
||||
this.root = rootStore;
|
||||
|
||||
@ -21,10 +21,13 @@ export default class InsuranceTable {
|
||||
insuranceTableConfig.defaultStatuses;
|
||||
|
||||
constructor(rootStore: RootStore) {
|
||||
this.validation = new Validation({
|
||||
err_key: 'ERR_INSURANCE_TABLE',
|
||||
err_title: 'Таблица страхования',
|
||||
});
|
||||
this.validation = new Validation(
|
||||
{
|
||||
err_key: 'ERR_INSURANCE_TABLE',
|
||||
err_title: 'Таблица страхования',
|
||||
},
|
||||
rootStore
|
||||
);
|
||||
|
||||
makeAutoObservable(this);
|
||||
this.root = rootStore;
|
||||
@ -95,7 +98,11 @@ export default class InsuranceTable {
|
||||
|
||||
getOptions: <V extends Insurance.Values>(valueName: V) => this.options[key][valueName],
|
||||
|
||||
getStatus: (valueName: Insurance.Values) => this.statuses[key][valueName],
|
||||
getStatus: (valueName: Insurance.Values) => {
|
||||
if (this.root.$process.has('Unlimited')) return 'Default';
|
||||
|
||||
return this.statuses[key][valueName];
|
||||
},
|
||||
|
||||
getValue: <V extends Insurance.Values>(valueName: V) => {
|
||||
const rowIndex = this.values.findIndex((x) => x.key === key);
|
||||
|
||||
@ -14,10 +14,13 @@ export default class PaymentsTable {
|
||||
private overridedStatus: IObservableValue<Status | undefined>;
|
||||
|
||||
constructor(rootStore: RootStore) {
|
||||
this.validation = new Validation({
|
||||
err_key: 'ERR_PAYMENTS_TABLE',
|
||||
err_title: 'Таблица платежей',
|
||||
});
|
||||
this.validation = new Validation(
|
||||
{
|
||||
err_key: 'ERR_PAYMENTS_TABLE',
|
||||
err_title: 'Таблица платежей',
|
||||
},
|
||||
rootStore
|
||||
);
|
||||
|
||||
this.values = observable<number>([]);
|
||||
this.statuses = observable<Status>([]);
|
||||
@ -50,6 +53,8 @@ export default class PaymentsTable {
|
||||
};
|
||||
|
||||
public getStatus(index: number) {
|
||||
if (this.root.$process.has('Unlimited')) return 'Default';
|
||||
|
||||
return this.overridedStatus.get() ?? this.statuses[index];
|
||||
}
|
||||
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
import type RootStore from '../root';
|
||||
import type { RemoveError, ValidationConfig, ValidationError, ValidationParams } from './types';
|
||||
import { makeAutoObservable } from 'mobx';
|
||||
import notification from 'ui/elements/notification';
|
||||
|
||||
export default class Validation {
|
||||
private root: RootStore;
|
||||
private params: ValidationConfig;
|
||||
private errors: Set<ValidationError>;
|
||||
|
||||
constructor(config: ValidationConfig) {
|
||||
constructor(config: ValidationConfig, rootStore: RootStore) {
|
||||
this.params = config;
|
||||
this.errors = new Set();
|
||||
this.root = rootStore;
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
@ -33,10 +36,11 @@ export default class Validation {
|
||||
this.errors.add({ key, message });
|
||||
|
||||
if (!silent) {
|
||||
notification.error({
|
||||
notification.open({
|
||||
description: message,
|
||||
key: this.params.err_key,
|
||||
message: this.params.err_title,
|
||||
type: this.root.$process.has('Unlimited') ? 'warning' : 'error',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ function Checkbox({
|
||||
value,
|
||||
setValue,
|
||||
status,
|
||||
isValid,
|
||||
validateStatus,
|
||||
help,
|
||||
text,
|
||||
...props
|
||||
@ -26,7 +26,7 @@ function Checkbox({
|
||||
}
|
||||
|
||||
return (
|
||||
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}>
|
||||
<FormItem hasFeedback help={help} validateStatus={validateStatus}>
|
||||
<AntCheckbox
|
||||
checked={value}
|
||||
disabled={status === 'Disabled'}
|
||||
|
||||
@ -5,13 +5,20 @@ import type { ChangeEvent, FC } from 'react';
|
||||
|
||||
const { Item: FormItem } = Form;
|
||||
|
||||
function Input({ value, setValue, status, isValid, help, ...props }: BaseElementProps<string>) {
|
||||
function Input({
|
||||
value,
|
||||
setValue,
|
||||
status,
|
||||
validateStatus,
|
||||
help,
|
||||
...props
|
||||
}: BaseElementProps<string>) {
|
||||
function handleChange(event: ChangeEvent<HTMLInputElement>) {
|
||||
setValue(event.target.value);
|
||||
}
|
||||
|
||||
return (
|
||||
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}>
|
||||
<FormItem hasFeedback help={help} validateStatus={validateStatus}>
|
||||
<AntInput disabled={status === 'Disabled'} onChange={handleChange} value={value} {...props} />
|
||||
</FormItem>
|
||||
);
|
||||
|
||||
@ -7,7 +7,13 @@ const { Item: FormItem } = Form;
|
||||
|
||||
type InputNumberProps = AntInputNumberProps<number>;
|
||||
|
||||
function InputNumber({ setValue, status, isValid, help, ...props }: BaseElementProps<number>) {
|
||||
function InputNumber({
|
||||
setValue,
|
||||
status,
|
||||
validateStatus,
|
||||
help,
|
||||
...props
|
||||
}: BaseElementProps<number>) {
|
||||
function handleChange(value: number | null) {
|
||||
if (value) {
|
||||
setValue(value);
|
||||
@ -17,7 +23,7 @@ function InputNumber({ setValue, status, isValid, help, ...props }: BaseElementP
|
||||
}
|
||||
|
||||
return (
|
||||
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}>
|
||||
<FormItem hasFeedback help={help} validateStatus={validateStatus}>
|
||||
<AntInputNumber
|
||||
disabled={status === 'Disabled'}
|
||||
onChange={handleChange}
|
||||
|
||||
@ -19,7 +19,7 @@ function Radio({
|
||||
setValue,
|
||||
options,
|
||||
status,
|
||||
isValid,
|
||||
validateStatus,
|
||||
help,
|
||||
spaceProps,
|
||||
...props
|
||||
@ -29,7 +29,7 @@ function Radio({
|
||||
}
|
||||
|
||||
return (
|
||||
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}>
|
||||
<FormItem hasFeedback help={help} validateStatus={validateStatus}>
|
||||
<AntRadio.Group
|
||||
disabled={status === 'Disabled'}
|
||||
onChange={handleChange}
|
||||
|
||||
@ -9,9 +9,17 @@ type ElementProps = BaseElementProps<number | string> & {
|
||||
options: BaseOption[];
|
||||
};
|
||||
|
||||
function Segmented({ value, setValue, options, status, isValid, help, ...props }: ElementProps) {
|
||||
function Segmented({
|
||||
value,
|
||||
setValue,
|
||||
options,
|
||||
status,
|
||||
validateStatus,
|
||||
help,
|
||||
...props
|
||||
}: ElementProps) {
|
||||
return (
|
||||
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}>
|
||||
<FormItem hasFeedback help={help} validateStatus={validateStatus}>
|
||||
<AntSegmented
|
||||
disabled={status === 'Disabled'}
|
||||
onChange={setValue}
|
||||
|
||||
@ -15,7 +15,7 @@ function Select({
|
||||
setValue,
|
||||
options = [],
|
||||
status,
|
||||
isValid,
|
||||
validateStatus,
|
||||
help,
|
||||
...props
|
||||
}: BaseElementProps<string | null> & ElementProps) {
|
||||
@ -31,7 +31,7 @@ function Select({
|
||||
);
|
||||
|
||||
return (
|
||||
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}>
|
||||
<FormItem hasFeedback help={help} validateStatus={validateStatus}>
|
||||
<AntSelect
|
||||
disabled={status === 'Disabled'}
|
||||
loading={status === 'Loading'}
|
||||
|
||||
@ -5,9 +5,16 @@ import type { FC } from 'react';
|
||||
|
||||
const { Item: FormItem } = Form;
|
||||
|
||||
function Switch({ value, setValue, status, isValid, help, ...props }: BaseElementProps<boolean>) {
|
||||
function Switch({
|
||||
value,
|
||||
setValue,
|
||||
status,
|
||||
validateStatus,
|
||||
help,
|
||||
...props
|
||||
}: BaseElementProps<boolean>) {
|
||||
return (
|
||||
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}>
|
||||
<FormItem hasFeedback help={help} validateStatus={validateStatus}>
|
||||
<AntSwitch checked={value} disabled={status === 'Disabled'} onChange={setValue} {...props} />
|
||||
</FormItem>
|
||||
);
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import type { ValidateStatus } from 'antd/es/form/FormItem';
|
||||
|
||||
export type Status = 'Default' | 'Disabled' | 'Hidden' | 'Loading';
|
||||
|
||||
export type BaseElementProps<Value> = {
|
||||
help?: string;
|
||||
isValid?: boolean;
|
||||
setValue: (value: Value) => void;
|
||||
status?: Status;
|
||||
validateStatus?: ValidateStatus;
|
||||
value: Value;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user