Pull request #923: story/TEAMMSBMOB-15549: разметка метрики в депозитах

Merge in MCB_FE/mcb-platform-monorepo from story/TEAMMSBMOB-15549_yandex-metrika-deposits to develop

* commit 'a52b1feb184987ffd1baebfae4e4edac257888ad':
  story(TEAMMSBMOB-15549): error события в депозитах
  story(TEAMMSBMOB-15549): button click события в депозитах
  story(TEAMMSBMOB-15549): screen view события в депозитах
This commit is contained in:
Даниил Лисицын
2025-10-14 15:51:07 +03:00
31 changed files with 666 additions and 358 deletions
@@ -1,7 +1,7 @@
import type { GetCalculatorVisibleDto, CalculateDepositRateDto } from '@msb/http/treasury-deals-client/endpoints';
const CALCULATOR_VISIBLE_MOCK: GetCalculatorVisibleDto = {
data: true,
data: false,
};
const CALCULATE_DEPOSIT_RATE_MOCK: CalculateDepositRateDto = {
@@ -11,7 +11,7 @@ const GET_BEST_RATES_MOCK: GetBestRatesMSBDto = {
amountFrom,
periodFrom: 1,
periodTo: 1,
clientId,
clientId: '1814d014-0bd1-40f1-9a2a-9653bda2ee74',
},
{
dealType: 'DEPOSIT',
@@ -19,7 +19,7 @@ const GET_BEST_RATES_MOCK: GetBestRatesMSBDto = {
amountFrom,
periodFrom: 121,
periodTo: 150,
clientId,
clientId: '173ed58e-c8ad-45d8-a9c1-2e16b380363b',
},
{
dealType: 'MNO',
@@ -27,7 +27,7 @@ const GET_BEST_RATES_MOCK: GetBestRatesMSBDto = {
amountFrom,
periodFrom: 151,
periodTo: 180,
clientId,
clientId: '64b3578f-eaa2-4367-90f2-98965b589262',
},
],
};
@@ -78,148 +78,148 @@ const TREASURY_COMMON_CLIENT_USER_INFO_UNION_MOCK: TreasuryCommonClientUserInfoU
summaryPrivilegeLevel: 'SIGN',
},
userInformationByClient: [
// {
// clientId: '871610b3-35f8-4eea-9eeb-01b3693a3e75',
// clientWebDealingId: '401445f6-eb8e-428d-bb9a-b9200e48cf2d',
// clientFullName: '"ГПБ Комплект" (Акционерное общество)',
// clientShortName: '"ГПБ Комплект" (АО)',
// signer: false,
// systemAgreementExist: true,
// userInformationByDealType: [
// {
// dealType: 'FX',
// privilegeLevel: 'SIGN',
// dealsExist: false,
// ratesExist: false,
// generalAgreementsExist: true,
// generalAgreementsDUExist: true,
// allowedForRequest: false,
// dealsListEnabled: false,
// },
// {
// generalAgreementsDUExist: false,
// privilegeLevel: 'SIGN',
// dealsExist: false,
// ratesExist: false,
// dealsListEnabled: false,
// allowedForRequest: false,
// generalAgreementsExist: false,
// dealType: 'DEPOSIT',
// },
// {
// dealType: 'GSNO',
// privilegeLevel: 'NONE',
// dealsExist: false,
// ratesExist: true,
// generalAgreementsExist: true,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: false,
// },
// {
// dealType: 'FX_AUTO',
// privilegeLevel: 'NONE',
// dealsExist: false,
// ratesExist: true,
// generalAgreementsExist: true,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: false,
// },
// {
// dealType: 'MNO',
// privilegeLevel: 'SIGN',
// dealsExist: false,
// ratesExist: true,
// generalAgreementsExist: true,
// generalAgreementsDUExist: false,
// allowedForRequest: true,
// dealsListEnabled: true,
// },
// ],
// accountsExist: false,
// accountsPrivilegeLevel: 'EDIT',
// generalAgreementsExist: true,
// generalAgreementsDUExist: false,
// generalAgreementsPrivilegeLevel: 'EDIT',
// gsnoReportsPrivilegeLevel: 'NONE',
// depositReportsPrivilegeLevel: 'EDIT',
// agrReqGsnoChildHeadPrivilegeLevel: 'SIGN',
// addReqChangeAccountsPrivilegeLevel: 'SIGN',
// dealsExist: false,
// dealsPrivilegeLevel: 'SIGN',
// },
// {
// clientId: '1814d014-0bd1-40f1-9a2a-9653bda2ee74',
// clientWebDealingId: '4cf1be8d-c6be-4185-abd0-b932312e0fa9',
// clientFullName: 'АКЦИОНЕРНОЕ ОБЩЕСТВО "БИОКАД"',
// clientShortName: 'АО "БИОКАД"',
// signer: false,
// systemAgreementExist: false,
// userInformationByDealType: [
// {
// dealType: 'FX',
// privilegeLevel: 'SIGN',
// dealsExist: false,
// ratesExist: false,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: true,
// },
// {
// dealType: 'DEPOSIT',
// privilegeLevel: 'SIGN',
// dealsExist: false,
// ratesExist: false,
// generalAgreementsExist: true,
// generalAgreementsDUExist: false,
// allowedForRequest: true,
// dealsListEnabled: true,
// },
// {
// dealType: 'GSNO',
// privilegeLevel: 'NONE',
// dealsExist: false,
// ratesExist: true,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: false,
// },
// {
// dealType: 'FX_AUTO',
// privilegeLevel: 'NONE',
// dealsExist: false,
// ratesExist: true,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: false,
// },
// {
// dealType: 'MNO',
// privilegeLevel: 'SIGN',
// dealsExist: false,
// ratesExist: true,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: false,
// },
// ],
// accountsExist: true,
// accountsPrivilegeLevel: 'EDIT',
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// generalAgreementsPrivilegeLevel: 'EDIT',
// gsnoReportsPrivilegeLevel: 'NONE',
// depositReportsPrivilegeLevel: 'EDIT',
// agrReqGsnoChildHeadPrivilegeLevel: 'SIGN',
// addReqChangeAccountsPrivilegeLevel: 'SIGN',
// dealsExist: false,
// dealsPrivilegeLevel: 'SIGN',
// },
{
clientId: '871610b3-35f8-4eea-9eeb-01b3693a3e75',
clientWebDealingId: '401445f6-eb8e-428d-bb9a-b9200e48cf2d',
clientFullName: '"ГПБ Комплект" (Акционерное общество)',
clientShortName: '"ГПБ Комплект" (АО)',
signer: false,
systemAgreementExist: true,
userInformationByDealType: [
{
dealType: 'FX',
privilegeLevel: 'SIGN',
dealsExist: false,
ratesExist: false,
generalAgreementsExist: true,
generalAgreementsDUExist: true,
allowedForRequest: false,
dealsListEnabled: false,
},
{
generalAgreementsDUExist: false,
privilegeLevel: 'SIGN',
dealsExist: false,
ratesExist: false,
dealsListEnabled: false,
allowedForRequest: false,
generalAgreementsExist: false,
dealType: 'DEPOSIT',
},
{
dealType: 'GSNO',
privilegeLevel: 'NONE',
dealsExist: false,
ratesExist: true,
generalAgreementsExist: true,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: false,
},
{
dealType: 'FX_AUTO',
privilegeLevel: 'NONE',
dealsExist: false,
ratesExist: true,
generalAgreementsExist: true,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: false,
},
{
dealType: 'MNO',
privilegeLevel: 'SIGN',
dealsExist: false,
ratesExist: true,
generalAgreementsExist: true,
generalAgreementsDUExist: false,
allowedForRequest: true,
dealsListEnabled: true,
},
],
accountsExist: false,
accountsPrivilegeLevel: 'EDIT',
generalAgreementsExist: true,
generalAgreementsDUExist: false,
generalAgreementsPrivilegeLevel: 'EDIT',
gsnoReportsPrivilegeLevel: 'NONE',
depositReportsPrivilegeLevel: 'EDIT',
agrReqGsnoChildHeadPrivilegeLevel: 'SIGN',
addReqChangeAccountsPrivilegeLevel: 'SIGN',
dealsExist: false,
dealsPrivilegeLevel: 'SIGN',
},
{
clientId: '1814d014-0bd1-40f1-9a2a-9653bda2ee74',
clientWebDealingId: '4cf1be8d-c6be-4185-abd0-b932312e0fa9',
clientFullName: 'АКЦИОНЕРНОЕ ОБЩЕСТВО "БИОКАД"',
clientShortName: 'АО "БИОКАД"',
signer: false,
systemAgreementExist: false,
userInformationByDealType: [
{
dealType: 'FX',
privilegeLevel: 'SIGN',
dealsExist: false,
ratesExist: false,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: true,
},
{
dealType: 'DEPOSIT',
privilegeLevel: 'SIGN',
dealsExist: false,
ratesExist: false,
generalAgreementsExist: true,
generalAgreementsDUExist: false,
allowedForRequest: true,
dealsListEnabled: true,
},
{
dealType: 'GSNO',
privilegeLevel: 'NONE',
dealsExist: false,
ratesExist: true,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: false,
},
{
dealType: 'FX_AUTO',
privilegeLevel: 'NONE',
dealsExist: false,
ratesExist: true,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: false,
},
{
dealType: 'MNO',
privilegeLevel: 'SIGN',
dealsExist: false,
ratesExist: true,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: false,
},
],
accountsExist: true,
accountsPrivilegeLevel: 'EDIT',
generalAgreementsExist: false,
generalAgreementsDUExist: false,
generalAgreementsPrivilegeLevel: 'EDIT',
gsnoReportsPrivilegeLevel: 'NONE',
depositReportsPrivilegeLevel: 'EDIT',
agrReqGsnoChildHeadPrivilegeLevel: 'SIGN',
addReqChangeAccountsPrivilegeLevel: 'SIGN',
dealsExist: false,
dealsPrivilegeLevel: 'SIGN',
},
{
clientId: '28738bc1-c280-4b51-aea5-0baa3801dd07',
clientWebDealingId: 'fcd417bf-5242-4969-be1a-02c889cb1cc2',
@@ -291,148 +291,148 @@ const TREASURY_COMMON_CLIENT_USER_INFO_UNION_MOCK: TreasuryCommonClientUserInfoU
dealsExist: false,
dealsPrivilegeLevel: 'SIGN',
},
// {
// clientId: '173ed58e-c8ad-45d8-a9c1-2e16b380363b',
// clientWebDealingId: 'b7f1cc09-f914-452a-83df-98c4b736cc57',
// clientFullName: 'Общество с ограниченной ответственностью "Мантрак Восток"',
// clientShortName: 'ООО "Мантрак Восток"',
// signer: false,
// systemAgreementExist: false,
// userInformationByDealType: [
// {
// dealType: 'FX',
// privilegeLevel: 'SIGN',
// dealsExist: false,
// ratesExist: false,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: false,
// },
// {
// dealType: 'DEPOSIT',
// privilegeLevel: 'SIGN',
// dealsExist: true,
// ratesExist: true,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: true,
// dealsListEnabled: false,
// },
// {
// dealType: 'GSNO',
// privilegeLevel: 'NONE',
// dealsExist: false,
// ratesExist: false,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: false,
// },
// {
// dealType: 'FX_AUTO',
// privilegeLevel: 'NONE',
// dealsExist: false,
// ratesExist: true,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: false,
// },
// {
// dealType: 'MNO',
// privilegeLevel: 'SIGN',
// dealsExist: false,
// ratesExist: false,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: false,
// },
// ],
// accountsExist: true,
// accountsPrivilegeLevel: 'EDIT',
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// generalAgreementsPrivilegeLevel: 'EDIT',
// gsnoReportsPrivilegeLevel: 'NONE',
// depositReportsPrivilegeLevel: 'EDIT',
// agrReqGsnoChildHeadPrivilegeLevel: 'SIGN',
// addReqChangeAccountsPrivilegeLevel: 'SIGN',
// dealsExist: false,
// dealsPrivilegeLevel: 'SIGN',
// },
// {
// clientId: '64b3578f-eaa2-4367-90f2-98965b589262',
// clientWebDealingId: 'b6ea6126-61d3-41e4-93fd-22b8e9fe6848',
// clientFullName: 'Общество с ограниченной ответственностью "Ньютон Инвестиции"',
// clientShortName: 'ООО "Ньютон Инвестиции"',
// signer: false,
// systemAgreementExist: false,
// userInformationByDealType: [
// {
// dealType: 'FX',
// privilegeLevel: 'SIGN',
// dealsExist: true,
// ratesExist: false,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: true,
// },
// {
// dealType: 'DEPOSIT',
// privilegeLevel: 'NONE',
// dealsExist: true,
// ratesExist: true,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: true,
// },
// {
// dealType: 'GSNO',
// privilegeLevel: 'NONE',
// dealsExist: true,
// ratesExist: true,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: false,
// },
// {
// dealType: 'FX_AUTO',
// privilegeLevel: 'NONE',
// dealsExist: true,
// ratesExist: true,
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// allowedForRequest: false,
// dealsListEnabled: false,
// },
// {
// dealType: 'MNO',
// privilegeLevel: 'SIGN',
// dealsExist: true,
// ratesExist: true,
// generalAgreementsExist: false,
// generalAgreementsDUExist: true,
// allowedForRequest: true,
// dealsListEnabled: true,
// },
// ],
// accountsExist: true,
// accountsPrivilegeLevel: 'EDIT',
// generalAgreementsExist: false,
// generalAgreementsDUExist: false,
// generalAgreementsPrivilegeLevel: 'EDIT',
// gsnoReportsPrivilegeLevel: 'NONE',
// depositReportsPrivilegeLevel: 'EDIT',
// agrReqGsnoChildHeadPrivilegeLevel: 'SIGN',
// addReqChangeAccountsPrivilegeLevel: 'SIGN',
// dealsExist: true,
// dealsPrivilegeLevel: 'SIGN',
// },
{
clientId: '173ed58e-c8ad-45d8-a9c1-2e16b380363b',
clientWebDealingId: 'b7f1cc09-f914-452a-83df-98c4b736cc57',
clientFullName: 'Общество с ограниченной ответственностью "Мантрак Восток"',
clientShortName: 'ООО "Мантрак Восток"',
signer: false,
systemAgreementExist: false,
userInformationByDealType: [
{
dealType: 'FX',
privilegeLevel: 'SIGN',
dealsExist: false,
ratesExist: false,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: false,
},
{
dealType: 'DEPOSIT',
privilegeLevel: 'SIGN',
dealsExist: true,
ratesExist: true,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: true,
dealsListEnabled: false,
},
{
dealType: 'GSNO',
privilegeLevel: 'NONE',
dealsExist: false,
ratesExist: false,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: false,
},
{
dealType: 'FX_AUTO',
privilegeLevel: 'NONE',
dealsExist: false,
ratesExist: true,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: false,
},
{
dealType: 'MNO',
privilegeLevel: 'SIGN',
dealsExist: false,
ratesExist: false,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: false,
},
],
accountsExist: true,
accountsPrivilegeLevel: 'EDIT',
generalAgreementsExist: false,
generalAgreementsDUExist: false,
generalAgreementsPrivilegeLevel: 'EDIT',
gsnoReportsPrivilegeLevel: 'NONE',
depositReportsPrivilegeLevel: 'EDIT',
agrReqGsnoChildHeadPrivilegeLevel: 'SIGN',
addReqChangeAccountsPrivilegeLevel: 'SIGN',
dealsExist: false,
dealsPrivilegeLevel: 'SIGN',
},
{
clientId: '64b3578f-eaa2-4367-90f2-98965b589262',
clientWebDealingId: 'b6ea6126-61d3-41e4-93fd-22b8e9fe6848',
clientFullName: 'Общество с ограниченной ответственностью "Ньютон Инвестиции"',
clientShortName: 'ООО "Ньютон Инвестиции"',
signer: false,
systemAgreementExist: false,
userInformationByDealType: [
{
dealType: 'FX',
privilegeLevel: 'SIGN',
dealsExist: true,
ratesExist: false,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: true,
},
{
dealType: 'DEPOSIT',
privilegeLevel: 'NONE',
dealsExist: true,
ratesExist: true,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: true,
},
{
dealType: 'GSNO',
privilegeLevel: 'NONE',
dealsExist: true,
ratesExist: true,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: false,
},
{
dealType: 'FX_AUTO',
privilegeLevel: 'NONE',
dealsExist: true,
ratesExist: true,
generalAgreementsExist: false,
generalAgreementsDUExist: false,
allowedForRequest: false,
dealsListEnabled: false,
},
{
dealType: 'MNO',
privilegeLevel: 'SIGN',
dealsExist: true,
ratesExist: true,
generalAgreementsExist: false,
generalAgreementsDUExist: true,
allowedForRequest: true,
dealsListEnabled: true,
},
],
accountsExist: true,
accountsPrivilegeLevel: 'EDIT',
generalAgreementsExist: false,
generalAgreementsDUExist: false,
generalAgreementsPrivilegeLevel: 'EDIT',
gsnoReportsPrivilegeLevel: 'NONE',
depositReportsPrivilegeLevel: 'EDIT',
agrReqGsnoChildHeadPrivilegeLevel: 'SIGN',
addReqChangeAccountsPrivilegeLevel: 'SIGN',
dealsExist: true,
dealsPrivilegeLevel: 'SIGN',
},
],
clientsByFxDocSortOrder: [
'64b3578f-eaa2-4367-90f2-98965b589262',
@@ -1,5 +1,5 @@
import type { ReactElement } from 'react';
import { useState, useCallback, useMemo, useRef, useLayoutEffect } from 'react';
import { useState, useCallback, useMemo, useRef, memo, useLayoutEffect } from 'react';
import { Icon } from '@fractal-ui/library';
import type { IconName } from '@fractal-ui/library/dist-types/icon/types';
import { Calendar } from '@msb/fractal-ui-composites';
@@ -15,7 +15,7 @@ import CalendarFolder from '@msb/shared/assets/calendar_folder.png';
const MAX_VISIBLE_RECORDS = 2;
const EventCalendar = (): ReactElement => {
const EventCalendar = memo(({ onDateChange }: { onDateChange?: () => void }): ReactElement => {
const [selectedDate, setSelectedDate] = useState<Date>(new Date());
const [visibleMonth, setVisibleMonth] = useState(dayjs());
const [recordHeight, setRecordHeight] = useState<number>(0);
@@ -32,6 +32,7 @@ const EventCalendar = (): ReactElement => {
const isLoading = isLoadingWorkCalendar || isLoadingDealMarkers || isLoadingDealEvents;
const handleDateChange = useCallback((date: DateValue) => {
onDateChange?.();
setSelectedDate(Array.isArray(date) ? date[0] : date);
}, []);
@@ -134,6 +135,6 @@ const EventCalendar = (): ReactElement => {
</S.EventRecordsWrapper>
</S.EventCalendarContent>
);
};
});
export { EventCalendar };
@@ -1,7 +1,21 @@
import { DOC_TYPES } from '@msb/shared';
import { BUTTON_CLICK, SCREEN_NAME } from '@/shared/constants';
const PERMISSIONS: Record<string, string[]> = {
DEPOSIT: ['TREASURY_COMMON', 'TREASURY_DEPOSIT_DEALS_COMMON', 'TREASURY_GENERAL_AGREEMENTS_COMMON'],
MNO: ['TREASURY_COMMON', 'TREASURY_MNO_DEALS_COMMON', 'TREASURY_GENERAL_AGREEMENTS_COMMON'],
GSNO: ['TREASURY_COMMON', 'TREASURY_GSNO_DEALS_COMMON', 'TREASURY_GENERAL_AGREEMENTS_COMMON'],
};
export { PERMISSIONS };
const SCREEN_NAME_MATCHER: Record<string, string> = {
deposits: SCREEN_NAME.DEPOSITS,
products: SCREEN_NAME.DEPOSITS_PRODUCTS,
};
const ELEMENT_NAME_MATCHER: Record<string, string> = {
[DOC_TYPES.DEPOSIT]: BUTTON_CLICK.ELEMENT_NAME.OPEN_DEPOSIT,
[DOC_TYPES.MNO]: BUTTON_CLICK.ELEMENT_NAME.OPEN_MNO,
[DOC_TYPES.GSNO]: BUTTON_CLICK.ELEMENT_NAME.OPEN_GSNO,
};
export { PERMISSIONS, SCREEN_NAME_MATCHER, ELEMENT_NAME_MATCHER };
@@ -1,7 +1,8 @@
import { checkHaveUserPermissions, useAppContext, useUnauthorizedModal, DOC_TYPES } from '@msb/shared';
import { useHistory } from 'react-router-dom';
import { PERMISSIONS } from '../constants';
import { PATHS } from '@/shared/constants';
import { useMemo } from 'react';
import { checkHaveUserPermissions, useAppContext, useUnauthorizedModal, DOC_TYPES, useYaMetrika, YM_GOALS } from '@msb/shared';
import { useHistory, useLocation } from 'react-router-dom';
import { ELEMENT_NAME_MATCHER, PERMISSIONS, SCREEN_NAME_MATCHER } from '../constants';
import { ACTIONS_LEADING_TO_TREASURY_DEALS_FORM, BUTTON_CLICK, PATHS } from '@/shared/constants';
import type { HistoryState } from '@/shared/model';
/**
@@ -11,6 +12,9 @@ const useOpenTreasuryDeals = () => {
const { userAuthorities } = useAppContext();
const history = useHistory();
const { showUnauthorizedModal: notEnoughRights } = useUnauthorizedModal();
const { handleReachGoal } = useYaMetrika();
const { pathname } = useLocation();
const segment = useMemo(() => pathname.split('/').pop() || '', [pathname]);
if (!userAuthorities?.data) {
return { openDeposit: notEnoughRights, openMNO: notEnoughRights, openGSNO: notEnoughRights };
@@ -18,7 +22,21 @@ const useOpenTreasuryDeals = () => {
const { authorities } = userAuthorities.data;
const handleMetrika = (docType: DOC_TYPES, payload?: HistoryState) => {
const actionType = payload?.actionType;
const screenName = SCREEN_NAME_MATCHER[segment];
const elementName =
actionType === ACTIONS_LEADING_TO_TREASURY_DEALS_FORM.SHOWCASE
? BUTTON_CLICK.ELEMENT_NAME.DEPOSIT_OFFER
: ELEMENT_NAME_MATCHER[docType];
handleReachGoal(YM_GOALS.BUTTON_CLICK, { [YM_GOALS.BUTTON_CLICK]: { [screenName]: { element_name: elementName } } });
};
// TODO: привести все к одной функции открытия продукта, так как функционал повторяется
const openDeposit = (payload?: HistoryState) => {
handleMetrika(DOC_TYPES.DEPOSIT, payload);
const havePermission = checkHaveUserPermissions(authorities, PERMISSIONS.DEPOSIT);
if (!havePermission) {
@@ -27,10 +45,12 @@ const useOpenTreasuryDeals = () => {
return;
}
history.push(PATHS.TREASURY_DEALS.PATH, { ...payload, docType: DOC_TYPES.DEPOSIT, showcasePath: PATHS.HOME.PATH });
history.push(PATHS.TREASURY_DEALS.PATH, { ...payload, docType: DOC_TYPES.DEPOSIT });
};
const openMNO = (payload?: HistoryState) => {
handleMetrika(DOC_TYPES.MNO, payload);
const havePermission = checkHaveUserPermissions(authorities, PERMISSIONS.MNO);
if (!havePermission) {
@@ -39,10 +59,12 @@ const useOpenTreasuryDeals = () => {
return;
}
history.push(PATHS.TREASURY_DEALS.PATH, { ...payload, docType: DOC_TYPES.MNO, showcasePath: PATHS.HOME.PATH });
history.push(PATHS.TREASURY_DEALS.PATH, { ...payload, docType: DOC_TYPES.MNO });
};
const openGSNO = (payload?: HistoryState) => {
handleMetrika(DOC_TYPES.GSNO, payload);
const havePermission = checkHaveUserPermissions(authorities, PERMISSIONS.GSNO);
if (!havePermission) {
@@ -51,7 +73,7 @@ const useOpenTreasuryDeals = () => {
return;
}
history.push(PATHS.TREASURY_DEALS.PATH, { ...payload, docType: DOC_TYPES.GSNO, showcasePath: PATHS.HOME.PATH });
history.push(PATHS.TREASURY_DEALS.PATH, { ...payload, docType: DOC_TYPES.GSNO });
};
return { openDeposit, openMNO, openGSNO };
@@ -0,0 +1,11 @@
import { DOC_TYPES } from '@msb/shared';
import { SCREEN_NAME } from '@/shared/constants';
const SCREEN_NAME_MATCHER: Record<DOC_TYPES, string> = {
[DOC_TYPES.DEPOSIT]: SCREEN_NAME.DEPOSIT_FORM,
[DOC_TYPES.MNO]: SCREEN_NAME.MNO_FORM,
[DOC_TYPES.GSNO]: SCREEN_NAME.GSNO_FORM,
[DOC_TYPES.OVERNIGHT]: SCREEN_NAME.DEPOSIT_FORM,
};
export { SCREEN_NAME_MATCHER };
@@ -1 +1,2 @@
export * from './localization';
export * from './constants';
@@ -2,9 +2,10 @@ import { useEffect } from 'react';
import { Button } from '@fractal-ui/core';
import type { DocumentNewForEditDto, SaveTemplateRequestBody } from '@msb/http';
import type { DOC_TYPES } from '@msb/shared';
import { Flex } from '@msb/shared';
import { TREASURY_DEALS_ACTIONS_BUTTONS } from '../constants';
import { Flex, useYaMetrika, YM_GOALS } from '@msb/shared';
import { SCREEN_NAME_MATCHER, TREASURY_DEALS_ACTIONS_BUTTONS } from '../constants';
import { useHandleSave } from '../model';
import { BUTTON_CLICK } from '@/shared/constants';
interface Props {
isSigner?: boolean;
@@ -24,6 +25,7 @@ interface Props {
const TreasuryDealsActionsButtons = ({ isSigner, requestBody, setRequestBody, handleSubmit, docType }: Props) => {
const { handleSave, saveTemplateData } = useHandleSave(docType);
const { handleReachGoal } = useYaMetrika();
useEffect(() => {
const draft = saveTemplateData?.data;
@@ -33,13 +35,27 @@ const TreasuryDealsActionsButtons = ({ isSigner, requestBody, setRequestBody, ha
}
}, [saveTemplateData, setRequestBody]);
const handleClickSaveButton = () => {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME_MATCHER[docType]]: { element_name: BUTTON_CLICK.ELEMENT_NAME.SAVE_DRAFT } },
});
handleSave(requestBody);
};
const handleClickSumbitButton = () => {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME_MATCHER[docType]]: { element_name: BUTTON_CLICK.ELEMENT_NAME.SIGN } },
});
handleSubmit();
};
return (
<Flex row gap={3} justifyContent="flex-end" width="100%">
<Button dataAction="save" shape="default" variant="blue" width={'118px'} onClick={() => handleSave(requestBody)}>
<Button dataAction="save" shape="default" variant="blue" width={'118px'} onClick={handleClickSaveButton}>
{TREASURY_DEALS_ACTIONS_BUTTONS.SAVE}
</Button>
{isSigner && (
<Button dataAction="submit" shape="default" variant="primary" width={'210px'} onClick={handleSubmit}>
<Button dataAction="submit" shape="default" variant="primary" width={'210px'} onClick={handleClickSumbitButton}>
{TREASURY_DEALS_ACTIONS_BUTTONS.SUBMIT}
</Button>
)}
@@ -2,10 +2,12 @@ import type { RefObject } from 'react';
import { useEffect, useState } from 'react';
import { Title, Wrapper } from '@fractal-ui/styling';
import type { BestRatesResponseDto } from '@msb/http';
import { useYaMetrika, YM_GOALS } from '@msb/shared';
import { localization } from '../constants';
import { RadioGroupItem } from './RadioGroupItem';
import * as S from './TreasuryDealsBestRates.styles';
import { TREASURY_DEALS_FORM_FIELDS } from '@/entities/treasuryDealsForm';
import { BUTTON_CLICK, SCREEN_NAME } from '@/shared/constants';
interface Props {
treausuryDealsBestRatesData: BestRatesResponseDto;
@@ -16,8 +18,12 @@ interface Props {
const TreasuryDealsBestRates = ({ treausuryDealsBestRatesData, rateValue, currency, formRef }: Props) => {
const [selectedRate, setSelectedRate] = useState<number | null>(null);
const { handleReachGoal } = useYaMetrika();
const handleRateChange = (index: number) => {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME.DEPOSIT_FORM]: { element_name: BUTTON_CLICK.ELEMENT_NAME.BEST_RATE } },
});
setSelectedRate(index);
};
@@ -1,6 +1,7 @@
import type { ReactElement } from 'react';
import { useEffect, useState, useMemo } from 'react';
import { Button } from '@fractal-ui/core';
import type { DOC_TYPES } from '@msb/shared';
import { useRedirect } from '@msb/shared';
import dayjs from 'dayjs';
import { useLocation } from 'react-router-dom';
@@ -14,7 +15,7 @@ import { SignCancelDocuments } from '@/widgets/SignCancelDocuments';
interface LocationState {
id: string;
docType: string;
docType: DOC_TYPES;
}
const titleVariant: Record<string, string> = {
@@ -1,7 +1,15 @@
import type { ReactElement } from 'react';
import { useCallback, type ReactElement } from 'react';
import { SystemResponse } from '@fractal-ui/extended';
import { Title } from '@fractal-ui/styling';
import { PageLayoutWithSections, EventCalendar, checkHaveUserPermissions, useAppContext, useRedirect } from '@msb/shared';
import {
PageLayoutWithSections,
EventCalendar,
checkHaveUserPermissions,
useAppContext,
useRedirect,
useYaMetrika,
YM_GOALS,
} from '@msb/shared';
import {
LOCALIZATION,
TREASURY_COMMON,
@@ -13,6 +21,7 @@ import * as S from './DepositsMainPage.styles';
import { useCalculator } from '@/entities/calculator';
import { OpenTreasuryDealsButton } from '@/features/OpenTreasuryDealsButton';
import { NavBar } from '@/pages/DepositsMainPage/ui/NavBar';
import { BUTTON_CLICK, SCREEN_NAME } from '@/shared/constants';
import { DepositCalculator } from '@/widgets/DepositCalculator';
import { Showcase } from '@/widgets/Showcase';
@@ -20,6 +29,7 @@ const DepositsMainPage = (): ReactElement => {
const { isCalculatorVisible } = useCalculator();
const { userAuthorities } = useAppContext();
const redirectToProduct = useRedirect('b');
const { handleReachGoal } = useYaMetrika();
const userAuthoritiesList = userAuthorities?.data.authorities || [];
@@ -32,8 +42,14 @@ const DepositsMainPage = (): ReactElement => {
const haveShowcasePermission = haveMainSignatire && haveOtherSignatire;
const onDateChange = useCallback(() => {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME.DEPOSITS]: { element_name: BUTTON_CLICK.ELEMENT_NAME.CALENDAR_DATE } },
});
}, [handleReachGoal]);
return (
<PageLayoutWithSections aside={<EventCalendar />}>
<PageLayoutWithSections aside={<EventCalendar onDateChange={onDateChange} />}>
<S.HeaderWrapper>
<Title.H1>{LOCALIZATION.DEPOSITS_AND_MNO}</Title.H1>
{haveShowcasePermission && <OpenTreasuryDealsButton />}
@@ -1,27 +1,38 @@
import type { ReactElement } from 'react';
import { useYaMetrika, YM_GOALS } from '@msb/shared';
import * as S from './NavBar.styles';
import { NAV_BUTTONS } from './constants';
import type { BUTTON_CLICK } from '@/shared/constants';
import { SCREEN_NAME } from '@/shared/constants';
const NavBar = (): ReactElement => {
const { handleReachGoal } = useYaMetrika();
const handleClick = (metrikaAttr: typeof BUTTON_CLICK.ELEMENT_NAME[keyof typeof BUTTON_CLICK.ELEMENT_NAME]) => () =>
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME.DEPOSITS]: { element_name: metrikaAttr } },
});
return (
<S.NavBar>
{NAV_BUTTONS.map(({ text, icon, href, isExternal, metrikaAttr }) => {
if (isExternal) {
return (
<S.NavLink key={text} href={href} target="_blank" onClick={handleClick(metrikaAttr)}>
<S.Icon as="img" src={icon} />
<S.NavButtonTitle>{text}</S.NavButtonTitle>
</S.NavLink>
);
}
const NavBar = (): ReactElement => (
<S.NavBar>
{NAV_BUTTONS.map(({ text, icon, href, isExternal }) => {
if (isExternal) {
return (
<S.NavLink key={text} href={href} target="_blank">
<S.NavButton key={text} to={href} onClick={handleClick(metrikaAttr)}>
<S.Icon as="img" src={icon} />
<S.NavButtonTitle>{text}</S.NavButtonTitle>
</S.NavLink>
</S.NavButton>
);
}
return (
<S.NavButton key={text} to={href}>
<S.Icon as="img" src={icon} />
<S.NavButtonTitle>{text}</S.NavButtonTitle>
</S.NavButton>
);
})}
</S.NavBar>
);
})}
</S.NavBar>
);
};
export { NavBar };
@@ -1,6 +1,6 @@
import { ECO_SERVICES_PATHS } from '@msb/shared';
import { Icons } from './assets';
import { PATHS } from '@/shared/constants';
import { BUTTON_CLICK, PATHS } from '@/shared/constants';
const NAV_BUTTONS = [
{
@@ -8,18 +8,21 @@ const NAV_BUTTONS = [
icon: Icons.myProducts,
href: PATHS.PRODUCTS.PATH,
isExternal: false,
metrikaAttr: BUTTON_CLICK.ELEMENT_NAME.MY_PRODUCTS,
},
{
text: 'Соглашения',
icon: Icons.accounts,
href: ECO_SERVICES_PATHS.WEB_DEALING_AGREEMENTS,
isExternal: true,
metrikaAttr: BUTTON_CLICK.ELEMENT_NAME.AGREEMENTS,
},
{
text: 'Счета',
icon: Icons.agreements,
href: ECO_SERVICES_PATHS.WEB_DEALING_ACCOUNTS,
isExternal: true,
metrikaAttr: BUTTON_CLICK.ELEMENT_NAME.ACCOUNTS,
},
];
@@ -1,10 +1,11 @@
import { useEffect } from 'react';
import type { UserInformationByDealType } from '@msb/http';
import type { DOC_TYPES } from '@msb/shared';
import { useYaMetrika, YM_GOALS, type DOC_TYPES } from '@msb/shared';
import type { FormApi } from 'final-form';
import { DEPOSIT_ERROR_TYPE, DEPOSIT_ERROR_ACTIONS, PRIVILEGE_LEVEL } from '../constants';
import { handleDepositResetForm, handleAgreementRedirect, handleAccountsRedirect } from './handleDepositErrors';
import { useCheckDepositModal } from '@/features/useCheckDepositModal';
import { ERROR } from '@/shared/constants';
interface UserDepositInfoProps {
userInformationByDealType?: UserInformationByDealType[];
@@ -24,12 +25,14 @@ const useCheckDepositErrors = ({
const { showDepositErrorModal, hideDepositErrorModal } = useCheckDepositModal();
const depositInfo = userInformationByDealType.find(d => d.dealType === docType);
const resetFormAndClose = () => handleDepositResetForm({ formRef, setChosenOrgId });
const { handleReachGoal } = useYaMetrika();
useEffect(() => {
if (!depositInfo) return;
// Сценарий 1: Недостаточно прав
if (depositInfo.privilegeLevel === PRIVILEGE_LEVEL.NONE) {
handleReachGoal(YM_GOALS.ERROR, { [YM_GOALS.ERROR]: { deposits: { error_description: ERROR.RIGHTS_ERROR[docType] } } });
showDepositErrorModal({
errorType: DEPOSIT_ERROR_TYPE.NO_PERMISSION,
actions: [{ dataAction: 'privelege', name: 'PRIVILEGE', text: DEPOSIT_ERROR_ACTIONS.CLOSE.text }],
@@ -41,6 +44,7 @@ const useCheckDepositErrors = ({
// Сценарий 2: Режим сделок
if (!depositInfo.ratesExist || !depositInfo.allowedForRequest) {
handleReachGoal(YM_GOALS.ERROR, { [YM_GOALS.ERROR]: { deposits: { error_description: ERROR.RATE_ERROR[docType] } } });
showDepositErrorModal({
errorType: DEPOSIT_ERROR_TYPE.NO_DEALS,
actions: [{ dataAction: 'deals', name: 'DEALS', text: DEPOSIT_ERROR_ACTIONS.CLOSE.text }],
@@ -52,6 +56,7 @@ const useCheckDepositErrors = ({
// Сценарий 3: Нет ген.Соглашения
if (!depositInfo.generalAgreementsExist) {
handleReachGoal(YM_GOALS.ERROR, { [YM_GOALS.ERROR]: { deposits: { error_description: ERROR.AGREEMENT_ERROR[docType] } } });
showDepositErrorModal({
errorType: DEPOSIT_ERROR_TYPE.NO_AGREEMENT,
actions: [
@@ -73,6 +78,7 @@ const useCheckDepositErrors = ({
// Сценарий 4: Нет счетов для зачисления процентов
if (!accountsExist) {
handleReachGoal(YM_GOALS.ERROR, { [YM_GOALS.ERROR]: { deposits: { error_description: ERROR.ACCOUNTS_ERROR[docType] } } });
showDepositErrorModal({
errorType: DEPOSIT_ERROR_TYPE.NO_ACCOUNTS_AVAILABLE,
actions: [
@@ -4,12 +4,13 @@ import type { DocumentRateResponseDto, DocumentValidateRequestBody, MessagesResp
import { fetchValidate, to } from '@msb/http';
import { localization } from '@msb/localization';
import type { DOC_TYPES } from '@msb/shared';
import { BaseDialog, checkHaveUserPermissions, PATHS, useAppContext, useModal, useRedirect } from '@msb/shared';
import { BaseDialog, checkHaveUserPermissions, PATHS, useAppContext, useModal, useRedirect, useYaMetrika, YM_GOALS } from '@msb/shared';
import type { ValidationErrors } from 'final-form';
import { DIGITAL_SIGNATURE_TOOL_VIEW, LOCALIZATION } from '../constants';
import { transformValidationErrors } from './useAsyncValidation';
import { validate } from './validation';
import { generateSignDataDepositDocument, signAndSendDepositDocument, useLazyCreateToSignDepositDocument } from '@/entities/documents';
import { SCREEN_VIEW } from '@/shared/constants';
import { parseSignDataToCryptoData } from '@/shared/lib';
interface Params {
@@ -22,6 +23,7 @@ interface Params {
const useHandleSubmit = (docType: DOC_TYPES) => {
const { userAuthorities } = useAppContext();
const { handleReachGoal } = useYaMetrika();
const { createToSignDepositDocumentAsync } = useLazyCreateToSignDepositDocument(docType);
const { showModal } = useModal(BaseDialog);
const toDeposits = useRedirect(PATHS.DEPOSITS);
@@ -131,6 +133,7 @@ const useHandleSubmit = (docType: DOC_TYPES) => {
});
if (response.signedDocs.length > 0) {
handleReachGoal(YM_GOALS.SCREEN_VIEW, { [YM_GOALS.SCREEN_VIEW]: { screen_name: SCREEN_VIEW.SUCCESS[docType] } });
await showModal({
header: LOCALIZATION.MODAL_HEADER,
message: accountWriteOff
@@ -3,3 +3,4 @@ export * from './maps';
export * from './documents';
export * from './localization';
export * from './actions';
export * from './metrika';
@@ -0,0 +1,87 @@
import { DOC_TYPES } from '@msb/shared';
const SCREEN_NAME = {
DEPOSITS: 'deposits',
DEPOSITS_CALCULATOR: 'deposits_calculator',
DEPOSITS_PRODUCTS: 'deposits_products',
DEPOSIT_FORM: 'deposit_form',
MNO_FORM: 'mno_form',
GSNO_FORM: 'gsno_form',
DEPOSIT_CONFIRM: 'deposit_confirm',
MNO_CONFIRM: 'mno_confirm',
GSNO_CONFIRM: 'gsno_confirm',
DEPOSIT_EARLY_REFUND: 'deposit_earlyRefund',
DEPOSIT_CANCEL: 'deposit_cancel',
MNO_CANCEL: 'mno_cancel',
GSNO_CANCEL: 'gsno_cancel',
} as const;
const SCREEN_VIEW = {
SUCCESS: {
[DOC_TYPES.DEPOSIT]: 'deposit_success',
[DOC_TYPES.MNO]: 'mno_success',
[DOC_TYPES.GSNO]: 'gsno_success',
[DOC_TYPES.OVERNIGHT]: 'deposit_success',
EARLY_REFUND: 'deposit_earlyRefund_success',
DOCUMENT_CANCEL: {
[DOC_TYPES.DEPOSIT]: 'deposit_cancel_success',
[DOC_TYPES.MNO]: 'mno_cancel_success',
[DOC_TYPES.GSNO]: 'gsno_cancel_success',
[DOC_TYPES.OVERNIGHT]: 'deposit_cancel_success',
},
},
} as const;
const BUTTON_CLICK = {
ELEMENT_NAME: {
DEPOSIT_OFFER: 'deposit_offer',
OPEN_PRODUCT: 'open_product',
CALENDAR_DATE: 'calendar_date',
MY_PRODUCTS: 'my_products',
AGREEMENTS: 'agreements',
ACCOUNTS: 'accounts',
OPEN_DEPOSIT: 'open_deposit',
OPEN_MNO: 'open_mno',
OPEN_GSNO: 'open_gsno',
SIGN: 'sign',
CONFIRM: 'confirm',
SHOW_MORE: 'show_more',
VIOLATED: 'violated',
CONFIRMATION: 'confirmation',
ALL: 'all',
FILTER: 'filter',
EARLY_REFUND: 'early_refund',
CANCEL: 'cancel',
SAVE_DRAFT: 'save_draft',
BEST_RATE: 'best_rate',
},
} as const;
const ERROR = {
AGREEMENT_ERROR: {
[DOC_TYPES.DEPOSIT]: 'no_deposit_agreement',
[DOC_TYPES.MNO]: 'no_mno_agreement',
[DOC_TYPES.GSNO]: 'no_gsno_agreement',
[DOC_TYPES.OVERNIGHT]: 'no_deposit_agreement',
},
RATE_ERROR: {
[DOC_TYPES.DEPOSIT]: 'no_deposit_rate',
[DOC_TYPES.MNO]: 'no_mno_rate',
[DOC_TYPES.GSNO]: 'no_gsno_rate',
[DOC_TYPES.OVERNIGHT]: 'no_deposit_rate',
},
ACCOUNTS_ERROR: {
[DOC_TYPES.DEPOSIT]: 'no_deposit_accounts',
[DOC_TYPES.MNO]: 'no_mno_accounts',
[DOC_TYPES.GSNO]: 'no_gsno_accounts',
[DOC_TYPES.OVERNIGHT]: 'no_deposit_accounts',
},
RIGHTS_ERROR: {
[DOC_TYPES.DEPOSIT]: 'no_deposit_rights',
[DOC_TYPES.MNO]: 'no_mno_rights',
[DOC_TYPES.GSNO]: 'no_gsno_rights',
[DOC_TYPES.OVERNIGHT]: 'no_deposit_rights',
},
};
export { SCREEN_NAME, SCREEN_VIEW, BUTTON_CLICK, ERROR };
@@ -1,22 +1,26 @@
import { useState } from 'react';
import { StatusModal } from '@fractal-ui/overlays';
import { Title, Text } from '@fractal-ui/styling';
import { ECO_SERVICES_PATHS } from '@msb/shared';
import { ECO_SERVICES_PATHS, useYaMetrika, YM_GOALS } from '@msb/shared';
import { initialFormData, LOCALIZATION } from '../constants';
import { CalculatorCardResult } from './CalculatorCardResult';
import { CalculatorForm } from './CalculatorForm';
import * as S from './DepositCalculator.styles';
import { useDepositCalculatorForm } from './useDepositCalculatorForm';
import { BUTTON_CLICK, SCREEN_NAME } from '@/shared/constants';
import { PageLayout } from '@/shared/ui';
const DepositCalculator = () => {
const { handleChangeFormData, calculateData, formData, isCalculateLoading } = useDepositCalculatorForm();
const { handleReachGoal } = useYaMetrika();
const [opened, setOpened] = useState<boolean>(false);
const handleOpen = () => setOpened(true);
const handleOpen = () => {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME.DEPOSITS_CALCULATOR]: { element_name: BUTTON_CLICK.ELEMENT_NAME.OPEN_PRODUCT } },
});
setOpened(true);
};
const handleClose = () => setOpened(false);
const goToAgreement = () => window.open(ECO_SERVICES_PATHS.TREASURY_AGREEMENT, '_blank');
return (
@@ -5,14 +5,14 @@ import { OkIcon, PdfIcon } from '@fractal-ui/library';
import type { ModalProps } from '@fractal-ui/overlays';
import { Modal, useSnackbar } from '@fractal-ui/overlays';
import { Text } from '@fractal-ui/styling';
import { DAYS, getFormattedBalance, pluralize } from '@msb/shared';
import { DAYS, getFormattedBalance, pluralize, useYaMetrika, YM_GOALS } from '@msb/shared';
import { useHistory } from 'react-router-dom';
import { LOCALIZATION } from '../../constants';
import { getActionsOrder, getCopyData } from '../../lib';
import type { RowDataProps } from '../../model';
import * as S from './ExpandedComponent.styled';
import { SignersContent } from './SignersContent';
import { PATHS, paymentMethodsMap, documentsTypeMap } from '@/shared/constants';
import { PATHS, paymentMethodsMap, documentsTypeMap, SCREEN_NAME, BUTTON_CLICK } from '@/shared/constants';
import { fetchDocument } from '@/shared/lib';
interface Props {
@@ -39,6 +39,7 @@ const ExpandedComponentContent = ({ row }: Props): ReactElement => {
} = row;
const history = useHistory();
const { showSnackbarMessage } = useSnackbar();
const { handleReachGoal } = useYaMetrika();
const [open, setOpen] = useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
@@ -86,11 +87,26 @@ const ExpandedComponentContent = ({ row }: Props): ReactElement => {
};
// TODO: подумать о переносе экшенов сюда mcb-platform-monorepo/services/msb-deposits/src/widgets/ProductTable/constants/common.ts
const cancelDocumentAction = () => history.push(PATHS.CANCEL_DOCUMENT.PATH, { id, docType });
const earlyRefundAction = () => history.push(PATHS.EARLY_REFUND.PATH, { id });
const cancelDocumentAction = () => {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME.DEPOSITS_PRODUCTS]: { element_name: BUTTON_CLICK.ELEMENT_NAME.CANCEL } },
});
history.push(PATHS.CANCEL_DOCUMENT.PATH, { id, docType });
};
const earlyRefundAction = () => {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME.DEPOSITS_PRODUCTS]: { element_name: BUTTON_CLICK.ELEMENT_NAME.EARLY_REFUND } },
});
history.push(PATHS.EARLY_REFUND.PATH, { id });
};
const retryAction = () => history.push(PATHS.TREASURY_DEALS.PATH, { id, docType, actionType: 'COPY' });
const editAction = () => history.push(PATHS.TREASURY_DEALS.PATH, { id, docType, actionType: 'EDIT' });
const confirmAction = () => history.push(PATHS.CONFIRMATION.PATH, { id, docType, actionType: 'CONFIRM' });
const confirmAction = () => {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME.DEPOSITS_PRODUCTS]: { element_name: BUTTON_CLICK.ELEMENT_NAME.CONFIRM } },
});
history.push(PATHS.CONFIRMATION.PATH, { id, docType, actionType: 'CONFIRM' });
};
return (
<S.Content>
@@ -1,4 +1,4 @@
import type { ReactElement } from 'react';
import { type ReactElement } from 'react';
import { Table, Cell, CELL_TYPE, type CellDataProps, type UnionColumnProps } from '@fractal-ui/table';
import type { FetchNextPageOptions, InfiniteQueryObserverResult, ProductsResponseDto } from '@msb/http';
import { getFormattedBalance } from '@msb/shared';
@@ -108,6 +108,24 @@ const ProductTable = ({
}: ProductTableProps): ReactElement => {
const resultData = parseGetPageRespToColumns(productsData);
const resultColumns = clientIdsCount > 1 ? columns : columns.filter(el => el.name !== 'organization');
// const [expandedRows, setExpandedRows] = useState<RowDataProps[]>([]);
// const { handleReachGoal } = useYaMetrika();
// Обработчик изменения раскрытых строк (TODO: пока ломает подкапотную логику раскрытия, надо будет позже вернуться к этому)
// const handleExpandedRowsChange = useCallback((rows: Array<RowDataProps>) => {
// setExpandedRows((prevRows) => {
// const prevCount = prevRows.length;
// const currentCount = rows.length;
// //Если текущее значение раскрытых строк больше предыдущего, то это означает, что пользователь раскрыл expandedComponent, в противном случае он скрыл expandedComponent
// if (currentCount > prevCount) {
// console.log({ [YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME.DEPOSITS_PRODUCTS]: { element_name: BUTTON_CLICK.ELEMENT_NAME.SHOW_MORE } } })
// handleReachGoal(YM_GOALS.BUTTON_CLICK, { [YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME.DEPOSITS_PRODUCTS]: { element_name: BUTTON_CLICK.ELEMENT_NAME.SHOW_MORE } } });
// }
// return rows
// });
// }, []);
return (
<Table
@@ -118,6 +136,8 @@ const ProductTable = ({
columns={resultColumns}
data={resultData}
expandedRowComponent={ExpandedComponent}
// expandedRows={expandedRows}
// onExpandedRowsChange={handleExpandedRowsChange}
lazyLoadProps={{
isLazyLoading: isProductsDataLoading,
onIntersecting: async () => {
@@ -1,18 +1,28 @@
import type { TabOption } from '@msb/fractal-ui-composites';
import { BUTTON_CLICK } from '@/shared/constants';
const allTab: TabOption = {
label: 'Все ',
interface ExtendedTabOption extends TabOption {
elementName: string;
}
const allTab: ExtendedTabOption = {
label: 'Все',
value: '0',
elementName: BUTTON_CLICK.ELEMENT_NAME.ALL,
};
const violatedTab: TabOption = {
const violatedTab: ExtendedTabOption = {
label: 'Нарушено',
value: '1',
status: 'warning',
elementName: BUTTON_CLICK.ELEMENT_NAME.VIOLATED,
};
const confirmationTab: TabOption = {
const confirmationTab: ExtendedTabOption = {
label: 'Требуют подтверждения',
value: '2',
status: 'warning',
elementName: BUTTON_CLICK.ELEMENT_NAME.CONFIRMATION,
};
export { allTab, violatedTab, confirmationTab };
const TabsOptions = [allTab, violatedTab, confirmationTab];
export { allTab, violatedTab, confirmationTab, TabsOptions };
@@ -2,11 +2,12 @@ import type { ReactElement } from 'react';
import { useCallback, useMemo, useRef, useEffect } from 'react';
import { createField } from '@fractal-ui/form';
import { Select } from '@msb/fractal-ui-composites';
import { isEqual, MultiSelect, useAppContext } from '@msb/shared';
import { isEqual, MultiSelect, useAppContext, useYaMetrika, YM_GOALS } from '@msb/shared';
import { FormSpy, Form } from 'react-final-form';
import { DOCUMENTS_FILTER_VALUES, LOCALIZATION } from '../constants';
import * as S from './ProductsFilters.styles';
import { useFetchedFilters } from '@/entities/filters';
import { BUTTON_CLICK, SCREEN_NAME } from '@/shared/constants';
import { useFiltersContext } from '@/shared/lib';
import { useSelectMaxWidth } from '@/widgets/Products/ui/ProductsFilters/lib';
@@ -20,7 +21,7 @@ const ProductsFilters = (): ReactElement => {
const { organizations } = useAppContext();
const { fetchedFilters } = useFetchedFilters();
const { filters, updateFilter } = useFiltersContext();
const { handleReachGoal } = useYaMetrika();
const wrapperRef = useRef<HTMLDivElement>(null);
const formRef = useRef<any>(null);
@@ -43,10 +44,13 @@ const ProductsFilters = (): ReactElement => {
const handleChange = useCallback(
values => {
if (!isEqual(values, filters)) {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME.DEPOSITS_PRODUCTS]: { element_name: BUTTON_CLICK.ELEMENT_NAME.FILTER } },
});
updateFilter(values.values);
}
},
[filters, updateFilter]
[filters, updateFilter, handleReachGoal]
);
const EmptyFn = useCallback(() => {}, []);
@@ -5,11 +5,11 @@ import { Informer } from '@fractal-ui/extended';
import type { TabOption } from '@msb/fractal-ui-composites';
import { Tabs } from '@msb/fractal-ui-composites';
import type { FetchNextPageOptions, InfiniteQueryObserverResult, ProductsResponseDto } from '@msb/http';
import { pluralize, REQUEST, SystemResponseStatus, UNCONFIRMED } from '@msb/shared';
import { allTab, confirmationTab, violatedTab, LOCALIZATION } from '../constants';
import { pluralize, REQUEST, SystemResponseStatus, UNCONFIRMED, useYaMetrika, YM_GOALS } from '@msb/shared';
import { allTab, confirmationTab, violatedTab, LOCALIZATION, TabsOptions } from '../constants';
import type { TreasuryDealsFilters } from '../constants';
import * as S from './Products.styles';
import { PATHS } from '@/shared/constants';
import { PATHS, SCREEN_NAME } from '@/shared/constants';
import { useFiltersContext } from '@/shared/lib';
import { PageLayout, PageHeader } from '@/shared/ui';
import { ProductTable } from '@/widgets/ProductTable';
@@ -60,7 +60,18 @@ const ProductsTableContent = ({
const [currentTab, setCurrentTab] = useState<string>('0');
const [tabs, setTabs] = useState<TabOption[]>([allTab]);
const tabHandleChange = (tab: string) => setCurrentTab(tab);
const { handleReachGoal } = useYaMetrika();
const tabHandleChange = (tab: string) => {
const tabElementName = TabsOptions.find(option => option.value === tab)?.elementName;
if (tabElementName) {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME.DEPOSITS_PRODUCTS]: { element_name: tabElementName } },
});
}
setCurrentTab(tab);
};
const [didAutoSelect, setDidAutoSelect] = useState(false);
@@ -0,0 +1,11 @@
import { DOC_TYPES } from '@msb/shared';
import { SCREEN_NAME } from '@/shared/constants';
const SCREEN_NAME_MATCHER: Record<DOC_TYPES, string> = {
[DOC_TYPES.DEPOSIT]: SCREEN_NAME.DEPOSIT_CANCEL,
[DOC_TYPES.MNO]: SCREEN_NAME.MNO_CANCEL,
[DOC_TYPES.GSNO]: SCREEN_NAME.GSNO_CANCEL,
[DOC_TYPES.OVERNIGHT]: SCREEN_NAME.DEPOSIT_CANCEL,
};
export { SCREEN_NAME_MATCHER };
@@ -1,2 +1,3 @@
export * from './localization';
export * from './endpoints';
export * from './constants';
@@ -2,12 +2,14 @@ import { useEffect } from 'react';
import { Button } from '@fractal-ui/core';
import { openSignModal } from '@msb/crypto';
import type { CancelDocumentDto } from '@msb/http';
import { useModal, BaseDialog, useRedirect, PATHS, PATHS_DEPOSITS } from '@msb/shared';
import { LOCALIZATION } from '../constants';
import type { DOC_TYPES } from '@msb/shared';
import { useModal, BaseDialog, useRedirect, PATHS, PATHS_DEPOSITS, useYaMetrika, YM_GOALS } from '@msb/shared';
import { LOCALIZATION, SCREEN_NAME_MATCHER } from '../constants';
import { useSignCancelDocuments } from './useSignCancelDocuments';
import { BUTTON_CLICK, SCREEN_VIEW } from '@/shared/constants';
interface SignCancelDocumentsProps {
docType: string;
docType: DOC_TYPES;
cancelDocument: CancelDocumentDto;
clientId: string;
timeExpired: boolean;
@@ -17,11 +19,16 @@ interface SignCancelDocumentsProps {
const SignCancelDocuments = ({ docType, clientId, cancelDocument, timeExpired, fields }: SignCancelDocumentsProps) => {
const { signData, signService } = useSignCancelDocuments(cancelDocument, docType, fields, clientId);
const { showModal, hideModal } = useModal(BaseDialog);
const { handleReachGoal } = useYaMetrika();
const toDeposits = useRedirect(PATHS_DEPOSITS.PRODUCTS);
const toMain = useRedirect(PATHS.HOME);
const handleClick = async () => {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME_MATCHER[docType]]: { element_name: BUTTON_CLICK.ELEMENT_NAME.SIGN } },
});
if (signData) {
try {
const response = await openSignModal({
@@ -34,6 +41,7 @@ const SignCancelDocuments = ({ docType, clientId, cancelDocument, timeExpired, f
console.log(response);
if (response.signedDocs.length > 0) {
handleReachGoal(YM_GOALS.SCREEN_VIEW, { [YM_GOALS.SCREEN_VIEW]: { screen_name: SCREEN_VIEW.SUCCESS.DOCUMENT_CANCEL[docType] } });
await showModal({
header: LOCALIZATION.MODAL_HEADER,
message: LOCALIZATION.MODAL_MESSAGE,
@@ -0,0 +1,11 @@
import { DOC_TYPES } from '@msb/shared';
import { SCREEN_NAME } from '@/shared/constants';
const SCREEN_NAME_MATCHER: Record<DOC_TYPES, string> = {
[DOC_TYPES.DEPOSIT]: SCREEN_NAME.DEPOSIT_CONFIRM,
[DOC_TYPES.MNO]: SCREEN_NAME.MNO_CONFIRM,
[DOC_TYPES.GSNO]: SCREEN_NAME.GSNO_CONFIRM,
[DOC_TYPES.OVERNIGHT]: SCREEN_NAME.DEPOSIT_CONFIRM,
};
export { SCREEN_NAME_MATCHER };
@@ -1 +1,2 @@
export * from './localization';
export * from './constants';
@@ -11,8 +11,9 @@ import type {
import { useTreasuryDealsI18n } from '@msb/http';
import type { AccountDetails } from '@msb/http/model';
import type { DOC_TYPES } from '@msb/shared';
import { PATHS, useRedirect, BaseDialog, useModal } from '@msb/shared';
import { LOCALIZATION } from '../constants';
import { PATHS, useRedirect, BaseDialog, useModal, useYaMetrika, YM_GOALS } from '@msb/shared';
import { LOCALIZATION, SCREEN_NAME_MATCHER } from '../constants';
import { BUTTON_CLICK } from '@/shared/constants';
import { handleSign } from '@/widgets/SignConfirmation/lib';
interface AccountsDetailsWrapper {
@@ -33,6 +34,7 @@ interface SignConfirmationProps {
}
const SignConfirmation = (props: SignConfirmationProps) => {
const { handleReachGoal } = useYaMetrika();
const { showModal } = useModal(BaseDialog);
const toDeposits = useRedirect(PATHS.DEPOSITS);
const toMain = useRedirect(PATHS.HOME);
@@ -40,6 +42,10 @@ const SignConfirmation = (props: SignConfirmationProps) => {
const { treasuryDealsI18nData } = useTreasuryDealsI18n();
const handleClick = async () => {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME_MATCHER[docType]]: { element_name: BUTTON_CLICK.ELEMENT_NAME.SIGN } },
});
const form = formRef.current;
await form.submit();
@@ -2,10 +2,10 @@ import { useCallback } from 'react';
import { Button } from '@fractal-ui/core';
import { openSignModal } from '@msb/crypto';
import type { BankAccount, DocumentData } from '@msb/http';
import { BaseDialog, useModal, useRedirect, PATHS as GLOBAL_PATHS } from '@msb/shared';
import { BaseDialog, useModal, useRedirect, PATHS as GLOBAL_PATHS, useYaMetrika, YM_GOALS } from '@msb/shared';
import { LOCALIZATION } from '../constants';
import { useSignEarlyRefund } from './useSignEarlyRefund';
import { PATHS } from '@/shared/constants';
import { BUTTON_CLICK, PATHS, SCREEN_NAME, SCREEN_VIEW } from '@/shared/constants';
interface SignEarlyRefundProps {
currentAccount: BankAccount;
@@ -17,11 +17,16 @@ interface SignEarlyRefundProps {
const SignEarlyRefund = ({ clientId, currentAccount, refundDocument, fields }: SignEarlyRefundProps) => {
const { signService, signData } = useSignEarlyRefund(clientId, currentAccount, refundDocument, fields);
const { showModal } = useModal(BaseDialog);
const { handleReachGoal } = useYaMetrika();
const toDeposits = useRedirect(GLOBAL_PATHS.DEPOSITS);
const toMain = useRedirect(GLOBAL_PATHS.HOME);
const handleClick = useCallback(async () => {
handleReachGoal(YM_GOALS.BUTTON_CLICK, {
[YM_GOALS.BUTTON_CLICK]: { [SCREEN_NAME.DEPOSIT_EARLY_REFUND]: { element_name: BUTTON_CLICK.ELEMENT_NAME.SIGN } },
});
if (signData) {
const response = await openSignModal({
type: 'single',
@@ -36,6 +41,7 @@ const SignEarlyRefund = ({ clientId, currentAccount, refundDocument, fields }: S
});
if (response.signedDocs.length > 0) {
handleReachGoal(YM_GOALS.SCREEN_VIEW, { [YM_GOALS.SCREEN_VIEW]: { screen_name: SCREEN_VIEW.SUCCESS.EARLY_REFUND } });
await showModal({
header: LOCALIZATION.MODAL_HEADER,
message: LOCALIZATION.MODAL_MESSAGE,
@@ -49,7 +55,7 @@ const SignEarlyRefund = ({ clientId, currentAccount, refundDocument, fields }: S
return response;
}
}
}, [showModal, signData, signService, toDeposits, toMain]);
}, [showModal, signData, signService, toDeposits, toMain, handleReachGoal]);
return (
<Button dataAction="sign-and-send" shape="default" size="M" variant="primary" onClick={handleClick}>