From 7b6f435b99a8d92e8fd4134f19bc2396b939a0bf Mon Sep 17 00:00:00 2001 From: Max <133934232+Kleostro@users.noreply.github.com> Date: Mon, 10 Jun 2024 09:11:19 +0300 Subject: [PATCH 1/2] refactor: put methods for search parameters into separate helper functions --- src/app/Router/helpers/helpers.ts | 9 +++++++ src/app/Router/model/RouterModel.ts | 38 +++++++++-------------------- 2 files changed, 20 insertions(+), 27 deletions(-) create mode 100644 src/app/Router/helpers/helpers.ts diff --git a/src/app/Router/helpers/helpers.ts b/src/app/Router/helpers/helpers.ts new file mode 100644 index 00000000..25450c1e --- /dev/null +++ b/src/app/Router/helpers/helpers.ts @@ -0,0 +1,9 @@ +export const remove = (url: URL, key: string | string[]): void => { + if (Array.isArray(key)) { + key.forEach((k) => url.searchParams.delete(k)); + } else { + url.searchParams.delete(key); + } +}; +export const append = (url: URL, key: string, value: string): void => url.searchParams.append(key, value); +export const set = (url: URL, key: string, value: string): void => url.searchParams.set(key, value); diff --git a/src/app/Router/model/RouterModel.ts b/src/app/Router/model/RouterModel.ts index 9f3117fb..72d1a88f 100644 --- a/src/app/Router/model/RouterModel.ts +++ b/src/app/Router/model/RouterModel.ts @@ -45,13 +45,13 @@ class RouterModel { return; } - this.handleRequest(currentPage, currentPath); + this.handleRequest(currentPage, currentPath).catch(showErrorMessage); }); } - public static appendSearchParams(key: string, value: string): void { + public static changeSearchParams(callback: (url: URL) => void): void { const url = new URL(decodeURIComponent(window.location.href)); - url.searchParams.append(key, value); + callback(url); const path = url.pathname + url.search.toString(); window.history.pushState({ path: path.slice(NEXT_SEGMENT) }, '', path); } @@ -62,13 +62,6 @@ class RouterModel { window.history.pushState({ path: path.slice(NEXT_SEGMENT) }, '', path); } - public static deleteSearchParams(key: string): void { - const url = new URL(decodeURIComponent(window.location.href)); - url.searchParams.delete(key); - const path = url.pathname + url.search.toString(); - window.history.pushState({ path: path.slice(NEXT_SEGMENT) }, '', path); - } - public static getCurrentPage(): string { return window.location.pathname.slice(PATH_SEGMENTS_TO_KEEP).split(DEFAULT_SEGMENT)[NEXT_SEGMENT]; } @@ -98,14 +91,6 @@ class RouterModel { return new URL(decodeURIComponent(window.location.href)).searchParams; } - public static setSearchParams(key: string, value: string): void { - const url = new URL(decodeURIComponent(window.location.href)); - url.searchParams.delete(key); - url.searchParams.set(key, value); - const path = url.pathname + url.search.toString(); - window.history.pushState({ path: path.slice(NEXT_SEGMENT) }, '', path); - } - private async checkPageAndParams(currentPage: string, path: string): Promise { const hasRoute = this.routes.has(currentPage); @@ -120,14 +105,13 @@ class RouterModel { return hasRoute; } - private handleRequest(currentPage: string, path: string): void { - this.checkPageAndParams(currentPage, path) - .then((check) => { - if (check) { - this.routes.get(currentPage)?.().catch(showErrorMessage); - } - }) - .catch(showErrorMessage); + private async handleRequest(currentPage: string, path: string): Promise { + try { + await this.checkPageAndParams(currentPage, path); + this.routes.get(currentPage)?.().catch(showErrorMessage); + } catch (error) { + showErrorMessage(error); + } } public navigateTo(path: string): void { @@ -136,7 +120,7 @@ class RouterModel { PAGE_ID.DEFAULT_PAGE; if (currentPage !== getStore().getState().currentPage || currentPage === PAGE_ID.DEFAULT_PAGE) { - this.handleRequest(currentPage, path); + this.handleRequest(currentPage, path).catch(showErrorMessage); } history.pushState({ path }, '', `/${path}`); } From 42cf9943fb17fe9f61ca672de15f1cefb537f641 Mon Sep 17 00:00:00 2001 From: Max <133934232+Kleostro@users.noreply.github.com> Date: Mon, 10 Jun 2024 09:11:57 +0300 Subject: [PATCH 2/2] refactor: use key instead of id to display categories in URL --- .../model/ProductModalSliderModel.ts | 11 ++- .../ProductFilters/view/ProductFiltersView.ts | 86 +++++++++++-------- .../ProductSearch/model/ProductSearchModel.ts | 7 +- .../ProductSorts/view/ProductSortsView.ts | 11 ++- .../ProductPage/model/ProductPageModel.ts | 4 +- src/widgets/Catalog/model/CatalogModel.ts | 42 ++++++--- src/widgets/Footer/model/FooterModel.ts | 2 +- src/widgets/Header/view/HeaderView.ts | 13 +-- .../ProductInfo/model/ProductInfoModel.ts | 16 ++-- .../ProductInfo/view/productInfoView.scss | 1 + 10 files changed, 118 insertions(+), 75 deletions(-) diff --git a/src/entities/ProductModalSlider/model/ProductModalSliderModel.ts b/src/entities/ProductModalSlider/model/ProductModalSliderModel.ts index 4809d93e..cc98b2e3 100644 --- a/src/entities/ProductModalSlider/model/ProductModalSliderModel.ts +++ b/src/entities/ProductModalSlider/model/ProductModalSliderModel.ts @@ -1,5 +1,6 @@ import type { ProductInfoParams } from '@/shared/types/product.ts'; +import { set } from '@/app/Router/helpers/helpers.ts'; import RouterModel from '@/app/Router/model/RouterModel.ts'; import { SEARCH_PARAMS_FIELD } from '@/shared/constants/product.ts'; import Swiper from 'swiper'; @@ -53,9 +54,9 @@ class ProductModalSliderModel { const slideInSearch = Number(RouterModel.getSearchParams().get(SEARCH_PARAMS_FIELD.SLIDE)); if (slideInSearch < this.view.getModalSliderSlides().length) { - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.SLIDE, String(slideInSearch + 1)); + RouterModel.changeSearchParams((url) => set(url, SEARCH_PARAMS_FIELD.SLIDE, String(slideInSearch + 1))); } else { - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.SLIDE, String(1)); + RouterModel.changeSearchParams((url) => set(url, SEARCH_PARAMS_FIELD.SLIDE, String(1))); } }); } @@ -66,9 +67,11 @@ class ProductModalSliderModel { const slideInSearch = Number(RouterModel.getSearchParams().get(SEARCH_PARAMS_FIELD.SLIDE)); if (slideInSearch > 1) { - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.SLIDE, String(slideInSearch - 1)); + RouterModel.changeSearchParams((url) => set(url, SEARCH_PARAMS_FIELD.SLIDE, String(slideInSearch - 1))); } else { - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.SLIDE, String(this.view.getModalSliderSlides().length)); + RouterModel.changeSearchParams((url) => + set(url, SEARCH_PARAMS_FIELD.SLIDE, String(this.view.getModalSliderSlides().length)), + ); } }); } diff --git a/src/features/ProductFilters/view/ProductFiltersView.ts b/src/features/ProductFilters/view/ProductFiltersView.ts index 07369f99..050bf871 100644 --- a/src/features/ProductFilters/view/ProductFiltersView.ts +++ b/src/features/ProductFilters/view/ProductFiltersView.ts @@ -2,6 +2,7 @@ import type { SizeProductCount } from '@/shared/API/types/type'; import type { Category } from '@/shared/types/product'; import type ProductFiltersParams from '@/shared/types/productFilters'; +import { append, remove, set } from '@/app/Router/helpers/helpers.ts'; import RouterModel from '@/app/Router/model/RouterModel.ts'; import ButtonModel from '@/shared/Button/model/ButtonModel.ts'; import EventMediatorModel from '@/shared/EventMediator/model/EventMediatorModel.ts'; @@ -14,6 +15,7 @@ import { AUTOCOMPLETE_OPTION, LANGUAGE_CHOICE } from '@/shared/constants/common. import MEDIATOR_EVENT from '@/shared/constants/events.ts'; import { META_FILTERS, META_FILTERS_ID, PRICE_RANGE_LABEL, TITLE } from '@/shared/constants/filters.ts'; import { INPUT_TYPE } from '@/shared/constants/forms.ts'; +import { PAGE_ID } from '@/shared/constants/pages.ts'; import { SEARCH_PARAMS_FIELD } from '@/shared/constants/product.ts'; import createBaseElement from '@/shared/utils/createBaseElement.ts'; import * as noUiSlider from 'nouislider'; @@ -66,16 +68,17 @@ class ProductFiltersView { private categoryClickHandler(parentCategory: { category: Category; count: number } | null): void { const searchParams = RouterModel.getSearchParams(); - if ( - searchParams.has(SEARCH_PARAMS_FIELD.CATEGORY) && - searchParams.get(SEARCH_PARAMS_FIELD.CATEGORY) === parentCategory?.category.parent?.id - ) { - RouterModel.deleteSearchParams(SEARCH_PARAMS_FIELD.CATEGORY); - } else { - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.CATEGORY, parentCategory?.category.parent?.id ?? ''); - } - - RouterModel.deleteSearchParams(SEARCH_PARAMS_FIELD.PAGE); + const handleCategoryChange = (url: URL, key: string, value: string): void => { + if (searchParams.has(key) && searchParams.get(key) === value) { + remove(url, key); + } else { + set(url, key, value); + } + }; + RouterModel.changeSearchParams((url) => { + handleCategoryChange(url, SEARCH_PARAMS_FIELD.CATEGORY, parentCategory?.category.parent?.key ?? ''); + remove(url, SEARCH_PARAMS_FIELD.PAGE); + }); this.callback(); } @@ -132,7 +135,7 @@ class ProductFiltersView { const span = createBaseElement({ attributes: { - id: category.category.id, + id: category.category.key, }, cssClasses: [styles.categoryLinkCount], innerContent, @@ -264,8 +267,10 @@ class ProductFiltersView { link.getHTML().addEventListener('click', (event) => { event.preventDefault(); - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.META, id); - RouterModel.deleteSearchParams(SEARCH_PARAMS_FIELD.PAGE); + RouterModel.changeSearchParams((url) => { + set(url, SEARCH_PARAMS_FIELD.META, id); + remove(url, SEARCH_PARAMS_FIELD.PAGE); + }); this.metaLinks.forEach((link) => this.switchSelectedFilter(link, false)); this.switchSelectedFilter(link, true); this.callback(); @@ -335,10 +340,11 @@ class ProductFiltersView { const [min, max] = values; this.priceInputs.get(PRICE_RANGE_LABEL[getStore().getState().currentLanguage].FROM)?.setValue(String(min)); this.priceInputs.get(PRICE_RANGE_LABEL[getStore().getState().currentLanguage].TO)?.setValue(String(max)); - RouterModel.deleteSearchParams(SEARCH_PARAMS_FIELD.MIN_PRICE); - RouterModel.deleteSearchParams(SEARCH_PARAMS_FIELD.MAX_PRICE); - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.MIN_PRICE, String(min)); - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.MAX_PRICE, String(max)); + RouterModel.changeSearchParams((url) => { + remove(url, [SEARCH_PARAMS_FIELD.MIN_PRICE, SEARCH_PARAMS_FIELD.MAX_PRICE]); + set(url, SEARCH_PARAMS_FIELD.MIN_PRICE, String(min)); + set(url, SEARCH_PARAMS_FIELD.MAX_PRICE, String(max)); + }); this.callback(); }); @@ -394,7 +400,7 @@ class ProductFiltersView { } }); - RouterModel.clearSearchParams(); + RouterModel.getInstance().navigateTo(PAGE_ID.CATALOG_PAGE); EventMediatorModel.getInstance().notify(MEDIATOR_EVENT.CLEAR_CATALOG_SEARCH, ''); this.callback(); }); @@ -418,8 +424,10 @@ class ProductFiltersView { sizeLink.getHTML().addEventListener('click', (event) => { event.preventDefault(); - RouterModel.deleteSearchParams(SEARCH_PARAMS_FIELD.PAGE); - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.SIZE, size.size); + RouterModel.changeSearchParams((url) => { + remove(url, SEARCH_PARAMS_FIELD.PAGE); + set(url, SEARCH_PARAMS_FIELD.SIZE, size.size); + }); this.sizeLinks.forEach((link) => this.switchSelectedFilter(link, false)); this.switchSelectedFilter(sizeLink, true); this.callback(); @@ -516,7 +524,7 @@ class ProductFiltersView { private redrawProductsCount(): void { this.params?.categoriesProductCount?.forEach((categoryCount) => { - const currentSpan = this.categoryCountSpan.find((span) => span.id === categoryCount.category.id) ?? null; + const currentSpan = this.categoryCountSpan.find((span) => span.id === categoryCount.category.key) ?? null; if (currentSpan) { currentSpan.innerText = `(${categoryCount.count})`; } @@ -539,30 +547,32 @@ class ProductFiltersView { } private subcategoryClickHandler(subcategory: { category: Category; count: number }): void { - const currentSubcategories = RouterModel.getSearchParams().getAll(SEARCH_PARAMS_FIELD.SUBCATEGORY); - const currentSubcategory = currentSubcategories?.find((id) => id === subcategory.category.id); - const currentLink = this.categoryLinks.find((link) => link.getHTML().id === subcategory.category.id); - RouterModel.deleteSearchParams(SEARCH_PARAMS_FIELD.PAGE); + const subcategories = RouterModel.getSearchParams().getAll(SEARCH_PARAMS_FIELD.SUBCATEGORY); + const currentSubcategory = subcategories?.find((key) => key === subcategory.category.key); + const currentLink = this.categoryLinks.find((link) => link.getHTML().id === subcategory.category.key); + RouterModel.changeSearchParams((url) => remove(url, SEARCH_PARAMS_FIELD.PAGE)); if (currentSubcategory) { - const filteredSubcategories = currentSubcategories.filter((id) => id !== currentSubcategory); - if (!filteredSubcategories.length) { - RouterModel.deleteSearchParams(SEARCH_PARAMS_FIELD.SUBCATEGORY); + const filteredSubcategory = subcategories.filter((key) => key !== currentSubcategory); + if (!filteredSubcategory.length) { + RouterModel.changeSearchParams((url) => remove(url, SEARCH_PARAMS_FIELD.SUBCATEGORY)); if (currentLink) { this.switchSelectedFilter(currentLink, false); } } else { - RouterModel.deleteSearchParams(SEARCH_PARAMS_FIELD.SUBCATEGORY); - filteredSubcategories.forEach((id) => RouterModel.appendSearchParams(SEARCH_PARAMS_FIELD.SUBCATEGORY, id)); - filteredSubcategories.forEach((id) => { - const currentLink = this.categoryLinks.find((link) => link.getHTML().id === id); + RouterModel.changeSearchParams((url) => remove(url, SEARCH_PARAMS_FIELD.SUBCATEGORY)); + filteredSubcategory.forEach((key) => + RouterModel.changeSearchParams((url) => append(url, SEARCH_PARAMS_FIELD.SUBCATEGORY, key)), + ); + filteredSubcategory.forEach((key) => { + const currentLink = this.categoryLinks.find((link) => link.getHTML().id === key); if (currentLink) { this.switchSelectedFilter(currentLink, true); } }); } } else { - RouterModel.appendSearchParams(SEARCH_PARAMS_FIELD.SUBCATEGORY, subcategory.category.id); + RouterModel.changeSearchParams((url) => append(url, SEARCH_PARAMS_FIELD.SUBCATEGORY, subcategory.category.key)); if (currentLink) { this.switchSelectedFilter(currentLink, true); } @@ -584,8 +594,10 @@ class ProductFiltersView { } private updateSelectedPrice(from: InputModel | null = null, to: InputModel | null = null): void { - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.MIN_PRICE, from?.getValue() ?? '0'); - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.MAX_PRICE, to?.getValue() ?? '0'); + RouterModel.changeSearchParams((url) => { + set(url, SEARCH_PARAMS_FIELD.MIN_PRICE, from?.getValue() ?? '0'); + set(url, SEARCH_PARAMS_FIELD.MAX_PRICE, to?.getValue() ?? '0'); + }); this.callback(); } @@ -630,8 +642,8 @@ class ProductFiltersView { this.categoryLinks.forEach((link) => this.switchSelectedFilter(link, false)); this.metaLinks.forEach((link) => this.switchSelectedFilter(link, false)); - activeFilters.categoryLinks.forEach((id) => { - const currentLink = this.categoryLinks.find((link) => link.getHTML().id === id); + activeFilters.categoryLinks.forEach((key) => { + const currentLink = this.categoryLinks.find((link) => link.getHTML().id === key); if (currentLink) { this.switchSelectedFilter(currentLink, true); } diff --git a/src/features/ProductSearch/model/ProductSearchModel.ts b/src/features/ProductSearch/model/ProductSearchModel.ts index faae9a5f..7b5d1115 100644 --- a/src/features/ProductSearch/model/ProductSearchModel.ts +++ b/src/features/ProductSearch/model/ProductSearchModel.ts @@ -1,3 +1,4 @@ +import { remove, set } from '@/app/Router/helpers/helpers.ts'; import RouterModel from '@/app/Router/model/RouterModel.ts'; import EventMediatorModel from '@/shared/EventMediator/model/EventMediatorModel.ts'; import MEDIATOR_EVENT from '@/shared/constants/events.ts'; @@ -19,8 +20,10 @@ class ProductSearchModel { } private handleSearchInput(): void { - RouterModel.deleteSearchParams(SEARCH_PARAMS_FIELD.PAGE); - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.SEARCH, this.view.getSearchField().getValue()); + RouterModel.changeSearchParams((url) => { + remove(url, SEARCH_PARAMS_FIELD.PAGE); + set(url, SEARCH_PARAMS_FIELD.SEARCH, this.view.getSearchField().getValue()); + }); this.callback(); } diff --git a/src/features/ProductSorts/view/ProductSortsView.ts b/src/features/ProductSorts/view/ProductSortsView.ts index 0f2fedce..d225fcb6 100644 --- a/src/features/ProductSorts/view/ProductSortsView.ts +++ b/src/features/ProductSorts/view/ProductSortsView.ts @@ -1,3 +1,4 @@ +import { set } from '@/app/Router/helpers/helpers.ts'; import RouterModel from '@/app/Router/model/RouterModel.ts'; import { SortDirection } from '@/shared/API/types/type.ts'; import LinkModel from '@/shared/Link/model/LinkModel.ts'; @@ -99,12 +100,10 @@ class ProductSortsView { link.getHTML().classList.add(styles.activeLink); this.currentSortingSpan.innerText = text; - - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.FIELD, link.getHTML().id); - RouterModel.setSearchParams( - SEARCH_PARAMS_FIELD.DIRECTION, - String(link.getHTML().getAttribute(DATA_KEYS.DIRECTION)), - ); + RouterModel.changeSearchParams((url) => { + set(url, SEARCH_PARAMS_FIELD.FIELD, link.getHTML().id); + set(url, SEARCH_PARAMS_FIELD.DIRECTION, String(link.getHTML().getAttribute(DATA_KEYS.DIRECTION))); + }); this.callback(); }); diff --git a/src/pages/ProductPage/model/ProductPageModel.ts b/src/pages/ProductPage/model/ProductPageModel.ts index 686a0eda..ab692ec6 100644 --- a/src/pages/ProductPage/model/ProductPageModel.ts +++ b/src/pages/ProductPage/model/ProductPageModel.ts @@ -44,14 +44,14 @@ class ProductPageModel implements Page { if (category) { links.push({ - link: buildPath.catalogPathWithQuery({ category: [category.id] }), + link: buildPath.catalogPathWithQuery({ category: [category.key] }), name: category.name[Number(isRuLanguage)].value, }); } if (subcategory && category) { links.push({ - link: buildPath.catalogPathWithQuery({ subcategory: [subcategory.id] }), + link: buildPath.catalogPathWithQuery({ subcategory: [subcategory.key] }), name: subcategory.name[Number(isRuLanguage)].value, }); } diff --git a/src/widgets/Catalog/model/CatalogModel.ts b/src/widgets/Catalog/model/CatalogModel.ts index af1d016b..781846ed 100644 --- a/src/widgets/Catalog/model/CatalogModel.ts +++ b/src/widgets/Catalog/model/CatalogModel.ts @@ -1,8 +1,10 @@ import type { OptionsRequest, SortOptions } from '@/shared/API/types/type.ts'; +import type { Category } from '@/shared/types/product.ts'; import type ProductFiltersParams from '@/shared/types/productFilters.ts'; import type { SelectedFilters } from '@/shared/types/productFilters.ts'; import type { SelectedSorting } from '@/shared/types/productSorting.ts'; +import { set } from '@/app/Router/helpers/helpers.ts'; import RouterModel from '@/app/Router/model/RouterModel.ts'; import ProductCardModel from '@/entities/ProductCard/model/ProductCardModel.ts'; import PaginationModel from '@/features/Pagination/model/PaginationModel.ts'; @@ -62,19 +64,22 @@ class CatalogModel { } } - private decodeSearchParams(): { + private async decodeSearchParams(): Promise<{ page: string; searchValue: null | string; selectedFilters: SelectedFilters; - selectedSorting?: SelectedSorting; - } | null { + selectedSorting?: SelectedSorting | undefined; + } | null> { if (RouterModel.getPageID()) { return null; } const searchParams = RouterModel.getSearchParams(); const searchCategory = searchParams.getAll(SEARCH_PARAMS_FIELD.CATEGORY); searchCategory.push(...searchParams.getAll(SEARCH_PARAMS_FIELD.SUBCATEGORY)); - const category = new Set(searchCategory); + const categorySetWithKey = new Set(searchCategory); + const categories = await getProductModel().getCategories(); + const categorySetWithID: Set = this.replaceCategoryKeyWithID(categories, categorySetWithKey); + const metaFilter = searchParams.get(SEARCH_PARAMS_FIELD.META) ?? META_FILTERS.en.ALL_PRODUCTS; const size = searchParams.get(SEARCH_PARAMS_FIELD.SIZE) ?? null; const price = { @@ -87,7 +92,7 @@ class CatalogModel { const searchValue = searchParams.get(SEARCH_PARAMS_FIELD.SEARCH) ?? null; const page = searchParams.get(SEARCH_PARAMS_FIELD.PAGE) ?? DEFAULT_PAGE.toString(); const selectedFilters = { - category, + category: categorySetWithID, metaFilter, price, size, @@ -105,7 +110,7 @@ class CatalogModel { this.productCards = []; const productList = this.view.getItemsList(); productList.innerHTML = ''; - const options = this.getOptions(); + const options = await this.getOptions(); const productsInfo = await this.getProductsInfo(options); this.paginationTop?.getHTML().remove(); this.paginationBottom?.getHTML().remove(); @@ -139,10 +144,10 @@ class CatalogModel { this.view.switchEmptyList(!productsInfo?.products?.length); } - private getOptions(): OptionsRequest { + private async getOptions(): Promise { let result = {}; - const params = this.decodeSearchParams(); + const params = await this.decodeSearchParams(); if (!params) { return {}; } @@ -170,14 +175,14 @@ class CatalogModel { result = { filter, page: Number(params.page), - search: { locale: currentLanguage, value: params.searchValue }, + search: params.searchValue ? { locale: currentLanguage, value: params.searchValue } : null, sort: currentSort ?? null, }; } else { result = { filter, page: Number(params.page), - search: { locale: currentLanguage, value: params.searchValue }, + search: params.searchValue ? { locale: currentLanguage, value: params.searchValue } : null, }; } @@ -258,8 +263,23 @@ class CatalogModel { } } + private replaceCategoryKeyWithID(categories: Category[], categorySet: Set): Set { + const categoriesWithID: Set = new Set(); + categories.forEach((category) => { + categorySet.forEach((item) => { + if (category.key === item) { + categoriesWithID.add(category.id); + } else if (category.parent?.key === item) { + categoriesWithID.add(category.parent.id); + } + }); + }); + + return categoriesWithID; + } + private setCurrentPage(page: string): void { - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.PAGE, page); + RouterModel.changeSearchParams((url) => set(url, SEARCH_PARAMS_FIELD.PAGE, page)); this.drawProducts().catch(showErrorMessage); } diff --git a/src/widgets/Footer/model/FooterModel.ts b/src/widgets/Footer/model/FooterModel.ts index df4e685d..962a94f3 100644 --- a/src/widgets/Footer/model/FooterModel.ts +++ b/src/widgets/Footer/model/FooterModel.ts @@ -92,7 +92,7 @@ function generateRandomCategoryLink(categoriesArr: Category[]): Link[] { const category = subCategory[randomIndex]; subCategory.splice(randomIndex, 1); result.push({ - href: buildPath.catalogPathWithQuery({ subcategory: [category.id] }), + href: buildPath.catalogPathWithQuery({ subcategory: [category.key] }), name: { en: category.name[0].value, ru: category.name[1].value, diff --git a/src/widgets/Header/view/HeaderView.ts b/src/widgets/Header/view/HeaderView.ts index 3087cbee..e7731beb 100644 --- a/src/widgets/Header/view/HeaderView.ts +++ b/src/widgets/Header/view/HeaderView.ts @@ -1,5 +1,6 @@ import type { LanguageChoiceType } from '@/shared/constants/common.ts'; +import RouterModel from '@/app/Router/model/RouterModel.ts'; import ButtonModel from '@/shared/Button/model/ButtonModel.ts'; import InputModel from '@/shared/Input/model/InputModel.ts'; import LinkModel from '@/shared/Link/model/LinkModel.ts'; @@ -271,12 +272,12 @@ class HeaderView { this.toCartLink .getHTML() - .classList.toggle(styles.cartLinkActive, getStore().getState().currentPage === PAGE_ID.CART_PAGE); + .classList.toggle(styles.cartLinkActive, RouterModel.getCurrentPage() === PAGE_ID.CART_PAGE); observeStore(selectCurrentPage, () => this.toCartLink .getHTML() - .classList.toggle(styles.cartLinkActive, getStore().getState().currentPage === PAGE_ID.CART_PAGE), + .classList.toggle(styles.cartLinkActive, RouterModel.getCurrentPage() === PAGE_ID.CART_PAGE), ); return this.toCartLink; @@ -304,12 +305,12 @@ class HeaderView { this.toProfileLink .getHTML() - .classList.toggle(styles.profileLinkActive, getStore().getState().currentPage === PAGE_ID.USER_PROFILE_PAGE); + .classList.toggle(styles.profileLinkActive, RouterModel.getCurrentPage() === PAGE_ID.USER_PROFILE_PAGE); observeStore(selectCurrentPage, () => this.toProfileLink .getHTML() - .classList.toggle(styles.profileLinkActive, getStore().getState().currentPage === PAGE_ID.USER_PROFILE_PAGE), + .classList.toggle(styles.profileLinkActive, RouterModel.getCurrentPage() === PAGE_ID.USER_PROFILE_PAGE), ); return this.toProfileLink; @@ -330,12 +331,12 @@ class HeaderView { this.toWishlistLink .getHTML() - .classList.toggle(styles.cartLinkActive, getStore().getState().currentPage === PAGE_ID.WISHLIST_PAGE); + .classList.toggle(styles.cartLinkActive, RouterModel.getCurrentPage() === PAGE_ID.WISHLIST_PAGE); observeStore(selectCurrentPage, () => this.toWishlistLink .getHTML() - .classList.toggle(styles.cartLinkActive, getStore().getState().currentPage === PAGE_ID.WISHLIST_PAGE), + .classList.toggle(styles.cartLinkActive, RouterModel.getCurrentPage() === PAGE_ID.WISHLIST_PAGE), ); return this.toWishlistLink; diff --git a/src/widgets/ProductInfo/model/ProductInfoModel.ts b/src/widgets/ProductInfo/model/ProductInfoModel.ts index b89006a1..7ca03971 100644 --- a/src/widgets/ProductInfo/model/ProductInfoModel.ts +++ b/src/widgets/ProductInfo/model/ProductInfoModel.ts @@ -1,6 +1,7 @@ import type { Cart } from '@/shared/types/cart.ts'; import type { ProductInfoParams, Variant } from '@/shared/types/product.ts'; +import { set } from '@/app/Router/helpers/helpers.ts'; import RouterModel from '@/app/Router/model/RouterModel.ts'; import ProductModalSliderModel from '@/entities/ProductModalSlider/model/ProductModalSliderModel.ts'; import ProductPriceModel from '@/entities/ProductPrice/model/ProductPriceModel.ts'; @@ -146,9 +147,9 @@ class ProductInfoModel { const slideInSearch = Number(RouterModel.getSearchParams().get(SEARCH_PARAMS_FIELD.SLIDE)); if (slideInSearch < this.view.getSliderSlides().length) { - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.SLIDE, String(slideInSearch + 1)); + RouterModel.changeSearchParams((url) => set(url, SEARCH_PARAMS_FIELD.SLIDE, String(slideInSearch + 1))); } else { - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.SLIDE, String(1)); + RouterModel.changeSearchParams((url) => set(url, SEARCH_PARAMS_FIELD.SLIDE, String(1))); } }); } @@ -159,9 +160,11 @@ class ProductInfoModel { const slideInSearch = Number(RouterModel.getSearchParams().get(SEARCH_PARAMS_FIELD.SLIDE)); if (slideInSearch > 1) { - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.SLIDE, String(slideInSearch - 1)); + RouterModel.changeSearchParams((url) => set(url, SEARCH_PARAMS_FIELD.SLIDE, String(slideInSearch - 1))); } else { - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.SLIDE, String(this.view.getSliderSlides().length)); + RouterModel.changeSearchParams((url) => + set(url, SEARCH_PARAMS_FIELD.SLIDE, String(this.view.getSliderSlides().length)), + ); } }); } @@ -186,8 +189,9 @@ class ProductInfoModel { private sliderHandler(): void { this.view.getSliderSlides().forEach((slide, index) => { slide.addEventListener('click', () => { - if (this.slider) { - RouterModel.setSearchParams(SEARCH_PARAMS_FIELD.SLIDE, String(this.slider.activeIndex + 1)); + const { slider } = this; + if (slider) { + RouterModel.changeSearchParams((url) => set(url, SEARCH_PARAMS_FIELD.SLIDE, String(slider.activeIndex + 1))); } const router = RouterModel.getInstance(); const modalSlider = new ProductModalSliderModel(this.params); diff --git a/src/widgets/ProductInfo/view/productInfoView.scss b/src/widgets/ProductInfo/view/productInfoView.scss index 5207c312..92af27d5 100644 --- a/src/widgets/ProductInfo/view/productInfoView.scss +++ b/src/widgets/ProductInfo/view/productInfoView.scss @@ -2,6 +2,7 @@ .wrapper { display: flex; + align-items: center; margin-bottom: var(--small-offset); gap: var(--small-offset);