Compare commits

...

11 Commits

Author SHA1 Message Date
vchikalkin
10a0618d17 add dot badge for validation tab 2023-03-28 20:17:23 +03:00
vchikalkin
291812f349 fix margin for tables Alerts 2023-03-28 18:45:33 +03:00
vchikalkin
631272101d stores: fix Loading status 2023-03-28 18:42:24 +03:00
vchikalkin
6163dbf994 use warning type for Alerts 2023-03-28 15:33:21 +03:00
vchikalkin
a4f0bc717a fix pass right user to create-kp 2023-03-28 15:29:22 +03:00
vchikalkin
4a4e29102b fix selectuser is null 2023-03-28 15:11:29 +03:00
vchikalkin
579b346532 fix build 2023-03-28 14:59:08 +03:00
vchikalkin
91f69e79e5 pages: add unlimited 2023-03-28 14:49:34 +03:00
vchikalkin
8268ba3c26 prepare frontend for /unlimited page 2023-03-28 12:41:19 +03:00
vchikalkin
c347095ded process: move init hooks to /hooks dir 2023-03-28 11:53:29 +03:00
vchikalkin
5e9e897535 move reactions hooks to process dir 2023-03-28 11:24:27 +03:00
70 changed files with 713 additions and 307 deletions

3
.env
View File

@ -2,9 +2,6 @@
USE_DEV_COLORS= USE_DEV_COLORS=
BASE_PATH= BASE_PATH=
####### USERS ########
USERS_SUPER=["akalinina","vchikalkin"]
####### URLS ######## ####### URLS ########
URL_GET_USER_DIRECT= URL_GET_USER_DIRECT=
URL_CRM_GRAPHQL_DIRECT= URL_CRM_GRAPHQL_DIRECT=

View File

