stores: refactor $calculation validation

This commit is contained in:
Chika 2022-10-26 16:56:56 +03:00
parent 99f82ec2f9
commit f54dd44810
12 changed files with 42 additions and 84 deletions

View File

@ -75,7 +75,8 @@
}
],
"import/no-unresolved": "warn",
"implicit-arrow-linebreak": "warn"
"implicit-arrow-linebreak": "warn",
"operator-linebreak": "warn"
},
"overrides": [
// Only uses Testing Library lint rules in test files

View File

@ -3,7 +3,6 @@ import { observer } from 'mobx-react-lite';
import { useStore } from 'stores/hooks';
import styled from 'styled-components';
import { Box, Flex } from 'UIKit/grid';
import titles from '../Calculation/config/elements-titles';
const Bold = styled.span`
font-weight: bold;
@ -20,13 +19,12 @@ function Message(title, text) {
}
function getElementsErrors($calculation) {
const { elementsErrors } = $calculation.$validation;
const errors = Object.keys(elementsErrors).map((elementName) => {
const elementErrors = elementsErrors[elementName];
const elementTitle = titles[elementName];
const errors = Object.values($calculation.$validation).map((validation) => {
const elementErrors = validation.getMessages();
const elementTitle = validation.params.err_title;
return elementErrors.map((error) => (
<Alert key={error.name} type="error" showIcon message={Message(elementTitle, error.text)} />
<Alert key={error.name} type="error" showIcon message={Message(elementTitle, error)} />
));
});

View File

@ -6,7 +6,9 @@ export default function validationReactions(store: RootStore, apolloClient: Apol
const { $calculation, $tables } = store;
reaction(
() => {
const hasElementsErrors = $calculation.$validation.hasErrors;
const hasElementsErrors = Object.values($calculation.$validation).every(
(validation) => validation.hasErrors
);
const hasPaymentsErrors = $tables.payments.validation.hasErrors;
const hasInsuranceErrors = $tables.insurance.validation.hasErrors;
const hasFingapErrors = $tables.fingap.validation.hasErrors;

View File

@ -1,24 +1,26 @@
/* eslint-disable import/no-cycle */
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 { BaseOption } from 'Elements/types';
import { observable } from 'mobx';
import type RootStore from 'stores/root';
import Validation from 'stores/validation';
import OptionsStore from './options';
import StatusStore from './statuses';
import ValidationStore from './validation';
import ValuesStore from './values';
export default class CalculationStore {
$values: ValuesStore;
$status: StatusStore;
$options: OptionsStore;
$validation: ValidationStore;
$validation: Partial<Record<Values.Elements, Validation>>;
constructor(rootStore: RootStore) {
this.$values = new ValuesStore(rootStore);
this.$status = new StatusStore(rootStore);
this.$options = new OptionsStore(rootStore);
this.$validation = new ValidationStore(rootStore);
this.$validation = observable.object({});
}
element = <E extends Values.Elements>(elementName: E) => ({
@ -28,7 +30,7 @@ export default class CalculationStore {
this.$options.resetOptions(elementName);
this.$status.resetStatus(elementName);
this.$validation.clearErrors(elementName);
this.$validation[elementName]?.clearErrors();
return this.element(elementName);
},
@ -83,5 +85,20 @@ export default class CalculationStore {
return this.element(elementName);
},
addError: (message: string) => {
if (!this.$validation[elementName]) {
this.$validation[elementName] = new Validation({
err_key: elementName,
err_title: titles[elementName],
});
}
return this.$validation[elementName]?.addError(message);
},
cleanErrors: () => {
this.$validation[elementName]?.clearErrors();
},
});
}

View File

@ -32,7 +32,6 @@ export default class OptionsStore {
*/
const value = this.root.$calculation.element(elementName).getValue();
if (
// eslint-disable-next-line operator-linebreak
!this.options[elementName]?.length ||
!this.options[elementName].some((x) => x.value === value)
) {

View File

@ -3,10 +3,16 @@ import { useStore } from 'stores/hooks';
export function useValidation(elementName) {
const { $calculation } = useStore();
const validationResult = $calculation.$validation.getValidation(elementName);
const messages = $calculation.$validation[elementName]?.getMessages();
if (messages?.length) {
return {
isValid: false,
help: 'Некорректные данные',
};
}
return {
...validationResult,
help: validationResult?.isValid === false ? 'Некорректные данные' : null,
isValid: true,
};
}

View File

@ -1,60 +0,0 @@
/* eslint-disable object-curly-newline */
import titles from 'Components/Calculation/config/elements-titles';
import type { Elements } from 'Components/Calculation/config/map/values';
import notification from 'Elements/notification';
import { makeAutoObservable, observable } from 'mobx';
import type RootStore from 'stores/root';
import type { ElementsErrors, Error } from './types';
export default class ValidationStore {
root: RootStore;
elementsErrors: Partial<ElementsErrors> = {};
constructor(rootStore: RootStore) {
makeAutoObservable(this);
this.root = rootStore;
}
get hasErrors() {
return (Object.keys(this.elementsErrors) as Elements[]).some(
(elementName) => this.elementsErrors[elementName]?.length
);
}
getValidation(elementName: Elements) {
return {
isValid: !this.elementsErrors[elementName]?.length,
errors: this.elementsErrors[elementName]?.map((x) => x.text),
};
}
addError = (elementName: Elements, error: Error) => {
if (!this.elementsErrors[elementName]) this.elementsErrors[elementName] = observable([]);
const errorIndex = this.elementsErrors[elementName]?.findIndex((x) => x.name === error.name);
const hasError = errorIndex !== undefined && errorIndex !== -1;
if (!hasError) {
this.elementsErrors[elementName]?.push(error);
} else {
this.elementsErrors[elementName]?.splice(errorIndex, 1, error);
}
notification.error({
key: error.name,
message: `${titles[elementName]}`,
description: error.text,
});
return () => this.#removeError(elementName, error.name);
};
#removeError = (elementName: Elements, errorName: Error['name']) => {
const errorIndex = this.elementsErrors[elementName]?.findIndex((x) => x.name === errorName);
if (errorIndex) this.elementsErrors[elementName]?.splice(errorIndex, 1);
};
clearErrors = (elementName: Elements) => {
this.elementsErrors[elementName]?.clear();
};
}

View File

@ -1,5 +0,0 @@
import type { Elements } from 'Components/Calculation/config/map/values';
import type { IObservableArray } from 'mobx';
export type Error = { name: string; text: string };
export type ElementsErrors = Record<Elements, IObservableArray<Error>>;

View File

@ -2,7 +2,7 @@ import type * as FinGAP from 'Components/Calculation/Form/Insurance/FinGAPTable/
import type { IObservableArray } from 'mobx';
import { makeAutoObservable, observable } from 'mobx';
import type RootStore from 'stores/root';
import Validation from '../validation';
import Validation from '../../validation';
export default class FinGAPTable {
root: RootStore;

View File

@ -3,7 +3,7 @@ import type * as Insurance from 'Components/Calculation/Form/Insurance/Insurance
import * as insuranceTableConfig from 'config/tables/insurance-table';
import { makeAutoObservable } from 'mobx';
import type RootStore from 'stores/root';
import Validation from '../validation';
import Validation from '../../validation';
export interface InsuranceTableData {
values?: Insurance.RowValues[];

View File

@ -3,7 +3,7 @@ import type { IObservableArray } from 'mobx';
import { makeAutoObservable, observable, reaction } from 'mobx';
import type RootStore from 'stores/root';
import Validation from '../validation';
import Validation from '../../validation';
import type { Row } from './types';
export default class PaymentsTable {