Merge branch 'story/TEAMMSBMOB-24034_ghost-banners' into 'develop'

feat(TEAMMSBMOB-24290): фикс дпп баннера призрака и карусели продуктов

See merge request MCB_FE/mcb-platform-monorepo!4046
This commit is contained in:
Ильдар Смышляев
2026-04-24 09:30:39 +00:00
8 changed files with 43 additions and 18 deletions
@@ -31,7 +31,7 @@
"gradient": "sale1",
"imageUrl": "",
"isECO": true,
"pressLink": "/cash",
"pressLink": "/credit-cabinet/msb/products/9c54ee32-c126-4d67-ad0b-ffd945faa5a9?uid={id}",
"adv": {
"name": "Romashka",
"inn": "1245124851",
@@ -397,7 +397,7 @@
"name": "product_for_you_mainpage_10",
"typeBanner": "productForYou",
"spaceCode": "mainPageIB",
"priority": 6,
"priority": 1,
"description": "Products for you carousel banner #10",
"toggles": ["productForYouIBMSB"],
"imageUrl": "",
@@ -406,7 +406,7 @@
"subtitle": "Advantage of the week",
"gradient": "sale11",
"imageUrl": "",
"pressLink": "https://google.com",
"pressLink": "www.google.com",
"adv": {
"name": "Romashka",
"inn": "1245124851",
+3 -1
View File
@@ -1,6 +1,8 @@
/* eslint-disable unicorn/better-regex */
const EXTERNAL_URL_REGEXP = /^https?:\/\//;
const WWW_DOMAIN_URL_REGEXP = /^www\./;
const ENG_LETTERS_AND_DIGITS_REGEXP = /^[a-zA-Z0-9]+$/;
const DIGITS_REGEXP = /^\d+$/;
const RUSSIAN_LETTERS_REGEXP = /^[а-яёА-ЯЁ]+$/;
export { EXTERNAL_URL_REGEXP, DIGITS_REGEXP, RUSSIAN_LETTERS_REGEXP, ENG_LETTERS_AND_DIGITS_REGEXP };
export { EXTERNAL_URL_REGEXP, DIGITS_REGEXP, RUSSIAN_LETTERS_REGEXP, ENG_LETTERS_AND_DIGITS_REGEXP, WWW_DOMAIN_URL_REGEXP };
@@ -0,0 +1,3 @@
const HREF_QUERY_UID_KEY = 'uid';
export { HREF_QUERY_UID_KEY };
@@ -1,3 +1,4 @@
export * from './storages';
export * from './localization';
export * from './sizes';
export * from './constants';
@@ -4,7 +4,7 @@ import { MEDIA } from '../../../../constants';
import { useAppContext } from '../../../../context';
import { useImageItemsLoader, useMediaQuery } from '../../../../lib';
import type { YmPage } from '../../../../yandex-metrika';
import { BANNER_WIDTH, MIN_NUM_SCROLLING_ELEMENTS, SMALL_BANNER_WIDTH, SMALL_MOBILE_MEDIA } from '../../constants';
import { BANNER_WIDTH, HREF_QUERY_UID_KEY, MIN_NUM_SCROLLING_ELEMENTS, SMALL_BANNER_WIDTH, SMALL_MOBILE_MEDIA } from '../../constants';
import { useShowBanners } from '../../model';
import type { BannerItemDto } from '../../model';
import { StaticBanner } from '../StaticBanner';
@@ -33,7 +33,6 @@ const GhostBanners = ({ banners, carouselOnMobile = true, page }: Props): ReactE
const renderBanner = (banner: (typeof loadedImageItems)[number]) => {
const uid = organizations?.[0]?.externalClientGuid;
const isExpressWarranty = banner.codeName === 'ghost_banners_bank_guarantees_application';
return (
<StaticBanner
@@ -41,7 +40,7 @@ const GhostBanners = ({ banners, carouselOnMobile = true, page }: Props): ReactE
dealType={banner.dealType}
description={banner.description}
gradient={banner.gradient}
href={isExpressWarranty && uid ? `${banner.href}&uid=${uid}` : banner.href}
href={uid ? banner.href.replace(`${HREF_QUERY_UID_KEY}={id}`, `${HREF_QUERY_UID_KEY}=${uid}`) : banner.href}
imagePath={banner.imagePath}
isEco={banner.isEco}
isMobile={isMobile}
@@ -42,7 +42,6 @@ const StaticBanner: FC<Props> = ({
ymSpaceCode,
closeYmCode,
dealType,
page,
isEco,
}) => {
const { handleReachGoal } = useYaMetrika();
@@ -92,7 +91,7 @@ const StaticBanner: FC<Props> = ({
<CrossIcon color="control.bg" size="XS" />
</S.CloseIconBox>
<S.Image src={imagePath} />
<TrackedElement goalParams={{ [page]: { element_name: ymCode } }} />
<TrackedElement goalParams={{ [ymSpaceCode]: { element_name: ymCode } }} />
</S.StaticBannerBox>
);
};
@@ -1,4 +1,4 @@
import { AdvertisingBadge, ECO_CLIENT_ENDPOINT, EXTERNAL_URL_REGEXP, useYaMetrika, YM_GOALS } from '@msb/shared';
import { AdvertisingBadge, ECO_CLIENT_ENDPOINT, EXTERNAL_URL_REGEXP, useYaMetrika, WWW_DOMAIN_URL_REGEXP, YM_GOALS } from '@msb/shared';
import { useHistory } from 'react-router-dom';
import type { ProductAd } from '../model';
import * as S from './ProductAdSlide.styles';
@@ -14,19 +14,40 @@ const ProductAdSlide = ({ productAd }: Props) => {
const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
const targetLinkOpen = '_blank';
const featuresLinkOpen = 'noopener,noreferrer';
if (productAd.ymCode && productAd.ymSpaceCode) {
handleReachGoal(YM_GOALS.BUTTON_CLICK, { [YM_GOALS.BUTTON_CLICK]: { [productAd.ymSpaceCode]: { element_name: productAd.ymCode } } });
}
if (productAd.isEcoPath) {
window.open(`${ECO_CLIENT_ENDPOINT}${productAd.navigatePath}`, '_blank', 'noopener,noreferrer');
} else if (productAd.navigateDocType) {
history.push(productAd.navigatePath, { docType: productAd.navigateDocType });
} else if (EXTERNAL_URL_REGEXP.test(productAd.navigatePath)) {
window.open(productAd.navigatePath, '_blank', 'noopener,noreferrer');
} else {
history.push(productAd.navigatePath);
window.open(`${ECO_CLIENT_ENDPOINT}${productAd.navigatePath}`, targetLinkOpen, featuresLinkOpen);
return;
}
if (productAd.navigateDocType) {
history.push(productAd.navigatePath, { docType: productAd.navigateDocType });
return;
}
if (EXTERNAL_URL_REGEXP.test(productAd.navigatePath)) {
window.open(productAd.navigatePath, targetLinkOpen, featuresLinkOpen);
return;
}
if (WWW_DOMAIN_URL_REGEXP.test(productAd.navigatePath)) {
const finalPath = `https://${productAd.navigatePath}`;
window.open(finalPath, targetLinkOpen, featuresLinkOpen);
return;
}
history.push(productAd.navigatePath);
};
if (productAd.isGift) {
@@ -66,7 +66,7 @@ const ProductCarousel = () => {
return (
<S.SlideWrapper key={product.id} $isFirst={index === 0} $isLast={index === loadedImageItems.length - 1}>
<TrackedElement goalParams={{ main_page: { element_name: product.ymCode } }}>
<TrackedElement goalParams={{ [product.ymSpaceCode || 'main_page']: { element_name: product.ymCode } }}>
<ProductAdSlide productAd={product} />
</TrackedElement>
</S.SlideWrapper>