@ -12,12 +12,18 @@ const Grid = styled(Flex)`
`; `;
const Validation = observer(() => { const Validation = observer(() => {
const store = useStore(); const { $tables, $process } = useStore();
const errors = store.$tables.fingap.validation.getErrors(); const errors = $tables.fingap.validation.getErrors();
if (errors?.length) { if (errors?.length) {
return <Alert type="error" banner message={errors[0].message} />; return (
<Alert
type={$process.has('Unlimited') ? 'warning' : 'error'}
banner
message={errors[0].message}
/>
);
} }
return null; return null;

View File

@ -17,12 +17,18 @@ const TableWrapper = styled.div`
`; `;
const Validation = observer(() => { const Validation = observer(() => {
const store = useStore(); const { $tables, $process } = useStore();
const errors = store.$tables.insurance.validation.getErrors(); const errors = $tables.insurance.validation.getErrors();
if (errors?.length) { if (errors?.length) {
return <Alert type="error" banner message={errors[0].message} />; return (
<Alert
type={$process.has('Unlimited') ? 'warning' : 'error'}
banner
message={errors[0].message}
/>
);
} }
return null; return null;

View File

@ -30,13 +30,19 @@ const TablesGroupGrid = styled(Box)`
`; `;
const Validation = observer(() => { const Validation = observer(() => {
const store = useStore(); const { $tables, $process } = useStore();
const { payments } = store.$tables; const { payments } = $tables;
const errors = payments.validation.getErrors(); const errors = payments.validation.getErrors();
if (errors?.length) { if (errors?.length) {
return <Alert type="error" banner message={errors[0].message} />; return (
<Alert
type={$process.has('Unlimited') ? 'warning' : 'error'}
banner
message={errors[0].message}
/>
);
} }
return null; return null;

View File

@ -0,0 +1,12 @@
import type { FormTabRows } from '../../lib/render-rows';
export const id = 'unlimited';
export const title = 'Без ограничений';
export const rows: FormTabRows = [
[['cbxDisableChecks', 'selectUser']],
[['selectTarif', 'tbxCreditRate', 'selectRate']],
[['tbxMinPriceChange', 'tbxMaxPriceChange']],
[['tbxImporterRewardPerc', 'tbxImporterRewardRub']],
[['tbxBonusCoefficient', 'tbxComissionRub', 'tbxComissionPerc']],
];

View File

@ -0,0 +1,12 @@
import renderFormRows from '../../lib/render-rows';
import { id, rows, title } from './config';
function Unlimited() {
return renderFormRows(rows);
}
export default {
Component: Unlimited,
id,
title,
};

View File

@ -5,12 +5,22 @@ import Leasing from './Leasing';
import LeasingObject from './LeasingObject'; import LeasingObject from './LeasingObject';
import Payments from './Payments'; import Payments from './Payments';
import SupplierAgent from './SupplierAgent'; import SupplierAgent from './SupplierAgent';
import Unlimited from './Unlimited';
import Background from '@/Components/Layout/Background'; import Background from '@/Components/Layout/Background';
import { min } from '@/styles/mq'; import { min } from '@/styles/mq';
import styled from 'styled-components'; import styled from 'styled-components';
import Tabs from 'ui/elements/layout/Tabs'; import Tabs from 'ui/elements/layout/Tabs';
const formTabs = [Leasing, Payments, LeasingObject, SupplierAgent, Insurance, AddProduct, CreateKP]; const formTabs = [
Leasing,
Payments,
LeasingObject,
SupplierAgent,
Insurance,
AddProduct,
CreateKP,
Unlimited,
];
const Wrapper = styled(Background)` const Wrapper = styled(Background)`
padding: 4px 6px; padding: 4px 6px;
@ -32,17 +42,19 @@ const ComponentWrapper = styled.div`
} }
`; `;
function Form() { function Form({ prune }) {
return ( return (
<Wrapper> <Wrapper>
<Tabs type="card" tabBarGutter="5px"> <Tabs type="card" tabBarGutter="5px">
{formTabs.map(({ id, title, Component }) => ( {formTabs
<Tabs.TabPane tab={title} key={id}> .filter((tab) => !prune?.includes(tab.id))
<ComponentWrapper> .map(({ id, title, Component }) => (
<Component /> <Tabs.TabPane tab={title} key={id}>
</ComponentWrapper> <ComponentWrapper>
</Tabs.TabPane> <Component />
))} </ComponentWrapper>
</Tabs.TabPane>
))}
</Tabs> </Tabs>
</Wrapper> </Wrapper>
); );

View File

@ -1,5 +1,5 @@
import type { Elements } from '../config/map/actions'; import type { Elements } from '../config/map/actions';
import { useProcessContext } from '@/process/hooks'; import { useProcessContext } from '@/process/hooks/common';
import { useStatus } from '@/stores/calculation/statuses/hooks'; import { useStatus } from '@/stores/calculation/statuses/hooks';
import { observer } from 'mobx-react-lite'; import { observer } from 'mobx-react-lite';
import type { ComponentType } from 'react'; import type { ComponentType } from 'react';

View File

@ -19,13 +19,13 @@ export default function buildOptions<T>(
return observer((props: T) => { return observer((props: T) => {
const [value, setValue] = useStoreValue(valueName); const [value, setValue] = useStoreValue(valueName);
const status = useStatus(elementName); const status = useStatus(elementName);
const { isValid, help } = useValidation(elementName); const { validateStatus, help } = useValidation(elementName);
const options = useOptions(elementName); const options = useOptions(elementName);
return ( return (
<Component <Component
help={help} help={help}
isValid={isValid} validateStatus={validateStatus}
options={options} options={options}
setValue={setValue} setValue={setValue}
status={status} status={status}

View File

@ -18,12 +18,12 @@ export default function buildValue<T>(
return observer((props: T) => { return observer((props: T) => {
const [value, setValue] = useStoreValue(valueName); const [value, setValue] = useStoreValue(valueName);
const status = useStatus(elementName); const status = useStatus(elementName);
const { isValid, help } = useValidation(elementName); const { validateStatus, help } = useValidation(elementName);
return ( return (
<Component <Component
help={help} help={help}
isValid={isValid} validateStatus={validateStatus}
setValue={setValue} setValue={setValue}
status={status} status={status}
value={value} value={value}

View File

@ -131,6 +131,7 @@ const components = wrapComponentsMap({
tbxBonusCoefficient: e.InputNumber, tbxBonusCoefficient: e.InputNumber,
selectLeasingWithoutKasko: e.Select, selectLeasingWithoutKasko: e.Select,
tbxVIN: e.Input, tbxVIN: e.Input,
selectUser: e.Select,
/** Readonly Elements */ /** Readonly Elements */
labelLeaseObjectRisk: e.Text, labelLeaseObjectRisk: e.Text,

View File

@ -444,6 +444,10 @@ const props: Partial<ElementsProps> = {
direction: 'vertical', direction: 'vertical',
}, },
}, },
selectUser: {
showSearch: true,
optionFilterProp: 'label',
},
}; };
export default props; export default props;

View File

@ -125,6 +125,7 @@ const titles: Record<ActionElements | ValuesElements, string> = {
tbxBonusCoefficient: 'Коэффициент снижения бонуса', tbxBonusCoefficient: 'Коэффициент снижения бонуса',
selectLeasingWithoutKasko: 'Лизинг без КАСКО', selectLeasingWithoutKasko: 'Лизинг без КАСКО',
tbxVIN: 'VIN', tbxVIN: 'VIN',
selectUser: 'Пользователь',
/** Link Elements */ /** Link Elements */
linkDownloadKp: '', linkDownloadKp: '',

View File

@ -162,6 +162,7 @@ const types = wrapElementsTypes({
tbxBonusCoefficient: t.Value, tbxBonusCoefficient: t.Value,
selectLeasingWithoutKasko: t.Options, selectLeasingWithoutKasko: t.Options,
tbxVIN: t.Value, tbxVIN: t.Value,
selectUser: t.Options,
labelLeaseObjectRisk: t.Readonly, labelLeaseObjectRisk: t.Readonly,
tbxInsKaskoPriceLeasePeriod: t.Readonly, tbxInsKaskoPriceLeasePeriod: t.Readonly,

View File

@ -128,6 +128,7 @@ const elementsToValues = wrapElementsMap({
tbxMinPriceChange: 'minPriceChange', tbxMinPriceChange: 'minPriceChange',
tbxBonusCoefficient: 'bonusCoefficient', tbxBonusCoefficient: 'bonusCoefficient',
tbxVIN: 'vin', tbxVIN: 'vin',
selectUser: 'user',
/** Readonly Elements */ /** Readonly Elements */
labelLeaseObjectRisk: 'leaseObjectRiskName', labelLeaseObjectRisk: 'leaseObjectRiskName',

View File

@ -1,10 +1,13 @@
/* eslint-disable react/forbid-component-props */ /* eslint-disable react/forbid-component-props */
import styles from './Logo.module.css'; import styles from './Logo.module.css';
import { useStore } from '@/stores/hooks';
import getColors from '@/styles/colors';
import { min } from '@/styles/mq'; import { min } from '@/styles/mq';
import { observer } from 'mobx-react-lite';
import Image from 'next/image'; import Image from 'next/image';
import logo from 'public/assets/images/logo-primary.svg'; import logo from 'public/assets/images/logo-primary.svg';
import styled from 'styled-components'; import styled from 'styled-components';
import { Flex } from 'ui'; import { Flex, Tag } from 'ui';
const ImageWrapper = styled.div` const ImageWrapper = styled.div`
width: 100px; width: 100px;
@ -26,13 +29,41 @@ const LogoText = styled.h3`
} }
`; `;
const TagWrapper = styled.div`
font-family: 'Montserrat';
font-weight: 500;
* {
font-size: 0.7rem;
}
`;
const { COLOR_PRIMARY } = getColors();
const UnlimitedTag = observer(() => {
const { $process } = useStore();
if ($process.has('Unlimited')) {
return (
<TagWrapper>
<Tag color={COLOR_PRIMARY} style={{ margin: '0 5px' }}>
без ограничений
</Tag>
</TagWrapper>
);
}
return false;
});
function Logo() { function Logo() {
return ( return (
<Flex flexDirection="column" alignItems="flex-start" justifyContent="space-between"> <Flex flexDirection="column" alignItems="flex-start" justifyContent="space-between">
<ImageWrapper> <ImageWrapper>
<Image priority className={styles.logo} alt="logo" src={logo} layout="responsive" /> <Image priority className={styles.logo} alt="logo" src={logo} layout="responsive" />
</ImageWrapper> </ImageWrapper>
<LogoText>Лизинговый Калькулятор</LogoText> <Flex justifyContent="space-between" alignItems="center">
<LogoText>Лизинговый Калькулятор</LogoText>
<UnlimitedTag />
</Flex>
</Flex> </Flex>
); );
} }

View File

@ -0,0 +1,27 @@
import { min } from '@/styles/mq';
import styled from 'styled-components';
import { Box } from 'ui/grid';
export const Grid = styled(Box)`
display: flex;
flex-direction: column;
gap: 10px;
${min('laptop')} {
display: grid;
align-items: flex-start;
grid-template-columns: 2fr 1fr;
}
${min('laptop-hd')} {
grid-template-columns: 2fr 1fr 1.5fr;
}
${min('desktop')} {
margin: 8px 5%;
}
${min('desktop-xl')} {
margin: 8px 10%;
}
`;

View File

@ -23,41 +23,61 @@ const AlertWrapper = styled(Box)`
margin: 0 0 5px 0; margin: 0 0 5px 0;
`; `;
function getElementsErrors($calculation) { function getElementsErrors({ $calculation, $process }) {
return Object.values($calculation.$validation).map((validation) => { return Object.values($calculation.$validation).map((validation) => {
const elementErrors = validation.getErrors(); const elementErrors = validation.getErrors();
const elementTitle = validation.params.err_title; const elementTitle = validation.params.err_title;
return elementErrors.map(({ key, message }) => ( return elementErrors.map(({ key, message }) => (
<AlertWrapper> <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> </AlertWrapper>
)); ));
}); });
} }
function getPaymentsTableErrors($tables) { function getPaymentsTableErrors({ $tables, $process }) {
const { payments } = $tables; const { payments } = $tables;
const errors = payments.validation.getErrors(); const errors = payments.validation.getErrors();
const title = payments.validation.params.err_title; const title = payments.validation.params.err_title;
return errors.map(({ key, message }) => ( return errors.map(({ key, message }) => (
<Alert key={key} type="error" showIcon message={Message(title, message)} /> <AlertWrapper>
<Alert
key={key}
type={$process.has('Unlimited') ? 'warning' : 'error'}
showIcon
message={Message(title, message)}
/>
</AlertWrapper>
)); ));
} }
function getInsuranceTableErrors($tables) { function getInsuranceTableErrors({ $tables, $process }) {
const { insurance } = $tables; const { insurance } = $tables;
const errors = insurance.validation.getErrors(); const errors = insurance.validation.getErrors();
const title = insurance.validation.params.err_title; const title = insurance.validation.params.err_title;
return errors.map(({ key, message }) => ( return errors.map(({ key, message }) => (
<Alert key={key} type="error" showIcon message={Message(title, message)} /> <AlertWrapper>
<Alert
key={key}
type={$process.has('Unlimited') ? 'warning' : 'error'}
showIcon
message={Message(title, message)}
/>
</AlertWrapper>
)); ));
} }
const Errors = observer(() => { const Errors = observer(() => {
const { $calculation, $tables } = useStore(); const store = useStore();
const { $calculation, $tables } = store;
const hasElementsErrors = Object.values($calculation.$validation).some( const hasElementsErrors = Object.values($calculation.$validation).some(
(validation) => validation.hasErrors (validation) => validation.hasErrors
@ -69,9 +89,9 @@ const Errors = observer(() => {
return <Alert type="success" showIcon message="Ошибок нет 🙂" />; return <Alert type="success" showIcon message="Ошибок нет 🙂" />;
} }
const elementsErrors = getElementsErrors($calculation); const elementsErrors = getElementsErrors(store);
const paymentsErrors = getPaymentsTableErrors($tables); const paymentsErrors = getPaymentsTableErrors(store);
const insuranceErrors = getInsuranceTableErrors($tables); const insuranceErrors = getInsuranceTableErrors(store);
const errors = [...elementsErrors, ...paymentsErrors, ...insuranceErrors]; const errors = [...elementsErrors, ...paymentsErrors, ...insuranceErrors];

View File

@ -2,11 +2,39 @@ import PaymentsTable from './PaymentsTable';
import Results from './Results'; import Results from './Results';
import Validation from './Validation'; import Validation from './Validation';
import Background from '@/Components/Layout/Background'; import Background from '@/Components/Layout/Background';
import { useStore } from '@/stores/hooks';
import { min } from '@/styles/mq'; import { min } from '@/styles/mq';
import { observer } from 'mobx-react-lite';
import styled from 'styled-components'; import styled from 'styled-components';
import Tabs from 'ui/elements/layout/Tabs'; import { Badge, Tabs } from 'ui';
const outputTabs = [PaymentsTable, Results, Validation]; const outputTabs = [PaymentsTable, Results, Validation];
const items = outputTabs.map(({ Component, id, title }) => {
let Label = () => title;
if (id === 'validation') {
Label = observer(() => {
const { $calculation, $tables } = useStore();
const hasErrors =
$calculation.hasErrors ||
$tables.fingap.hasErrors ||
$tables.insurance.hasErrors ||
$tables.payments.hasErrors;
return (
<Badge offset={[5, 0]} dot={hasErrors}>
{title}
</Badge>
);
});
}
return {
children: <Component />,
key: id,
label: <Label />,
};
});
const Wrapper = styled(Background)` const Wrapper = styled(Background)`
padding: 4px 10px; padding: 4px 10px;
@ -21,13 +49,7 @@ const Wrapper = styled(Background)`
function Output() { function Output() {
return ( return (
<Wrapper> <Wrapper>
<Tabs> <Tabs items={items} />
{outputTabs.map(({ id, title, Component }) => (
<Tabs.TabPane tab={title} key={id}>
<Component />
</Tabs.TabPane>
))}
</Tabs>
</Wrapper> </Wrapper>
); );
} }

View File

@ -138,8 +138,13 @@ const AdditionalDataSchema = z.object({
export type AdditionalData = z.infer<typeof AdditionalDataSchema>; export type AdditionalData = z.infer<typeof AdditionalDataSchema>;
const flagsSchema = z.object({
DISABLE_CHECKS_RESULTS: z.boolean(),
});
export const RequestCalculateSchema = z.object({ export const RequestCalculateSchema = z.object({
additionalData: AdditionalDataSchema, additionalData: AdditionalDataSchema,
flags: flagsSchema.optional(),
preparedPayments: PreparedPaymentSchema, preparedPayments: PreparedPaymentSchema,
preparedValues: PreparedValuesSchema, preparedValues: PreparedValuesSchema,
}); });

View File

@ -1,13 +1,8 @@
import type { User } from './types'; import type { User } from './types';
import { publicRuntimeConfigSchema } from '@/config/schema/runtime-config'; import { usersSuper } from '@/config/users';
import getConfig from 'next/config';
const { publicRuntimeConfig } = getConfig();
const { USERS_SUPER } = publicRuntimeConfigSchema.parse(publicRuntimeConfig);
export function love(user: User) { export function love(user: User) {
const superUsers: string[] = JSON.parse(USERS_SUPER); if (usersSuper?.includes(user.username)) user.displayName += '🧡';
if (superUsers?.includes(user.username)) user.displayName += '🧡';
return user; return user;
} }

View File

@ -493,6 +493,7 @@ const defaultOptions: CalculationOptions = {
tbxBonusCoefficient: [], tbxBonusCoefficient: [],
selectLeasingWithoutKasko: [], selectLeasingWithoutKasko: [],
tbxVIN: [], tbxVIN: [],
selectUser: [],
}; };
export default defaultOptions; export default defaultOptions;

View File

@ -86,6 +86,7 @@ const defaultStatuses: CalculationStatuses = {
selectTelematic: 'Default', selectTelematic: 'Default',
selectTownRegistration: 'Default', selectTownRegistration: 'Default',
selectTracker: 'Default', selectTracker: 'Default',
selectUser: 'Default',
tbxAddEquipmentPrice: 'Default', tbxAddEquipmentPrice: 'Default',
tbxBonusCoefficient: 'Default', tbxBonusCoefficient: 'Default',
tbxCalcBrokerRewardSum: 'Disabled', tbxCalcBrokerRewardSum: 'Disabled',

View File

@ -137,6 +137,7 @@ const defaultValues: CalculationValues = {
vehicleTaxInYear: 0, vehicleTaxInYear: 0,
withTrailer: false, withTrailer: false,
vin: null, vin: null,
user: null,
}; };
export default defaultValues; export default defaultValues;

View File

@ -1,42 +0,0 @@
import * as addProduct from '@/process/add-product';
import * as bonuses from '@/process/bonuses';
import * as calculate from '@/process/calculate';
import * as configurator from '@/process/configurator';
import * as createKP from '@/process/create-kp';
import * as fingap from '@/process/fingap';
import * as gibdd from '@/process/gibdd';
import { useProcess } from '@/process/hooks';
import * as insurance from '@/process/insurance';
import * as leadOpportunity from '@/process/lead-opportunity';
import * as leasingObject from '@/process/leasing-object';
import * as leasingWithoutKasko from '@/process/leasing-without-kasko';
import * as loadKP from '@/process/load-kp';
import * as payments from '@/process/payments';
import * as price from '@/process/price';
import * as recalc from '@/process/recalc';
import * as subsidy from '@/process/subsidy';
import * as subsidyImportProgram from '@/process/subsidy-import-program';
import * as supplierAgent from '@/process/supplier-agent';
import * as usedPl from '@/process/used-pl';
export default function useReactions() {
useProcess(leadOpportunity);
useProcess(loadKP);
useProcess(calculate);
useProcess(supplierAgent);
useProcess(price);
useProcess(fingap);
useProcess(leasingWithoutKasko);
useProcess(subsidy);
useProcess(leasingObject);
useProcess(configurator);
useProcess(createKP);
useProcess(bonuses);
useProcess(usedPl);
useProcess(subsidyImportProgram);
useProcess(payments);
useProcess(gibdd);
useProcess(addProduct);
useProcess(insurance);
useProcess(recalc);
}

View File

@ -1 +0,0 @@
export { default as useDefaultReactions } from './default';

View File

@ -10,7 +10,6 @@ const envSchema = z.object({
URL_CRM_GRAPHQL_DIRECT: z.string(), URL_CRM_GRAPHQL_DIRECT: z.string(),
URL_GET_USER_DIRECT: z.string(), URL_GET_USER_DIRECT: z.string(),
USE_DEV_COLORS: z.unknown().optional().transform(Boolean), USE_DEV_COLORS: z.unknown().optional().transform(Boolean),
USERS_SUPER: z.string().optional().default(''),
}); });
module.exports = envSchema; module.exports = envSchema;

View File

@ -3,7 +3,6 @@ const envSchema = require('./env');
const publicRuntimeConfigSchema = envSchema.pick({ const publicRuntimeConfigSchema = envSchema.pick({
BASE_PATH: true, BASE_PATH: true,
USE_DEV_COLORS: true, USE_DEV_COLORS: true,
USERS_SUPER: true,
}); });
const serverRuntimeConfigSchema = envSchema.pick({ const serverRuntimeConfigSchema = envSchema.pick({

View File

@ -123,6 +123,7 @@ const ValuesSchema = z.object({
vehicleTaxInYear: z.number(), vehicleTaxInYear: z.number(),
withTrailer: z.boolean(), withTrailer: z.boolean(),
vin: z.string().nullable(), vin: z.string().nullable(),
user: z.string().nullable(),
/** /**
* Link Values * Link Values

3
apps/web/config/users.js Normal file
View File

@ -0,0 +1,3 @@
export const unlimitedRoles = ['Калькулятор без ограничений'];
export const defaultRoles = ['МПЛ'];
export const usersSuper = ['akalinina', 'vchikalkin'];

View File

@ -639,3 +639,12 @@ query GetInsuranceCompanies {
label: name label: name
} }
} }
query GetRoles($roleName: String) {
roles(name: $roleName) {
systemusers {
label: fullname
value: domainname
}
}
}

View File

@ -470,6 +470,13 @@ export type GetInsuranceCompaniesQueryVariables = Exact<{ [key: string]: never;
export type GetInsuranceCompaniesQuery = { __typename?: 'Query', accounts: Array<{ __typename?: 'account', evo_type_ins_policy: Array<number> | null, evo_evokasko_access: boolean | null, evo_inn: string | null, value: string | null, label: string | null } | null> | null }; export type GetInsuranceCompaniesQuery = { __typename?: 'Query', accounts: Array<{ __typename?: 'account', evo_type_ins_policy: Array<number> | null, evo_evokasko_access: boolean | null, evo_inn: string | null, value: string | null, label: string | null } | null> | null };
export type GetRolesQueryVariables = Exact<{
roleName: InputMaybe<Scalars['String']>;
}>;
export type GetRolesQuery = { __typename?: 'Query', roles: Array<{ __typename?: 'role', systemusers: Array<{ __typename?: 'systemuser', label: string | null, value: string | null } | null> | null } | null> | null };
export type GetQuoteAddProductDataQueryVariables = Exact<{ export type GetQuoteAddProductDataQueryVariables = Exact<{
quoteId: Scalars['Uuid']; quoteId: Scalars['Uuid'];
}>; }>;
@ -642,6 +649,7 @@ export const GetInsNsibTypesDocument = {"kind":"Document","definitions":[{"kind"
export const GetLeasingWithoutKaskoTypesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetLeasingWithoutKaskoTypes"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"currentDate"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"DateTime"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_addproduct_types"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"statecode"},"value":{"kind":"IntValue","value":"0"}},{"kind":"Argument","name":{"kind":"Name","value":"evo_product_type"},"value":{"kind":"IntValue","value":"100000007"}},{"kind":"Argument","name":{"kind":"Name","value":"evo_datefrom_param"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"lte"},"value":{"kind":"Variable","name":{"kind":"Name","value":"currentDate"}}}]}},{"kind":"Argument","name":{"kind":"Name","value":"evo_dateto_param"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"gte"},"value":{"kind":"Variable","name":{"kind":"Name","value":"currentDate"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoreAddProductTypesFields"}},{"kind":"Field","name":{"kind":"Name","value":"evo_product_type"}},{"kind":"Field","name":{"kind":"Name","value":"evo_min_period"}},{"kind":"Field","name":{"kind":"Name","value":"evo_max_period"}},{"kind":"Field","name":{"kind":"Name","value":"evo_min_price"}},{"kind":"Field","name":{"kind":"Name","value":"evo_max_price"}},{"kind":"Field","name":{"kind":"Name","value":"evo_leasingobject_types"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_leasingobject_typeid"}}]}},{"kind":"Field","name":{"kind":"Name","value":"evo_visible_calc"}},{"kind":"Field","name":{"kind":"Name","value":"evo_min_first_payment_perc"}},{"kind":"Field","name":{"kind":"Name","value":"evo_max_first_payment_perc"}},{"kind":"Field","name":{"kind":"Name","value":"evo_models"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_modelid"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoreAddProductTypesFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"evo_addproduct_type"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_graph_price"}},{"kind":"Field","alias":{"kind":"Name","value":"label"},"name":{"kind":"Name","value":"evo_name"}},{"kind":"Field","alias":{"kind":"Name","value":"value"},"name":{"kind":"Name","value":"evo_addproduct_typeid"}}]}}]} as unknown as DocumentNode<GetLeasingWithoutKaskoTypesQuery, GetLeasingWithoutKaskoTypesQueryVariables>; export const GetLeasingWithoutKaskoTypesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetLeasingWithoutKaskoTypes"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"currentDate"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"DateTime"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_addproduct_types"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"statecode"},"value":{"kind":"IntValue","value":"0"}},{"kind":"Argument","name":{"kind":"Name","value":"evo_product_type"},"value":{"kind":"IntValue","value":"100000007"}},{"kind":"Argument","name":{"kind":"Name","value":"evo_datefrom_param"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"lte"},"value":{"kind":"Variable","name":{"kind":"Name","value":"currentDate"}}}]}},{"kind":"Argument","name":{"kind":"Name","value":"evo_dateto_param"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"gte"},"value":{"kind":"Variable","name":{"kind":"Name","value":"currentDate"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoreAddProductTypesFields"}},{"kind":"Field","name":{"kind":"Name","value":"evo_product_type"}},{"kind":"Field","name":{"kind":"Name","value":"evo_min_period"}},{"kind":"Field","name":{"kind":"Name","value":"evo_max_period"}},{"kind":"Field","name":{"kind":"Name","value":"evo_min_price"}},{"kind":"Field","name":{"kind":"Name","value":"evo_max_price"}},{"kind":"Field","name":{"kind":"Name","value":"evo_leasingobject_types"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_leasingobject_typeid"}}]}},{"kind":"Field","name":{"kind":"Name","value":"evo_visible_calc"}},{"kind":"Field","name":{"kind":"Name","value":"evo_min_first_payment_perc"}},{"kind":"Field","name":{"kind":"Name","value":"evo_max_first_payment_perc"}},{"kind":"Field","name":{"kind":"Name","value":"evo_models"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_modelid"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoreAddProductTypesFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"evo_addproduct_type"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_graph_price"}},{"kind":"Field","alias":{"kind":"Name","value":"label"},"name":{"kind":"Name","value":"evo_name"}},{"kind":"Field","alias":{"kind":"Name","value":"value"},"name":{"kind":"Name","value":"evo_addproduct_typeid"}}]}}]} as unknown as DocumentNode<GetLeasingWithoutKaskoTypesQuery, GetLeasingWithoutKaskoTypesQueryVariables>;
export const GetInsuranceCompanyDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetInsuranceCompany"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"accountId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Uuid"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"account"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"accountid"},"value":{"kind":"Variable","name":{"kind":"Name","value":"accountId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_osago_with_kasko"}}]}}]}}]} as unknown as DocumentNode<GetInsuranceCompanyQuery, GetInsuranceCompanyQueryVariables>; export const GetInsuranceCompanyDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetInsuranceCompany"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"accountId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Uuid"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"account"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"accountid"},"value":{"kind":"Variable","name":{"kind":"Name","value":"accountId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_osago_with_kasko"}}]}}]}}]} as unknown as DocumentNode<GetInsuranceCompanyQuery, GetInsuranceCompanyQueryVariables>;
export const GetInsuranceCompaniesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetInsuranceCompanies"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"accounts"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"evo_account_type"},"value":{"kind":"ListValue","values":[{"kind":"IntValue","value":"100000002"}]}},{"kind":"Argument","name":{"kind":"Name","value":"statecode"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_type_ins_policy"}},{"kind":"Field","name":{"kind":"Name","value":"evo_evokasko_access"}},{"kind":"Field","name":{"kind":"Name","value":"evo_inn"}},{"kind":"Field","alias":{"kind":"Name","value":"value"},"name":{"kind":"Name","value":"accountid"}},{"kind":"Field","alias":{"kind":"Name","value":"label"},"name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode<GetInsuranceCompaniesQuery, GetInsuranceCompaniesQueryVariables>; export const GetInsuranceCompaniesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetInsuranceCompanies"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"accounts"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"evo_account_type"},"value":{"kind":"ListValue","values":[{"kind":"IntValue","value":"100000002"}]}},{"kind":"Argument","name":{"kind":"Name","value":"statecode"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_type_ins_policy"}},{"kind":"Field","name":{"kind":"Name","value":"evo_evokasko_access"}},{"kind":"Field","name":{"kind":"Name","value":"evo_inn"}},{"kind":"Field","alias":{"kind":"Name","value":"value"},"name":{"kind":"Name","value":"accountid"}},{"kind":"Field","alias":{"kind":"Name","value":"label"},"name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode<GetInsuranceCompaniesQuery, GetInsuranceCompaniesQueryVariables>;
export const GetRolesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetRoles"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"roleName"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"roles"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"roleName"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"systemusers"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"label"},"name":{"kind":"Name","value":"fullname"}},{"kind":"Field","alias":{"kind":"Name","value":"value"},"name":{"kind":"Name","value":"domainname"}}]}}]}}]}}]} as unknown as DocumentNode<GetRolesQuery, GetRolesQueryVariables>;
export const GetQuoteAddProductDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetQuoteAddProductData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Uuid"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"quote"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"quoteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_addproduct_types"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_product_type"}},{"kind":"Field","name":{"kind":"Name","value":"evo_addproduct_typeid"}}]}}]}}]}}]} as unknown as DocumentNode<GetQuoteAddProductDataQuery, GetQuoteAddProductDataQueryVariables>; export const GetQuoteAddProductDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetQuoteAddProductData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Uuid"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"quote"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"quoteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_addproduct_types"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_product_type"}},{"kind":"Field","name":{"kind":"Name","value":"evo_addproduct_typeid"}}]}}]}}]}}]} as unknown as DocumentNode<GetQuoteAddProductDataQuery, GetQuoteAddProductDataQueryVariables>;
export const GetQuoteBonusDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetQuoteBonusData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Uuid"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"quote"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"quoteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_sale_bonus"}}]}}]}}]} as unknown as DocumentNode<GetQuoteBonusDataQuery, GetQuoteBonusDataQueryVariables>; export const GetQuoteBonusDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetQuoteBonusData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Uuid"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"quote"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"quoteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_sale_bonus"}}]}}]}}]} as unknown as DocumentNode<GetQuoteBonusDataQuery, GetQuoteBonusDataQueryVariables>;
export const GetQuoteConfiguratorDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetQuoteConfiguratorData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Uuid"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"quote"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"quoteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_baseproductid"}},{"kind":"Field","name":{"kind":"Name","value":"evo_client_typeid"}},{"kind":"Field","name":{"kind":"Name","value":"evo_msfo_irr"}}]}}]}}]} as unknown as DocumentNode<GetQuoteConfiguratorDataQuery, GetQuoteConfiguratorDataQueryVariables>; export const GetQuoteConfiguratorDataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetQuoteConfiguratorData"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Uuid"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"quote"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"quoteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"quoteId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"evo_baseproductid"}},{"kind":"Field","name":{"kind":"Name","value":"evo_client_typeid"}},{"kind":"Field","name":{"kind":"Name","value":"evo_msfo_irr"}}]}}]}}]} as unknown as DocumentNode<GetQuoteConfiguratorDataQuery, GetQuoteConfiguratorDataQueryVariables>;

View File

@ -36,7 +36,7 @@ export default class MyDocument extends Document {
<Head> <Head>
<meta charSet="utf-8" /> <meta charSet="utf-8" />
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#000000" />
<meta name="description" content="Лизинговый калькулятор Эволюция" /> <meta name="description" content="Лизинговый калькулятор - Эволюция" />
{metaFavicon} {metaFavicon}
</Head> </Head>
<body> <body>

View File

@ -2,44 +2,19 @@ import { getUser } from '@/api/user/query';
import initializeApollo from '@/apollo/client'; import initializeApollo from '@/apollo/client';
import * as Calculation from '@/Components/Calculation'; import * as Calculation from '@/Components/Calculation';
import { Error } from '@/Components/Common/Error'; import { Error } from '@/Components/Common/Error';
import { Grid } from '@/Components/Layout/Page';
import Output from '@/Components/Output'; import Output from '@/Components/Output';
import { useDefaultReactions } from '@/config/process'; import { defaultRoles } from '@/config/users';
import * as CRMTypes from '@/graphql/crm.types'; import * as CRMTypes from '@/graphql/crm.types';
import * as init from '@/process/init'; import { useInsuranceData, useMainData, useReactions } from '@/process/hooks';
import { min } from '@/styles/mq'; import { getInitialData } from '@/process/hooks/init';
import { dehydrate, QueryClient } from '@tanstack/react-query'; import { dehydrate, QueryClient } from '@tanstack/react-query';
import Head from 'next/head'; import Head from 'next/head';
import styled from 'styled-components';
import { Box } from 'ui/grid';
const Grid = styled(Box)` export default function Home(props) {
display: flex; useMainData();
flex-direction: column; useInsuranceData();
gap: 10px; useReactions();
${min('laptop')} {
display: grid;
align-items: flex-start;
grid-template-columns: 2fr 1fr;
}
${min('laptop-hd')} {
grid-template-columns: 2fr 1fr 1.5fr;
}
${min('desktop')} {
margin: 8px 5%;
}
${min('desktop-xl')} {
margin: 8px 10%;
}
`;
function Home(props) {
init.useMainData();
init.useInsuranceData();
useDefaultReactions();
if (props.statusCode !== 200) return <Error {...props} />; if (props.statusCode !== 200) return <Error {...props} />;
@ -48,65 +23,69 @@ function Home(props) {
<Head> <Head>
<title>Лизинговый калькулятор - Эволюция</title> <title>Лизинговый калькулятор - Эволюция</title>
</Head> </Head>
<Calculation.Form /> <Calculation.Form prune={['unlimited']} />
<Calculation.Settings /> <Calculation.Settings />
<Output /> <Output />
</Grid> </Grid>
); );
} }
/** @type {import('next').GetServerSideProps} */ export const makeGetServerSideProps = ({ roles }) =>
export const getServerSideProps = async ({ req }) => { /** @type {import('next').GetServerSideProps} */
const { cookie = '' } = req.headers; (
async function ({ req }) {
const { cookie = '' } = req.headers;
const queryClient = new QueryClient(); const queryClient = new QueryClient();
const user = await queryClient.fetchQuery(['user'], ({ signal }) => const user = await queryClient.fetchQuery(['user'], ({ signal }) =>
getUser({ getUser({
headers: { headers: {
cookie, cookie,
}, },
signal, signal,
}) })
);
const apolloClient = initializeApollo();
try {
const {
data: { systemuser },
} = await apolloClient.query({
fetchPolicy: 'network-only',
query: CRMTypes.GetSystemUserDocument,
variables: {
domainname: user.domainName,
},
});
if (!systemuser?.roles?.some((x) => x?.name && roles.includes(x.name))) {
return {
props: { statusCode: 403 },
};
}
const { values, options } = await getInitialData(apolloClient, user);
return {
props: {
calculation: {
options,
values,
},
initialApolloState: apolloClient.cache.extract(),
initialQueryState: dehydrate(queryClient),
statusCode: 200,
},
};
} catch (error) {
return {
props: {
error: JSON.stringify(error),
statusCode: 500,
},
};
}
}
); );
const apolloClient = initializeApollo(); export const getServerSideProps = makeGetServerSideProps({ roles: defaultRoles });
try {
const {
data: { systemuser },
} = await apolloClient.query({
query: CRMTypes.GetSystemUserDocument,
variables: {
domainname: user.domainName,
},
});
if (!systemuser.roles.some((x) => x.name === 'МПЛ')) {
return {
props: { statusCode: 403 },
};
}
const { values, options } = await init.getInitialData(apolloClient, user);
return {
props: {
calculation: {
options,
values,
},
initialApolloState: apolloClient.cache.extract(),
initialQueryState: dehydrate(queryClient),
statusCode: 200,
},
};
} catch (error) {
return {
props: {
error: JSON.stringify(error),
statusCode: 500,
},
};
}
};
export default Home;

View File

@ -0,0 +1,37 @@
import { makeGetServerSideProps } from '.';
import * as Calculation from '@/Components/Calculation';
import { Error } from '@/Components/Common/Error';
import { Grid } from '@/Components/Layout/Page';
import Output from '@/Components/Output';
import { unlimitedRoles } from '@/config/users';
import { useGetUsers, useInsuranceData, useMainData, useReactions } from '@/process/hooks';
import { useStore } from '@/stores/hooks';
import Head from 'next/head';
export default function Unlimited(props) {
const store = useStore();
store.$process.add('Unlimited');
useMainData();
useGetUsers();
useInsuranceData();
useReactions();
if (props.statusCode !== 200) return <Error {...props} />;
return (
<Grid>
<Head>
<title>Лизинговый калькулятор без ограничений - Эволюция</title>
<meta name="description" content="Лизинговый калькулятор без ограничений - Эволюция" />
</Head>
<Calculation.Form />
<Calculation.Settings />
<Output />
</Grid>
);
}
export const getServerSideProps = makeGetServerSideProps({
roles: unlimitedRoles,
});

View File

@ -5,6 +5,7 @@ import type { ProcessContext } from '@/process/types';
import ValidationHelper from '@/stores/validation/helper'; import ValidationHelper from '@/stores/validation/helper';
import { reaction } from 'mobx'; import { reaction } from 'mobx';
import { uid } from 'radash'; import { uid } from 'radash';
import { makeDisposable } from 'tools';
import type { BaseOption } from 'ui/elements/types'; import type { BaseOption } from 'ui/elements/types';
function hasInvalidValueOrOptions(value: unknown, options: Array<BaseOption<unknown>>) { 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) { export default function reactions({ store }: ProcessContext) {
const { $calculation, $tables } = store; const { $calculation, $tables, $process } = store;
reaction( makeDisposable(
() => { () =>
const hasElementsErrors = Object.values($calculation.$validation).some( reaction(
(validation) => validation.hasErrors () => {
); const hasElementsErrors = Object.values($calculation.$validation).some(
(validation) => validation.hasErrors
);
const hasPaymentsErrors = $tables.payments.validation.hasErrors; const hasPaymentsErrors = $tables.payments.validation.hasErrors;
const hasInsuranceErrors = $tables.insurance.validation.hasErrors; const hasInsuranceErrors = $tables.insurance.validation.hasErrors;
const hasFingapErrors = $tables.fingap.validation.hasErrors; const hasFingapErrors = $tables.fingap.validation.hasErrors;
return hasElementsErrors || hasPaymentsErrors || hasInsuranceErrors || hasFingapErrors; return hasElementsErrors || hasPaymentsErrors || hasInsuranceErrors || hasFingapErrors;
}, },
(hasErrors) => { (hasErrors) => {
if (hasErrors) { if (hasErrors) {
$calculation.$status.setStatus('btnCalculate', 'Disabled'); $calculation.$status.setStatus('btnCalculate', 'Disabled');
$calculation.$status.setStatus('btnCreateKP', 'Disabled'); $calculation.$status.setStatus('btnCreateKP', 'Disabled');
$calculation.$status.setStatus('btnCreateKPMini', 'Disabled'); $calculation.$status.setStatus('btnCreateKPMini', 'Disabled');
} else { } else {
$calculation.$status.setStatus('btnCalculate', 'Default'); $calculation.$status.setStatus('btnCalculate', 'Default');
$calculation.$status.setStatus('btnCreateKP', 'Default'); $calculation.$status.setStatus('btnCreateKP', 'Default');
$calculation.$status.setStatus('btnCreateKPMini', 'Default'); $calculation.$status.setStatus('btnCreateKPMini', 'Default');
} }
}, },
{ {
fireImmediately: true, fireImmediately: true,
} }
),
() => $process.has('Unlimited')
); );
/** /**

View File

@ -1,3 +1,4 @@
export { default as filters } from './filters'; export { default as filters } from './filters';
export { default as unlimited } from './unlimited';
export { default as validation } from './validation'; export { default as validation } from './validation';
export { default as values } from './values'; export { default as values } from './values';

View File

@ -0,0 +1,41 @@
import * as CRMTypes from '@/graphql/crm.types';
import type { ProcessContext } from '@/process/types';
import { reaction } from 'mobx';
import { makeDisposable, normalizeOptions } from 'tools';
export default function unlimitedReactions({ store, apolloClient }: ProcessContext) {
const { $calculation, $process } = store;
makeDisposable(
() =>
reaction(
() => $calculation.element('selectUser').getValue(),
async (domainname) => {
if (!domainname) {
$calculation.element('selectLead').reset();
$calculation.element('selectOpportunity').reset();
return;
}
const {
data: { leads },
} = await apolloClient.query({
query: CRMTypes.GetLeadsDocument,
variables: { domainname },
});
$calculation.element('selectLead').setOptions(normalizeOptions(leads));
const {
data: { opportunities },
} = await apolloClient.query({
query: CRMTypes.GetOpportunitiesDocument,
variables: { domainname },
});
$calculation.element('selectOpportunity').setOptions(normalizeOptions(opportunities));
}
),
() => !$process.has('Unlimited')
);
}

View File

@ -1,20 +1,11 @@
import { getUser } from '@/api/user/query'; import { getUser } from '@/api/user/query';
import { STALE_TIME } from '@/constants/request'; import { STALE_TIME } from '@/constants/request';
import type { Process, ProcessContext } from '@/process/types'; import type { ProcessContext } from '@/process/types';
import { useStore } from '@/stores/hooks'; import { useStore } from '@/stores/hooks';
import { trpcPureClient } from '@/trpc/client'; import { trpcPureClient } from '@/trpc/client';
import { useApolloClient } from '@apollo/client'; import { useApolloClient } from '@apollo/client';
import { useQuery, useQueryClient } from '@tanstack/react-query'; import { useQuery, useQueryClient } from '@tanstack/react-query';
export function useProcess({ reactions }: Process) {
const context = useProcessContext();
Object.keys(reactions).forEach((name) => {
const injector = reactions[name];
injector(context);
});
}
export function useProcessContext(): ProcessContext { export function useProcessContext(): ProcessContext {
const store = useStore(); const store = useStore();
const apolloClient = useApolloClient(); const apolloClient = useApolloClient();

View File

@ -0,0 +1,3 @@
export * from './common';
export * from './init';
export * from './reactions';

View File

@ -0,0 +1,37 @@
import * as CRMTypes from '@/graphql/crm.types';
import { useStore } from '@/stores/hooks';
import { useApolloClient } from '@apollo/client';
import { useEffect } from 'react';
import { normalizeOptions } from 'tools';
/**
* @param {import('@apollo/client').ApolloClient} apolloClient
* @param {*} onCompleted
*/
export function getUsers({ query }, onCompleted) {
query({
query: CRMTypes.GetRolesDocument,
variables: { roleName: 'МПЛ' },
}).then(({ data }) => {
const users = data.roles?.flatMap((x) => x?.systemusers);
onCompleted({
selectUser: users,
});
});
}
export function useGetUsers() {
const { $calculation } = useStore();
const apolloClient = useApolloClient();
function handleOnCompleted(options) {
Object.keys(options).forEach((elementName) => {
const elementOptions = options[elementName];
$calculation.element(elementName).setOptions(normalizeOptions(elementOptions));
});
}
useEffect(() => {
getUsers(apolloClient, handleOnCompleted);
}, []);
}

View File

@ -1,3 +1,4 @@
export * from './get-initial-data'; export * from './get-initial-data';
export * from './get-insurance-data'; export * from './get-insurance-data';
export * from './get-main-data'; export * from './get-main-data';
export * from './get-users';

View File

@ -0,0 +1,58 @@
import type { Process } from '../types';
import { useProcessContext } from './common';
import * as addProduct from '@/process/add-product';
import * as bonuses from '@/process/bonuses';
import * as calculate from '@/process/calculate';
import * as configurator from '@/process/configurator';
import * as createKP from '@/process/create-kp';
import * as fingap from '@/process/fingap';
import * as gibdd from '@/process/gibdd';
import * as insurance from '@/process/insurance';
import * as leadOpportunity from '@/process/lead-opportunity';
import * as leasingObject from '@/process/leasing-object';
import * as leasingWithoutKasko from '@/process/leasing-without-kasko';
import * as loadKP from '@/process/load-kp';
import * as payments from '@/process/payments';
import * as price from '@/process/price';
import * as recalc from '@/process/recalc';
import * as subsidy from '@/process/subsidy';
import * as subsidyImportProgram from '@/process/subsidy-import-program';
import * as supplierAgent from '@/process/supplier-agent';
import * as usedPl from '@/process/used-pl';
type Config = {
prune: string[];
};
function useProcess({ reactions }: Process, config?: Config) {
const context = useProcessContext();
Object.keys(reactions).forEach((name) => {
if (!config?.prune.includes(name)) {
const injector = reactions[name];
injector(context);
}
});
}
export function useReactions(config: Config) {
useProcess(leadOpportunity, config);
useProcess(loadKP, config);
useProcess(calculate, config);
useProcess(supplierAgent, config);
useProcess(price, config);
useProcess(fingap, config);
useProcess(leasingWithoutKasko, config);
useProcess(subsidy, config);
useProcess(leasingObject, config);
useProcess(configurator, config);
useProcess(createKP, config);
useProcess(bonuses, config);
useProcess(usedPl, config);
useProcess(subsidyImportProgram, config);
useProcess(payments, config);
useProcess(gibdd, config);
useProcess(addProduct, config);
useProcess(insurance, config);
useProcess(recalc, config);
}

View File

@ -9,7 +9,7 @@ export type ProcessContext = {
queryClient: QueryClient; queryClient: QueryClient;
store: RootStore; store: RootStore;
trpcClient: TRPCPureClient; trpcClient: TRPCPureClient;
user: User | undefined; user: Pick<User, 'domainName'> | undefined;
}; };
export type Process = { export type Process = {

View File

@ -1,19 +1,33 @@
import { t } from './trpc'; import { t } from './trpc';
import initializeApollo from '@/apollo/client';
import { unlimitedRoles } from '@/config/users';
import * as CRMTypes from '@/graphql/crm.types';
import { TRPCError } from '@trpc/server'; import { TRPCError } from '@trpc/server';
/** /**
* @see https://trpc.io/docs/v10/middlewares * @see https://trpc.io/docs/v10/middlewares
*/ */
export const userMiddleware = t.middleware(({ ctx, next }) => { export const userMiddleware = t.middleware(async ({ ctx, next }) => {
if (process.env.NODE_ENV !== 'development' && !ctx.user) { if (process.env.NODE_ENV !== 'development' && !ctx.user) {
throw new TRPCError({ throw new TRPCError({
code: 'UNAUTHORIZED', code: 'UNAUTHORIZED',
}); });
} }
const apolloClient = initializeApollo();
const {
data: { systemuser },
} = await apolloClient.query({
query: CRMTypes.GetSystemUserDocument,
variables: {
domainname: ctx.user.domainName,
},
});
return next({ return next({
ctx: { ctx: {
isAdmin: false, unlimited: systemuser?.roles?.some((x) => x?.name && unlimitedRoles.includes(x.name)),
}, },
}); });
}); });

View File

@ -4,6 +4,7 @@ import { transformCalculateResults } from './lib/transform';
import { validate } from './lib/validation'; import { validate } from './lib/validation';
import { CalculateInputSchema, CalculateOutputSchema } from './types'; import { CalculateInputSchema, CalculateOutputSchema } from './types';
import { calculate } from '@/api/core/query'; import { calculate } from '@/api/core/query';
import type { User } from '@/api/user/types';
import initializeApollo from '@/apollo/client'; import initializeApollo from '@/apollo/client';
import { protectedProcedure } from '@/server/procedure'; import { protectedProcedure } from '@/server/procedure';
import { QueryClient } from '@tanstack/react-query'; import { QueryClient } from '@tanstack/react-query';
@ -16,30 +17,37 @@ export const calculateRouter = router({
const apolloClient = initializeApollo(); const apolloClient = initializeApollo();
const queryClient = new QueryClient(); const queryClient = new QueryClient();
const validationResult = await validate({ if (ctx.unlimited === false) {
context: { const validationResult = await validate({
apolloClient, context: {
queryClient, apolloClient,
user: ctx.user, queryClient,
}, user: ctx.user,
input, },
}); input,
});
if (validationResult.success === false) { if (validationResult.success === false) {
return { return {
error: validationResult.error, error: validationResult.error,
success: false, success: false,
}; };
}
}
let user: Pick<User, 'domainName'> = { domainName: ctx.user.domainName };
if (ctx.unlimited && input.values.user) {
user = { domainName: input.values.user };
} }
const requestData = await createRequestData({ const requestData = await createRequestData({
context: { context: {
apolloClient, apolloClient,
queryClient, queryClient,
user: ctx.user, ...ctx,
user,
}, },
input, input,
user: ctx.user,
}); });
const calculateResult = await calculate(requestData); const calculateResult = await calculate(requestData);

View File

@ -1,7 +1,6 @@
/* eslint-disable sonarjs/cognitive-complexity */ /* eslint-disable sonarjs/cognitive-complexity */
import type { CalculateInput, Context } from '../types'; import type { CalculateInput, Context } from '../types';
import type * as CoreTypes from '@/api/core/types'; import type * as CoreTypes from '@/api/core/types';
import type { User } from '@/api/user/types';
import { ESN, NSIB_MAX, VAT } from '@/constants/values'; import { ESN, NSIB_MAX, VAT } from '@/constants/values';
import * as CRMTypes from '@/graphql/crm.types'; import * as CRMTypes from '@/graphql/crm.types';
import helper from '@/process/calculate/lib/helper'; import helper from '@/process/calculate/lib/helper';
@ -13,9 +12,8 @@ import { max, sum } from 'radash';
dayjs.extend(utc); dayjs.extend(utc);
type Input = { type Input = {
context: Context; context: Context & { unlimited?: boolean };
input: CalculateInput; input: CalculateInput;
user: User;
}; };
type PreparedValuesGetters = { type PreparedValuesGetters = {
@ -29,9 +27,8 @@ type AdditionalDataGetters = {
export async function createRequestData({ export async function createRequestData({
context, context,
input, input,
user,
}: Input): Promise<CoreTypes.RequestCalculate> { }: Input): Promise<CoreTypes.RequestCalculate> {
const { apolloClient } = context; const { apolloClient, user, unlimited } = context;
const { values, insurance, payments } = input; const { values, insurance, payments } = input;
const { RUB } = createCurrencyUtility({ apolloClient }); const { RUB } = createCurrencyUtility({ apolloClient });
@ -59,14 +56,17 @@ export async function createRequestData({
).data.transactioncurrency ).data.transactioncurrency
: null; : null;
const { let systemuser: CRMTypes.GetSystemUserQuery['systemuser'] = null;
data: { systemuser },
} = await apolloClient.query({ if (user?.domainName) {
query: CRMTypes.GetSystemUserDocument, const { data } = await apolloClient.query({
variables: { query: CRMTypes.GetSystemUserDocument,
domainname: user.domainName, variables: {
}, domainname: user.domainName,
}); },
});
if (data.systemuser) systemuser = data.systemuser;
}
async function getDeprecation() { async function getDeprecation() {
if (values.leaseObjectType) { if (values.leaseObjectType) {
@ -1232,6 +1232,9 @@ export async function createRequestData({
return { return {
additionalData, additionalData,
flags: {
DISABLE_CHECKS_RESULTS: unlimited === true,
},
preparedPayments, preparedPayments,
preparedValues, preparedValues,
}; };

View File

@ -13,6 +13,7 @@ import {
} from './types'; } from './types';
import { calculate } from '@/api/core/query'; import { calculate } from '@/api/core/query';
import { createKP } from '@/api/crm/query'; import { createKP } from '@/api/crm/query';
import type { User } from '@/api/user/types';
import initializeApollo from '@/apollo/client'; import initializeApollo from '@/apollo/client';
import defaultValues from '@/config/default-values'; import defaultValues from '@/config/default-values';
import * as insuranceTable from '@/config/tables/insurance-table'; import * as insuranceTable from '@/config/tables/insurance-table';
@ -88,30 +89,37 @@ export const quoteRouter = router({
const apolloClient = initializeApollo(); const apolloClient = initializeApollo();
const queryClient = new QueryClient(); const queryClient = new QueryClient();
const validationResult = await validate({ if (ctx.unlimited === false) {
context: { const validationResult = await validate({
apolloClient, context: {
queryClient, apolloClient,
user: ctx.user, queryClient,
}, user: ctx.user,
input, },
}); input,
});
if (validationResult.success === false) { if (validationResult.success === false) {
return { return {
error: validationResult.error, error: validationResult.error,
success: false, success: false,
}; };
}
}
let user: Pick<User, 'domainName'> = { domainName: ctx.user.domainName };
if (ctx.unlimited && input.values.user) {
user = { domainName: input.values.user };
} }
const requestData = await createRequestData({ const requestData = await createRequestData({
context: { context: {
apolloClient, apolloClient,
queryClient, queryClient,
user: ctx.user, ...ctx,
user,
}, },
input, input,
user: ctx.user,
}); });
const calculateResult = await calculate(requestData); const calculateResult = await calculate(requestData);
@ -124,7 +132,7 @@ export const quoteRouter = router({
} }
const createKPResult = await createKP({ const createKPResult = await createKP({
domainName: ctx.user.domainName, domainName: user.domainName,
finGAP: input.fingap, finGAP: input.fingap,
insurance: Object.values(input.insurance.values), insurance: Object.values(input.insurance.values),
calculation: { calculation: {

View File

@ -1,3 +1,4 @@
import Validation from '../validation';
import type { ValidationParams } from '../validation/types'; import type { ValidationParams } from '../validation/types';
import OptionsStore from './options'; import OptionsStore from './options';
import StatusStore from './statuses'; import StatusStore from './statuses';
@ -6,17 +7,24 @@ import titles from '@/Components/Calculation/config/elements-titles';
import type * as Values from '@/Components/Calculation/config/map/values'; import type * as Values from '@/Components/Calculation/config/map/values';
import { getValueName } from '@/Components/Calculation/config/map/values'; import { getValueName } from '@/Components/Calculation/config/map/values';
import type RootStore from '@/stores/root'; import type RootStore from '@/stores/root';
import Validation from '@/stores/validation';
import { observable } from 'mobx'; import { observable } from 'mobx';
import type { BaseOption } from 'ui/elements/types'; import type { BaseOption } from 'ui/elements/types';
export default class CalculationStore { export default class CalculationStore {
private root: RootStore;
public $values: ValuesStore; public $values: ValuesStore;
public $status: StatusStore; public $status: StatusStore;
public $options: OptionsStore; public $options: OptionsStore;
public $validation: Partial<Record<Values.Elements, Validation>>; public $validation: Partial<Record<Values.Elements, Validation>>;
public get hasErrors() {
return (Object.keys(this.$validation) as Values.Elements[]).some(
(elementName) => this.$validation[elementName]?.hasErrors
);
}
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {
this.root = rootStore;
this.$values = new ValuesStore(rootStore); this.$values = new ValuesStore(rootStore);
this.$status = new StatusStore(rootStore); this.$status = new StatusStore(rootStore);
this.$options = new OptionsStore(rootStore); this.$options = new OptionsStore(rootStore);
@ -24,10 +32,13 @@ export default class CalculationStore {
} }
private createElementValidation = <E extends Values.Elements>(elementName: E) => { private createElementValidation = <E extends Values.Elements>(elementName: E) => {
this.$validation[elementName] = new Validation({ this.$validation[elementName] = new Validation(
err_key: elementName, {
err_title: titles[elementName], err_key: elementName,
}); err_title: titles[elementName],
},
this.root
);
}; };
public element = <E extends Values.Elements>(elementName: E) => ({ public element = <E extends Values.Elements>(elementName: E) => ({

View File

@ -21,7 +21,13 @@ export default class StatusStore {
}; };
public getStatus(elementName: ElementsActions | ElementsValues) { public getStatus(elementName: ElementsActions | ElementsValues) {
return this.overrided[elementName] || this.statuses[elementName]; const status = this.overrided[elementName] || this.statuses[elementName];
if (this.root.$process.has('Unlimited') && status === 'Disabled') {
return 'Default';
}
return status;
} }
public setStatus = (elementName: ElementsActions | ElementsValues, status: Status) => { public setStatus = (elementName: ElementsActions | ElementsValues, status: Status) => {

View File

@ -1,16 +1,16 @@
import { useStore } from '@/stores/hooks'; import { useStore } from '@/stores/hooks';
export function useValidation(elementName) { export function useValidation(elementName) {
const { $calculation } = useStore(); const { $calculation, $process } = useStore();
const hasErrors = $calculation.$validation?.[elementName]?.hasErrors; const hasErrors = $calculation.$validation?.[elementName]?.hasErrors;
if (hasErrors) { if (hasErrors) {
return { return {
help: 'Некорректные данные', help: 'Некорректные данные',
isValid: false, validateStatus: $process.has('Unlimited') ? 'warning' : 'error',
}; };
} }
return { return {
isValid: true, validateStatus: '',
}; };
} }

View File

@ -1,7 +1,7 @@
import type { ObservableSet } from 'mobx'; import type { ObservableSet } from 'mobx';
import { observable } from 'mobx'; import { observable } from 'mobx';
export type Process = 'ELT' | 'LoadKP'; export type Process = 'ELT' | 'LoadKP' | 'Unlimited';
export type ProcessStore = ObservableSet<Process>; export type ProcessStore = ObservableSet<Process>;
export default function createProcessStore() { export default function createProcessStore() {

View File

@ -15,15 +15,22 @@ export default class FinGAPTable {
this.selectedKeys = new Set(); this.selectedKeys = new Set();
this.risks = observable<FinGAP.Risk>([]); this.risks = observable<FinGAP.Risk>([]);
this.validation = new Validation({ this.validation = new Validation(
err_key: 'ERR_FINGAP_TABLE', {
err_title: 'Таблица рисков Safe Finance', err_key: 'ERR_FINGAP_TABLE',
}); err_title: 'Таблица рисков Safe Finance',
},
rootStore
);
makeAutoObservable(this); makeAutoObservable(this);
this.root = rootStore; this.root = rootStore;
} }
public get hasErrors() {
return this.validation.hasErrors;
}
public getSelectedRisks() { public getSelectedRisks() {
return toJS(this.risks.filter((x) => this.selectedKeys.has(x.key))); return toJS(this.risks.filter((x) => this.selectedKeys.has(x.key)));
} }

View File

@ -21,15 +21,22 @@ export default class InsuranceTable {
insuranceTableConfig.defaultStatuses; insuranceTableConfig.defaultStatuses;
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {
this.validation = new Validation({ this.validation = new Validation(
err_key: 'ERR_INSURANCE_TABLE', {
err_title: 'Таблица страхования', err_key: 'ERR_INSURANCE_TABLE',
}); err_title: 'Таблица страхования',
},
rootStore
);
makeAutoObservable(this); makeAutoObservable(this);
this.root = rootStore; this.root = rootStore;
} }
public get hasErrors() {
return this.validation.hasErrors;
}
public hydrate = ({ public hydrate = ({
values: initialValues, values: initialValues,
options: initialOptions, options: initialOptions,
@ -95,7 +102,11 @@ export default class InsuranceTable {
getOptions: <V extends Insurance.Values>(valueName: V) => this.options[key][valueName], 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) => { getValue: <V extends Insurance.Values>(valueName: V) => {
const rowIndex = this.values.findIndex((x) => x.key === key); const rowIndex = this.values.findIndex((x) => x.key === key);

View File

@ -14,10 +14,13 @@ export default class PaymentsTable {
private overridedStatus: IObservableValue<Status | undefined>; private overridedStatus: IObservableValue<Status | undefined>;
constructor(rootStore: RootStore) { constructor(rootStore: RootStore) {
this.validation = new Validation({ this.validation = new Validation(
err_key: 'ERR_PAYMENTS_TABLE', {
err_title: 'Таблица платежей', err_key: 'ERR_PAYMENTS_TABLE',
}); err_title: 'Таблица платежей',
},
rootStore
);
this.values = observable<number>([]); this.values = observable<number>([]);
this.statuses = observable<Status>([]); this.statuses = observable<Status>([]);
@ -37,6 +40,10 @@ export default class PaymentsTable {
); );
} }
public get hasErrors() {
return this.validation.hasErrors;
}
public getValue(index: number) { public getValue(index: number) {
return this.values[index]; return this.values[index];
} }
@ -50,6 +57,8 @@ export default class PaymentsTable {
}; };
public getStatus(index: number) { public getStatus(index: number) {
if (this.root.$process.has('Unlimited')) return 'Default';
return this.overridedStatus.get() ?? this.statuses[index]; return this.overridedStatus.get() ?? this.statuses[index];
} }

View File

@ -1,14 +1,17 @@
import type RootStore from '../root';
import type { RemoveError, ValidationConfig, ValidationError, ValidationParams } from './types'; import type { RemoveError, ValidationConfig, ValidationError, ValidationParams } from './types';
import { makeAutoObservable } from 'mobx'; import { makeAutoObservable } from 'mobx';
import notification from 'ui/elements/notification'; import notification from 'ui/elements/notification';
export default class Validation { export default class Validation {
private root: RootStore;
private params: ValidationConfig; private params: ValidationConfig;
private errors: Set<ValidationError>; private errors: Set<ValidationError>;
constructor(config: ValidationConfig) { constructor(config: ValidationConfig, rootStore: RootStore) {
this.params = config; this.params = config;
this.errors = new Set(); this.errors = new Set();
this.root = rootStore;
makeAutoObservable(this); makeAutoObservable(this);
} }
@ -33,10 +36,11 @@ export default class Validation {
this.errors.add({ key, message }); this.errors.add({ key, message });
if (!silent) { if (!silent) {
notification.error({ notification.open({
description: message, description: message,
key: this.params.err_key, key: this.params.err_key,
message: this.params.err_title, message: this.params.err_title,
type: this.root.$process.has('Unlimited') ? 'warning' : 'error',
}); });
} }

View File

@ -16,7 +16,7 @@ function Checkbox({
value, value,
setValue, setValue,
status, status,
isValid, validateStatus,
help, help,
text, text,
...props ...props
@ -26,7 +26,7 @@ function Checkbox({
} }
return ( return (
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}> <FormItem hasFeedback help={help} validateStatus={validateStatus}>
<AntCheckbox <AntCheckbox
checked={value} checked={value}
disabled={status === 'Disabled'} disabled={status === 'Disabled'}

View File

@ -5,13 +5,20 @@ import type { ChangeEvent, FC } from 'react';
const { Item: FormItem } = Form; 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>) { function handleChange(event: ChangeEvent<HTMLInputElement>) {
setValue(event.target.value); setValue(event.target.value);
} }
return ( return (
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}> <FormItem hasFeedback help={help} validateStatus={validateStatus}>
<AntInput disabled={status === 'Disabled'} onChange={handleChange} value={value} {...props} /> <AntInput disabled={status === 'Disabled'} onChange={handleChange} value={value} {...props} />
</FormItem> </FormItem>
); );

View File

@ -7,7 +7,13 @@ const { Item: FormItem } = Form;
type InputNumberProps = AntInputNumberProps<number>; 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) { function handleChange(value: number | null) {
if (value) { if (value) {
setValue(value); setValue(value);
@ -17,7 +23,7 @@ function InputNumber({ setValue, status, isValid, help, ...props }: BaseElementP
} }
return ( return (
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}> <FormItem hasFeedback help={help} validateStatus={validateStatus}>
<AntInputNumber <AntInputNumber
disabled={status === 'Disabled'} disabled={status === 'Disabled'}
onChange={handleChange} onChange={handleChange}

View File

@ -19,7 +19,7 @@ function Radio({
setValue, setValue,
options, options,
status, status,
isValid, validateStatus,
help, help,
spaceProps, spaceProps,
...props ...props
@ -29,7 +29,7 @@ function Radio({
} }
return ( return (
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}> <FormItem hasFeedback help={help} validateStatus={validateStatus}>
<AntRadio.Group <AntRadio.Group
disabled={status === 'Disabled'} disabled={status === 'Disabled'}
onChange={handleChange} onChange={handleChange}

View File

@ -9,9 +9,17 @@ type ElementProps = BaseElementProps<number | string> & {
options: BaseOption[]; options: BaseOption[];
}; };
function Segmented({ value, setValue, options, status, isValid, help, ...props }: ElementProps) { function Segmented({
value,
setValue,
options,
status,
validateStatus,
help,
...props
}: ElementProps) {
return ( return (
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}> <FormItem hasFeedback help={help} validateStatus={validateStatus}>
<AntSegmented <AntSegmented
disabled={status === 'Disabled'} disabled={status === 'Disabled'}
onChange={setValue} onChange={setValue}

View File

@ -15,7 +15,7 @@ function Select({
setValue, setValue,
options = [], options = [],
status, status,
isValid, validateStatus,
help, help,
...props ...props
}: BaseElementProps<string | null> & ElementProps) { }: BaseElementProps<string | null> & ElementProps) {
@ -31,7 +31,7 @@ function Select({
); );
return ( return (
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}> <FormItem hasFeedback help={help} validateStatus={validateStatus}>
<AntSelect <AntSelect
disabled={status === 'Disabled'} disabled={status === 'Disabled'}
loading={status === 'Loading'} loading={status === 'Loading'}

View File

@ -5,9 +5,16 @@ import type { FC } from 'react';
const { Item: FormItem } = Form; 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 ( return (
<FormItem hasFeedback help={help} validateStatus={isValid === false ? 'error' : ''}> <FormItem hasFeedback help={help} validateStatus={validateStatus}>
<AntSwitch checked={value} disabled={status === 'Disabled'} onChange={setValue} {...props} /> <AntSwitch checked={value} disabled={status === 'Disabled'} onChange={setValue} {...props} />
</FormItem> </FormItem>
); );

View File

@ -0,0 +1 @@
export { Badge } from 'antd';

View File

@ -1,3 +1,4 @@
export * from './badge';
export { default as Button } from './Button'; export { default as Button } from './Button';
export { default as Checkbox } from './Checkbox'; export { default as Checkbox } from './Checkbox';
export { default as AntdConfig } from './Config'; export { default as AntdConfig } from './Config';
@ -13,5 +14,6 @@ export { default as Segmented } from './Segmented';
export { default as Select } from './Select'; export { default as Select } from './Select';
export { default as Switch } from './Switch'; export { default as Switch } from './Switch';
export { default as Table } from './Table'; export { default as Table } from './Table';
export * from './tag';
export { default as Text } from './Text'; export { default as Text } from './Text';
export { default as Tooltip } from './Tooltip'; export { default as Tooltip } from './Tooltip';

View File

@ -0,0 +1 @@
export { Tag } from 'antd';

View File

@ -1,10 +1,12 @@
import type { ValidateStatus } from 'antd/es/form/FormItem';
export type Status = 'Default' | 'Disabled' | 'Hidden' | 'Loading'; export type Status = 'Default' | 'Disabled' | 'Hidden' | 'Loading';
export type BaseElementProps<Value> = { export type BaseElementProps<Value> = {
help?: string; help?: string;
isValid?: boolean;
setValue: (value: Value) => void; setValue: (value: Value) => void;
status?: Status; status?: Status;
validateStatus?: ValidateStatus;
value: Value; value: Value;
}; };