From 1bbf115bb0510d845d51b39e84501441cfefd190 Mon Sep 17 00:00:00 2001 From: Graham Rogers Date: Mon, 23 Sep 2024 16:45:30 -0600 Subject: [PATCH] format with prettier --- .eslintrc.cjs | 4 +- babel.config.js | 48 +- babelrc.js | 40 +- docs/MSRCH-4696.md | 6 +- jest.config.js | 50 +- src/api/fragments.ts | 6 +- src/api/graphql.ts | 29 +- src/api/mutations.ts | 21 +- src/api/queries.ts | 26 +- src/api/search.ts | 344 ++++--- .../AddToCartButton/AddToCartButton.test.tsx | 28 +- src/components/AddToCartButton/index.ts | 4 +- src/components/Alert/index.ts | 4 +- .../Breadcrumbs/Breadcrumbs.test.tsx | 18 +- src/components/Breadcrumbs/MockPages.ts | 6 +- src/components/Breadcrumbs/index.ts | 4 +- .../ButtonShimmer/ButtonShimmer.tsx | 18 +- src/components/ButtonShimmer/index.ts | 4 +- .../CategoryFilters/CategoryFilters.test.tsx | 40 +- .../CategoryFilters/CategoryFilters.tsx | 102 +- src/components/CategoryFilters/index.tsx | 2 +- src/components/Facets/Facets.tsx | 73 +- .../Facets/Range/RangeFacet.test.tsx | 18 +- src/components/Facets/Range/RangeFacet.tsx | 40 +- .../Facets/Scalar/ScalarFacet.test.tsx | 18 +- src/components/Facets/Scalar/ScalarFacet.tsx | 36 +- src/components/Facets/SelectedFilters.tsx | 114 +-- src/components/Facets/format.ts | 74 +- src/components/Facets/index.ts | 10 +- src/components/Facets/mocks.tsx | 193 ++-- .../FacetsShimmer/FacetsShimmer.tsx | 40 +- src/components/FacetsShimmer/index.ts | 4 +- .../FilterButton/FilterButton.test.tsx | 30 +- src/components/FilterButton/index.ts | 4 +- src/components/ImageCarousel/Image.tsx | 64 +- .../ImageCarousel/ImageCarousel.test.tsx | 25 +- .../ImageCarousel/ImageCarousel.tsx | 202 ++-- src/components/ImageCarousel/index.ts | 4 +- .../InputButtonGroup.test.tsx | 46 +- .../InputButtonGroup/InputButtonGroup.tsx | 250 +++-- src/components/InputButtonGroup/index.ts | 4 +- .../LabelledInput/LabelledInput.test.tsx | 36 +- .../LabelledInput/LabelledInput.tsx | 86 +- src/components/LabelledInput/index.ts | 4 +- src/components/Loading/Loading.test.tsx | 40 +- src/components/Loading/index.ts | 4 +- src/components/NoResults/NoResults.test.tsx | 18 +- src/components/NoResults/NoResults.tsx | 90 +- src/components/NoResults/index.ts | 4 +- src/components/Pagination/Pagination.test.tsx | 18 +- src/components/Pagination/index.ts | 2 +- .../PerPagePicker/PerPagePicker.test.tsx | 26 +- src/components/PerPagePicker/index.ts | 4 +- src/components/Pill/Pill.test.tsx | 16 +- src/components/Pill/index.ts | 4 +- src/components/Pill/mock.tsx | 24 +- .../ProductCardShimmer/ProductCardShimmer.tsx | 26 +- src/components/ProductCardShimmer/index.ts | 4 +- src/components/ProductItem/MockData.ts | 894 +++++++++--------- .../ProductItem/ProductItem.test.tsx | 56 +- src/components/ProductItem/ProductPrice.tsx | 308 +++--- src/components/ProductItem/index.ts | 4 +- src/components/ProductList/MockData.ts | 320 ++++--- .../ProductList/ProductList.test.tsx | 18 +- src/components/ProductList/ProductList.tsx | 202 ++-- src/components/ProductList/index.ts | 4 +- src/components/SearchBar/SearchBar.test.tsx | 18 +- src/components/SearchBar/SearchBar.tsx | 44 +- src/components/SearchBar/index.ts | 4 +- src/components/Shimmer/Shimmer.tsx | 96 +- src/components/Shimmer/index.ts | 4 +- src/components/Slider/Slider.test.tsx | 72 +- src/components/Slider/Slider.tsx | 165 ++-- src/components/Slider/index.tsx | 4 +- .../SliderDoubleControl.test.tsx | 74 +- .../SliderDoubleControl.tsx | 501 +++++----- src/components/SliderDoubleControl/index.tsx | 4 +- .../SortDropdown/SortDropdown.test.tsx | 30 +- src/components/SortDropdown/index.ts | 4 +- .../SwatchButton/SwatchButton.test.tsx | 28 +- src/components/SwatchButton/SwatchButton.tsx | 111 +-- src/components/SwatchButton/index.ts | 4 +- .../SwatchButtonGroup.test.tsx | 86 +- .../SwatchButtonGroup/SwatchButtonGroup.tsx | 138 +-- src/components/SwatchButtonGroup/index.ts | 4 +- src/components/ViewSwitcher/index.ts | 4 +- .../WishlistButton/WishlistButton.test.tsx | 20 +- .../WishlistButton/WishlistButton.tsx | 107 +-- src/components/WishlistButton/index.ts | 4 +- src/components/index.ts | 6 +- src/components/mocks.tsx | 173 ++-- src/containers/App.tsx | 236 +++-- src/containers/ProductListingPage.tsx | 96 +- src/containers/ProductsContainer.tsx | 241 +++-- src/containers/ProductsHeader.tsx | 194 ++-- src/context/attributeMetadata.tsx | 83 +- src/context/cart.tsx | 126 ++- src/context/displayChange.tsx | 104 +- src/context/events.tsx | 258 +++-- src/context/index.ts | 20 +- src/context/products.tsx | 693 +++++++------- src/context/search.tsx | 264 +++--- src/context/store.tsx | 135 ++- src/context/translation.tsx | 168 ++-- src/context/widgetConfig.tsx | 208 ++-- src/context/wishlist.tsx | 164 ++-- src/hooks/useAccessibleDropdown.ts | 254 +++-- src/hooks/usePagination.ts | 98 +- src/hooks/useRangeFacet.ts | 85 +- src/hooks/useScalarFacet.ts | 104 +- src/hooks/useSliderFacet.ts | 58 +- src/i18n/Sorani.ts | 97 +- src/i18n/ar_AE.ts | 97 +- src/i18n/bg_BG.ts | 97 +- src/i18n/bn_IN.ts | 98 +- src/i18n/ca_ES.ts | 97 +- src/i18n/cs_CZ.ts | 97 +- src/i18n/da_DK.ts | 97 +- src/i18n/de_DE.ts | 97 +- src/i18n/el_GR.ts | 97 +- src/i18n/en_GA.ts | 97 +- src/i18n/en_GB.ts | 97 +- src/i18n/en_US.ts | 117 ++- src/i18n/es_ES.ts | 97 +- src/i18n/et_EE.ts | 97 +- src/i18n/eu_ES.ts | 97 +- src/i18n/fa_IR.ts | 98 +- src/i18n/fi_FI.ts | 97 +- src/i18n/fr_FR.ts | 98 +- src/i18n/gl_ES.ts | 97 +- src/i18n/hi_IN.ts | 97 +- src/i18n/hu_HU.ts | 97 +- src/i18n/hy_AM.ts | 97 +- src/i18n/id_ID.ts | 97 +- src/i18n/index.ts | 156 +-- src/i18n/it_IT.ts | 97 +- src/i18n/ja_JP.ts | 97 +- src/i18n/ko_KR.ts | 97 +- src/i18n/lt_LT.ts | 97 +- src/i18n/lv_LV.ts | 97 +- src/i18n/nb_NO.ts | 97 +- src/i18n/nl_NL.ts | 97 +- src/i18n/pt_BR.ts | 97 +- src/i18n/pt_PT.ts | 97 +- src/i18n/ro_RO.ts | 97 +- src/i18n/ru_RU.ts | 97 +- src/i18n/sv_SE.ts | 97 +- src/i18n/th_TH.ts | 97 +- src/i18n/tr_TR.ts | 97 +- src/i18n/zh_Hans_CN.ts | 97 +- src/i18n/zh_Hant_TW.ts | 97 +- src/index.tsx | 100 +- src/main.tsx | 10 +- src/types/custom.d.ts | 30 +- src/types/globals.d.ts | 28 +- src/types/interface.ts | 624 ++++++------ src/types/widget.ts | 94 +- src/utils/constants.ts | 24 +- src/utils/decodeHtmlString.ts | 4 +- src/utils/dom.ts | 4 +- src/utils/getProductImage.ts | 136 ++- src/utils/getProductPrice.ts | 82 +- src/utils/getUserViewHistory.ts | 27 +- src/utils/handleUrlFilters.ts | 233 +++-- src/utils/htmlStringDecode.ts | 4 +- src/utils/sort.ts | 132 ++- src/utils/tests/translations.test.ts | 107 +-- src/utils/tests/utils.test.ts | 239 +++-- src/utils/useIntersectionObserver.ts | 41 +- src/utils/validateStoreDetails.ts | 63 +- storybook-stories.js | 10 +- tsconfig.app.json | 52 +- tsconfig.json | 5 +- vite.config.ts | 20 +- webpack.common.js | 190 ++-- webpack.dev.js | 46 +- webpack.prod.js | 40 +- 177 files changed, 7615 insertions(+), 8251 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 5c53edb..5040ab2 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -82,7 +82,7 @@ module.exports = { "node_modules", "dist", "config", - "**/*.test.ts", - "**/*.test.tsx" + // "**/*.test.ts", + // "**/*.test.tsx" ], }; diff --git a/babel.config.js b/babel.config.js index eeebfd8..1b21964 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,29 +1,29 @@ module.exports = { - presets: [ - [ - '@babel/preset-env', - { - modules: false, - targets: { - browsers: ['last 2 versions'], - }, - }, + presets: [ + [ + "@babel/preset-env", + { + modules: false, + targets: { + browsers: ["last 2 versions"], + }, + }, + ], + ["@babel/preset-typescript", { jsxPragma: "h" }], ], - ['@babel/preset-typescript', { jsxPragma: 'h' }], - ], - plugins: [ - ['babel-plugin-tsconfig-paths'], - [ - '@babel/plugin-transform-react-jsx', - { - runtime: 'automatic', - importSource: 'preact', - }, + plugins: [ + ["babel-plugin-tsconfig-paths"], + [ + "@babel/plugin-transform-react-jsx", + { + runtime: "automatic", + importSource: "preact", + }, + ], ], - ], - env: { - test: { - plugins: ['dynamic-import-node', 'istanbul'], + env: { + test: { + plugins: ["dynamic-import-node", "istanbul"], + }, }, - }, }; diff --git a/babelrc.js b/babelrc.js index e5a08b6..db46b3b 100644 --- a/babelrc.js +++ b/babelrc.js @@ -1,24 +1,24 @@ -const plugins = ['babel-plugin-istanbul']; +const plugins = ["babel-plugin-istanbul"]; module.exports = { - presets: [ - [ - '@babel/preset-env', - { - useBuiltIns: 'usage', // alternative mode: "entry" - corejs: 3, // default would be 2 - targets: '> 0.25%, not dead', - // set your own target environment here (see Browserslist) - }, + presets: [ + [ + "@babel/preset-env", + { + useBuiltIns: "usage", // alternative mode: "entry" + corejs: 3, // default would be 2 + targets: "> 0.25%, not dead", + // set your own target environment here (see Browserslist) + }, + ], + "@babel/typescript", + [ + "@babel/preset-react", + { + development: true, + }, + ], ], - '@babel/typescript', - [ - '@babel/preset-react', - { - development: true, - }, - ], - ], - plugins, - babelrc: false, + plugins, + babelrc: false, }; diff --git a/docs/MSRCH-4696.md b/docs/MSRCH-4696.md index 7ef8053..3d5ce8c 100644 --- a/docs/MSRCH-4696.md +++ b/docs/MSRCH-4696.md @@ -1,5 +1,5 @@ # Highlights -- Using vite instead of webpack for better DX -- Vite builds LiveSearchPLP widget in library mode for easier reusabliity -- Consistant organization of types +- Using vite instead of webpack for better DX +- Vite builds LiveSearchPLP widget in library mode for easier reusabliity +- Consistant organization of types diff --git a/jest.config.js b/jest.config.js index b6e1b55..57a1d10 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,31 +1,31 @@ const config = { - preset: 'jest-preset-preact', + preset: "jest-preset-preact", - roots: ['/src'], - clearMocks: true, - testEnvironment: 'jsdom', - moduleFileExtensions: ['ts', 'tsx', 'js'], - setupFilesAfterEnv: ['@testing-library/jest-dom', 'jest-styled-components'], - transform: { - '^.+\\.tsx?$': 'ts-jest', - '^.+\\.svg$': 'jest-transformer-svg', - }, - moduleDirectories: ['/src', 'node_modules'], - moduleNameMapper: { - '\\.(css|less)$': 'identity-obj-proxy', - '^components(.*)$': '/src/components$1', - '^styles(.*)$': '/src/styles$1', - '^utils(.*)$': '/src/utils$1', + roots: ["/src"], + clearMocks: true, + testEnvironment: "jsdom", + moduleFileExtensions: ["ts", "tsx", "js"], + setupFilesAfterEnv: ["@testing-library/jest-dom", "jest-styled-components"], + transform: { + "^.+\\.tsx?$": "ts-jest", + "^.+\\.svg$": "jest-transformer-svg", + }, + moduleDirectories: ["/src", "node_modules"], + moduleNameMapper: { + "\\.(css|less)$": "identity-obj-proxy", + "^components(.*)$": "/src/components$1", + "^styles(.*)$": "/src/styles$1", + "^utils(.*)$": "/src/utils$1", - // Add aliases here ---> "^alias(.*)$": "/src/alias-path$1", <--- - }, - testPathIgnorePatterns: ['/src/components/Facets'], - globals: { - API_URL: '', - TEST_URL: '', - API_KEY: '', - SANDBOX_KEY: '', - }, + // Add aliases here ---> "^alias(.*)$": "/src/alias-path$1", <--- + }, + testPathIgnorePatterns: ["/src/components/Facets"], + globals: { + API_URL: "", + TEST_URL: "", + API_KEY: "", + SANDBOX_KEY: "", + }, }; module.exports = config; diff --git a/src/api/fragments.ts b/src/api/fragments.ts index 27d6e61..7c2fe48 100644 --- a/src/api/fragments.ts +++ b/src/api/fragments.ts @@ -7,7 +7,7 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -const Facet = ` +const Facet = /* GraphQL */` fragment Facet on Aggregation { title attribute @@ -35,7 +35,7 @@ const Facet = ` } `; -const ProductView = ` +const ProductView = /* GraphQL */` fragment ProductView on ProductSearchItem { productView { __typename @@ -119,7 +119,7 @@ const ProductView = ` } `; -const Product = ` +const Product = /* GraphQL */` fragment Product on ProductSearchItem { product { __typename diff --git a/src/api/graphql.ts b/src/api/graphql.ts index d62f990..2951ae6 100644 --- a/src/api/graphql.ts +++ b/src/api/graphql.ts @@ -1,22 +1,15 @@ -async function getGraphQL( - query = '', - variables = {}, - store = '', - baseUrl = '' -) { - const graphqlEndpoint = baseUrl - ? `${baseUrl}/graphql` - : `${window.origin}/graphql`; - const response = await fetch(graphqlEndpoint, { - method: 'POST', - headers: { 'Content-Type': 'application/json', Store: store }, - body: JSON.stringify({ - query, - variables, - }), - }).then((res) => res.json()); +async function getGraphQL(query = "", variables = {}, store = "", baseUrl = "") { + const graphqlEndpoint = baseUrl ? `${baseUrl}/graphql` : `${window.origin}/graphql`; + const response = await fetch(graphqlEndpoint, { + method: "POST", + headers: { "Content-Type": "application/json", Store: store }, + body: JSON.stringify({ + query, + variables, + }), + }).then((res) => res.json()); - return response; + return response; } export { getGraphQL }; diff --git a/src/api/mutations.ts b/src/api/mutations.ts index ad1cce0..03df1c0 100644 --- a/src/api/mutations.ts +++ b/src/api/mutations.ts @@ -1,10 +1,10 @@ -const CREATE_EMPTY_CART = ` - mutation createEmptyCart($input: createEmptyCartInput) { - createEmptyCart(input: $input) - } +const CREATE_EMPTY_CART = /* GraphQL */` + mutation createEmptyCart($input: createEmptyCartInput) { + createEmptyCart(input: $input) + } `; -const ADD_TO_CART = ` +const ADD_TO_CART = /* GraphQL */` mutation addProductsToCart( $cartId: String! $cartItems: [CartItemInput!]! @@ -30,7 +30,7 @@ const ADD_TO_CART = ` } `; -const ADD_TO_WISHLIST = ` +const ADD_TO_WISHLIST = /* GraphQL */` mutation addProductsToWishlist( $wishlistId: ID! $wishlistItems: [WishlistItemInput!]! @@ -58,7 +58,7 @@ const ADD_TO_WISHLIST = ` } `; -const REMOVE_FROM_WISHLIST = ` +const REMOVE_FROM_WISHLIST = /* GraphQL */` mutation removeProductsFromWishlist ( $wishlistId: ID! $wishlistItemsIds: [ID!]! @@ -86,9 +86,4 @@ const REMOVE_FROM_WISHLIST = ` } `; -export { - CREATE_EMPTY_CART, - ADD_TO_CART, - ADD_TO_WISHLIST, - REMOVE_FROM_WISHLIST, -}; +export { CREATE_EMPTY_CART, ADD_TO_CART, ADD_TO_WISHLIST, REMOVE_FROM_WISHLIST }; diff --git a/src/api/queries.ts b/src/api/queries.ts index a166d4e..7dbfe8a 100644 --- a/src/api/queries.ts +++ b/src/api/queries.ts @@ -7,9 +7,9 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { Facet, Product, ProductView } from './fragments'; +import { Facet, Product, ProductView } from "./fragments"; -const ATTRIBUTE_METADATA_QUERY = ` +const ATTRIBUTE_METADATA_QUERY = /* GraphQL */` query attributeMetadata { attributeMetadata { sortable { @@ -26,7 +26,7 @@ const ATTRIBUTE_METADATA_QUERY = ` } `; -const QUICK_SEARCH_QUERY = ` +const QUICK_SEARCH_QUERY = /* GraphQL */` query quickSearch( $phrase: String! $pageSize: Int = 20 @@ -57,7 +57,7 @@ const QUICK_SEARCH_QUERY = ` ${Product} `; -const PRODUCT_SEARCH_QUERY = ` +const PRODUCT_SEARCH_QUERY = /* GraphQL */` query productSearch( $phrase: String! $pageSize: Int @@ -101,7 +101,7 @@ const PRODUCT_SEARCH_QUERY = ` ${Facet} `; -const REFINE_PRODUCT_QUERY = ` +const REFINE_PRODUCT_QUERY = /* GraphQL */` query refineProduct( $optionIds: [String!]! $sku: String! @@ -177,7 +177,7 @@ const REFINE_PRODUCT_QUERY = ` } `; -const GET_CUSTOMER_CART = ` +const GET_CUSTOMER_CART = /* GraphQL */` query customerCart { customerCart { id @@ -193,7 +193,7 @@ const GET_CUSTOMER_CART = ` } `; -const GET_CUSTOMER_WISHLISTS = ` +const GET_CUSTOMER_WISHLISTS = /* GraphQL */` query customer { customer { wishlists { @@ -216,10 +216,10 @@ const GET_CUSTOMER_WISHLISTS = ` `; export { - ATTRIBUTE_METADATA_QUERY, - PRODUCT_SEARCH_QUERY, - QUICK_SEARCH_QUERY, - REFINE_PRODUCT_QUERY, - GET_CUSTOMER_CART, - GET_CUSTOMER_WISHLISTS, + ATTRIBUTE_METADATA_QUERY, + PRODUCT_SEARCH_QUERY, + QUICK_SEARCH_QUERY, + REFINE_PRODUCT_QUERY, + GET_CUSTOMER_CART, + GET_CUSTOMER_WISHLISTS, }; diff --git a/src/api/search.ts b/src/api/search.ts index c221648..c531229 100644 --- a/src/api/search.ts +++ b/src/api/search.ts @@ -7,217 +7,197 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { v4 as uuidv4 } from 'uuid'; +import { v4 as uuidv4 } from "uuid"; -import { updateSearchInputCtx, updateSearchResultsCtx } from '../context'; +import { updateSearchInputCtx, updateSearchResultsCtx } from "../context"; import { - AttributeMetadataResponse, - ClientProps, - MagentoHeaders, - ProductSearchQuery, - ProductSearchResponse, - RefinedProduct, - RefineProductQuery, -} from '../types/interface'; -import { SEARCH_UNIT_ID } from '../utils/constants'; -import { - ATTRIBUTE_METADATA_QUERY, - PRODUCT_SEARCH_QUERY, - REFINE_PRODUCT_QUERY, -} from './queries'; + AttributeMetadataResponse, + ClientProps, + MagentoHeaders, + ProductSearchQuery, + ProductSearchResponse, + RefinedProduct, + RefineProductQuery, +} from "../types/interface"; +import { SEARCH_UNIT_ID } from "../utils/constants"; +import { ATTRIBUTE_METADATA_QUERY, PRODUCT_SEARCH_QUERY, REFINE_PRODUCT_QUERY } from "./queries"; const getHeaders = (headers: MagentoHeaders) => { - return { - 'Magento-Environment-Id': headers.environmentId, - 'Magento-Website-Code': headers.websiteCode, - 'Magento-Store-Code': headers.storeCode, - 'Magento-Store-View-Code': headers.storeViewCode, - 'X-Api-Key': headers.apiKey, - 'X-Request-Id': headers.xRequestId, - 'Content-Type': 'application/json', - 'Magento-Customer-Group': headers.customerGroup, - }; + return { + "Magento-Environment-Id": headers.environmentId, + "Magento-Website-Code": headers.websiteCode, + "Magento-Store-Code": headers.storeCode, + "Magento-Store-View-Code": headers.storeViewCode, + "X-Api-Key": headers.apiKey, + "X-Request-Id": headers.xRequestId, + "Content-Type": "application/json", + "Magento-Customer-Group": headers.customerGroup, + }; }; const getProductSearch = async ({ - environmentId, - websiteCode, - storeCode, - storeViewCode, - apiKey, - apiUrl, - phrase, - pageSize = 24, - displayOutOfStock, - currentPage = 1, - xRequestId = uuidv4(), - filter = [], - sort = [], - context, - categorySearch = false, -}: ProductSearchQuery & ClientProps): Promise< - ProductSearchResponse['data'] -> => { - const variables = { - phrase, - pageSize, - currentPage, - filter, - sort, - context, - }; - - // default filters if search is "catalog (category)" or "search" - let searchType = 'Search'; - if (categorySearch) { - searchType = 'Catalog'; - } - const defaultFilters = { - attribute: 'visibility', - in: [searchType, 'Catalog, Search'], - }; - - variables.filter.push(defaultFilters); //add default visibility filter - - const displayInStockOnly = displayOutOfStock != '1'; // '!=' is intentional for conversion - - const inStockFilter = { - attribute: 'inStock', - eq: 'true', - }; - - if (displayInStockOnly) { - variables.filter.push(inStockFilter); - } - - const headers = getHeaders({ environmentId, websiteCode, storeCode, storeViewCode, apiKey, - xRequestId, - customerGroup: context?.customerGroup ?? '', - }); - - // ====== initialize data collection ===== - const searchRequestId = uuidv4(); - - updateSearchInputCtx( - SEARCH_UNIT_ID, - searchRequestId, + apiUrl, phrase, - filter, - pageSize, - currentPage, - sort - ); - - const magentoStorefrontEvtPublish = window.magentoStorefrontEvents?.publish; - - magentoStorefrontEvtPublish?.searchRequestSent && - magentoStorefrontEvtPublish.searchRequestSent(SEARCH_UNIT_ID); - // ====== end of data collection ===== - - const response = await fetch(apiUrl, { - method: 'POST', - headers, - body: JSON.stringify({ - query: PRODUCT_SEARCH_QUERY, - variables: { ...variables }, - }), - }); - - const results = await response.json(); - // ====== initialize data collection ===== - updateSearchResultsCtx( - SEARCH_UNIT_ID, - searchRequestId, - results?.data?.productSearch - ); - - magentoStorefrontEvtPublish?.searchResponseReceived && - magentoStorefrontEvtPublish.searchResponseReceived(SEARCH_UNIT_ID); - - if (categorySearch) { - magentoStorefrontEvtPublish?.categoryResultsView && - magentoStorefrontEvtPublish.categoryResultsView(SEARCH_UNIT_ID); - } else { - magentoStorefrontEvtPublish?.searchResultsView && - magentoStorefrontEvtPublish.searchResultsView(SEARCH_UNIT_ID); - } - // ====== end of data collection ===== - - return results?.data; + pageSize = 24, + displayOutOfStock, + currentPage = 1, + xRequestId = uuidv4(), + filter = [], + sort = [], + context, + categorySearch = false, +}: ProductSearchQuery & ClientProps): Promise => { + const variables = { + phrase, + pageSize, + currentPage, + filter, + sort, + context, + }; + + // default filters if search is "catalog (category)" or "search" + let searchType = "Search"; + if (categorySearch) { + searchType = "Catalog"; + } + const defaultFilters = { + attribute: "visibility", + in: [searchType, "Catalog, Search"], + }; + + variables.filter.push(defaultFilters); //add default visibility filter + + const displayInStockOnly = displayOutOfStock != "1"; // '!=' is intentional for conversion + + const inStockFilter = { + attribute: "inStock", + eq: "true", + }; + + if (displayInStockOnly) { + variables.filter.push(inStockFilter); + } + + const headers = getHeaders({ + environmentId, + websiteCode, + storeCode, + storeViewCode, + apiKey, + xRequestId, + customerGroup: context?.customerGroup ?? "", + }); + + // ====== initialize data collection ===== + const searchRequestId = uuidv4(); + + updateSearchInputCtx(SEARCH_UNIT_ID, searchRequestId, phrase, filter, pageSize, currentPage, sort); + + const magentoStorefrontEvtPublish = window.magentoStorefrontEvents?.publish; + + magentoStorefrontEvtPublish?.searchRequestSent && magentoStorefrontEvtPublish.searchRequestSent(SEARCH_UNIT_ID); + // ====== end of data collection ===== + + const response = await fetch(apiUrl, { + method: "POST", + headers, + body: JSON.stringify({ + query: PRODUCT_SEARCH_QUERY, + variables: { ...variables }, + }), + }); + + const results = await response.json(); + // ====== initialize data collection ===== + updateSearchResultsCtx(SEARCH_UNIT_ID, searchRequestId, results?.data?.productSearch); + + magentoStorefrontEvtPublish?.searchResponseReceived && + magentoStorefrontEvtPublish.searchResponseReceived(SEARCH_UNIT_ID); + + if (categorySearch) { + magentoStorefrontEvtPublish?.categoryResultsView && + magentoStorefrontEvtPublish.categoryResultsView(SEARCH_UNIT_ID); + } else { + magentoStorefrontEvtPublish?.searchResultsView && magentoStorefrontEvtPublish.searchResultsView(SEARCH_UNIT_ID); + } + // ====== end of data collection ===== + + return results?.data; }; const getAttributeMetadata = async ({ - environmentId, - websiteCode, - storeCode, - storeViewCode, - apiKey, - apiUrl, - xRequestId = uuidv4(), -}: ClientProps): Promise => { - const headers = getHeaders({ environmentId, websiteCode, storeCode, storeViewCode, apiKey, - xRequestId, - customerGroup: '', - }); - - const response = await fetch(apiUrl, { - method: 'POST', - headers, - body: JSON.stringify({ - query: ATTRIBUTE_METADATA_QUERY, - }), - }); - const results = await response.json(); - return results?.data; + apiUrl, + xRequestId = uuidv4(), +}: ClientProps): Promise => { + const headers = getHeaders({ + environmentId, + websiteCode, + storeCode, + storeViewCode, + apiKey, + xRequestId, + customerGroup: "", + }); + + const response = await fetch(apiUrl, { + method: "POST", + headers, + body: JSON.stringify({ + query: ATTRIBUTE_METADATA_QUERY, + }), + }); + const results = await response.json(); + return results?.data; }; const refineProductSearch = async ({ - environmentId, - websiteCode, - storeCode, - storeViewCode, - apiKey, - apiUrl, - xRequestId = uuidv4(), - context, - optionIds, - sku, -}: RefineProductQuery & ClientProps): Promise => { - const variables = { - optionIds, - sku, - }; - - const headers = getHeaders({ environmentId, websiteCode, storeCode, storeViewCode, apiKey, - xRequestId, - customerGroup: context?.customerGroup ?? '', - }); - - const response = await fetch(apiUrl, { - method: 'POST', - headers, - body: JSON.stringify({ - query: REFINE_PRODUCT_QUERY, - variables: { ...variables }, - }), - }); - const results = await response.json(); - return results?.data; + apiUrl, + xRequestId = uuidv4(), + context, + optionIds, + sku, +}: RefineProductQuery & ClientProps): Promise => { + const variables = { + optionIds, + sku, + }; + + const headers = getHeaders({ + environmentId, + websiteCode, + storeCode, + storeViewCode, + apiKey, + xRequestId, + customerGroup: context?.customerGroup ?? "", + }); + + const response = await fetch(apiUrl, { + method: "POST", + headers, + body: JSON.stringify({ + query: REFINE_PRODUCT_QUERY, + variables: { ...variables }, + }), + }); + const results = await response.json(); + return results?.data; }; export { getAttributeMetadata, getProductSearch, refineProductSearch }; diff --git a/src/components/AddToCartButton/AddToCartButton.test.tsx b/src/components/AddToCartButton/AddToCartButton.test.tsx index 3606d1e..85c34f1 100644 --- a/src/components/AddToCartButton/AddToCartButton.test.tsx +++ b/src/components/AddToCartButton/AddToCartButton.test.tsx @@ -7,22 +7,22 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { AddToCartButton } from './AddToCartButton'; +import { AddToCartButton } from "./AddToCartButton"; -describe('WidgetSDK - UIKit/AddToCartButton', () => { - test('renders', () => { - const { container } = render( - { - return; - }} - /> - ); +describe("WidgetSDK - UIKit/AddToCartButton", () => { + test("renders", () => { + const { container } = render( + { + return; + }} + />, + ); - const elem = container.querySelector('.ds-sdk-add-to-cart-button'); + const elem = container.querySelector(".ds-sdk-add-to-cart-button"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/AddToCartButton/index.ts b/src/components/AddToCartButton/index.ts index eed7538..ac78031 100644 --- a/src/components/AddToCartButton/index.ts +++ b/src/components/AddToCartButton/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './AddToCartButton'; -export { AddToCartButton as default } from './AddToCartButton'; +export * from "./AddToCartButton"; +export { AddToCartButton as default } from "./AddToCartButton"; diff --git a/src/components/Alert/index.ts b/src/components/Alert/index.ts index 42e633d..187d31f 100644 --- a/src/components/Alert/index.ts +++ b/src/components/Alert/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './Alert'; -export { Alert as default } from './Alert'; +export * from "./Alert"; +export { Alert as default } from "./Alert"; diff --git a/src/components/Breadcrumbs/Breadcrumbs.test.tsx b/src/components/Breadcrumbs/Breadcrumbs.test.tsx index cbf7003..298554d 100644 --- a/src/components/Breadcrumbs/Breadcrumbs.test.tsx +++ b/src/components/Breadcrumbs/Breadcrumbs.test.tsx @@ -8,17 +8,17 @@ it. */ /// ; -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import Breadcrumbs from './Breadcrumbs'; -import { pages } from './MockPages'; +import Breadcrumbs from "./Breadcrumbs"; +import { pages } from "./MockPages"; -describe('WidgetSDK - UIKit/Breadcrumbs', () => { - it('renders', () => { - const { container } = render(); +describe("WidgetSDK - UIKit/Breadcrumbs", () => { + it("renders", () => { + const { container } = render(); - const elem = container.querySelector('.ds-sdk-breadcrumbs'); + const elem = container.querySelector(".ds-sdk-breadcrumbs"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/Breadcrumbs/MockPages.ts b/src/components/Breadcrumbs/MockPages.ts index ffdf377..2cf8d8d 100644 --- a/src/components/Breadcrumbs/MockPages.ts +++ b/src/components/Breadcrumbs/MockPages.ts @@ -8,7 +8,7 @@ it. */ export const pages = [ - { name: 'Category I', href: '#', current: false }, - { name: 'Category II', href: '#', current: false }, - { name: 'Category III', href: '#', current: true }, + { name: "Category I", href: "#", current: false }, + { name: "Category II", href: "#", current: false }, + { name: "Category III", href: "#", current: true }, ]; diff --git a/src/components/Breadcrumbs/index.ts b/src/components/Breadcrumbs/index.ts index 7cc8ca1..539cdae 100644 --- a/src/components/Breadcrumbs/index.ts +++ b/src/components/Breadcrumbs/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './Breadcrumbs'; -export { Breadcrumbs as default } from './Breadcrumbs'; +export * from "./Breadcrumbs"; +export { Breadcrumbs as default } from "./Breadcrumbs"; diff --git a/src/components/ButtonShimmer/ButtonShimmer.tsx b/src/components/ButtonShimmer/ButtonShimmer.tsx index ead9826..2f39fda 100644 --- a/src/components/ButtonShimmer/ButtonShimmer.tsx +++ b/src/components/ButtonShimmer/ButtonShimmer.tsx @@ -7,18 +7,18 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; -import '../ButtonShimmer/ButtonShimmer.css'; +import "../ButtonShimmer/ButtonShimmer.css"; export const ButtonShimmer: FunctionComponent = () => { - return ( - <> -
-
-
- - ); + return ( + <> +
+
+
+ + ); }; export default ButtonShimmer; diff --git a/src/components/ButtonShimmer/index.ts b/src/components/ButtonShimmer/index.ts index 42ac21f..a49b853 100644 --- a/src/components/ButtonShimmer/index.ts +++ b/src/components/ButtonShimmer/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './ButtonShimmer'; -export { ButtonShimmer as default } from './ButtonShimmer'; +export * from "./ButtonShimmer"; +export { ButtonShimmer as default } from "./ButtonShimmer"; diff --git a/src/components/CategoryFilters/CategoryFilters.test.tsx b/src/components/CategoryFilters/CategoryFilters.test.tsx index 717fa74..0836267 100644 --- a/src/components/CategoryFilters/CategoryFilters.test.tsx +++ b/src/components/CategoryFilters/CategoryFilters.test.tsx @@ -8,28 +8,28 @@ it. */ /// ; -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { CategoryFilters } from './CategoryFilters'; +import { CategoryFilters } from "./CategoryFilters"; -describe('PLP widget/CategoryFilters', () => { - it('renders', () => { - const { container } = render( - true} - filterCount={0} - /> - ); +describe("PLP widget/CategoryFilters", () => { + it("renders", () => { + const { container } = render( + true} + filterCount={0} + />, + ); - const elem = container.querySelector('.ds-widgets_actions_header'); + const elem = container.querySelector(".ds-widgets_actions_header"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/CategoryFilters/CategoryFilters.tsx b/src/components/CategoryFilters/CategoryFilters.tsx index c956da7..5bca645 100644 --- a/src/components/CategoryFilters/CategoryFilters.tsx +++ b/src/components/CategoryFilters/CategoryFilters.tsx @@ -7,65 +7,63 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; -import { useTranslation } from '../../context/translation'; -import { Facet } from '../../types/interface'; -import { Facets } from '../Facets'; -import { FilterButton } from '../FilterButton'; +import { useTranslation } from "../../context/translation"; +import { Facet } from "../../types/interface"; +import { Facets } from "../Facets"; +import { FilterButton } from "../FilterButton"; interface CategoryFiltersProps { - loading: boolean; - pageLoading: boolean; - totalCount: number; - facets: Facet[]; - categoryName: string; - phrase: string; - showFilters: boolean; - setShowFilters: (showFilters: boolean) => void; - filterCount: number; + loading: boolean; + pageLoading: boolean; + totalCount: number; + facets: Facet[]; + categoryName: string; + phrase: string; + showFilters: boolean; + setShowFilters: (showFilters: boolean) => void; + filterCount: number; } export const CategoryFilters: FunctionComponent = ({ - loading, - pageLoading, - totalCount, - facets, - categoryName, - phrase, - setShowFilters, - filterCount, + loading, + pageLoading, + totalCount, + facets, + categoryName, + phrase, + setShowFilters, + filterCount, }) => { - const translation = useTranslation(); - let title = categoryName || ''; - if (phrase) { - const text = translation.CategoryFilters.results; - title = text.replace('{phrase}', `"${phrase}"`); - } - const resultsTranslation = translation.CategoryFilters.products; - const results = resultsTranslation.replace('{totalCount}', `${totalCount}`); + const translation = useTranslation(); + let title = categoryName || ""; + if (phrase) { + const text = translation.CategoryFilters.results; + title = text.replace("{phrase}", `"${phrase}"`); + } + const resultsTranslation = translation.CategoryFilters.products; + const results = resultsTranslation.replace("{totalCount}", `${totalCount}`); - return ( -
-
- {title && {title}} - {!loading && {results}} -
+ return ( +
+
+ {title && {title}} + {!loading && {results}} +
- {!pageLoading && facets.length > 0 && ( - <> -
- setShowFilters(false)} - type="desktop" - title={`${translation.Filter.hideTitle}${ - filterCount > 0 ? ` (${filterCount})` : '' - }`} - /> -
- - - )} -
- ); + {!pageLoading && facets.length > 0 && ( + <> +
+ setShowFilters(false)} + type="desktop" + title={`${translation.Filter.hideTitle}${filterCount > 0 ? ` (${filterCount})` : ""}`} + /> +
+ + + )} +
+ ); }; diff --git a/src/components/CategoryFilters/index.tsx b/src/components/CategoryFilters/index.tsx index faaa9ce..0813e06 100644 --- a/src/components/CategoryFilters/index.tsx +++ b/src/components/CategoryFilters/index.tsx @@ -7,4 +7,4 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './CategoryFilters'; +export * from "./CategoryFilters"; diff --git a/src/components/Facets/Facets.tsx b/src/components/Facets/Facets.tsx index 88c747c..2d9c277 100644 --- a/src/components/Facets/Facets.tsx +++ b/src/components/Facets/Facets.tsx @@ -7,48 +7,43 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; -import { useStore } from '../../context'; -import { Facet as FacetType, PriceFacet } from '../../types/interface'; -import SliderDoubleControl from '../SliderDoubleControl'; -import { RangeFacet } from './Range/RangeFacet'; -import { ScalarFacet } from './Scalar/ScalarFacet'; +import { useStore } from "../../context"; +import { Facet as FacetType, PriceFacet } from "../../types/interface"; +import SliderDoubleControl from "../SliderDoubleControl"; +import { RangeFacet } from "./Range/RangeFacet"; +import { ScalarFacet } from "./Scalar/ScalarFacet"; interface FacetsProps { - searchFacets: FacetType[]; + searchFacets: FacetType[]; } -export const Facets: FunctionComponent = ({ - searchFacets, -}: FacetsProps) => { - const { - config: { priceSlider }, - } = useStore(); - return ( -
-
- {searchFacets?.map((facet) => { - const bucketType = facet?.buckets[0]?.__typename; - switch (bucketType) { - case 'ScalarBucket': - return ; - case 'RangeBucket': - return priceSlider ? ( - - ) : ( - - ); - case 'CategoryView': - return ; - default: - return null; - } - })} - -
- ); +export const Facets: FunctionComponent = ({ searchFacets }: FacetsProps) => { + const { + config: { priceSlider }, + } = useStore(); + return ( +
+
+ {searchFacets?.map((facet) => { + const bucketType = facet?.buckets[0]?.__typename; + switch (bucketType) { + case "ScalarBucket": + return ; + case "RangeBucket": + return priceSlider ? ( + + ) : ( + + ); + case "CategoryView": + return ; + default: + return null; + } + })} + +
+ ); }; diff --git a/src/components/Facets/Range/RangeFacet.test.tsx b/src/components/Facets/Range/RangeFacet.test.tsx index 3b1224f..554b4c2 100644 --- a/src/components/Facets/Range/RangeFacet.test.tsx +++ b/src/components/Facets/Range/RangeFacet.test.tsx @@ -8,18 +8,18 @@ it. */ /// ; -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { PriceFacet } from '@/types/interface'; +import { PriceFacet } from "@/types/interface"; -import { RangeFacet } from './RangeFacet'; +import { RangeFacet } from "./RangeFacet"; -describe('PLP widget/RangeFacet', () => { - it('renders', () => { - const { container } = render(); +describe("PLP widget/RangeFacet", () => { + it("renders", () => { + const { container } = render(); - const elem = container.querySelector('.ds-sdk-input'); + const elem = container.querySelector(".ds-sdk-input"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/Facets/Range/RangeFacet.tsx b/src/components/Facets/Range/RangeFacet.tsx index 4890fa8..21fa440 100644 --- a/src/components/Facets/Range/RangeFacet.tsx +++ b/src/components/Facets/Range/RangeFacet.tsx @@ -7,31 +7,29 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; -import useRangeFacet from '../../../hooks/useRangeFacet'; -import { PriceFacet } from '../../../types/interface'; -import { InputButtonGroup } from '../../InputButtonGroup'; +import useRangeFacet from "../../../hooks/useRangeFacet"; +import { PriceFacet } from "../../../types/interface"; +import { InputButtonGroup } from "../../InputButtonGroup"; interface RangeFacetProps { - filterData: PriceFacet; + filterData: PriceFacet; } -export const RangeFacet: FunctionComponent = ({ - filterData, -}) => { - const { isSelected, onChange } = useRangeFacet(filterData); +export const RangeFacet: FunctionComponent = ({ filterData }) => { + const { isSelected, onChange } = useRangeFacet(filterData); - return ( - { - onChange(e.value); - }} - /> - ); + return ( + { + onChange(e.value); + }} + /> + ); }; diff --git a/src/components/Facets/Scalar/ScalarFacet.test.tsx b/src/components/Facets/Scalar/ScalarFacet.test.tsx index 400e9b2..2ec8b9d 100644 --- a/src/components/Facets/Scalar/ScalarFacet.test.tsx +++ b/src/components/Facets/Scalar/ScalarFacet.test.tsx @@ -8,17 +8,17 @@ it. */ /// ; -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { PriceFacet } from '../../../types/interface'; -import { ScalarFacet } from './ScalarFacet'; +import { PriceFacet } from "../../../types/interface"; +import { ScalarFacet } from "./ScalarFacet"; -describe('PLP widget/RangeFacet', () => { - it('renders', () => { - const { container } = render(); +describe("PLP widget/RangeFacet", () => { + it("renders", () => { + const { container } = render(); - const elem = container.querySelector('.ds-sdk-input'); + const elem = container.querySelector(".ds-sdk-input"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/Facets/Scalar/ScalarFacet.tsx b/src/components/Facets/Scalar/ScalarFacet.tsx index 1233a6e..6b31cf5 100644 --- a/src/components/Facets/Scalar/ScalarFacet.tsx +++ b/src/components/Facets/Scalar/ScalarFacet.tsx @@ -7,29 +7,27 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; -import useScalarFacet from '../../../hooks/useScalarFacet'; -import { Facet as FacetType, PriceFacet } from '../../../types/interface'; -import { InputButtonGroup } from '../../InputButtonGroup'; +import useScalarFacet from "../../../hooks/useScalarFacet"; +import { Facet as FacetType, PriceFacet } from "../../../types/interface"; +import { InputButtonGroup } from "../../InputButtonGroup"; interface ScalarFacetProps { - filterData: FacetType | PriceFacet; + filterData: FacetType | PriceFacet; } -export const ScalarFacet: FunctionComponent = ({ - filterData, -}) => { - const { isSelected, onChange } = useScalarFacet(filterData); +export const ScalarFacet: FunctionComponent = ({ filterData }) => { + const { isSelected, onChange } = useScalarFacet(filterData); - return ( - onChange(args.value, args.selected)} - /> - ); + return ( + onChange(args.value, args.selected)} + /> + ); }; diff --git a/src/components/Facets/SelectedFilters.tsx b/src/components/Facets/SelectedFilters.tsx index c73485f..89f4f2a 100644 --- a/src/components/Facets/SelectedFilters.tsx +++ b/src/components/Facets/SelectedFilters.tsx @@ -7,67 +7,67 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; -import { useProducts, useSearch, useTranslation } from '../../context'; -import Pill from '../Pill'; -import { formatBinaryLabel, formatRangeLabel } from './format'; +import { useProducts, useSearch, useTranslation } from "../../context"; +import Pill from "../Pill"; +import { formatBinaryLabel, formatRangeLabel } from "./format"; export const SelectedFilters: FunctionComponent = ({}) => { - const searchCtx = useSearch(); - const productsCtx = useProducts(); - const translation = useTranslation(); + const searchCtx = useSearch(); + const productsCtx = useProducts(); + const translation = useTranslation(); - return ( -
- {searchCtx.filters?.length > 0 && ( -
- {searchCtx.filters.map((filter) => ( -
- {filter.in?.map((option) => ( - searchCtx.updateFilterOptions(filter, option)} - /> - ))} - {filter.range && ( - { - searchCtx.removeFilter(filter.attribute); - }} - /> - )} -
- ))} -
- -
+ onClick={() => searchCtx.clearFilters()} + > + {translation.Filter.clearAll} + +
+
+ )}
- )} -
- ); + ); }; diff --git a/src/components/Facets/format.ts b/src/components/Facets/format.ts index a102371..3192a09 100644 --- a/src/components/Facets/format.ts +++ b/src/components/Facets/format.ts @@ -7,55 +7,47 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FacetFilter } from '../../types/interface'; +import { FacetFilter } from "../../types/interface"; // format range with null "to" -const formatRangeLabel = ( - filter: FacetFilter, - currencyRate: string, - currencySymbol: string -) => { - const range = filter.range; - - const rate = currencyRate ? currencyRate : '1'; - const symbol = currencySymbol ? currencySymbol : '$'; - const label = `${symbol}${ - range?.from && parseFloat(rate) * parseInt(range.from.toFixed(0), 10) - ? (parseFloat(rate) * parseInt(range.from?.toFixed(0), 10))?.toFixed(2) - : 0 - }${ - range?.to && parseFloat(rate) * parseInt(range.to.toFixed(0), 10) - ? ` - ${symbol}${( - parseFloat(rate) * parseInt(range.to.toFixed(0), 10) - ).toFixed(2)}` - : ' and above' - }`; - return label; +const formatRangeLabel = (filter: FacetFilter, currencyRate: string, currencySymbol: string) => { + const range = filter.range; + + const rate = currencyRate ? currencyRate : "1"; + const symbol = currencySymbol ? currencySymbol : "$"; + const label = `${symbol}${ + range?.from && parseFloat(rate) * parseInt(range.from.toFixed(0), 10) + ? (parseFloat(rate) * parseInt(range.from?.toFixed(0), 10))?.toFixed(2) + : 0 + }${ + range?.to && parseFloat(rate) * parseInt(range.to.toFixed(0), 10) + ? ` - ${symbol}${(parseFloat(rate) * parseInt(range.to.toFixed(0), 10)).toFixed(2)}` + : " and above" + }`; + return label; }; const formatBinaryLabel = ( - filter: FacetFilter, - option: string, - categoryNames?: { value: string; name: string; attribute: string }[], - categoryPath?: string + filter: FacetFilter, + option: string, + categoryNames?: { value: string; name: string; attribute: string }[], + categoryPath?: string, ) => { - if (categoryPath && categoryNames) { - const category = categoryNames.find( - (facet) => facet.attribute === filter.attribute && facet.value === option - ); + if (categoryPath && categoryNames) { + const category = categoryNames.find((facet) => facet.attribute === filter.attribute && facet.value === option); + + if (category?.name) { + return category.name; + } + } - if (category?.name) { - return category.name; + const title = filter.attribute?.split("_"); + if (option === "yes") { + return title.join(" "); + } else if (option === "no") { + return `not ${title.join(" ")}`; } - } - - const title = filter.attribute?.split('_'); - if (option === 'yes') { - return title.join(' '); - } else if (option === 'no') { - return `not ${title.join(' ')}`; - } - return option; + return option; }; export { formatBinaryLabel, formatRangeLabel }; diff --git a/src/components/Facets/index.ts b/src/components/Facets/index.ts index 84d9a13..59bc9cc 100644 --- a/src/components/Facets/index.ts +++ b/src/components/Facets/index.ts @@ -7,8 +7,8 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './Facets'; -export * from './SelectedFilters'; -export * from './Range/RangeFacet'; -export * from './Scalar/ScalarFacet'; -export { Facets as default } from './Facets'; +export * from "./Facets"; +export * from "./SelectedFilters"; +export * from "./Range/RangeFacet"; +export * from "./Scalar/ScalarFacet"; +export { Facets as default } from "./Facets"; diff --git a/src/components/Facets/mocks.tsx b/src/components/Facets/mocks.tsx index 2b4c77d..bac6c86 100644 --- a/src/components/Facets/mocks.tsx +++ b/src/components/Facets/mocks.tsx @@ -7,118 +7,113 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { - Facet, - PriceFacet, - RangeBucket, - ScalarBucket, -} from '../../types/interface'; +import { Facet, PriceFacet, RangeBucket, ScalarBucket } from "../../types/interface"; const colorBuckets: ScalarBucket[] = [ - { - count: 5, - title: 'Green', - __typename: 'ScalarBucket', - }, - { - count: 4, - title: 'Black', - __typename: 'ScalarBucket', - }, - { - count: 3, - title: 'Blue', - __typename: 'ScalarBucket', - }, - { - count: 2, - title: 'Gray', - __typename: 'ScalarBucket', - }, - { - count: 1, - title: 'Pink', - __typename: 'ScalarBucket', - }, - { - count: 0, - title: 'Yellow', - __typename: 'ScalarBucket', - }, + { + count: 5, + title: "Green", + __typename: "ScalarBucket", + }, + { + count: 4, + title: "Black", + __typename: "ScalarBucket", + }, + { + count: 3, + title: "Blue", + __typename: "ScalarBucket", + }, + { + count: 2, + title: "Gray", + __typename: "ScalarBucket", + }, + { + count: 1, + title: "Pink", + __typename: "ScalarBucket", + }, + { + count: 0, + title: "Yellow", + __typename: "ScalarBucket", + }, ]; const sizeBuckets: ScalarBucket[] = [ - { - count: 2, - title: '32', - __typename: 'ScalarBucket', - }, - { - count: 2, - title: '33', - __typename: 'ScalarBucket', - }, - { - count: 1, - title: 'L', - __typename: 'ScalarBucket', - }, + { + count: 2, + title: "32", + __typename: "ScalarBucket", + }, + { + count: 2, + title: "33", + __typename: "ScalarBucket", + }, + { + count: 1, + title: "L", + __typename: "ScalarBucket", + }, ]; const priceBuckets: RangeBucket[] = [ - { - title: '0.0-25.0', - __typename: 'RangeBucket', - from: 0, - to: 25, - count: 45, - }, - { - title: '25.0-50.0', - __typename: 'RangeBucket', - from: 25, - to: 50, - count: 105, - }, - { - title: '75.0-100.0', - __typename: 'RangeBucket', - from: 75, - to: 100, - count: 6, - }, - { - title: '200.0-225.0', - __typename: 'RangeBucket', - from: 200, - to: 225, - count: 2, - }, + { + title: "0.0-25.0", + __typename: "RangeBucket", + from: 0, + to: 25, + count: 45, + }, + { + title: "25.0-50.0", + __typename: "RangeBucket", + from: 25, + to: 50, + count: 105, + }, + { + title: "75.0-100.0", + __typename: "RangeBucket", + from: 75, + to: 100, + count: 6, + }, + { + title: "200.0-225.0", + __typename: "RangeBucket", + from: 200, + to: 225, + count: 2, + }, ]; export const mockFilters: Facet[] = [ - { - title: 'Color', - attribute: 'color', - buckets: colorBuckets, - __typename: 'ScalarBucket', - }, - { - title: 'Size', - attribute: 'size', - buckets: sizeBuckets, - __typename: 'ScalarBucket', - }, + { + title: "Color", + attribute: "color", + buckets: colorBuckets, + __typename: "ScalarBucket", + }, + { + title: "Size", + attribute: "size", + buckets: sizeBuckets, + __typename: "ScalarBucket", + }, ]; export const mockColorFilter: Facet = { - title: 'Color', - attribute: 'color', - buckets: colorBuckets, - __typename: 'ScalarBucket', + title: "Color", + attribute: "color", + buckets: colorBuckets, + __typename: "ScalarBucket", }; export const mockPriceFilter: PriceFacet = { - title: 'Price', - attribute: 'price', - buckets: priceBuckets, - __typename: 'RangeBucket', + title: "Price", + attribute: "price", + buckets: priceBuckets, + __typename: "RangeBucket", }; diff --git a/src/components/FacetsShimmer/FacetsShimmer.tsx b/src/components/FacetsShimmer/FacetsShimmer.tsx index 7b7e255..9ed54d7 100644 --- a/src/components/FacetsShimmer/FacetsShimmer.tsx +++ b/src/components/FacetsShimmer/FacetsShimmer.tsx @@ -7,29 +7,29 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; -import '../FacetsShimmer/FacetsShimmer.css'; +import "../FacetsShimmer/FacetsShimmer.css"; export const FacetsShimmer: FunctionComponent = () => { - return ( - <> -
-
-
-
-
-
-
-
-
-
-
-
-
-
- - ); + return ( + <> +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + ); }; export default FacetsShimmer; diff --git a/src/components/FacetsShimmer/index.ts b/src/components/FacetsShimmer/index.ts index a97bbb3..6a94985 100644 --- a/src/components/FacetsShimmer/index.ts +++ b/src/components/FacetsShimmer/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './FacetsShimmer'; -export { FacetsShimmer as default } from './FacetsShimmer'; +export * from "./FacetsShimmer"; +export { FacetsShimmer as default } from "./FacetsShimmer"; diff --git a/src/components/FilterButton/FilterButton.test.tsx b/src/components/FilterButton/FilterButton.test.tsx index ef80ddf..8b9ba81 100644 --- a/src/components/FilterButton/FilterButton.test.tsx +++ b/src/components/FilterButton/FilterButton.test.tsx @@ -7,23 +7,23 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { FilterButton } from './FilterButton'; +import { FilterButton } from "./FilterButton"; -describe('WidgetSDK - UIKit/FilterButton', () => { - test('renders', () => { - const { container } = render( - { - return; - }} - type="mobile" - /> - ); +describe("WidgetSDK - UIKit/FilterButton", () => { + test("renders", () => { + const { container } = render( + { + return; + }} + type="mobile" + />, + ); - const elem = container.querySelector('.ds-sdk-filter-button'); + const elem = container.querySelector(".ds-sdk-filter-button"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/FilterButton/index.ts b/src/components/FilterButton/index.ts index 1cdc708..4bb7a15 100644 --- a/src/components/FilterButton/index.ts +++ b/src/components/FilterButton/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './FilterButton'; -export { FilterButton as default } from './FilterButton'; +export * from "./FilterButton"; +export { FilterButton as default } from "./FilterButton"; diff --git a/src/components/ImageCarousel/Image.tsx b/src/components/ImageCarousel/Image.tsx index 4beb519..2c7d60d 100644 --- a/src/components/ImageCarousel/Image.tsx +++ b/src/components/ImageCarousel/Image.tsx @@ -1,43 +1,41 @@ -import { useEffect, useRef, useState } from 'preact/compat'; +import { useEffect, useRef, useState } from "preact/compat"; -import { useIntersectionObserver } from '../../utils/useIntersectionObserver'; +import { useIntersectionObserver } from "../../utils/useIntersectionObserver"; export const Image = ({ - image, - alt, - carouselIndex, - index, + image, + alt, + carouselIndex, + index, }: { - image: { src: string; srcset: any } | string; - alt: string; - carouselIndex: number; - index: number; + image: { src: string; srcset: any } | string; + alt: string; + carouselIndex: number; + index: number; }) => { - const imageRef = useRef(null); - const [imageUrl, setImageUrl] = useState(''); - const [isVisible, setIsVisible] = useState(false); - const entry = useIntersectionObserver(imageRef, { rootMargin: '200px' }); + const imageRef = useRef(null); + const [imageUrl, setImageUrl] = useState(""); + const [isVisible, setIsVisible] = useState(false); + const entry = useIntersectionObserver(imageRef, { rootMargin: "200px" }); - useEffect(() => { - if (!entry) return; + useEffect(() => { + if (!entry) return; - if (entry?.isIntersecting && index === carouselIndex) { - setIsVisible(true); + if (entry?.isIntersecting && index === carouselIndex) { + setIsVisible(true); - setImageUrl((entry?.target as HTMLElement)?.dataset.src || ''); - } - }, [entry, carouselIndex, index, image]); + setImageUrl((entry?.target as HTMLElement)?.dataset.src || ""); + } + }, [entry, carouselIndex, index, image]); - return ( - {alt} - ); + return ( + {alt} + ); }; diff --git a/src/components/ImageCarousel/ImageCarousel.test.tsx b/src/components/ImageCarousel/ImageCarousel.test.tsx index d793f37..b6d8631 100644 --- a/src/components/ImageCarousel/ImageCarousel.test.tsx +++ b/src/components/ImageCarousel/ImageCarousel.test.tsx @@ -7,23 +7,18 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { ImageCarousel } from './ImageCarousel'; +import { ImageCarousel } from "./ImageCarousel"; -describe('WidgetSDK - UIKit/ImageCarousel', () => { - test('renders', () => { - const { container } = render( - {}} - /> - ); +describe("WidgetSDK - UIKit/ImageCarousel", () => { + test("renders", () => { + const { container } = render( + {}} />, + ); - const elem = container.querySelector('.ds-sdk-product-image-carousel'); + const elem = container.querySelector(".ds-sdk-product-image-carousel"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/ImageCarousel/ImageCarousel.tsx b/src/components/ImageCarousel/ImageCarousel.tsx index 2285269..3057715 100644 --- a/src/components/ImageCarousel/ImageCarousel.tsx +++ b/src/components/ImageCarousel/ImageCarousel.tsx @@ -7,115 +7,115 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; -import { SetStateAction, useState } from 'react'; +import { FunctionComponent } from "preact"; +import { SetStateAction, useState } from "react"; -import { Image } from './Image'; +import { Image } from "./Image"; export interface ImageCarouselProps { - images: string[] | { src: string; srcset: any }[]; - productName: string; - carouselIndex: number; - setCarouselIndex: (carouselIndex: number | SetStateAction) => void; + images: string[] | { src: string; srcset: any }[]; + productName: string; + carouselIndex: number; + setCarouselIndex: (carouselIndex: number | SetStateAction) => void; } export const ImageCarousel: FunctionComponent = ({ - images, - productName, - carouselIndex, - setCarouselIndex, + images, + productName, + carouselIndex, + setCarouselIndex, }) => { - const [swipeIndex, setSwipeIndex] = useState(0); - const cirHandler = (index: SetStateAction) => { - setCarouselIndex(index); - }; + const [swipeIndex, setSwipeIndex] = useState(0); + const cirHandler = (index: SetStateAction) => { + setCarouselIndex(index); + }; - const prevHandler = () => { - if (carouselIndex === 0) { - setCarouselIndex(0); - } else { - setCarouselIndex((prev: number) => prev - 1); - } - }; - const nextHandler = () => { - if (carouselIndex === images.length - 1) { - setCarouselIndex(0); - } else { - setCarouselIndex((prev: number) => prev + 1); - } - }; + const prevHandler = () => { + if (carouselIndex === 0) { + setCarouselIndex(0); + } else { + setCarouselIndex((prev: number) => prev - 1); + } + }; + const nextHandler = () => { + if (carouselIndex === images.length - 1) { + setCarouselIndex(0); + } else { + setCarouselIndex((prev: number) => prev + 1); + } + }; - return ( - <> - + + ); }; diff --git a/src/components/ImageCarousel/index.ts b/src/components/ImageCarousel/index.ts index 7df3a73..0ab0c63 100644 --- a/src/components/ImageCarousel/index.ts +++ b/src/components/ImageCarousel/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './ImageCarousel'; -export { ImageCarousel as default } from './ImageCarousel'; +export * from "./ImageCarousel"; +export { ImageCarousel as default } from "./ImageCarousel"; diff --git a/src/components/InputButtonGroup/InputButtonGroup.test.tsx b/src/components/InputButtonGroup/InputButtonGroup.test.tsx index 518cf3a..5f34ee0 100644 --- a/src/components/InputButtonGroup/InputButtonGroup.test.tsx +++ b/src/components/InputButtonGroup/InputButtonGroup.test.tsx @@ -7,34 +7,34 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { InputButtonGroup, InputButtonGroupProps } from './InputButtonGroup'; +import { InputButtonGroup, InputButtonGroupProps } from "./InputButtonGroup"; const mockButtonGroup: InputButtonGroupProps = { - title: 'button', - attribute: 'button', - buckets: [], - isSelected: () => true, - onChange: () => {}, - type: 'radio', + title: "button", + attribute: "button", + buckets: [], + isSelected: () => true, + onChange: () => {}, + type: "radio", }; -describe('WidgetSDK - UIKit/InputButtonGroup', () => { - test('renders', () => { - const { container } = render( - - ); +describe("WidgetSDK - UIKit/InputButtonGroup", () => { + test("renders", () => { + const { container } = render( + , + ); - const elem = container.querySelector('.ds-sdk-input'); + const elem = container.querySelector(".ds-sdk-input"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/InputButtonGroup/InputButtonGroup.tsx b/src/components/InputButtonGroup/InputButtonGroup.tsx index 873793a..17c2e9f 100644 --- a/src/components/InputButtonGroup/InputButtonGroup.tsx +++ b/src/components/InputButtonGroup/InputButtonGroup.tsx @@ -7,161 +7,139 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; -import { ChangeEvent, useState } from 'preact/compat'; +import { FunctionComponent } from "preact"; +import { ChangeEvent, useState } from "preact/compat"; -import { Plus as PlusIcon} from '@/icons'; +import { Plus as PlusIcon } from "@/icons"; -import { useProducts, useTranslation } from '../../context'; -import { BOOLEAN_NO, BOOLEAN_YES } from '../../utils/constants'; -import { LabelledInput } from '../LabelledInput'; +import { useProducts, useTranslation } from "../../context"; +import { BOOLEAN_NO, BOOLEAN_YES } from "../../utils/constants"; +import { LabelledInput } from "../LabelledInput"; export type InputButtonGroupOnChangeProps = { - value: string; - selected?: boolean; + value: string; + selected?: boolean; }; -export type InputButtonGroupOnChange = ( - arg0: InputButtonGroupOnChangeProps -) => void; +export type InputButtonGroupOnChange = (arg0: InputButtonGroupOnChangeProps) => void; export type InputButtonGroupTitleSlot = (label: string) => FunctionComponent; export type Bucket = { - title: string; - id?: string; - count: number; - to?: number; - from?: number; - name?: string; - __typename: 'ScalarBucket' | 'RangeBucket' | 'CategoryView'; + title: string; + id?: string; + count: number; + to?: number; + from?: number; + name?: string; + __typename: "ScalarBucket" | "RangeBucket" | "CategoryView"; }; export interface InputButtonGroupProps { - title: string; - attribute: string; - buckets: Bucket[]; - isSelected: (title: string) => boolean | undefined; - onChange: InputButtonGroupOnChange; - type: 'radio' | 'checkbox'; - inputGroupTitleSlot?: InputButtonGroupTitleSlot; + title: string; + attribute: string; + buckets: Bucket[]; + isSelected: (title: string) => boolean | undefined; + onChange: InputButtonGroupOnChange; + type: "radio" | "checkbox"; + inputGroupTitleSlot?: InputButtonGroupTitleSlot; } const numberOfOptionsShown = 5; export const InputButtonGroup: FunctionComponent = ({ - title, - attribute, - buckets, - isSelected, - onChange, - type, - inputGroupTitleSlot, + title, + attribute, + buckets, + isSelected, + onChange, + type, + inputGroupTitleSlot, }) => { - const translation = useTranslation(); - const productsCtx = useProducts(); + const translation = useTranslation(); + const productsCtx = useProducts(); - const [showMore, setShowMore] = useState( - buckets.length < numberOfOptionsShown - ); + const [showMore, setShowMore] = useState(buckets.length < numberOfOptionsShown); - const numberOfOptions = showMore ? buckets.length : numberOfOptionsShown; + const numberOfOptions = showMore ? buckets.length : numberOfOptionsShown; - const onInputChange = (title: string, e: ChangeEvent) => { - onChange({ - value: title, - selected: (e?.target as HTMLInputElement)?.checked, - }); - }; + const onInputChange = (title: string, e: ChangeEvent) => { + onChange({ + value: title, + selected: (e?.target as HTMLInputElement)?.checked, + }); + }; - const formatLabel = (title: string, bucket: Bucket) => { - if (bucket.__typename === 'RangeBucket') { - const currencyRate = productsCtx.currencyRate - ? productsCtx.currencyRate - : '1'; - const currencySymbol = productsCtx.currencySymbol - ? productsCtx.currencySymbol - : '$'; - const label = `${currencySymbol}${ - bucket?.from && - parseFloat(currencyRate) * parseInt(bucket.from.toFixed(0), 10) - ? ( - parseFloat(currencyRate) * parseInt(bucket.from.toFixed(0), 10) - ).toFixed(2) - : 0 - }${ - bucket?.to && - parseFloat(currencyRate) * parseInt(bucket.to.toFixed(0), 10) - ? ` - ${currencySymbol}${( - parseFloat(currencyRate) * parseInt(bucket.to.toFixed(0), 10) - ).toFixed(2)}` - : translation.InputButtonGroup.priceRange - }`; - return label; - } else if (bucket.__typename === 'CategoryView') { - return productsCtx.categoryPath - ? bucket.name ?? bucket.title - : bucket.title; - } else if (bucket.title === BOOLEAN_YES) { - return title; - } else if (bucket.title === BOOLEAN_NO) { - const excludedMessageTranslation = - translation.InputButtonGroup.priceExcludedMessage; - const excludedMessage = excludedMessageTranslation.replace( - '{title}', - `${title}` - ); - return excludedMessage; - } - return bucket.title; - }; + const formatLabel = (title: string, bucket: Bucket) => { + if (bucket.__typename === "RangeBucket") { + const currencyRate = productsCtx.currencyRate ? productsCtx.currencyRate : "1"; + const currencySymbol = productsCtx.currencySymbol ? productsCtx.currencySymbol : "$"; + const label = `${currencySymbol}${ + bucket?.from && parseFloat(currencyRate) * parseInt(bucket.from.toFixed(0), 10) + ? (parseFloat(currencyRate) * parseInt(bucket.from.toFixed(0), 10)).toFixed(2) + : 0 + }${ + bucket?.to && parseFloat(currencyRate) * parseInt(bucket.to.toFixed(0), 10) + ? ` - ${currencySymbol}${(parseFloat(currencyRate) * parseInt(bucket.to.toFixed(0), 10)).toFixed( + 2, + )}` + : translation.InputButtonGroup.priceRange + }`; + return label; + } else if (bucket.__typename === "CategoryView") { + return productsCtx.categoryPath ? (bucket.name ?? bucket.title) : bucket.title; + } else if (bucket.title === BOOLEAN_YES) { + return title; + } else if (bucket.title === BOOLEAN_NO) { + const excludedMessageTranslation = translation.InputButtonGroup.priceExcludedMessage; + const excludedMessage = excludedMessageTranslation.replace("{title}", `${title}`); + return excludedMessage; + } + return bucket.title; + }; - return ( -
- {inputGroupTitleSlot ? ( - inputGroupTitleSlot(title) - ) : ( - - )} -
-
- {buckets.slice(0, numberOfOptions).map((option) => { - if (!option.title) { - return null; - } - const checked = isSelected(option.title); - const noShowPriceBucketCount = option.__typename === 'RangeBucket'; - return ( - ) => - onInputChange(option.title, e) - } - type={type} - /> - ); - })} - {!showMore && buckets.length > numberOfOptionsShown && ( -
setShowMore(true)} - > - - -
- )} + return ( +
+ {inputGroupTitleSlot ? ( + inputGroupTitleSlot(title) + ) : ( + + )} +
+
+ {buckets.slice(0, numberOfOptions).map((option) => { + if (!option.title) { + return null; + } + const checked = isSelected(option.title); + const noShowPriceBucketCount = option.__typename === "RangeBucket"; + return ( + ) => onInputChange(option.title, e)} + type={type} + /> + ); + })} + {!showMore && buckets.length > numberOfOptionsShown && ( +
setShowMore(true)} + > + + +
+ )} +
+
+
-
-
-
- ); + ); }; diff --git a/src/components/InputButtonGroup/index.ts b/src/components/InputButtonGroup/index.ts index 0a8f3fa..15e3dc0 100644 --- a/src/components/InputButtonGroup/index.ts +++ b/src/components/InputButtonGroup/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './InputButtonGroup'; -export { InputButtonGroup as default } from './InputButtonGroup'; +export * from "./InputButtonGroup"; +export { InputButtonGroup as default } from "./InputButtonGroup"; diff --git a/src/components/LabelledInput/LabelledInput.test.tsx b/src/components/LabelledInput/LabelledInput.test.tsx index bf6b383..8546c5f 100644 --- a/src/components/LabelledInput/LabelledInput.test.tsx +++ b/src/components/LabelledInput/LabelledInput.test.tsx @@ -7,26 +7,26 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { LabelledInput } from './LabelledInput'; +import { LabelledInput } from "./LabelledInput"; -describe('WidgetSDK - UIKit/InputButtonGroup', () => { - test('renders', () => { - const { container } = render( - {}} - label="" - value="" - attribute="" - /> - ); +describe("WidgetSDK - UIKit/InputButtonGroup", () => { + test("renders", () => { + const { container } = render( + {}} + label="" + value="" + attribute="" + />, + ); - const elem = container.querySelector('.ds-sdk-labelled-input'); + const elem = container.querySelector(".ds-sdk-labelled-input"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/LabelledInput/LabelledInput.tsx b/src/components/LabelledInput/LabelledInput.tsx index 5473c14..77ac666 100644 --- a/src/components/LabelledInput/LabelledInput.tsx +++ b/src/components/LabelledInput/LabelledInput.tsx @@ -7,58 +7,50 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; -import { ChangeEvent } from 'preact/compat'; +import { FunctionComponent } from "preact"; +import { ChangeEvent } from "preact/compat"; // Maybe someday extend the `type` field to allow more inputs like `range` or `time` export interface LabelledInputProps { - checked: boolean; - name: string; - attribute: string; - type: 'checkbox' | 'radio'; - onChange: (e: ChangeEvent) => void; - label: string; - value: string; - count?: number | null; + checked: boolean; + name: string; + attribute: string; + type: "checkbox" | "radio"; + onChange: (e: ChangeEvent) => void; + label: string; + value: string; + count?: number | null; } export const LabelledInput: FunctionComponent = ({ - type, - checked, - onChange, - name, - label, - attribute, - value, - count, + type, + checked, + onChange, + name, + label, + attribute, + value, + count, }) => { - return ( -
- - -
- ); + return ( +
+ + +
+ ); }; diff --git a/src/components/LabelledInput/index.ts b/src/components/LabelledInput/index.ts index 434ce5f..b044bac 100644 --- a/src/components/LabelledInput/index.ts +++ b/src/components/LabelledInput/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './LabelledInput'; -export { LabelledInput as default } from './LabelledInput'; +export * from "./LabelledInput"; +export { LabelledInput as default } from "./LabelledInput"; diff --git a/src/components/Loading/Loading.test.tsx b/src/components/Loading/Loading.test.tsx index bf2d085..b2fc619 100644 --- a/src/components/Loading/Loading.test.tsx +++ b/src/components/Loading/Loading.test.tsx @@ -8,30 +8,30 @@ it. */ /// ; -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import Loading from './Loading'; +import Loading from "./Loading"; -Object.defineProperty(window, 'matchMedia', { - writable: true, - value: jest.fn().mockImplementation((query) => ({ - matches: false, - media: query, - onchange: null, - addListener: jest.fn(), // Deprecated - removeListener: jest.fn(), // Deprecated - addEventListener: jest.fn(), - removeEventListener: jest.fn(), - dispatchEvent: jest.fn(), - })), +Object.defineProperty(window, "matchMedia", { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), }); -describe('WidgetSDK - UIKit/Loading', () => { - test('renders', () => { - const { container } = render(); +describe("WidgetSDK - UIKit/Loading", () => { + test("renders", () => { + const { container } = render(); - const elem = container.querySelector('.ds-sdk-loading'); + const elem = container.querySelector(".ds-sdk-loading"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/Loading/index.ts b/src/components/Loading/index.ts index 0b160df..a6384c5 100644 --- a/src/components/Loading/index.ts +++ b/src/components/Loading/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './Loading'; -export { Loading as default } from './Loading'; +export * from "./Loading"; +export { Loading as default } from "./Loading"; diff --git a/src/components/NoResults/NoResults.test.tsx b/src/components/NoResults/NoResults.test.tsx index 52821a4..99257d2 100644 --- a/src/components/NoResults/NoResults.test.tsx +++ b/src/components/NoResults/NoResults.test.tsx @@ -7,18 +7,16 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { NoResults } from './NoResults'; +import { NoResults } from "./NoResults"; -describe('WidgetSDK - UIKit/NoResults', () => { - test('renders', () => { - const { container } = render( - - ); +describe("WidgetSDK - UIKit/NoResults", () => { + test("renders", () => { + const { container } = render(); - const elem = container.querySelector('.ds-sdk-no-results__page'); + const elem = container.querySelector(".ds-sdk-no-results__page"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/NoResults/NoResults.tsx b/src/components/NoResults/NoResults.tsx index e0d88e9..ef267c4 100644 --- a/src/components/NoResults/NoResults.tsx +++ b/src/components/NoResults/NoResults.tsx @@ -7,58 +7,50 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; export interface NoResultsProps { - heading: string; - subheading: string; - isError: boolean; + heading: string; + subheading: string; + isError: boolean; } -export const NoResults: FunctionComponent = ({ - heading, - subheading, - isError, -}: NoResultsProps) => { - return ( -
- {isError ? ( - - - - ) : ( - - - - )} +export const NoResults: FunctionComponent = ({ heading, subheading, isError }: NoResultsProps) => { + return ( +
+ {isError ? ( + + + + ) : ( + + + + )} -

- {heading} -

-

- {subheading} -

-
- ); +

{heading}

+

{subheading}

+
+ ); }; diff --git a/src/components/NoResults/index.ts b/src/components/NoResults/index.ts index b92d658..b603a50 100644 --- a/src/components/NoResults/index.ts +++ b/src/components/NoResults/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './NoResults'; -export { NoResults as default } from './NoResults'; +export * from "./NoResults"; +export { NoResults as default } from "./NoResults"; diff --git a/src/components/Pagination/Pagination.test.tsx b/src/components/Pagination/Pagination.test.tsx index 1a9c39e..0baaaf6 100644 --- a/src/components/Pagination/Pagination.test.tsx +++ b/src/components/Pagination/Pagination.test.tsx @@ -8,18 +8,16 @@ it. */ /// ; -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import Pagination from './Pagination'; +import Pagination from "./Pagination"; -describe('PLP widget/Pagination', () => { - it('renders', () => { - const { container } = render( - {}} /> - ); +describe("PLP widget/Pagination", () => { + it("renders", () => { + const { container } = render( {}} />); - const elem = container.querySelector('.ds-plp-pagination'); + const elem = container.querySelector(".ds-plp-pagination"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/Pagination/index.ts b/src/components/Pagination/index.ts index daa25f6..b2d5019 100644 --- a/src/components/Pagination/index.ts +++ b/src/components/Pagination/index.ts @@ -7,4 +7,4 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './Pagination'; +export * from "./Pagination"; diff --git a/src/components/PerPagePicker/PerPagePicker.test.tsx b/src/components/PerPagePicker/PerPagePicker.test.tsx index de052e7..89b3080 100644 --- a/src/components/PerPagePicker/PerPagePicker.test.tsx +++ b/src/components/PerPagePicker/PerPagePicker.test.tsx @@ -7,23 +7,19 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { PerPagePicker } from './PerPagePicker'; +import { PerPagePicker } from "./PerPagePicker"; -describe('WidgetSDK - UIKit/PerPagePicker', () => { - test('renders', () => { - const handleChange = jest.fn(); - const { container } = render( - - ); +describe("WidgetSDK - UIKit/PerPagePicker", () => { + test("renders", () => { + const handleChange = jest.fn(); + const { container } = render( + , + ); - const elem = container.querySelector('.ds-sdk-per-page-picker'); + const elem = container.querySelector(".ds-sdk-per-page-picker"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/PerPagePicker/index.ts b/src/components/PerPagePicker/index.ts index 58414dd..ad8cd8e 100644 --- a/src/components/PerPagePicker/index.ts +++ b/src/components/PerPagePicker/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './PerPagePicker'; -export { PerPagePicker as default } from './PerPagePicker'; +export * from "./PerPagePicker"; +export { PerPagePicker as default } from "./PerPagePicker"; diff --git a/src/components/Pill/Pill.test.tsx b/src/components/Pill/Pill.test.tsx index f6883e8..fcf7d24 100644 --- a/src/components/Pill/Pill.test.tsx +++ b/src/components/Pill/Pill.test.tsx @@ -7,16 +7,16 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { Pill } from './Pill'; +import { Pill } from "./Pill"; -describe('WidgetSDK - UIKit/Pill', () => { - test('renders', () => { - const { container } = render( {}} />); +describe("WidgetSDK - UIKit/Pill", () => { + test("renders", () => { + const { container } = render( {}} />); - const elem = container.querySelector('.ds-sdk-pill'); + const elem = container.querySelector(".ds-sdk-pill"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/Pill/index.ts b/src/components/Pill/index.ts index 89f11c5..ce00a84 100644 --- a/src/components/Pill/index.ts +++ b/src/components/Pill/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './Pill'; -export { Pill as default } from './Pill'; +export * from "./Pill"; +export { Pill as default } from "./Pill"; diff --git a/src/components/Pill/mock.tsx b/src/components/Pill/mock.tsx index 9081994..52a8d7a 100644 --- a/src/components/Pill/mock.tsx +++ b/src/components/Pill/mock.tsx @@ -8,16 +8,16 @@ it. */ export const CTA = ( - - - + + + ); diff --git a/src/components/ProductCardShimmer/ProductCardShimmer.tsx b/src/components/ProductCardShimmer/ProductCardShimmer.tsx index 9195fee..036395a 100644 --- a/src/components/ProductCardShimmer/ProductCardShimmer.tsx +++ b/src/components/ProductCardShimmer/ProductCardShimmer.tsx @@ -7,23 +7,23 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; -import './ProductCardShimmer.css'; +import "./ProductCardShimmer.css"; export const ProductCardShimmer: FunctionComponent = () => { - return ( -
-
-
-
-
+ return ( +
+
+
+
+
+
+
+
+
-
-
-
-
- ); + ); }; export default ProductCardShimmer; diff --git a/src/components/ProductCardShimmer/index.ts b/src/components/ProductCardShimmer/index.ts index 03e0fc3..b70c0c7 100644 --- a/src/components/ProductCardShimmer/index.ts +++ b/src/components/ProductCardShimmer/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './ProductCardShimmer'; -export { ProductCardShimmer as default } from './ProductCardShimmer'; +export * from "./ProductCardShimmer"; +export { ProductCardShimmer as default } from "./ProductCardShimmer"; diff --git a/src/components/ProductItem/MockData.ts b/src/components/ProductItem/MockData.ts index 2d6dbb7..94b9d41 100644 --- a/src/components/ProductItem/MockData.ts +++ b/src/components/ProductItem/MockData.ts @@ -7,483 +7,477 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { Product } from '../../types/interface'; +import { Product } from "../../types/interface"; export const sampleProductNoImage: Product = { - product: { - __typename: 'SimpleProduct', - id: 21, - uid: '21', - name: 'Sprite Foam Yoga Brick', - sku: '24-WG084', - description: { - html: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', - }, - short_description: null, - attribute_set_id: null, - meta_title: null, - meta_keyword: null, - meta_description: null, - image: null, - small_image: null, - thumbnail: null, - new_from_date: null, - new_to_date: null, - created_at: null, - updated_at: null, - price_range: { - minimum_price: { - fixed_product_taxes: null, - regular_price: { value: 8, currency: 'USD' }, - final_price: { value: 5, currency: 'USD' }, - discount: null, - }, - maximum_price: { - fixed_product_taxes: null, - regular_price: { value: 5, currency: 'USD' }, - final_price: { value: 5, currency: 'USD' }, - discount: null, - }, - }, - gift_message_available: null, - canonical_url: - '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html', - media_gallery: null, - custom_attributes: null, - add_to_cart_allowed: null, - }, - productView: { - __typename: 'SimpleProduct', - id: 21, - uid: '21', - name: 'Sprite Foam Yoga Brick', - sku: '24-WG084', - description: { - html: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', - }, - short_description: null, - attribute_set_id: null, - meta_title: null, - meta_keyword: null, - meta_description: null, - images: null, - new_from_date: null, - new_to_date: null, - created_at: null, - updated_at: null, - price: { - final: { - amount: { - value: 5, - currency: 'USD', + product: { + __typename: "SimpleProduct", + id: 21, + uid: "21", + name: "Sprite Foam Yoga Brick", + sku: "24-WG084", + description: { + html: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', }, - adjustments: null, - }, - regular: { - amount: { - value: 5, - currency: 'USD', + short_description: null, + attribute_set_id: null, + meta_title: null, + meta_keyword: null, + meta_description: null, + image: null, + small_image: null, + thumbnail: null, + new_from_date: null, + new_to_date: null, + created_at: null, + updated_at: null, + price_range: { + minimum_price: { + fixed_product_taxes: null, + regular_price: { value: 8, currency: "USD" }, + final_price: { value: 5, currency: "USD" }, + discount: null, + }, + maximum_price: { + fixed_product_taxes: null, + regular_price: { value: 5, currency: "USD" }, + final_price: { value: 5, currency: "USD" }, + discount: null, + }, }, - adjustments: null, - }, + gift_message_available: null, + canonical_url: "//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html", + media_gallery: null, + custom_attributes: null, + add_to_cart_allowed: null, }, - priceRange: { - maximum: { - final: { - amount: { - value: 5, - currency: 'USD', - }, - adjustments: null, + productView: { + __typename: "SimpleProduct", + id: 21, + uid: "21", + name: "Sprite Foam Yoga Brick", + sku: "24-WG084", + description: { + html: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', }, - regular: { - amount: { - value: 5, - currency: 'USD', - }, - adjustments: null, + short_description: null, + attribute_set_id: null, + meta_title: null, + meta_keyword: null, + meta_description: null, + images: null, + new_from_date: null, + new_to_date: null, + created_at: null, + updated_at: null, + price: { + final: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, + regular: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, }, - }, - minimum: { - final: { - amount: { - value: 5, - currency: 'USD', - }, - adjustments: null, + priceRange: { + maximum: { + final: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, + regular: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, + }, + minimum: { + final: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, + regular: { + amount: { + value: 8, + currency: "USD", + }, + adjustments: null, + }, + }, }, - regular: { - amount: { - value: 8, - currency: 'USD', - }, - adjustments: null, - }, - }, - }, - gift_message_available: null, - url: 'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html', - urlKey: 'sprite-foam-yoga-brick', - media_gallery: null, - custom_attributes: null, - add_to_cart_allowed: null, - options: null, - }, - highlights: [ - { - attribute: 'name', - value: 'Sprite Foam Yoga Brick', - matched_words: [], - }, - { - attribute: 'description', - value: - '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', - matched_words: [], + gift_message_available: null, + url: "http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html", + urlKey: "sprite-foam-yoga-brick", + media_gallery: null, + custom_attributes: null, + add_to_cart_allowed: null, + options: null, }, - ], + highlights: [ + { + attribute: "name", + value: "Sprite Foam Yoga Brick", + matched_words: [], + }, + { + attribute: "description", + value: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', + matched_words: [], + }, + ], }; export const sampleProductDiscounted: Product = { - product: { - __typename: 'SimpleProduct', - id: 21, - uid: '21', - name: 'Sprite Foam Yoga Brick', - sku: '24-WG084', - description: { - html: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', - }, - short_description: null, - attribute_set_id: null, - meta_title: null, - meta_keyword: null, - meta_description: null, - image: { - url: '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg', - label: null, - position: null, - disabled: null, - }, - small_image: { - url: '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg', - label: null, - position: null, - disabled: null, - }, - thumbnail: { - url: '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg', - label: null, - position: null, - disabled: null, - }, - new_from_date: null, - new_to_date: null, - created_at: null, - updated_at: null, - price_range: { - minimum_price: { - fixed_product_taxes: null, - regular_price: { value: 8, currency: 'USD' }, - final_price: { value: 5, currency: 'USD' }, - discount: null, - }, - maximum_price: { - fixed_product_taxes: null, - regular_price: { value: 5, currency: 'USD' }, - final_price: { value: 5, currency: 'USD' }, - discount: null, - }, - }, - gift_message_available: null, - canonical_url: - '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html', - media_gallery: null, - custom_attributes: null, - add_to_cart_allowed: null, - }, - productView: { - __typename: 'SimpleProduct', - id: 21, - uid: '21', - name: 'Sprite Foam Yoga Brick', - sku: '24-WG084', - description: { - html: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', - }, - short_description: null, - attribute_set_id: null, - meta_title: null, - meta_keyword: null, - meta_description: null, - images: [ - { - url: 'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg', - label: null, - position: null, - disabled: null, - roles: ['thumbnail'], - }, - { - url: 'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg', - label: null, - position: null, - disabled: null, - roles: ['thumbnail'], - }, - { - url: 'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg', - label: null, - position: null, - disabled: null, - roles: ['thumbnail'], - }, - ], - new_from_date: null, - new_to_date: null, - created_at: null, - updated_at: null, - price: { - final: { - amount: { - value: 5, - currency: 'USD', + product: { + __typename: "SimpleProduct", + id: 21, + uid: "21", + name: "Sprite Foam Yoga Brick", + sku: "24-WG084", + description: { + html: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', }, - adjustments: null, - }, - regular: { - amount: { - value: 5, - currency: 'USD', + short_description: null, + attribute_set_id: null, + meta_title: null, + meta_keyword: null, + meta_description: null, + image: { + url: "//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg", + label: null, + position: null, + disabled: null, }, - adjustments: null, - }, - }, - priceRange: { - maximum: { - final: { - amount: { - value: 5, - currency: 'USD', - }, - adjustments: null, - }, - regular: { - amount: { - value: 5, - currency: 'USD', - }, - adjustments: null, + small_image: { + url: "//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg", + label: null, + position: null, + disabled: null, }, - }, - minimum: { - final: { - amount: { - value: 5, - currency: 'USD', - }, - adjustments: null, + thumbnail: { + url: "//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg", + label: null, + position: null, + disabled: null, }, - regular: { - amount: { - value: 8, - currency: 'USD', - }, - adjustments: null, + new_from_date: null, + new_to_date: null, + created_at: null, + updated_at: null, + price_range: { + minimum_price: { + fixed_product_taxes: null, + regular_price: { value: 8, currency: "USD" }, + final_price: { value: 5, currency: "USD" }, + discount: null, + }, + maximum_price: { + fixed_product_taxes: null, + regular_price: { value: 5, currency: "USD" }, + final_price: { value: 5, currency: "USD" }, + discount: null, + }, }, - }, - }, - gift_message_available: null, - url: 'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html', - urlKey: 'sprite-foam-yoga-brick', - media_gallery: null, - custom_attributes: null, - add_to_cart_allowed: null, - options: null, - }, - highlights: [ - { - attribute: 'name', - value: 'Sprite Foam Yoga Brick', - matched_words: [], + gift_message_available: null, + canonical_url: "//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html", + media_gallery: null, + custom_attributes: null, + add_to_cart_allowed: null, }, - { - attribute: 'description', - value: - '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', - matched_words: [], + productView: { + __typename: "SimpleProduct", + id: 21, + uid: "21", + name: "Sprite Foam Yoga Brick", + sku: "24-WG084", + description: { + html: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', + }, + short_description: null, + attribute_set_id: null, + meta_title: null, + meta_keyword: null, + meta_description: null, + images: [ + { + url: "http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg", + label: null, + position: null, + disabled: null, + roles: ["thumbnail"], + }, + { + url: "http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg", + label: null, + position: null, + disabled: null, + roles: ["thumbnail"], + }, + { + url: "http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg", + label: null, + position: null, + disabled: null, + roles: ["thumbnail"], + }, + ], + new_from_date: null, + new_to_date: null, + created_at: null, + updated_at: null, + price: { + final: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, + regular: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, + }, + priceRange: { + maximum: { + final: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, + regular: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, + }, + minimum: { + final: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, + regular: { + amount: { + value: 8, + currency: "USD", + }, + adjustments: null, + }, + }, + }, + gift_message_available: null, + url: "http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html", + urlKey: "sprite-foam-yoga-brick", + media_gallery: null, + custom_attributes: null, + add_to_cart_allowed: null, + options: null, }, - ], + highlights: [ + { + attribute: "name", + value: "Sprite Foam Yoga Brick", + matched_words: [], + }, + { + attribute: "description", + value: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', + matched_words: [], + }, + ], }; export const sampleProductNotDiscounted: Product = { - product: { - __typename: 'SimpleProduct', - id: 21, - uid: '21', - name: 'Sprite Foam Yoga Brick', - sku: '24-WG084', - description: { - html: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', - }, - short_description: null, - attribute_set_id: null, - meta_title: null, - meta_keyword: null, - meta_description: null, - image: { - url: '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg', - label: null, - position: null, - disabled: null, - }, - small_image: { - url: '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg', - label: null, - position: null, - disabled: null, - }, - thumbnail: { - url: '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg', - label: null, - position: null, - disabled: null, - }, - new_from_date: null, - new_to_date: null, - created_at: null, - updated_at: null, - price_range: { - minimum_price: { - fixed_product_taxes: null, - regular_price: { value: 5, currency: 'USD' }, - final_price: { value: 5, currency: 'USD' }, - discount: null, - }, - maximum_price: { - fixed_product_taxes: null, - regular_price: { value: 8, currency: 'USD' }, - final_price: { value: 8, currency: 'USD' }, - discount: null, - }, - }, - gift_message_available: null, - canonical_url: - '//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html', - media_gallery: null, - custom_attributes: null, - add_to_cart_allowed: null, - }, - productView: { - __typename: 'SimpleProduct', - id: 21, - uid: '21', - name: 'Sprite Foam Yoga Brick', - sku: '24-WG084', - description: { - html: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', - }, - short_description: null, - attribute_set_id: null, - meta_title: null, - meta_keyword: null, - meta_description: null, - images: [ - { - url: 'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg', - label: null, - position: null, - disabled: null, - roles: ['thumbnail'], - }, - { - url: 'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg', - label: null, - position: null, - disabled: null, - roles: ['thumbnail'], - }, - { - url: 'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg', - label: null, - position: null, - disabled: null, - roles: ['thumbnail'], - }, - ], - new_from_date: null, - new_to_date: null, - created_at: null, - updated_at: null, - price: { - final: { - amount: { - value: 5, - currency: 'USD', - }, - adjustments: null, - }, - regular: { - amount: { - value: 5, - currency: 'USD', + product: { + __typename: "SimpleProduct", + id: 21, + uid: "21", + name: "Sprite Foam Yoga Brick", + sku: "24-WG084", + description: { + html: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', }, - adjustments: null, - }, - }, - priceRange: { - maximum: { - final: { - amount: { - value: 8, - currency: 'USD', - }, - adjustments: null, + short_description: null, + attribute_set_id: null, + meta_title: null, + meta_keyword: null, + meta_description: null, + image: { + url: "//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg", + label: null, + position: null, + disabled: null, }, - regular: { - amount: { - value: 8, - currency: 'USD', - }, - adjustments: null, + small_image: { + url: "//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg", + label: null, + position: null, + disabled: null, }, - }, - minimum: { - final: { - amount: { - value: 5, - currency: 'USD', - }, - adjustments: null, + thumbnail: { + url: "//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg", + label: null, + position: null, + disabled: null, }, - regular: { - amount: { - value: 8, - currency: 'USD', - }, - adjustments: null, + new_from_date: null, + new_to_date: null, + created_at: null, + updated_at: null, + price_range: { + minimum_price: { + fixed_product_taxes: null, + regular_price: { value: 5, currency: "USD" }, + final_price: { value: 5, currency: "USD" }, + discount: null, + }, + maximum_price: { + fixed_product_taxes: null, + regular_price: { value: 8, currency: "USD" }, + final_price: { value: 8, currency: "USD" }, + discount: null, + }, }, - }, + gift_message_available: null, + canonical_url: "//master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html", + media_gallery: null, + custom_attributes: null, + add_to_cart_allowed: null, }, - gift_message_available: null, - url: 'http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html', - urlKey: 'sprite-foam-yoga-brick', - media_gallery: null, - custom_attributes: null, - add_to_cart_allowed: null, - options: null, - }, - highlights: [ - { - attribute: 'name', - value: 'Sprite Foam Yoga Brick', - matched_words: [], - }, - { - attribute: 'description', - value: - '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', - matched_words: [], + productView: { + __typename: "SimpleProduct", + id: 21, + uid: "21", + name: "Sprite Foam Yoga Brick", + sku: "24-WG084", + description: { + html: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', + }, + short_description: null, + attribute_set_id: null, + meta_title: null, + meta_keyword: null, + meta_description: null, + images: [ + { + url: "http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg", + label: null, + position: null, + disabled: null, + roles: ["thumbnail"], + }, + { + url: "http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg", + label: null, + position: null, + disabled: null, + roles: ["thumbnail"], + }, + { + url: "http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/media/catalog/product/l/u/luma-yoga-brick.jpg", + label: null, + position: null, + disabled: null, + roles: ["thumbnail"], + }, + ], + new_from_date: null, + new_to_date: null, + created_at: null, + updated_at: null, + price: { + final: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, + regular: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, + }, + priceRange: { + maximum: { + final: { + amount: { + value: 8, + currency: "USD", + }, + adjustments: null, + }, + regular: { + amount: { + value: 8, + currency: "USD", + }, + adjustments: null, + }, + }, + minimum: { + final: { + amount: { + value: 5, + currency: "USD", + }, + adjustments: null, + }, + regular: { + amount: { + value: 8, + currency: "USD", + }, + adjustments: null, + }, + }, + }, + gift_message_available: null, + url: "http://master-7rqtwti-eragxvhtzr4am.us-4.magentosite.cloud/sprite-foam-yoga-brick.html", + urlKey: "sprite-foam-yoga-brick", + media_gallery: null, + custom_attributes: null, + add_to_cart_allowed: null, + options: null, }, - ], + highlights: [ + { + attribute: "name", + value: "Sprite Foam Yoga Brick", + matched_words: [], + }, + { + attribute: "description", + value: '

Our top-selling yoga prop, the 4-inch, high-quality Sprite Foam Yoga Brick is popular among yoga novices and studio professionals alike. An essential yoga accessory, the yoga brick is a critical tool for finding balance and alignment in many common yoga poses. Choose from 5 color options.

\n
    \n
  • Standard Large Size: 4" x 6" x 9".\n
  • Beveled edges for ideal contour grip.\n
  • Durable and soft, scratch-proof foam.\n
  • Individually wrapped.\n
  • Ten color choices.\n
', + matched_words: [], + }, + ], }; diff --git a/src/components/ProductItem/ProductItem.test.tsx b/src/components/ProductItem/ProductItem.test.tsx index a89ac86..f536fe9 100644 --- a/src/components/ProductItem/ProductItem.test.tsx +++ b/src/components/ProductItem/ProductItem.test.tsx @@ -7,39 +7,39 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { sampleProductNotDiscounted } from './MockData'; -import ProductItem from './ProductItem'; +import { sampleProductNotDiscounted } from "./MockData"; +import ProductItem from "./ProductItem"; beforeEach(() => { - // IntersectionObserver isn't available in test environment - const mockIntersectionObserver = jest.fn(); - mockIntersectionObserver.mockReturnValue({ - observe: () => null, - unobserve: () => null, - disconnect: () => null, - }); - window.IntersectionObserver = mockIntersectionObserver; + // IntersectionObserver isn't available in test environment + const mockIntersectionObserver = jest.fn(); + mockIntersectionObserver.mockReturnValue({ + observe: () => null, + unobserve: () => null, + disconnect: () => null, + }); + window.IntersectionObserver = mockIntersectionObserver; }); -describe('WidgetSDK - UIKit/ProductItem', () => { - test('renders', () => { - const { container } = render( - {}} - setItemAdded={() => 'test'} - setCartUpdated={() => true} - setError={() => ''} - /> - ); +describe("WidgetSDK - UIKit/ProductItem", () => { + test("renders", () => { + const { container } = render( + {}} + setItemAdded={() => "test"} + setCartUpdated={() => true} + setError={() => ""} + />, + ); - const elem = container.querySelector('.ds-sdk-product-item'); + const elem = container.querySelector(".ds-sdk-product-item"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/ProductItem/ProductPrice.tsx b/src/components/ProductItem/ProductPrice.tsx index 74649e5..76b8f30 100644 --- a/src/components/ProductItem/ProductPrice.tsx +++ b/src/components/ProductItem/ProductPrice.tsx @@ -7,195 +7,165 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; -import { useContext } from 'preact/hooks'; +import { FunctionComponent } from "preact"; +import { useContext } from "preact/hooks"; -import { TranslationContext } from '../../context/translation'; -import { Product, RefinedProduct } from '../../types/interface'; -import { getProductPrice } from '../../utils/getProductPrice'; +import { TranslationContext } from "../../context/translation"; +import { Product, RefinedProduct } from "../../types/interface"; +import { getProductPrice } from "../../utils/getProductPrice"; export interface ProductPriceProps { - isComplexProductView: boolean; - item: Product | RefinedProduct; - isBundle: boolean; - isGrouped: boolean; - isGiftCard: boolean; - isConfigurable: boolean; - discount: boolean | undefined; - currencySymbol: string; - currencyRate?: string; + isComplexProductView: boolean; + item: Product | RefinedProduct; + isBundle: boolean; + isGrouped: boolean; + isGiftCard: boolean; + isConfigurable: boolean; + discount: boolean | undefined; + currencySymbol: string; + currencyRate?: string; } export const ProductPrice: FunctionComponent = ({ - isComplexProductView, - item, - isBundle, - isGrouped, - isGiftCard, - isConfigurable, - discount, - currencySymbol, - currencyRate, + isComplexProductView, + item, + isBundle, + isGrouped, + isGiftCard, + isConfigurable, + discount, + currencySymbol, + currencyRate, }: ProductPriceProps) => { - const translation = useContext(TranslationContext); - let price; + const translation = useContext(TranslationContext); + let price; - if ('product' in item) { - price = - item?.product?.price_range?.minimum_price?.final_price ?? - item?.product?.price_range?.minimum_price?.regular_price; - } else { - price = - item?.refineProduct?.priceRange?.minimum?.final ?? - item?.refineProduct?.price?.final; - } - const getBundledPrice = ( - item: Product | RefinedProduct, - currencySymbol: string, - currencyRate: string | undefined - ) => { - const bundlePriceTranslationOrder = - translation.ProductCard.bundlePrice.split(' '); - return bundlePriceTranslationOrder.map((word: string, index: any) => - word === '{fromBundlePrice}' ? ( - `${getProductPrice(item, currencySymbol, currencyRate, false, true)} ` - ) : word === '{toBundlePrice}' ? ( - getProductPrice(item, currencySymbol, currencyRate, true, true) - ) : ( - - {word} - - ) - ); - }; - - const getPriceFormat = ( - item: Product | RefinedProduct, - currencySymbol: string, - currencyRate: string | undefined, - isGiftCard: boolean - ) => { - const priceTranslation = isGiftCard - ? translation.ProductCard.from - : translation.ProductCard.startingAt; - const startingAtTranslationOrder = priceTranslation.split('{productPrice}'); - return startingAtTranslationOrder.map((word: string, index: any) => - word === '' ? ( - getProductPrice(item, currencySymbol, currencyRate, false, true) - ) : ( - - {word} - - ) - ); - }; + if ("product" in item) { + price = + item?.product?.price_range?.minimum_price?.final_price ?? + item?.product?.price_range?.minimum_price?.regular_price; + } else { + price = item?.refineProduct?.priceRange?.minimum?.final ?? item?.refineProduct?.price?.final; + } + const getBundledPrice = ( + item: Product | RefinedProduct, + currencySymbol: string, + currencyRate: string | undefined, + ) => { + const bundlePriceTranslationOrder = translation.ProductCard.bundlePrice.split(" "); + return bundlePriceTranslationOrder.map((word: string, index: any) => + word === "{fromBundlePrice}" ? ( + `${getProductPrice(item, currencySymbol, currencyRate, false, true)} ` + ) : word === "{toBundlePrice}" ? ( + getProductPrice(item, currencySymbol, currencyRate, true, true) + ) : ( + + {word} + + ), + ); + }; - const getDiscountedPrice = (discount: boolean | undefined) => { - const discountPrice = discount ? ( - <> - - {getProductPrice(item, currencySymbol, currencyRate, false, false)} - - - {getProductPrice(item, currencySymbol, currencyRate, false, true)} - - - ) : ( - getProductPrice(item, currencySymbol, currencyRate, false, true) - ); - const discountedPriceTranslation = translation.ProductCard.asLowAs; - const discountedPriceTranslationOrder = - discountedPriceTranslation.split('{discountPrice}'); - return discountedPriceTranslationOrder.map((word: string, index: any) => - word === '' ? ( - discountPrice - ) : ( - - {word} - - ) - ); - }; + const getPriceFormat = ( + item: Product | RefinedProduct, + currencySymbol: string, + currencyRate: string | undefined, + isGiftCard: boolean, + ) => { + const priceTranslation = isGiftCard ? translation.ProductCard.from : translation.ProductCard.startingAt; + const startingAtTranslationOrder = priceTranslation.split("{productPrice}"); + return startingAtTranslationOrder.map((word: string, index: any) => + word === "" ? ( + getProductPrice(item, currencySymbol, currencyRate, false, true) + ) : ( + + {word} + + ), + ); + }; - return ( - <> - {price && ( -
- {!isBundle && - !isGrouped && - !isConfigurable && - !isComplexProductView && - discount && ( -

+ const getDiscountedPrice = (discount: boolean | undefined) => { + const discountPrice = discount ? ( + <> - {getProductPrice( - item, - currencySymbol, - currencyRate, - false, - false - )} + {getProductPrice(item, currencySymbol, currencyRate, false, false)} - {getProductPrice( - item, - currencySymbol, - currencyRate, - false, - true - )} + {getProductPrice(item, currencySymbol, currencyRate, false, true)} -

- )} + + ) : ( + getProductPrice(item, currencySymbol, currencyRate, false, true) + ); + const discountedPriceTranslation = translation.ProductCard.asLowAs; + const discountedPriceTranslationOrder = discountedPriceTranslation.split("{discountPrice}"); + return discountedPriceTranslationOrder.map((word: string, index: any) => + word === "" ? ( + discountPrice + ) : ( + + {word} + + ), + ); + }; - {!isBundle && - !isGrouped && - !isGiftCard && - !isConfigurable && - !isComplexProductView && - !discount && ( -

- {getProductPrice( - item, - currencySymbol, - currencyRate, - false, - true - )} -

- )} + return ( + <> + {price && ( +
+ {!isBundle && !isGrouped && !isConfigurable && !isComplexProductView && discount && ( +

+ + {getProductPrice(item, currencySymbol, currencyRate, false, false)} + + + {getProductPrice(item, currencySymbol, currencyRate, false, true)} + +

+ )} + + {!isBundle && + !isGrouped && + !isGiftCard && + !isConfigurable && + !isComplexProductView && + !discount && ( +

+ {getProductPrice(item, currencySymbol, currencyRate, false, true)} +

+ )} - {isBundle && ( -
-

- {getBundledPrice(item, currencySymbol, currencyRate)} -

-
- )} + {isBundle && ( +
+

+ {getBundledPrice(item, currencySymbol, currencyRate)} +

+
+ )} - {isGrouped && ( -

- {getPriceFormat(item, currencySymbol, currencyRate, false)} -

- )} + {isGrouped && ( +

+ {getPriceFormat(item, currencySymbol, currencyRate, false)} +

+ )} - {isGiftCard && ( -

- {getPriceFormat(item, currencySymbol, currencyRate, true)} -

- )} + {isGiftCard && ( +

+ {getPriceFormat(item, currencySymbol, currencyRate, true)} +

+ )} - {!isGrouped && - !isBundle && - (isConfigurable || isComplexProductView) && ( -

- {getDiscountedPrice(discount)} -

+ {!isGrouped && !isBundle && (isConfigurable || isComplexProductView) && ( +

+ {getDiscountedPrice(discount)} +

+ )} +
)} -
- )} - - ); + + ); }; export default ProductPrice; diff --git a/src/components/ProductItem/index.ts b/src/components/ProductItem/index.ts index c5d8978..4217cbf 100644 --- a/src/components/ProductItem/index.ts +++ b/src/components/ProductItem/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './ProductItem'; -export { ProductItem as default } from './ProductItem'; +export * from "./ProductItem"; +export { ProductItem as default } from "./ProductItem"; diff --git a/src/components/ProductList/MockData.ts b/src/components/ProductList/MockData.ts index 4cd08f9..44f7bae 100644 --- a/src/components/ProductList/MockData.ts +++ b/src/components/ProductList/MockData.ts @@ -8,177 +8,175 @@ it. */ const SimpleProduct = { - product: { - sku: '24-WG088', - name: 'Sprite Foam Roller', - canonical_url: - 'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/sprite-foam-roller.html', - }, - productView: { - __typename: 'SimpleProductView', - sku: '24-WG088', - name: 'Sprite Foam Roller', - url: 'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/sprite-foam-roller.html', - urlKey: 'sprite-foam-roller', - images: [ - { - label: 'Image', - url: 'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/media/catalog/product/l/u/luma-foam-roller.jpg', - }, - ], - price: { - final: { - amount: { - value: 19.0, - currency: 'USD', - }, - }, - regular: { - amount: { - value: 19.0, - currency: 'USD', - }, - }, + product: { + sku: "24-WG088", + name: "Sprite Foam Roller", + canonical_url: "http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/sprite-foam-roller.html", }, - }, - highlights: [ - { - attribute: 'name', - value: 'Sprite Foam Roller', - matched_words: [], + productView: { + __typename: "SimpleProductView", + sku: "24-WG088", + name: "Sprite Foam Roller", + url: "http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/sprite-foam-roller.html", + urlKey: "sprite-foam-roller", + images: [ + { + label: "Image", + url: "http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/media/catalog/product/l/u/luma-foam-roller.jpg", + }, + ], + price: { + final: { + amount: { + value: 19.0, + currency: "USD", + }, + }, + regular: { + amount: { + value: 19.0, + currency: "USD", + }, + }, + }, }, - ], + highlights: [ + { + attribute: "name", + value: "Sprite Foam Roller", + matched_words: [], + }, + ], }; const ComplexProduct = { - product: { - sku: 'MSH06', - name: 'Lono Yoga Short', - canonical_url: - 'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/lono-yoga-short.html', - }, - productView: { - __typename: 'ComplexProductView', - sku: 'MSH06', - name: 'Lono Yoga Short', - url: 'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/lono-yoga-short.html', - urlKey: 'lono-yoga-short', - images: [ - { - label: '', - url: 'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/media/catalog/product/m/s/msh06-gray_main_2.jpg', - }, - { - label: '', - url: 'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/media/catalog/product/m/s/msh06-gray_alt1_2.jpg', - }, - { - label: '', - url: 'http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/media/catalog/product/m/s/msh06-gray_back_2.jpg', - }, - ], - priceRange: { - maximum: { - final: { - amount: { - value: 32.0, - currency: 'USD', - }, - }, - regular: { - amount: { - value: 32.0, - currency: 'USD', - }, - }, - }, - minimum: { - final: { - amount: { - value: 32.0, - currency: 'USD', - }, - }, - regular: { - amount: { - value: 32.0, - currency: 'USD', - }, - }, - }, + product: { + sku: "MSH06", + name: "Lono Yoga Short", + canonical_url: "http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/lono-yoga-short.html", }, - options: [ - { - id: 'size', - title: 'Size', - values: [ - { - title: '32', - id: 'Y29uZmlndXJhYmxlLzE4Ni8xODQ=', - type: 'TEXT', - value: '32', - }, - { - title: '33', - id: 'Y29uZmlndXJhYmxlLzE4Ni8xODU=', - type: 'TEXT', - value: '33', - }, - { - title: '34', - id: 'Y29uZmlndXJhYmxlLzE4Ni8xODY=', - type: 'TEXT', - value: '34', - }, - { - title: '36', - id: 'Y29uZmlndXJhYmxlLzE4Ni8xODc=', - type: 'TEXT', - value: '36', - }, + productView: { + __typename: "ComplexProductView", + sku: "MSH06", + name: "Lono Yoga Short", + url: "http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/lono-yoga-short.html", + urlKey: "lono-yoga-short", + images: [ + { + label: "", + url: "http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/media/catalog/product/m/s/msh06-gray_main_2.jpg", + }, + { + label: "", + url: "http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/media/catalog/product/m/s/msh06-gray_alt1_2.jpg", + }, + { + label: "", + url: "http://master-7rqtwti-grxawiljl6f4y.us-4.magentosite.cloud/media/catalog/product/m/s/msh06-gray_back_2.jpg", + }, ], - }, - { - id: 'color', - title: 'Color', - values: [ - { - title: 'Blue', - id: 'Y29uZmlndXJhYmxlLzkzLzU5', - type: 'COLOR_HEX', - value: '#1857f7', - }, - { - title: 'Red', - id: 'Y29uZmlndXJhYmxlLzkzLzY3', - type: 'COLOR_HEX', - value: '#ff0000', - }, - { - title: 'Gray', - id: 'Y29uZmlndXJhYmxlLzkzLzYx', - type: 'COLOR_HEX', - value: '#8f8f8f', - }, + priceRange: { + maximum: { + final: { + amount: { + value: 32.0, + currency: "USD", + }, + }, + regular: { + amount: { + value: 32.0, + currency: "USD", + }, + }, + }, + minimum: { + final: { + amount: { + value: 32.0, + currency: "USD", + }, + }, + regular: { + amount: { + value: 32.0, + currency: "USD", + }, + }, + }, + }, + options: [ + { + id: "size", + title: "Size", + values: [ + { + title: "32", + id: "Y29uZmlndXJhYmxlLzE4Ni8xODQ=", + type: "TEXT", + value: "32", + }, + { + title: "33", + id: "Y29uZmlndXJhYmxlLzE4Ni8xODU=", + type: "TEXT", + value: "33", + }, + { + title: "34", + id: "Y29uZmlndXJhYmxlLzE4Ni8xODY=", + type: "TEXT", + value: "34", + }, + { + title: "36", + id: "Y29uZmlndXJhYmxlLzE4Ni8xODc=", + type: "TEXT", + value: "36", + }, + ], + }, + { + id: "color", + title: "Color", + values: [ + { + title: "Blue", + id: "Y29uZmlndXJhYmxlLzkzLzU5", + type: "COLOR_HEX", + value: "#1857f7", + }, + { + title: "Red", + id: "Y29uZmlndXJhYmxlLzkzLzY3", + type: "COLOR_HEX", + value: "#ff0000", + }, + { + title: "Gray", + id: "Y29uZmlndXJhYmxlLzkzLzYx", + type: "COLOR_HEX", + value: "#8f8f8f", + }, + ], + }, ], - }, - ], - }, - highlights: [ - { - attribute: 'name', - value: 'Lono Yoga Short', - matched_words: [], }, - ], + highlights: [ + { + attribute: "name", + value: "Lono Yoga Short", + matched_words: [], + }, + ], }; export const products = [ - SimpleProduct, - SimpleProduct, - SimpleProduct, - SimpleProduct, - SimpleProduct, - SimpleProduct, - ComplexProduct, + SimpleProduct, + SimpleProduct, + SimpleProduct, + SimpleProduct, + SimpleProduct, + SimpleProduct, + ComplexProduct, ]; diff --git a/src/components/ProductList/ProductList.test.tsx b/src/components/ProductList/ProductList.test.tsx index 4705135..9330ebf 100644 --- a/src/components/ProductList/ProductList.test.tsx +++ b/src/components/ProductList/ProductList.test.tsx @@ -7,18 +7,16 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { ProductList } from './ProductList'; +import { ProductList } from "./ProductList"; -describe('WidgetSDK - UIKit/ProductList', () => { - test('renders', () => { - const { container } = render( - - ); +describe("WidgetSDK - UIKit/ProductList", () => { + test("renders", () => { + const { container } = render(); - const elem = container.querySelector('.ds-sdk-product-list'); + const elem = container.querySelector(".ds-sdk-product-list"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/ProductList/ProductList.tsx b/src/components/ProductList/ProductList.tsx index 57a0679..7aa11f0 100644 --- a/src/components/ProductList/ProductList.tsx +++ b/src/components/ProductList/ProductList.tsx @@ -7,124 +7,108 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; -import { HTMLAttributes } from 'preact/compat'; -import { useEffect, useState } from 'preact/hooks'; +import { FunctionComponent } from "preact"; +import { HTMLAttributes } from "preact/compat"; +import { useEffect, useState } from "preact/hooks"; -import './product-list.css'; +import "./product-list.css"; -import { Alert } from '../../components/Alert'; -import { useProducts, useStore } from '../../context'; -import { Product } from '../../types/interface'; -import { classNames } from '../../utils/dom'; -import ProductItem from '../ProductItem'; +import { Alert } from "../../components/Alert"; +import { useProducts, useStore } from "../../context"; +import { Product } from "../../types/interface"; +import { classNames } from "../../utils/dom"; +import ProductItem from "../ProductItem"; export interface ProductListProps extends HTMLAttributes { - products: Array | null | undefined; - numberOfColumns: number; - showFilters: boolean; + products: Array | null | undefined; + numberOfColumns: number; + showFilters: boolean; } -export const ProductList: FunctionComponent = ({ - products, - numberOfColumns, - showFilters, -}) => { - const productsCtx = useProducts(); - const { - currencySymbol, - currencyRate, - setRoute, - refineProduct, - refreshCart, - addToCart, - } = productsCtx; - const [cartUpdated, setCartUpdated] = useState(false); - const [itemAdded, setItemAdded] = useState(''); - const { viewType } = useProducts(); - const [error, setError] = useState(false); - const { - config: { listview }, - } = useStore(); +export const ProductList: FunctionComponent = ({ products, numberOfColumns, showFilters }) => { + const productsCtx = useProducts(); + const { currencySymbol, currencyRate, setRoute, refineProduct, refreshCart, addToCart } = productsCtx; + const [cartUpdated, setCartUpdated] = useState(false); + const [itemAdded, setItemAdded] = useState(""); + const { viewType } = useProducts(); + const [error, setError] = useState(false); + const { + config: { listview }, + } = useStore(); - const className = showFilters - ? 'ds-sdk-product-list bg-body max-w-full pl-3 pb-2xl sm:pb-24' - : 'ds-sdk-product-list bg-body w-full mx-auto pb-2xl sm:pb-24'; + const className = showFilters + ? "ds-sdk-product-list bg-body max-w-full pl-3 pb-2xl sm:pb-24" + : "ds-sdk-product-list bg-body w-full mx-auto pb-2xl sm:pb-24"; - useEffect(() => { - refreshCart && refreshCart(); - }, [itemAdded]); + useEffect(() => { + refreshCart && refreshCart(); + }, [itemAdded]); - return ( -
- {cartUpdated && ( -
- setCartUpdated(false)} - /> -
- )} - {error && ( -
- setError(false)} - /> -
- )} + return ( +
+ {cartUpdated && ( +
+ setCartUpdated(false)} + /> +
+ )} + {error && ( +
+ setError(false)} + /> +
+ )} - {listview && viewType === 'listview' ? ( -
-
- {products?.map((product) => ( - - ))} -
-
- ) : ( -
- {products?.map((product) => ( - - ))} + {listview && viewType === "listview" ? ( +
+
+ {products?.map((product) => ( + + ))} +
+
+ ) : ( +
+ {products?.map((product) => ( + + ))} +
+ )}
- )} -
- ); + ); }; diff --git a/src/components/ProductList/index.ts b/src/components/ProductList/index.ts index aafccd5..6e18f55 100644 --- a/src/components/ProductList/index.ts +++ b/src/components/ProductList/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './ProductList'; -export { ProductList as default } from './ProductList'; +export * from "./ProductList"; +export { ProductList as default } from "./ProductList"; diff --git a/src/components/SearchBar/SearchBar.test.tsx b/src/components/SearchBar/SearchBar.test.tsx index e96294a..c34a5ef 100644 --- a/src/components/SearchBar/SearchBar.test.tsx +++ b/src/components/SearchBar/SearchBar.test.tsx @@ -7,18 +7,16 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { SearchBar } from './SearchBar'; +import { SearchBar } from "./SearchBar"; -describe('WidgetSDK - UIKit/SearchBar', () => { - test('renders', () => { - const { container } = render( - {}} onClear={() => {}} /> - ); +describe("WidgetSDK - UIKit/SearchBar", () => { + test("renders", () => { + const { container } = render( {}} onClear={() => {}} />); - const elem = container.querySelector('.ds-sdk-search-bar'); + const elem = container.querySelector(".ds-sdk-search-bar"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/SearchBar/SearchBar.tsx b/src/components/SearchBar/SearchBar.tsx index aaaa614..589076e 100644 --- a/src/components/SearchBar/SearchBar.tsx +++ b/src/components/SearchBar/SearchBar.tsx @@ -7,32 +7,28 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; -import { ChangeEvent, HTMLAttributes } from 'preact/compat'; +import { FunctionComponent } from "preact"; +import { ChangeEvent, HTMLAttributes } from "preact/compat"; export interface SearchBarProps extends HTMLAttributes { - phrase: string; - onKeyPress: (event: ChangeEvent) => void; - onClear: () => void; - placeholder?: string; + phrase: string; + onKeyPress: (event: ChangeEvent) => void; + onClear: () => void; + placeholder?: string; } -export const SearchBar: FunctionComponent = ({ - phrase, - onKeyPress, - placeholder, -}) => { - return ( -
- -
- ); +export const SearchBar: FunctionComponent = ({ phrase, onKeyPress, placeholder }) => { + return ( +
+ +
+ ); }; diff --git a/src/components/SearchBar/index.ts b/src/components/SearchBar/index.ts index 982c66f..2293964 100644 --- a/src/components/SearchBar/index.ts +++ b/src/components/SearchBar/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './SearchBar'; -export { SearchBar as default } from './SearchBar'; +export * from "./SearchBar"; +export { SearchBar as default } from "./SearchBar"; diff --git a/src/components/Shimmer/Shimmer.tsx b/src/components/Shimmer/Shimmer.tsx index edef707..921d25b 100644 --- a/src/components/Shimmer/Shimmer.tsx +++ b/src/components/Shimmer/Shimmer.tsx @@ -7,61 +7,61 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; -import { useSensor } from '@/context'; +import { useSensor } from "@/context"; -import ButtonShimmer from '../ButtonShimmer'; -import FacetsShimmer from '../FacetsShimmer'; -import ProductCardShimmer from '../ProductCardShimmer'; +import ButtonShimmer from "../ButtonShimmer"; +import FacetsShimmer from "../FacetsShimmer"; +import ProductCardShimmer from "../ProductCardShimmer"; export const Shimmer: FunctionComponent = () => { - const productCardArray = Array.from({ length: 8 }); - const facetsArray = Array.from({ length: 4 }); - const { screenSize } = useSensor(); - const numberOfColumns = screenSize.columns; + const productCardArray = Array.from({ length: 8 }); + const facetsArray = Array.from({ length: 4 }); + const { screenSize } = useSensor(); + const numberOfColumns = screenSize.columns; - return ( -
-
-
-
-
-
- + return ( +
+
+
+
+
+
+ +
+
+
+
+ {facetsArray.map((_, index) => ( + + ))} + +
+
+
+
+
+ +
+
+
+ {productCardArray.map((_, index) => ( + + ))} +
+
-
-
-
- {facetsArray.map((_, index) => ( - - ))} - -
-
-
-
- -
-
-
- {productCardArray.map((_, index) => ( - - ))} -
-
-
-
- ); + ); }; export default Shimmer; diff --git a/src/components/Shimmer/index.ts b/src/components/Shimmer/index.ts index b337050..127c8d5 100644 --- a/src/components/Shimmer/index.ts +++ b/src/components/Shimmer/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './Shimmer'; -export { Shimmer as default } from './Shimmer'; +export * from "./Shimmer"; +export { Shimmer as default } from "./Shimmer"; diff --git a/src/components/Slider/Slider.test.tsx b/src/components/Slider/Slider.test.tsx index 6e2af7f..b03ccbd 100644 --- a/src/components/Slider/Slider.test.tsx +++ b/src/components/Slider/Slider.test.tsx @@ -7,45 +7,45 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { PriceFacet } from '@/types/interface'; +import { PriceFacet } from "@/types/interface"; -import { Slider } from './Slider'; +import { Slider } from "./Slider"; -describe('PLP widget/Slider', () => { - test('renders', () => { - const filterData: PriceFacet = { - title: 'Price', - attribute: 'price', - buckets: [ - { - title: '10.0-25.0', - __typename: 'RangeBucket', - from: 10, - to: 25, - count: 1, - }, - { - title: '25.0-50.0', - __typename: 'RangeBucket', - from: 25, - to: 50, - count: 10, - }, - { - title: '50.0-75.0', - __typename: 'RangeBucket', - from: 50, - to: 75, - count: 1, - }, - ], - }; - const { container } = render(); +describe("PLP widget/Slider", () => { + test("renders", () => { + const filterData: PriceFacet = { + title: "Price", + attribute: "price", + buckets: [ + { + title: "10.0-25.0", + __typename: "RangeBucket", + from: 10, + to: 25, + count: 1, + }, + { + title: "25.0-50.0", + __typename: "RangeBucket", + from: 25, + to: 50, + count: 10, + }, + { + title: "50.0-75.0", + __typename: "RangeBucket", + from: 50, + to: 75, + count: 1, + }, + ], + }; + const { container } = render(); - const elem = container.querySelector('.ds-sdk-slider'); + const elem = container.querySelector(".ds-sdk-slider"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/Slider/Slider.tsx b/src/components/Slider/Slider.tsx index b2787da..b283839 100644 --- a/src/components/Slider/Slider.tsx +++ b/src/components/Slider/Slider.tsx @@ -7,111 +7,96 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; -import { HTMLAttributes, useState } from 'preact/compat'; -import { useEffect } from 'react'; +import { FunctionComponent } from "preact"; +import { HTMLAttributes, useState } from "preact/compat"; +import { useEffect } from "react"; -import '../Slider/Slider.css'; +import "../Slider/Slider.css"; -import { useProducts, useSearch } from '../../context'; -import useSliderFacet from '../../hooks/useSliderFacet'; -import { PriceFacet } from '../../types/interface'; +import { useProducts, useSearch } from "../../context"; +import useSliderFacet from "../../hooks/useSliderFacet"; +import { PriceFacet } from "../../types/interface"; export interface SliderProps extends HTMLAttributes { - filterData: PriceFacet; + filterData: PriceFacet; } export type Bucket = { - title: string; - id?: string; - count: number; - to?: number; - from?: number; - name?: string; - __typename: 'ScalarBucket' | 'RangeBucket' | 'CategoryView'; + title: string; + id?: string; + count: number; + to?: number; + from?: number; + name?: string; + __typename: "ScalarBucket" | "RangeBucket" | "CategoryView"; }; export const Slider: FunctionComponent = ({ filterData }) => { - const productsCtx = useProducts(); - const [isFirstRender, setIsFirstRender] = useState(true); - const preSelectedToPrice = productsCtx.variables.filter?.find( - (obj) => obj.attribute === 'price' - )?.range?.to; + const productsCtx = useProducts(); + const [isFirstRender, setIsFirstRender] = useState(true); + const preSelectedToPrice = productsCtx.variables.filter?.find((obj) => obj.attribute === "price")?.range?.to; - const searchCtx = useSearch(); + const searchCtx = useSearch(); - useEffect(() => { - if ( - searchCtx?.filters?.length === 0 || - !searchCtx?.filters?.find((obj) => obj.attribute === 'price') - ) { - setSelectedPrice(filterData.buckets[filterData.buckets.length - 1].to); - } - }, [searchCtx]); + useEffect(() => { + if (searchCtx?.filters?.length === 0 || !searchCtx?.filters?.find((obj) => obj.attribute === "price")) { + setSelectedPrice(filterData.buckets[filterData.buckets.length - 1].to); + } + }, [searchCtx]); - useEffect(() => { - if (!isFirstRender) { - setSelectedPrice(filterData.buckets[filterData.buckets.length - 1].to); - } - setIsFirstRender(false); - }, [filterData.buckets[filterData.buckets.length - 1].to]); + useEffect(() => { + if (!isFirstRender) { + setSelectedPrice(filterData.buckets[filterData.buckets.length - 1].to); + } + setIsFirstRender(false); + }, [filterData.buckets[filterData.buckets.length - 1].to]); - const { onChange } = useSliderFacet(filterData); - const [selectedPrice, setSelectedPrice] = useState( - !preSelectedToPrice - ? filterData.buckets[filterData.buckets.length - 1].to - : preSelectedToPrice - ); - const handleSliderChange = (event: any) => { - onChange(filterData.buckets[0].from, parseInt(event.target.value)); - }; - const handleNewPrice = (event: any) => { - setSelectedPrice(parseInt(event.target.value)); - }; + const { onChange } = useSliderFacet(filterData); + const [selectedPrice, setSelectedPrice] = useState( + !preSelectedToPrice ? filterData.buckets[filterData.buckets.length - 1].to : preSelectedToPrice, + ); + const handleSliderChange = (event: any) => { + onChange(filterData.buckets[0].from, parseInt(event.target.value)); + }; + const handleNewPrice = (event: any) => { + setSelectedPrice(parseInt(event.target.value)); + }; - const formatLabel = (price: number) => { - const currencyRate = productsCtx.currencyRate - ? productsCtx.currencyRate - : '1'; - const currencySymbol = productsCtx.currencySymbol - ? productsCtx.currencySymbol - : '$'; + const formatLabel = (price: number) => { + const currencyRate = productsCtx.currencyRate ? productsCtx.currencyRate : "1"; + const currencySymbol = productsCtx.currencySymbol ? productsCtx.currencySymbol : "$"; - const label = `${currencySymbol}${ - price && parseFloat(currencyRate) * parseInt(price.toFixed(0), 10) - ? (parseFloat(currencyRate) * parseInt(price.toFixed(0), 10)).toFixed(2) - : 0 - }`; - return label; - }; + const label = `${currencySymbol}${ + price && parseFloat(currencyRate) * parseInt(price.toFixed(0), 10) + ? (parseFloat(currencyRate) * parseInt(price.toFixed(0), 10)).toFixed(2) + : 0 + }`; + return label; + }; - return ( - <> -

{filterData.title}

-
- - {formatLabel(selectedPrice)} -
- - {formatLabel(filterData.buckets[0].from)} - - - {formatLabel(filterData.buckets[filterData.buckets.length - 1].to)} - -
-
-
- - ); + return ( + <> +

{filterData.title}

+
+ + {formatLabel(selectedPrice)} +
+ {formatLabel(filterData.buckets[0].from)} + {formatLabel(filterData.buckets[filterData.buckets.length - 1].to)} +
+
+
+ + ); }; diff --git a/src/components/Slider/index.tsx b/src/components/Slider/index.tsx index af745a8..ea50d01 100644 --- a/src/components/Slider/index.tsx +++ b/src/components/Slider/index.tsx @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './Slider'; -export { Slider as default } from './Slider'; +export * from "./Slider"; +export { Slider as default } from "./Slider"; diff --git a/src/components/SliderDoubleControl/SliderDoubleControl.test.tsx b/src/components/SliderDoubleControl/SliderDoubleControl.test.tsx index 067aa71..2fc6a4e 100644 --- a/src/components/SliderDoubleControl/SliderDoubleControl.test.tsx +++ b/src/components/SliderDoubleControl/SliderDoubleControl.test.tsx @@ -7,47 +7,45 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { PriceFacet } from '@/types/interface'; +import { PriceFacet } from "@/types/interface"; -import { SliderDoubleControl } from './SliderDoubleControl'; +import { SliderDoubleControl } from "./SliderDoubleControl"; -describe('PLP widget/SliderDoubleControl', () => { - test('renders', () => { - const filterData: PriceFacet = { - title: 'Price', - attribute: 'price', - buckets: [ - { - title: '10.0-25.0', - __typename: 'RangeBucket', - from: 10, - to: 25, - count: 1, - }, - { - title: '25.0-50.0', - __typename: 'RangeBucket', - from: 25, - to: 50, - count: 10, - }, - { - title: '50.0-75.0', - __typename: 'RangeBucket', - from: 50, - to: 75, - count: 1, - }, - ], - }; - const { container } = render( - - ); +describe("PLP widget/SliderDoubleControl", () => { + test("renders", () => { + const filterData: PriceFacet = { + title: "Price", + attribute: "price", + buckets: [ + { + title: "10.0-25.0", + __typename: "RangeBucket", + from: 10, + to: 25, + count: 1, + }, + { + title: "25.0-50.0", + __typename: "RangeBucket", + from: 25, + to: 50, + count: 10, + }, + { + title: "50.0-75.0", + __typename: "RangeBucket", + from: 50, + to: 75, + count: 1, + }, + ], + }; + const { container } = render(); - const elem = container.querySelector('.ds-sdk-slider'); + const elem = container.querySelector(".ds-sdk-slider"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/SliderDoubleControl/SliderDoubleControl.tsx b/src/components/SliderDoubleControl/SliderDoubleControl.tsx index ed34da7..2bf7010 100644 --- a/src/components/SliderDoubleControl/SliderDoubleControl.tsx +++ b/src/components/SliderDoubleControl/SliderDoubleControl.tsx @@ -7,146 +7,116 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; -import { HTMLAttributes, useEffect, useState } from 'preact/compat'; +import { FunctionComponent } from "preact"; +import { HTMLAttributes, useEffect, useState } from "preact/compat"; -import '../SliderDoubleControl/SliderDoubleControl.css'; +import "../SliderDoubleControl/SliderDoubleControl.css"; -import { useProducts, useSearch } from '../../context'; -import useSliderFacet from '../../hooks/useSliderFacet'; -import { PriceFacet } from '../../types/interface'; +import { useProducts, useSearch } from "../../context"; +import useSliderFacet from "../../hooks/useSliderFacet"; +import { PriceFacet } from "../../types/interface"; export interface SliderProps extends HTMLAttributes { - filterData: PriceFacet; + filterData: PriceFacet; } export type Bucket = { - title: string; - id?: string; - count: number; - to?: number; - from?: number; - name?: string; - __typename: 'ScalarBucket' | 'RangeBucket' | 'CategoryView'; + title: string; + id?: string; + count: number; + to?: number; + from?: number; + name?: string; + __typename: "ScalarBucket" | "RangeBucket" | "CategoryView"; }; -export const SliderDoubleControl: FunctionComponent = ({ - filterData, -}) => { - const productsCtx = useProducts(); - const searchCtx = useSearch(); - const min = filterData.buckets[0].from; - const max = filterData.buckets[filterData.buckets.length - 1].to; - const preSelectedToPrice = productsCtx.variables.filter?.find( - (obj) => obj.attribute === 'price' - )?.range?.to; - const preSelectedFromPrice = productsCtx.variables.filter?.find( - (obj) => obj.attribute === 'price' - )?.range?.from; - const [minVal, setMinVal] = useState( - preSelectedFromPrice ? preSelectedFromPrice : min - ); - const [maxVal, setMaxVal] = useState( - preSelectedToPrice ? preSelectedToPrice : max - ); - const { onChange } = useSliderFacet(filterData); +export const SliderDoubleControl: FunctionComponent = ({ filterData }) => { + const productsCtx = useProducts(); + const searchCtx = useSearch(); + const min = filterData.buckets[0].from; + const max = filterData.buckets[filterData.buckets.length - 1].to; + const preSelectedToPrice = productsCtx.variables.filter?.find((obj) => obj.attribute === "price")?.range?.to; + const preSelectedFromPrice = productsCtx.variables.filter?.find((obj) => obj.attribute === "price")?.range?.from; + const [minVal, setMinVal] = useState(preSelectedFromPrice ? preSelectedFromPrice : min); + const [maxVal, setMaxVal] = useState(preSelectedToPrice ? preSelectedToPrice : max); + const { onChange } = useSliderFacet(filterData); - const fromSliderId = `fromSlider_${filterData.attribute}`; - const toSliderId = `toSlider_${filterData.attribute}`; - const fromInputId = `fromInput_${filterData.attribute}`; - const toInputId = `toInput_${filterData.attribute}`; + const fromSliderId = `fromSlider_${filterData.attribute}`; + const toSliderId = `toSlider_${filterData.attribute}`; + const fromInputId = `fromInput_${filterData.attribute}`; + const toInputId = `toInput_${filterData.attribute}`; - useEffect(() => { - if ( - searchCtx?.filters?.length === 0 || - !searchCtx?.filters?.find((obj) => obj.attribute === filterData.attribute) - ) { - setMinVal(min); - setMaxVal(max); - } - }, [searchCtx]); + useEffect(() => { + if ( + searchCtx?.filters?.length === 0 || + !searchCtx?.filters?.find((obj) => obj.attribute === filterData.attribute) + ) { + setMinVal(min); + setMaxVal(max); + } + }, [searchCtx]); - useEffect(() => { - const controlFromInput = ( - fromSlider: any, - fromInput: any, - toInput: any, - controlSlider: any - ) => { - const [from, to] = getParsed(fromInput, toInput); + useEffect(() => { + const controlFromInput = (fromSlider: any, fromInput: any, toInput: any, controlSlider: any) => { + const [from, to] = getParsed(fromInput, toInput); - fillSlider(fromInput, toInput, '#C6C6C6', '#383838', controlSlider); - if (from > to) { - fromSlider.value = to; - fromInput.value = to; - } else { - fromSlider.value = from; - } - }; + fillSlider(fromInput, toInput, "#C6C6C6", "#383838", controlSlider); + if (from > to) { + fromSlider.value = to; + fromInput.value = to; + } else { + fromSlider.value = from; + } + }; - const controlToInput = ( - toSlider: any, - fromInput: any, - toInput: any, - controlSlider: any - ) => { - const [from, to] = getParsed(fromInput, toInput); - fillSlider(fromInput, toInput, '#C6C6C6', '#383838', controlSlider); - if (from <= to) { - toSlider.value = to; - toInput.value = to; - } else { - toInput.value = from; - } - }; + const controlToInput = (toSlider: any, fromInput: any, toInput: any, controlSlider: any) => { + const [from, to] = getParsed(fromInput, toInput); + fillSlider(fromInput, toInput, "#C6C6C6", "#383838", controlSlider); + if (from <= to) { + toSlider.value = to; + toInput.value = to; + } else { + toInput.value = from; + } + }; - const controlFromSlider = ( - fromSlider: any, - toSlider: any, - fromInput: any - ) => { - const [from, to] = getParsed(fromSlider, toSlider); - fillSlider(fromSlider, toSlider, '#C6C6C6', '#383838', toSlider); + const controlFromSlider = (fromSlider: any, toSlider: any, fromInput: any) => { + const [from, to] = getParsed(fromSlider, toSlider); + fillSlider(fromSlider, toSlider, "#C6C6C6", "#383838", toSlider); - if (from > to) { - setMinVal(to); - fromSlider.value = to; - fromInput.value = to; - } else { - fromInput.value = from; - } - }; + if (from > to) { + setMinVal(to); + fromSlider.value = to; + fromInput.value = to; + } else { + fromInput.value = from; + } + }; - const controlToSlider = (fromSlider: any, toSlider: any, toInput: any) => { - const [from, to] = getParsed(fromSlider, toSlider); - fillSlider(fromSlider, toSlider, '#C6C6C6', '#383838', toSlider); - if (from <= to) { - toSlider.value = to; - toInput.value = to; - } else { - setMaxVal(from); - toInput.value = from; - toSlider.value = from; - } - }; + const controlToSlider = (fromSlider: any, toSlider: any, toInput: any) => { + const [from, to] = getParsed(fromSlider, toSlider); + fillSlider(fromSlider, toSlider, "#C6C6C6", "#383838", toSlider); + if (from <= to) { + toSlider.value = to; + toInput.value = to; + } else { + setMaxVal(from); + toInput.value = from; + toSlider.value = from; + } + }; - const getParsed = (currentFrom: any, currentTo: any) => { - const from = parseInt(currentFrom.value, 10); - const to = parseInt(currentTo.value, 10); - return [from, to]; - }; + const getParsed = (currentFrom: any, currentTo: any) => { + const from = parseInt(currentFrom.value, 10); + const to = parseInt(currentTo.value, 10); + return [from, to]; + }; - const fillSlider = ( - from: any, - to: any, - sliderColor: any, - rangeColor: any, - controlSlider: any - ) => { - const rangeDistance = to.max - to.min; - const fromPosition = from.value - to.min; - const toPosition = to.value - to.min; - controlSlider.style.background = `linear-gradient( + const fillSlider = (from: any, to: any, sliderColor: any, rangeColor: any, controlSlider: any) => { + const rangeDistance = to.max - to.min; + const fromPosition = from.value - to.min; + const toPosition = to.value - to.min; + controlSlider.style.background = `linear-gradient( to right, ${sliderColor} 0%, ${sliderColor} ${(fromPosition / rangeDistance) * 100}%, @@ -154,168 +124,145 @@ export const SliderDoubleControl: FunctionComponent = ({ ${rangeColor} ${(toPosition / rangeDistance) * 100}%, ${sliderColor} ${(toPosition / rangeDistance) * 100}%, ${sliderColor} 100%)`; - }; + }; - const fromSlider = document.querySelector( - `#${fromSliderId}` - )! as HTMLInputElement; - const toSlider = document.querySelector( - `#${toSliderId}` - )! as HTMLInputElement; - const fromInput = document.querySelector( - `#${fromInputId}` - )! as HTMLInputElement; - const toInput = document.querySelector( - `#${toInputId}` - )! as HTMLInputElement; + const fromSlider = document.querySelector(`#${fromSliderId}`)! as HTMLInputElement; + const toSlider = document.querySelector(`#${toSliderId}`)! as HTMLInputElement; + const fromInput = document.querySelector(`#${fromInputId}`)! as HTMLInputElement; + const toInput = document.querySelector(`#${toInputId}`)! as HTMLInputElement; - fillSlider(fromSlider, toSlider, '#C6C6C6', '#383838', toSlider); + fillSlider(fromSlider, toSlider, "#C6C6C6", "#383838", toSlider); - fromSlider.oninput = () => - controlFromSlider(fromSlider, toSlider, fromInput); - toSlider.oninput = () => controlToSlider(fromSlider, toSlider, toInput); - fromInput.oninput = () => - controlFromInput(fromSlider, fromInput, toInput, toSlider); - toInput.oninput = () => - controlToInput(toSlider, fromInput, toInput, toSlider); - }, [minVal, maxVal]); + fromSlider.oninput = () => controlFromSlider(fromSlider, toSlider, fromInput); + toSlider.oninput = () => controlToSlider(fromSlider, toSlider, toInput); + fromInput.oninput = () => controlFromInput(fromSlider, fromInput, toInput, toSlider); + toInput.oninput = () => controlToInput(toSlider, fromInput, toInput, toSlider); + }, [minVal, maxVal]); - const formatLabel = (price: number) => { - const currencyRate = productsCtx.currencyRate - ? productsCtx.currencyRate - : '1'; - const currencySymbol = productsCtx.currencySymbol - ? productsCtx.currencySymbol - : '$'; + const formatLabel = (price: number) => { + const currencyRate = productsCtx.currencyRate ? productsCtx.currencyRate : "1"; + const currencySymbol = productsCtx.currencySymbol ? productsCtx.currencySymbol : "$"; - const label = `${currencySymbol}${ - price && parseFloat(currencyRate) * parseInt(price.toFixed(0), 10) - ? (parseFloat(currencyRate) * parseInt(price.toFixed(0), 10)).toFixed(2) - : 0 - }`; - return label; - }; + const label = `${currencySymbol}${ + price && parseFloat(currencyRate) * parseInt(price.toFixed(0), 10) + ? (parseFloat(currencyRate) * parseInt(price.toFixed(0), 10)).toFixed(2) + : 0 + }`; + return label; + }; - return ( -
- + return ( +
+ -
-
- { - if (target instanceof HTMLInputElement) { - setMinVal(Math.round(Number(target.value))); - } - }} - onMouseUp={() => { - onChange(minVal, maxVal); - }} - onTouchEnd={() => { - onChange(minVal, maxVal); - }} - onKeyUp={() => { - onChange(minVal, maxVal); - }} - /> - { - if (target instanceof HTMLInputElement) { - setMaxVal(Math.round(Number(target.value))); - } - }} - onMouseUp={() => { - onChange(minVal, maxVal); - }} - onTouchEnd={() => { - onChange(minVal, maxVal); - }} - onKeyUp={() => { - onChange(minVal, maxVal); - }} - /> -
-
-
-
Min
- { - if (target instanceof HTMLInputElement) { - setMinVal(Math.round(Number(target.value))); - } - }} - onMouseUp={() => { - onChange(minVal, maxVal); - }} - onTouchEnd={() => { - onChange(minVal, maxVal); - }} - onKeyUp={() => { - onChange(minVal, maxVal); - }} - /> -
-
-
Max
- { - if (target instanceof HTMLInputElement) { - setMaxVal(Math.round(Number(target.value))); - } - }} - onMouseUp={() => { - onChange(minVal, maxVal); - }} - onTouchEnd={() => { - onChange(minVal, maxVal); - }} - onKeyUp={() => { - onChange(minVal, maxVal); - }} - /> -
-
-
+
+
+ { + if (target instanceof HTMLInputElement) { + setMinVal(Math.round(Number(target.value))); + } + }} + onMouseUp={() => { + onChange(minVal, maxVal); + }} + onTouchEnd={() => { + onChange(minVal, maxVal); + }} + onKeyUp={() => { + onChange(minVal, maxVal); + }} + /> + { + if (target instanceof HTMLInputElement) { + setMaxVal(Math.round(Number(target.value))); + } + }} + onMouseUp={() => { + onChange(minVal, maxVal); + }} + onTouchEnd={() => { + onChange(minVal, maxVal); + }} + onKeyUp={() => { + onChange(minVal, maxVal); + }} + /> +
+
+
+
Min
+ { + if (target instanceof HTMLInputElement) { + setMinVal(Math.round(Number(target.value))); + } + }} + onMouseUp={() => { + onChange(minVal, maxVal); + }} + onTouchEnd={() => { + onChange(minVal, maxVal); + }} + onKeyUp={() => { + onChange(minVal, maxVal); + }} + /> +
+
+
Max
+ { + if (target instanceof HTMLInputElement) { + setMaxVal(Math.round(Number(target.value))); + } + }} + onMouseUp={() => { + onChange(minVal, maxVal); + }} + onTouchEnd={() => { + onChange(minVal, maxVal); + }} + onKeyUp={() => { + onChange(minVal, maxVal); + }} + /> +
+
+
-
- - Between{' '} - - {formatLabel(minVal)} - {' '} - and{' '} - - {formatLabel(maxVal)} - - -
-
-
- ); +
+ + Between {formatLabel(minVal)} and{" "} + {formatLabel(maxVal)} + +
+
+
+ ); }; diff --git a/src/components/SliderDoubleControl/index.tsx b/src/components/SliderDoubleControl/index.tsx index 1b85d04..63bc08e 100644 --- a/src/components/SliderDoubleControl/index.tsx +++ b/src/components/SliderDoubleControl/index.tsx @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './SliderDoubleControl'; -export { SliderDoubleControl as default } from './SliderDoubleControl'; +export * from "./SliderDoubleControl"; +export { SliderDoubleControl as default } from "./SliderDoubleControl"; diff --git a/src/components/SortDropdown/SortDropdown.test.tsx b/src/components/SortDropdown/SortDropdown.test.tsx index 05d46f5..5da2151 100644 --- a/src/components/SortDropdown/SortDropdown.test.tsx +++ b/src/components/SortDropdown/SortDropdown.test.tsx @@ -7,23 +7,23 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { SortDropdown } from './SortDropdown'; +import { SortDropdown } from "./SortDropdown"; -describe('WidgetSDK - UIKit/SortDropdown', () => { - test('renders', () => { - const handleChange = jest.fn(); - const { container } = render( - - ); +describe("WidgetSDK - UIKit/SortDropdown", () => { + test("renders", () => { + const handleChange = jest.fn(); + const { container } = render( + , + ); - const elem = container.querySelector('.ds-sdk-sort-dropdown'); + const elem = container.querySelector(".ds-sdk-sort-dropdown"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/SortDropdown/index.ts b/src/components/SortDropdown/index.ts index 2bf7705..dbd5147 100644 --- a/src/components/SortDropdown/index.ts +++ b/src/components/SortDropdown/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './SortDropdown'; -export { SortDropdown as default } from './SortDropdown'; +export * from "./SortDropdown"; +export { SortDropdown as default } from "./SortDropdown"; diff --git a/src/components/SwatchButton/SwatchButton.test.tsx b/src/components/SwatchButton/SwatchButton.test.tsx index 9c46c6a..64c58f7 100644 --- a/src/components/SwatchButton/SwatchButton.test.tsx +++ b/src/components/SwatchButton/SwatchButton.test.tsx @@ -7,25 +7,19 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { SwatchButton } from './SwatchButton'; +import { SwatchButton } from "./SwatchButton"; -describe('WidgetSDK - UIKit/SwatchButton', () => { - test('renders', () => { - const handleChange = jest.fn(); - const { container } = render( - - ); +describe("WidgetSDK - UIKit/SwatchButton", () => { + test("renders", () => { + const handleChange = jest.fn(); + const { container } = render( + , + ); - const elem = container.querySelector('.ds-sdk-swatch-button_test'); + const elem = container.querySelector(".ds-sdk-swatch-button_test"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/SwatchButton/SwatchButton.tsx b/src/components/SwatchButton/SwatchButton.tsx index e38219d..bc0346d 100644 --- a/src/components/SwatchButton/SwatchButton.tsx +++ b/src/components/SwatchButton/SwatchButton.tsx @@ -7,76 +7,61 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; export interface SwatchButtonProps { - id: string; - value: string; - type: 'COLOR_HEX' | 'IMAGE' | 'TEXT'; - checked: boolean; - onClick: (e: any) => any; + id: string; + value: string; + type: "COLOR_HEX" | "IMAGE" | "TEXT"; + checked: boolean; + onClick: (e: any) => any; } export const SwatchButton: FunctionComponent = ({ - id, - value, - type, - checked, - onClick, + id, + value, + type, + checked, + onClick, }: SwatchButtonProps) => { - const outlineColor = checked - ? 'border-black' - : type === 'COLOR_HEX' - ? 'border-transparent' - : 'border-gray'; + const outlineColor = checked ? "border-black" : type === "COLOR_HEX" ? "border-transparent" : "border-gray"; - if (type === 'COLOR_HEX') { - const color = value.toLowerCase(); - const className = `min-w-[32px] rounded-full p-sm border border-[1.5px] ${outlineColor} h-[32px] outline-transparent`; - const isWhite = color === '#ffffff' || color === '#fff'; - return ( -
-
- ); - } + if (type === "COLOR_HEX") { + const color = value.toLowerCase(); + const className = `min-w-[32px] rounded-full p-sm border border-[1.5px] ${outlineColor} h-[32px] outline-transparent`; + const isWhite = color === "#ffffff" || color === "#fff"; + return ( +
+
+ ); + } - if (type === 'IMAGE' && value) { - const className = `object-cover object-center min-w-[32px] rounded-full p-sm border border-[1.5px] ${outlineColor} h-[32px] outline-transparent`; - const style = `background: url(${value}) no-repeat center; background-size: initial`; + if (type === "IMAGE" && value) { + const className = `object-cover object-center min-w-[32px] rounded-full p-sm border border-[1.5px] ${outlineColor} h-[32px] outline-transparent`; + const style = `background: url(${value}) no-repeat center; background-size: initial`; + return ( +
+
+ ); + } + + // assume TEXT type + const className = `flex items-center bg-white rounded-full p-sm border border-[1.5px]h-[32px] ${outlineColor} outline-transparent`; return ( -
-
+
+ +
); - } - - // assume TEXT type - const className = `flex items-center bg-white rounded-full p-sm border border-[1.5px]h-[32px] ${outlineColor} outline-transparent`; - return ( -
- -
- ); }; diff --git a/src/components/SwatchButton/index.ts b/src/components/SwatchButton/index.ts index 98febef..2123272 100644 --- a/src/components/SwatchButton/index.ts +++ b/src/components/SwatchButton/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './SwatchButton'; -export { SwatchButton as default } from './SwatchButton'; +export * from "./SwatchButton"; +export { SwatchButton as default } from "./SwatchButton"; diff --git a/src/components/SwatchButtonGroup/SwatchButtonGroup.test.tsx b/src/components/SwatchButtonGroup/SwatchButtonGroup.test.tsx index 678855a..fc39aa5 100644 --- a/src/components/SwatchButtonGroup/SwatchButtonGroup.test.tsx +++ b/src/components/SwatchButtonGroup/SwatchButtonGroup.test.tsx @@ -7,55 +7,53 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { SwatchButtonGroup, SwatchButtonGroupProps } from './SwatchButtonGroup'; +import { SwatchButtonGroup, SwatchButtonGroupProps } from "./SwatchButtonGroup"; const mockButtonGroup: SwatchButtonGroupProps = { - swatches: [ - { - title: 'Blue', - id: 'Y29uZmlndXJhYmxlLzkzLzU5', - type: 'COLOR_HEX', - value: '#1857f7', - }, - { - title: 'Purple', - id: 'Y29uZmlndXJhYmxlLzkzLzY2', - type: 'COLOR_HEX', - value: '#ef3dff', - }, - { - title: 'Red', - id: 'Y29uZmlndXJhYmxlLzkzLzY3', - type: 'COLOR_HEX', - value: '#ff0000', - }, - ], - isSelected: () => true, - showMore: () => {}, - productUrl: '', - onClick: () => {}, - sku: 'test', + swatches: [ + { + title: "Blue", + id: "Y29uZmlndXJhYmxlLzkzLzU5", + type: "COLOR_HEX", + value: "#1857f7", + }, + { + title: "Purple", + id: "Y29uZmlndXJhYmxlLzkzLzY2", + type: "COLOR_HEX", + value: "#ef3dff", + }, + { + title: "Red", + id: "Y29uZmlndXJhYmxlLzkzLzY3", + type: "COLOR_HEX", + value: "#ff0000", + }, + ], + isSelected: () => true, + showMore: () => {}, + productUrl: "", + onClick: () => {}, + sku: "test", }; -describe('WidgetSDK - UIKit/SwatchButtonGroup', () => { - test('renders', () => { - const { container } = render( - - ); +describe("WidgetSDK - UIKit/SwatchButtonGroup", () => { + test("renders", () => { + const { container } = render( + , + ); - const elem = container.querySelector( - '.ds-sdk-product-item__product-swatch-group' - ); + const elem = container.querySelector(".ds-sdk-product-item__product-swatch-group"); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/SwatchButtonGroup/SwatchButtonGroup.tsx b/src/components/SwatchButtonGroup/SwatchButtonGroup.tsx index a5a31d8..223e12d 100644 --- a/src/components/SwatchButtonGroup/SwatchButtonGroup.tsx +++ b/src/components/SwatchButtonGroup/SwatchButtonGroup.tsx @@ -7,84 +7,84 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; -import { SwatchValues } from '../../types/interface'; -import { SwatchButton } from '../SwatchButton'; +import { SwatchValues } from "../../types/interface"; +import { SwatchButton } from "../SwatchButton"; export interface SwatchButtonGroupProps { - isSelected: (id: string) => boolean | undefined; - swatches: SwatchValues[]; - showMore: () => any; - productUrl: string; - onClick: (optionIds: string[], sku: string) => any; - sku: string; + isSelected: (id: string) => boolean | undefined; + swatches: SwatchValues[]; + showMore: () => any; + productUrl: string; + onClick: (optionIds: string[], sku: string) => any; + sku: string; } const MAX_SWATCHES = 5; export const SwatchButtonGroup: FunctionComponent = ({ - isSelected, - swatches, - showMore, - productUrl, - onClick, - sku, + isSelected, + swatches, + showMore, + productUrl, + onClick, + sku, }: SwatchButtonGroupProps) => { - const moreSwatches = swatches.length > MAX_SWATCHES; - const numberOfOptions = moreSwatches ? MAX_SWATCHES - 1 : swatches.length; - return ( -
- {moreSwatches ? ( -
- {swatches.slice(0, numberOfOptions).map((swatch) => { - const checked = isSelected(swatch.id); - return ( - swatch && - swatch.type == 'COLOR_HEX' && ( -
- onClick([swatch.id], sku)} - /> + const moreSwatches = swatches.length > MAX_SWATCHES; + const numberOfOptions = moreSwatches ? MAX_SWATCHES - 1 : swatches.length; + return ( +
+ {moreSwatches ? ( +
+ {swatches.slice(0, numberOfOptions).map((swatch) => { + const checked = isSelected(swatch.id); + return ( + swatch && + swatch.type == "COLOR_HEX" && ( +
+ onClick([swatch.id], sku)} + /> +
+ ) + ); + })} + +
+ +
+
- ) - ); - })} - -
- -
-
+ ) : ( + swatches.slice(0, numberOfOptions).map((swatch) => { + const checked = isSelected(swatch.id); + return ( + swatch && + swatch.type == "COLOR_HEX" && ( +
+ onClick([swatch.id], sku)} + /> +
+ ) + ); + }) + )}
- ) : ( - swatches.slice(0, numberOfOptions).map((swatch) => { - const checked = isSelected(swatch.id); - return ( - swatch && - swatch.type == 'COLOR_HEX' && ( -
- onClick([swatch.id], sku)} - /> -
- ) - ); - }) - )} -
- ); + ); }; diff --git a/src/components/SwatchButtonGroup/index.ts b/src/components/SwatchButtonGroup/index.ts index 98ef054..c4953cf 100644 --- a/src/components/SwatchButtonGroup/index.ts +++ b/src/components/SwatchButtonGroup/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './SwatchButtonGroup'; -export { SwatchButtonGroup as default } from './SwatchButtonGroup'; +export * from "./SwatchButtonGroup"; +export { SwatchButtonGroup as default } from "./SwatchButtonGroup"; diff --git a/src/components/ViewSwitcher/index.ts b/src/components/ViewSwitcher/index.ts index d23ffb1..d79f0ec 100644 --- a/src/components/ViewSwitcher/index.ts +++ b/src/components/ViewSwitcher/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './ViewSwitcher'; -export { ViewSwitcher as default } from './ViewSwitcher'; +export * from "./ViewSwitcher"; +export { ViewSwitcher as default } from "./ViewSwitcher"; diff --git a/src/components/WishlistButton/WishlistButton.test.tsx b/src/components/WishlistButton/WishlistButton.test.tsx index 8dba494..2ef1256 100644 --- a/src/components/WishlistButton/WishlistButton.test.tsx +++ b/src/components/WishlistButton/WishlistButton.test.tsx @@ -7,20 +7,16 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from '@testing-library/preact'; +import { render } from "@testing-library/preact"; -import { WishlistButton } from './WishlistButton'; +import { WishlistButton } from "./WishlistButton"; -describe('WidgetSDK - UIKit/FilterButton', () => { - test('renders', () => { - const { container } = render( - - ); +describe("WidgetSDK - UIKit/FilterButton", () => { + test("renders", () => { + const { container } = render(); - const elem = container.querySelector( - `.ds-sdk-wishlist-inLineWithName-button` - ); + const elem = container.querySelector(`.ds-sdk-wishlist-inLineWithName-button`); - expect(!!elem).toEqual(true); - }); + expect(!!elem).toEqual(true); + }); }); diff --git a/src/components/WishlistButton/WishlistButton.tsx b/src/components/WishlistButton/WishlistButton.tsx index 16b4364..2cf7bd0 100644 --- a/src/components/WishlistButton/WishlistButton.tsx +++ b/src/components/WishlistButton/WishlistButton.tsx @@ -7,72 +7,65 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; +import { FunctionComponent } from "preact"; -import {EmptyHeart, FilledHeart } from '@/icons'; +import { EmptyHeart, FilledHeart } from "@/icons"; -import { useWishlist } from '../../context'; -import { WishlistItem } from '../../types/interface'; -import { AddToWishlistPlacement } from '../../types/widget'; -import { classNames } from '../../utils/dom'; +import { useWishlist } from "../../context"; +import { WishlistItem } from "../../types/interface"; +import { AddToWishlistPlacement } from "../../types/widget"; +import { classNames } from "../../utils/dom"; export interface WishlistButtonProps { - type: AddToWishlistPlacement; - productSku: string; + type: AddToWishlistPlacement; + productSku: string; } -export const WishlistButton: FunctionComponent = ({ - type, - productSku, -}: WishlistButtonProps) => { - const { isAuthorized, wishlist, addItemToWishlist, removeItemFromWishlist } = - useWishlist(); - const wishlistItemStatus: WishlistItem | undefined = - wishlist?.items_v2?.items.filter((ws) => ws.product.sku === productSku)[0]; - const isWishlistItem = !!wishlistItemStatus; +export const WishlistButton: FunctionComponent = ({ type, productSku }: WishlistButtonProps) => { + const { isAuthorized, wishlist, addItemToWishlist, removeItemFromWishlist } = useWishlist(); + const wishlistItemStatus: WishlistItem | undefined = wishlist?.items_v2?.items.filter( + (ws) => ws.product.sku === productSku, + )[0]; + const isWishlistItem = !!wishlistItemStatus; - const heart = isWishlistItem ? : ; + const heart = isWishlistItem ? : ; - const preventBubbleUp = (e: any) => { - // prevent parent link from firing - e.stopPropagation(); - e.preventDefault(); - }; + const preventBubbleUp = (e: any) => { + // prevent parent link from firing + e.stopPropagation(); + e.preventDefault(); + }; - const handleAddWishlist = (e: any) => { - preventBubbleUp(e); - const selectedWishlistId = wishlist?.id as string; - if (isAuthorized) { - const wishlistItem = { - sku: productSku, - quantity: 1, - }; - addItemToWishlist(selectedWishlistId, wishlistItem); - } else { - // FIXME: This will need revisit for AEM/CIF since this url does not exist - window.location.href = `${window.origin}/customer/account/login/`; - } - }; + const handleAddWishlist = (e: any) => { + preventBubbleUp(e); + const selectedWishlistId = wishlist?.id as string; + if (isAuthorized) { + const wishlistItem = { + sku: productSku, + quantity: 1, + }; + addItemToWishlist(selectedWishlistId, wishlistItem); + } else { + // FIXME: This will need revisit for AEM/CIF since this url does not exist + window.location.href = `${window.origin}/customer/account/login/`; + } + }; - const handleRemoveWishlist = (e: any) => { - preventBubbleUp(e); - if (!wishlistItemStatus) return; - const selectedWishlistId = wishlist?.id as string; - removeItemFromWishlist(selectedWishlistId, wishlistItemStatus.id); - }; + const handleRemoveWishlist = (e: any) => { + preventBubbleUp(e); + if (!wishlistItemStatus) return; + const selectedWishlistId = wishlist?.id as string; + removeItemFromWishlist(selectedWishlistId, wishlistItemStatus.id); + }; - return ( -
-
- {heart} -
-
- ); + return ( +
+
{heart}
+
+ ); }; diff --git a/src/components/WishlistButton/index.ts b/src/components/WishlistButton/index.ts index c365457..e2103d7 100644 --- a/src/components/WishlistButton/index.ts +++ b/src/components/WishlistButton/index.ts @@ -7,5 +7,5 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './WishlistButton'; -export { WishlistButton as default } from './WishlistButton'; +export * from "./WishlistButton"; +export { WishlistButton as default } from "./WishlistButton"; diff --git a/src/components/index.ts b/src/components/index.ts index 90e0d54..38172d0 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -7,6 +7,6 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './CategoryFilters'; -export * from './Facets'; -export * from './Pagination'; +export * from "./CategoryFilters"; +export * from "./Facets"; +export * from "./Pagination"; diff --git a/src/components/mocks.tsx b/src/components/mocks.tsx index 5590410..b6923c2 100644 --- a/src/components/mocks.tsx +++ b/src/components/mocks.tsx @@ -7,108 +7,103 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { - Facet, - PriceFacet, - RangeBucket, - ScalarBucket, -} from '@/types/interface'; +import { Facet, PriceFacet, RangeBucket, ScalarBucket } from "@/types/interface"; const colorBuckets: ScalarBucket[] = [ - { - count: 3, - title: 'Green', - __typename: 'ScalarBucket', - }, - { - count: 2, - title: 'Black', - __typename: 'ScalarBucket', - }, - { - count: 1, - title: 'Blue', - __typename: 'ScalarBucket', - }, - { - count: 1, - title: 'Gray', - __typename: 'ScalarBucket', - }, + { + count: 3, + title: "Green", + __typename: "ScalarBucket", + }, + { + count: 2, + title: "Black", + __typename: "ScalarBucket", + }, + { + count: 1, + title: "Blue", + __typename: "ScalarBucket", + }, + { + count: 1, + title: "Gray", + __typename: "ScalarBucket", + }, ]; const sizeBuckets: ScalarBucket[] = [ - { - count: 2, - title: '32', - __typename: 'ScalarBucket', - }, - { - count: 2, - title: '33', - __typename: 'ScalarBucket', - }, - { - count: 1, - title: 'L', - __typename: 'ScalarBucket', - }, + { + count: 2, + title: "32", + __typename: "ScalarBucket", + }, + { + count: 2, + title: "33", + __typename: "ScalarBucket", + }, + { + count: 1, + title: "L", + __typename: "ScalarBucket", + }, ]; const priceBuckets: RangeBucket[] = [ - { - title: '0.0-25.0', - __typename: 'RangeBucket', - from: 0, - to: 25, - count: 45, - }, - { - title: '25.0-50.0', - __typename: 'RangeBucket', - from: 25, - to: 50, - count: 105, - }, - { - title: '75.0-100.0', - __typename: 'RangeBucket', - from: 75, - to: 100, - count: 6, - }, - { - title: '200.0-225.0', - __typename: 'RangeBucket', - from: 200, - to: 225, - count: 2, - }, + { + title: "0.0-25.0", + __typename: "RangeBucket", + from: 0, + to: 25, + count: 45, + }, + { + title: "25.0-50.0", + __typename: "RangeBucket", + from: 25, + to: 50, + count: 105, + }, + { + title: "75.0-100.0", + __typename: "RangeBucket", + from: 75, + to: 100, + count: 6, + }, + { + title: "200.0-225.0", + __typename: "RangeBucket", + from: 200, + to: 225, + count: 2, + }, ]; export const mockFilters: Facet[] = [ - { - title: 'Color', - attribute: 'color', - buckets: colorBuckets, - __typename: 'ScalarBucket', - }, - { - title: 'Size', - attribute: 'size', - buckets: sizeBuckets, - __typename: 'ScalarBucket', - }, + { + title: "Color", + attribute: "color", + buckets: colorBuckets, + __typename: "ScalarBucket", + }, + { + title: "Size", + attribute: "size", + buckets: sizeBuckets, + __typename: "ScalarBucket", + }, ]; export const mockColorFilter: Facet = { - title: 'Color', - attribute: 'color', - buckets: colorBuckets, - __typename: 'ScalarBucket', + title: "Color", + attribute: "color", + buckets: colorBuckets, + __typename: "ScalarBucket", }; export const mockPriceFilter: PriceFacet = { - title: 'Price', - attribute: 'price', - buckets: priceBuckets, - __typename: 'RangeBucket', + title: "Price", + attribute: "price", + buckets: priceBuckets, + __typename: "RangeBucket", }; diff --git a/src/containers/App.tsx b/src/containers/App.tsx index 6a784a3..786482f 100644 --- a/src/containers/App.tsx +++ b/src/containers/App.tsx @@ -7,141 +7,129 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; -import { useState } from 'preact/hooks'; +import { FunctionComponent } from "preact"; +import { useState } from "preact/hooks"; -import FilterButton from '@/components/FilterButton'; -import Loading from '@/components/Loading'; -import Shimmer from '@/components/Shimmer'; +import FilterButton from "@/components/FilterButton"; +import Loading from "@/components/Loading"; +import Shimmer from "@/components/Shimmer"; -import { CategoryFilters } from '../components/CategoryFilters'; -import { SelectedFilters } from '../components/Facets'; -import { - useProducts, - useSearch, - useSensor, - useStore, - useTranslation, -} from '../context'; -import { ProductsContainer } from './ProductsContainer'; -import { ProductsHeader } from './ProductsHeader'; +import { CategoryFilters } from "../components/CategoryFilters"; +import { SelectedFilters } from "../components/Facets"; +import { useProducts, useSearch, useSensor, useStore, useTranslation } from "../context"; +import { ProductsContainer } from "./ProductsContainer"; +import { ProductsHeader } from "./ProductsHeader"; export const App: FunctionComponent = () => { - const searchCtx = useSearch(); - const productsCtx = useProducts(); - const { screenSize } = useSensor(); - const translation = useTranslation(); - const { displayMode } = useStore().config; - const [showFilters, setShowFilters] = useState(true); + const searchCtx = useSearch(); + const productsCtx = useProducts(); + const { screenSize } = useSensor(); + const translation = useTranslation(); + const { displayMode } = useStore().config; + const [showFilters, setShowFilters] = useState(true); - const loadingLabel = translation.Loading.title; + const loadingLabel = translation.Loading.title; - let title = productsCtx.categoryName || ''; - if (productsCtx.variables.phrase) { - const text = translation.CategoryFilters.results; - title = text.replace('{phrase}', `"${productsCtx.variables.phrase ?? ''}"`); - } - const getResults = (totalCount: number) => { - const resultsTranslation = translation.CategoryFilters.products; - const results = resultsTranslation.replace('{totalCount}', `${totalCount}`); - return results; - }; + let title = productsCtx.categoryName || ""; + if (productsCtx.variables.phrase) { + const text = translation.CategoryFilters.results; + title = text.replace("{phrase}", `"${productsCtx.variables.phrase ?? ""}"`); + } + const getResults = (totalCount: number) => { + const resultsTranslation = translation.CategoryFilters.products; + const results = resultsTranslation.replace("{totalCount}", `${totalCount}`); + return results; + }; - return ( - <> - {!(displayMode === 'PAGE') && - (!screenSize.mobile && showFilters && productsCtx.facets.length > 0 ? ( -
-
- -
- - + return ( + <> + {!(displayMode === "PAGE") && + (!screenSize.mobile && showFilters && productsCtx.facets.length > 0 ? ( +
+
+ +
+ + - -
-
-
- ) : ( -
-
-
-
-
-
-
-
-
-
- {!screenSize.mobile && - !productsCtx.loading && - productsCtx.facets.length > 0 && ( -
- setShowFilters(true)} - type="desktop" - title={`${translation.Filter.showTitle}${ - searchCtx.filterCount > 0 - ? ` (${searchCtx.filterCount})` - : '' - }`} - /> -
- )} -
- {productsCtx.loading ? ( - screenSize.mobile ? ( - - ) : ( - - ) ) : ( - <> -
- +
+
+
+
+ +
+
+
+
+ {!screenSize.mobile && !productsCtx.loading && productsCtx.facets.length > 0 && ( +
+ setShowFilters(true)} + type="desktop" + title={`${translation.Filter.showTitle}${ + searchCtx.filterCount > 0 ? ` (${searchCtx.filterCount})` : "" + }`} + /> +
+ )} +
+ {productsCtx.loading ? ( + screenSize.mobile ? ( + + ) : ( + + ) + ) : ( + <> +
+ +
+ + 0} /> + + )} +
+
- - 0} - /> - - )} -
-
-
- ))} - - ); + ))} + + ); }; export default App; diff --git a/src/containers/ProductListingPage.tsx b/src/containers/ProductListingPage.tsx index 15adcf2..b3bd451 100644 --- a/src/containers/ProductListingPage.tsx +++ b/src/containers/ProductListingPage.tsx @@ -6,65 +6,65 @@ NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from 'preact'; +import { render } from "preact"; -import './styles/global.css'; -import { validateStoreDetailsKeys } from '@/utils/validateStoreDetails'; +import "./styles/global.css"; +import { validateStoreDetailsKeys } from "@/utils/validateStoreDetails"; import { - AttributeMetadataProvider, - CartProvider, - ProductsContextProvider, - SearchProvider, - StoreContextProvider, - StoreDetailsProps, -} from '../context'; -import Resize from '../context/displayChange'; -import Translation from '../context/translation'; -import { getUserViewHistory } from '../utils/getUserViewHistory'; -import App from './App'; + AttributeMetadataProvider, + CartProvider, + ProductsContextProvider, + SearchProvider, + StoreContextProvider, + StoreDetailsProps, +} from "../context"; +import Resize from "../context/displayChange"; +import Translation from "../context/translation"; +import { getUserViewHistory } from "../utils/getUserViewHistory"; +import App from "./App"; type MountSearchPlpProps = { - storeDetails: StoreDetailsProps; - root: HTMLElement; + storeDetails: StoreDetailsProps; + root: HTMLElement; }; // TODO: this file is not being used currently const LiveSearchPLP = ({ storeDetails, root }: MountSearchPlpProps) => { - if (!storeDetails) { - throw new Error("Livesearch PLP's storeDetails prop was not provided"); - } - if (!root) { - throw new Error("Livesearch PLP's Root prop was not provided"); - } + if (!storeDetails) { + throw new Error("Livesearch PLP's storeDetails prop was not provided"); + } + if (!root) { + throw new Error("Livesearch PLP's Root prop was not provided"); + } - const userViewHistory = getUserViewHistory(); + const userViewHistory = getUserViewHistory(); - const updatedStoreDetails = { - ...storeDetails, - context: { - ...storeDetails.context, - userViewHistory, - }, - }; + const updatedStoreDetails = { + ...storeDetails, + context: { + ...storeDetails.context, + userViewHistory, + }, + }; - render( - - - - - - - - - - - - - - - , - root - ); + render( + + + + + + + + + + + + + + + , + root, + ); }; export default LiveSearchPLP; diff --git a/src/containers/ProductsContainer.tsx b/src/containers/ProductsContainer.tsx index d850bf3..eb62704 100644 --- a/src/containers/ProductsContainer.tsx +++ b/src/containers/ProductsContainer.tsx @@ -7,150 +7,131 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionalComponent, FunctionComponent } from 'preact'; -import { useEffect } from 'preact/hooks'; +import { FunctionalComponent, FunctionComponent } from "preact"; +import { useEffect } from "preact/hooks"; -import { ProductCardShimmer } from '@/components/ProductCardShimmer'; -import { useProducts, useSensor, useTranslation } from '@/context'; -import { PageSizeOption } from '@/types/interface'; -import { - handleUrlPageSize, - handleUrlPagination, -} from '@/utils/handleUrlFilters'; +import { ProductCardShimmer } from "@/components/ProductCardShimmer"; +import { useProducts, useSensor, useTranslation } from "@/context"; +import { PageSizeOption } from "@/types/interface"; +import { handleUrlPageSize, handleUrlPagination } from "@/utils/handleUrlFilters"; -import { Alert } from '../components/Alert'; -import { Pagination } from '../components/Pagination'; -import { PerPagePicker, PerPagePickerProps } from '../components/PerPagePicker'; -import { ProductList } from '../components/ProductList'; +import { Alert } from "../components/Alert"; +import { Pagination } from "../components/Pagination"; +import { PerPagePicker, PerPagePickerProps } from "../components/PerPagePicker"; +import { ProductList } from "../components/ProductList"; interface Props { - showFilters: boolean; + showFilters: boolean; } -export const ProductsContainer: FunctionComponent = ({ - showFilters, -}) => { - const productsCtx = useProducts(); - const { screenSize } = useSensor(); +export const ProductsContainer: FunctionComponent = ({ showFilters }) => { + const productsCtx = useProducts(); + const { screenSize } = useSensor(); - const { - variables, - items, - setCurrentPage, - currentPage, - setPageSize, - pageSize, - totalPages, - totalCount, - minQueryLength, - minQueryLengthReached, - pageSizeOptions, - loading, - } = productsCtx; + const { + variables, + items, + setCurrentPage, + currentPage, + setPageSize, + pageSize, + totalPages, + totalCount, + minQueryLength, + minQueryLengthReached, + pageSizeOptions, + loading, + } = productsCtx; - useEffect(() => { - if (currentPage < 1) { - goToPage(1); - } - }, []); + useEffect(() => { + if (currentPage < 1) { + goToPage(1); + } + }, []); - const productCardArray = Array.from({ length: 8 }); + const productCardArray = Array.from({ length: 8 }); - const goToPage = (page: number | string) => { - if (typeof page === 'number') { - setCurrentPage(page); - handleUrlPagination(page); - } - }; + const goToPage = (page: number | string) => { + if (typeof page === "number") { + setCurrentPage(page); + handleUrlPagination(page); + } + }; - const onPageSizeChange = (pageSizeOption: number) => { - setPageSize(pageSizeOption); - handleUrlPageSize(pageSizeOption); - }; - const translation = useTranslation(); + const onPageSizeChange = (pageSizeOption: number) => { + setPageSize(pageSizeOption); + handleUrlPageSize(pageSizeOption); + }; + const translation = useTranslation(); - const getPageSizeTranslation = ( - pageSize: number, - pageSizeOptions: PageSizeOption[], - PerPagePicker: FunctionalComponent - ) => { - const pageSizeTranslation = translation.ProductContainers.pagePicker; - const pageSizeTranslationOrder = pageSizeTranslation.split(' '); - return pageSizeTranslationOrder.map((word: string, index: any) => - word === '{pageSize}' ? ( - - ) : ( - `${word} ` - ) - ); - }; + const getPageSizeTranslation = ( + pageSize: number, + pageSizeOptions: PageSizeOption[], + PerPagePicker: FunctionalComponent, + ) => { + const pageSizeTranslation = translation.ProductContainers.pagePicker; + const pageSizeTranslationOrder = pageSizeTranslation.split(" "); + return pageSizeTranslationOrder.map((word: string, index: any) => + word === "{pageSize}" ? ( + + ) : ( + `${word} ` + ), + ); + }; - if (!minQueryLengthReached) { - const templateMinQueryText = translation.ProductContainers.minquery; - const title = templateMinQueryText - .replace('{variables.phrase}', variables.phrase) - .replace('{minQueryLength}', minQueryLength); - return ( -
- -
- ); - } + if (!minQueryLengthReached) { + const templateMinQueryText = translation.ProductContainers.minquery; + const title = templateMinQueryText + .replace("{variables.phrase}", variables.phrase) + .replace("{minQueryLength}", minQueryLength); + return ( +
+ +
+ ); + } + + if (!totalCount) { + return ( +
+ +
+ ); + } - if (!totalCount) { return ( -
- -
+ <> + {loading ? ( +
+ {" "} + {productCardArray.map((_, index) => ( + + ))} +
+ ) : ( + + )} +
+
{getPageSizeTranslation(pageSize, pageSizeOptions, PerPagePicker)}
+ {totalPages > 1 && ( + + )} +
+ ); - } - - return ( - <> - {loading ? ( -
- {' '} - {productCardArray.map((_, index) => ( - - ))} -
- ) : ( - - )} -
-
- {getPageSizeTranslation(pageSize, pageSizeOptions, PerPagePicker)} -
- {totalPages > 1 && ( - - )} -
- - ); }; diff --git a/src/containers/ProductsHeader.tsx b/src/containers/ProductsHeader.tsx index e47d111..5b99bd7 100644 --- a/src/containers/ProductsHeader.tsx +++ b/src/containers/ProductsHeader.tsx @@ -7,126 +7,100 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { FunctionComponent } from 'preact'; -import { useCallback, useEffect, useState } from 'preact/hooks'; +import { FunctionComponent } from "preact"; +import { useCallback, useEffect, useState } from "preact/hooks"; -import ViewSwitcher from '@/components/ViewSwitcher'; +import ViewSwitcher from "@/components/ViewSwitcher"; -import Facets from '../components/Facets'; -import { FilterButton } from '../components/FilterButton'; -import { SearchBar } from '../components/SearchBar'; -import { SortDropdown } from '../components/SortDropdown'; -import { - useAttributeMetadata, - useProducts, - useSearch, - useStore, - useTranslation, -} from '../context'; -import { Facet } from '../types/interface'; -import { getValueFromUrl, handleUrlSort } from '../utils/handleUrlFilters'; -import { - defaultSortOptions, - generateGQLSortInput, - getSortOptionsfromMetadata, -} from '../utils/sort'; +import Facets from "../components/Facets"; +import { FilterButton } from "../components/FilterButton"; +import { SearchBar } from "../components/SearchBar"; +import { SortDropdown } from "../components/SortDropdown"; +import { useAttributeMetadata, useProducts, useSearch, useStore, useTranslation } from "../context"; +import { Facet } from "../types/interface"; +import { getValueFromUrl, handleUrlSort } from "../utils/handleUrlFilters"; +import { defaultSortOptions, generateGQLSortInput, getSortOptionsfromMetadata } from "../utils/sort"; interface Props { - facets: Facet[]; - totalCount: number; - screenSize: { - mobile: boolean; - tablet: boolean; - desktop: boolean; - columns: number; - }; + facets: Facet[]; + totalCount: number; + screenSize: { + mobile: boolean; + tablet: boolean; + desktop: boolean; + columns: number; + }; } -export const ProductsHeader: FunctionComponent = ({ - facets, - totalCount, - screenSize, -}) => { - const searchCtx = useSearch(); - const storeCtx = useStore(); - const attributeMetadata = useAttributeMetadata(); - const productsCtx = useProducts(); - const translation = useTranslation(); +export const ProductsHeader: FunctionComponent = ({ facets, totalCount, screenSize }) => { + const searchCtx = useSearch(); + const storeCtx = useStore(); + const attributeMetadata = useAttributeMetadata(); + const productsCtx = useProducts(); + const translation = useTranslation(); - const [showMobileFacet, setShowMobileFacet] = useState( - !!productsCtx.variables.filter?.length - ); - const [sortOptions, setSortOptions] = useState(defaultSortOptions()); + const [showMobileFacet, setShowMobileFacet] = useState(!!productsCtx.variables.filter?.length); + const [sortOptions, setSortOptions] = useState(defaultSortOptions()); - const getSortOptions = useCallback(() => { - setSortOptions( - getSortOptionsfromMetadata( - translation, - attributeMetadata?.sortable, - storeCtx?.config?.displayOutOfStock, - storeCtx?.config?.currentCategoryUrlPath - ) - ); - }, [storeCtx, translation, attributeMetadata]); + const getSortOptions = useCallback(() => { + setSortOptions( + getSortOptionsfromMetadata( + translation, + attributeMetadata?.sortable, + storeCtx?.config?.displayOutOfStock, + storeCtx?.config?.currentCategoryUrlPath, + ), + ); + }, [storeCtx, translation, attributeMetadata]); - useEffect(() => { - getSortOptions(); - }, [getSortOptions]); + useEffect(() => { + getSortOptions(); + }, [getSortOptions]); - const defaultSortOption = storeCtx.config?.currentCategoryUrlPath - ? 'position_ASC' - : 'relevance_DESC'; - const sortFromUrl = getValueFromUrl('product_list_order'); - const sortByDefault = sortFromUrl ? sortFromUrl : defaultSortOption; - const [sortBy, setSortBy] = useState(sortByDefault); - const onSortChange = (sortOption: string) => { - setSortBy(sortOption); - searchCtx.setSort(generateGQLSortInput(sortOption)); - handleUrlSort(sortOption); - }; + const defaultSortOption = storeCtx.config?.currentCategoryUrlPath ? "position_ASC" : "relevance_DESC"; + const sortFromUrl = getValueFromUrl("product_list_order"); + const sortByDefault = sortFromUrl ? sortFromUrl : defaultSortOption; + const [sortBy, setSortBy] = useState(sortByDefault); + const onSortChange = (sortOption: string) => { + setSortBy(sortOption); + searchCtx.setSort(generateGQLSortInput(sortOption)); + handleUrlSort(sortOption); + }; - return ( -
-
-
- {screenSize.mobile - ? totalCount > 0 && ( -
- setShowMobileFacet(!showMobileFacet)} - type="mobile" - /> + return ( +
+
+
+ {screenSize.mobile + ? totalCount > 0 && ( +
+ setShowMobileFacet(!showMobileFacet)} + type="mobile" + /> +
+ ) + : storeCtx.config.displaySearchBox && ( + { + if (e.key === "Enter") { + searchCtx.setPhrase(e?.target?.value); + } + }} + onClear={() => searchCtx.setPhrase("")} + placeholder={translation.SearchBar.placeholder} + /> + )}
- ) - : storeCtx.config.displaySearchBox && ( - { - if (e.key === 'Enter') { - searchCtx.setPhrase(e?.target?.value); - } - }} - onClear={() => searchCtx.setPhrase('')} - placeholder={translation.SearchBar.placeholder} - /> - )} -
- {totalCount > 0 && ( - <> - {storeCtx?.config?.listview && } + {totalCount > 0 && ( + <> + {storeCtx?.config?.listview && } - - - )} -
- {screenSize.mobile && showMobileFacet && } -
- ); + + + )} +
+ {screenSize.mobile && showMobileFacet && } +
+ ); }; diff --git a/src/context/attributeMetadata.tsx b/src/context/attributeMetadata.tsx index 24f6637..a194675 100644 --- a/src/context/attributeMetadata.tsx +++ b/src/context/attributeMetadata.tsx @@ -7,69 +7,68 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { createContext, FunctionComponent } from 'preact'; -import { useContext, useEffect, useState } from 'preact/hooks'; +import { createContext, FunctionComponent } from "preact"; +import { useContext, useEffect, useState } from "preact/hooks"; -import { getAttributeMetadata } from '../api/search'; -import { AttributeMetadata } from '../types/interface'; -import { useStore } from './store'; +import { getAttributeMetadata } from "../api/search"; +import { AttributeMetadata } from "../types/interface"; +import { useStore } from "./store"; interface WithChildrenProps { - children?: any; + children?: any; } export interface AttributeMetaDataProps extends WithChildrenProps { - sortable: AttributeMetadata[]; - filterableInSearch: string[] | null; + sortable: AttributeMetadata[]; + filterableInSearch: string[] | null; } const AttributeMetadataContext = createContext({ - sortable: [], - filterableInSearch: [], + sortable: [], + filterableInSearch: [], }); const AttributeMetadataProvider: FunctionComponent = ({ children }) => { - const [attributeMetadata, setAttributeMetadata] = - useState({ - sortable: [], - filterableInSearch: null, + const [attributeMetadata, setAttributeMetadata] = useState({ + sortable: [], + filterableInSearch: null, }); - const storeCtx = useStore(); + const storeCtx = useStore(); - useEffect(() => { - const fetchData = async () => { - const data = await getAttributeMetadata({ - ...storeCtx, - apiUrl: storeCtx.apiUrl, - }); - if (data?.attributeMetadata) { - setAttributeMetadata({ - sortable: data.attributeMetadata.sortable as AttributeMetadata[], - filterableInSearch: data.attributeMetadata.filterableInSearch.map( - (attribute) => attribute.attribute - ), - }); - } - }; + useEffect(() => { + const fetchData = async () => { + const data = await getAttributeMetadata({ + ...storeCtx, + apiUrl: storeCtx.apiUrl, + }); + if (data?.attributeMetadata) { + setAttributeMetadata({ + sortable: data.attributeMetadata.sortable as AttributeMetadata[], + filterableInSearch: data.attributeMetadata.filterableInSearch.map( + (attribute) => attribute.attribute, + ), + }); + } + }; - fetchData(); - }, []); + fetchData(); + }, []); - const attributeMetadataContext = { - ...attributeMetadata, - }; + const attributeMetadataContext = { + ...attributeMetadata, + }; - return ( - - {children} - - ); + return ( + + {children} + + ); }; const useAttributeMetadata = () => { - const attributeMetadataCtx = useContext(AttributeMetadataContext); - return attributeMetadataCtx; + const attributeMetadataCtx = useContext(AttributeMetadataContext); + return attributeMetadataCtx; }; export { AttributeMetadataProvider, useAttributeMetadata }; diff --git a/src/context/cart.tsx b/src/context/cart.tsx index c67581c..bddcb5d 100644 --- a/src/context/cart.tsx +++ b/src/context/cart.tsx @@ -7,91 +7,79 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { createContext, FunctionComponent } from 'preact'; -import { useContext, useState } from 'preact/hooks'; +import { createContext, FunctionComponent } from "preact"; +import { useContext, useState } from "preact/hooks"; -import { getGraphQL } from '../api/graphql'; -import { ADD_TO_CART } from '../api/mutations'; -import { GET_CUSTOMER_CART } from '../api/queries'; -import { useProducts } from './products'; -import { useStore } from './store'; +import { getGraphQL } from "../api/graphql"; +import { ADD_TO_CART } from "../api/mutations"; +import { GET_CUSTOMER_CART } from "../api/queries"; +import { useProducts } from "./products"; +import { useStore } from "./store"; export interface CartAttributesContext { - cart: CartProps; - initializeCustomerCart: () => Promise; - addToCartGraphQL: (sku: string) => Promise; - refreshCart?: () => void; + cart: CartProps; + initializeCustomerCart: () => Promise; + addToCartGraphQL: (sku: string) => Promise; + refreshCart?: () => void; } interface CartProps { - cartId: string; + cartId: string; } const CartContext = createContext({} as CartAttributesContext); const useCart = (): CartAttributesContext => { - return useContext(CartContext); + return useContext(CartContext); }; const CartProvider: FunctionComponent = ({ children }) => { - const [cart, setCart] = useState({ cartId: '' }); - const { refreshCart, resolveCartId } = useProducts(); - const { storeViewCode, config } = useStore(); - - const initializeCustomerCart = async (): Promise => { - let cartId = ''; - if (!resolveCartId) { - const customerResponse = await getGraphQL( - GET_CUSTOMER_CART, - {}, - storeViewCode, - config?.baseUrl - ); - cartId = customerResponse?.data.customerCart?.id ?? ''; - } else { - cartId = (await resolveCartId()) ?? ''; - } - setCart({ ...cart, cartId }); - return cartId; - }; - - const addToCartGraphQL = async (sku: string) => { - let cartId = cart.cartId; - if (!cartId) { - cartId = await initializeCustomerCart(); - } - const cartItems = [ - { - quantity: 1, - sku, - }, - ]; - - const variables = { - cartId, - cartItems, + const [cart, setCart] = useState({ cartId: "" }); + const { refreshCart, resolveCartId } = useProducts(); + const { storeViewCode, config } = useStore(); + + const initializeCustomerCart = async (): Promise => { + let cartId = ""; + if (!resolveCartId) { + const customerResponse = await getGraphQL(GET_CUSTOMER_CART, {}, storeViewCode, config?.baseUrl); + cartId = customerResponse?.data.customerCart?.id ?? ""; + } else { + cartId = (await resolveCartId()) ?? ""; + } + setCart({ ...cart, cartId }); + return cartId; }; - const response = await getGraphQL( - ADD_TO_CART, - variables, - storeViewCode, - config?.baseUrl - ); - - return response; - }; - - const cartContext: CartAttributesContext = { - cart, - initializeCustomerCart, - addToCartGraphQL, - refreshCart, - }; - - return ( - {children} - ); + const addToCartGraphQL = async (sku: string) => { + let cartId = cart.cartId; + if (!cartId) { + cartId = await initializeCustomerCart(); + } + const cartItems = [ + { + quantity: 1, + sku, + }, + ]; + + const variables = { + cartId, + cartItems, + }; + + const response = await getGraphQL(ADD_TO_CART, variables, storeViewCode, config?.baseUrl); + + return response; + }; + + const cartContext: CartAttributesContext = { + cart, + initializeCustomerCart, + addToCartGraphQL, + refreshCart, + }; + + return {children}; }; export { CartProvider, useCart }; diff --git a/src/context/displayChange.tsx b/src/context/displayChange.tsx index 0aba8f0..2fa146e 100644 --- a/src/context/displayChange.tsx +++ b/src/context/displayChange.tsx @@ -7,88 +7,82 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { createContext, FunctionComponent, useContext } from 'preact/compat'; -import { useEffect, useState } from 'preact/hooks'; +import { createContext, FunctionComponent, useContext } from "preact/compat"; +import { useEffect, useState } from "preact/hooks"; -import { PRODUCT_COLUMNS } from '../utils/constants'; +import { PRODUCT_COLUMNS } from "../utils/constants"; interface DisplayChange { - mobile: boolean; - tablet: boolean; - desktop: boolean; - columns: number; + mobile: boolean; + tablet: boolean; + desktop: boolean; + columns: number; } interface DisplayChangeContext { - screenSize: DisplayChange | null; + screenSize: DisplayChange | null; } const DefaultScreenSizeObject: DisplayChange = { - mobile: false, - tablet: false, - desktop: false, - columns: PRODUCT_COLUMNS.desktop, + mobile: false, + tablet: false, + desktop: false, + columns: PRODUCT_COLUMNS.desktop, }; const useSensor = () => { - const { screenSize } = useContext(ResizeChangeContext); + const { screenSize } = useContext(ResizeChangeContext); - const [result, setResult] = useState(DefaultScreenSizeObject); + const [result, setResult] = useState(DefaultScreenSizeObject); - useEffect(() => { - const size = screenSize ? screenSize : DefaultScreenSizeObject; - setResult(size); - }, [screenSize]); + useEffect(() => { + const size = screenSize ? screenSize : DefaultScreenSizeObject; + setResult(size); + }, [screenSize]); - return { screenSize: result }; + return { screenSize: result }; }; export const ResizeChangeContext = createContext({} as DisplayChangeContext); const getColumn = (screenSize: DisplayChange): number => { - if (screenSize.desktop) { + if (screenSize.desktop) { + return PRODUCT_COLUMNS.desktop; + } + if (screenSize.tablet) { + return PRODUCT_COLUMNS.tablet; + } + if (screenSize.mobile) { + return PRODUCT_COLUMNS.mobile; + } + // Fallback just incase return PRODUCT_COLUMNS.desktop; - } - if (screenSize.tablet) { - return PRODUCT_COLUMNS.tablet; - } - if (screenSize.mobile) { - return PRODUCT_COLUMNS.mobile; - } - // Fallback just incase - return PRODUCT_COLUMNS.desktop; }; const Resize: FunctionComponent = ({ children }) => { - const detectDevice = () => { - const result = DefaultScreenSizeObject; - - result.mobile = window.matchMedia('screen and (max-width: 767px)').matches; - result.tablet = window.matchMedia( - 'screen and (min-width: 768px) and (max-width: 960px)' - ).matches; - result.desktop = window.matchMedia('screen and (min-width: 961px)').matches; - result.columns = getColumn(result); - return result; - }; - - const [screenSize, setScreenSize] = useState(detectDevice()); - useEffect(() => { - window.addEventListener('resize', handleResize); - return () => { - window.removeEventListener('resize', handleResize); + const detectDevice = () => { + const result = DefaultScreenSizeObject; + + result.mobile = window.matchMedia("screen and (max-width: 767px)").matches; + result.tablet = window.matchMedia("screen and (min-width: 768px) and (max-width: 960px)").matches; + result.desktop = window.matchMedia("screen and (min-width: 961px)").matches; + result.columns = getColumn(result); + return result; }; - }); - const handleResize = () => { - setScreenSize({ ...screenSize, ...detectDevice() }); - }; + const [screenSize, setScreenSize] = useState(detectDevice()); + useEffect(() => { + window.addEventListener("resize", handleResize); + return () => { + window.removeEventListener("resize", handleResize); + }; + }); - return ( - - {children} - - ); + const handleResize = () => { + setScreenSize({ ...screenSize, ...detectDevice() }); + }; + + return {children}; }; export default Resize; diff --git a/src/context/events.tsx b/src/context/events.tsx index 921e629..bfd0acb 100644 --- a/src/context/events.tsx +++ b/src/context/events.tsx @@ -8,156 +8,144 @@ it. */ import { - SearchBucket, - SearchFacet, - SearchFilter, - SearchInputUnit, - SearchResultProduct, - SearchResultSuggestion, - SearchResultUnit, - SearchSort, -} from '@adobe/magento-storefront-events-sdk/dist/types/types/schemas'; - -import { ProductSearchResponse } from '../types/interface'; + SearchBucket, + SearchFacet, + SearchFilter, + SearchInputUnit, + SearchResultProduct, + SearchResultSuggestion, + SearchResultUnit, + SearchSort, +} from "@adobe/magento-storefront-events-sdk/dist/types/types/schemas"; + +import { ProductSearchResponse } from "../types/interface"; const updateSearchInputCtx = ( - searchUnitId: string, - searchRequestId: string, - phrase: string, - filters: Array, - pageSize: number, - currentPage: number, - sort: Array + searchUnitId: string, + searchRequestId: string, + phrase: string, + filters: Array, + pageSize: number, + currentPage: number, + sort: Array, ): void => { - const mse = window.magentoStorefrontEvents; - if (!mse) { - // don't break search if events are broken/not loading - return; - } - - const searchInputCtx = mse.context.getSearchInput() ?? { units: [] }; - - // create search input unit - const searchInputUnit: SearchInputUnit = { - searchUnitId, - searchRequestId, - queryTypes: ['products', 'suggestions'], - phrase, - pageSize, - currentPage, - filter: filters, - sort, - }; - - // find search input unit index - const searchInputUnitIndex = searchInputCtx.units.findIndex( - (unit) => unit.searchUnitId === searchUnitId - ); - - // update search input unit - if (searchInputUnitIndex < 0) { - searchInputCtx.units.push(searchInputUnit); - } else { - searchInputCtx.units[searchInputUnitIndex] = searchInputUnit; - } - - mse.context.setSearchInput(searchInputCtx); + const mse = window.magentoStorefrontEvents; + if (!mse) { + // don't break search if events are broken/not loading + return; + } + + const searchInputCtx = mse.context.getSearchInput() ?? { units: [] }; + + // create search input unit + const searchInputUnit: SearchInputUnit = { + searchUnitId, + searchRequestId, + queryTypes: ["products", "suggestions"], + phrase, + pageSize, + currentPage, + filter: filters, + sort, + }; + + // find search input unit index + const searchInputUnitIndex = searchInputCtx.units.findIndex((unit) => unit.searchUnitId === searchUnitId); + + // update search input unit + if (searchInputUnitIndex < 0) { + searchInputCtx.units.push(searchInputUnit); + } else { + searchInputCtx.units[searchInputUnitIndex] = searchInputUnit; + } + + mse.context.setSearchInput(searchInputCtx); }; const updateSearchResultsCtx = ( - searchUnitId: string, - searchRequestId: string, - results: ProductSearchResponse['data']['productSearch'] + searchUnitId: string, + searchRequestId: string, + results: ProductSearchResponse["data"]["productSearch"], ): void => { - const mse = window.magentoStorefrontEvents; - if (!mse) { - // don't break search if events are broken/not loading - return; - } - const searchResultsCtx = mse.context.getSearchResults() ?? { units: [] }; - - // find search result unit index - const searchResultUnitIndex = searchResultsCtx.units.findIndex( - (unit) => unit.searchUnitId === searchUnitId - ); - - // create search result unit - const searchResultUnit: SearchResultUnit = { - searchUnitId, - searchRequestId, - products: createProducts(results.items), - categories: [], - suggestions: createSuggestions(results.suggestions), - page: results?.page_info?.current_page || 1, - perPage: results?.page_info?.page_size || 20, - facets: createFacets(results.facets), - }; - - // update search result unit - if (searchResultUnitIndex < 0) { - searchResultsCtx.units.push(searchResultUnit); - } else { - searchResultsCtx.units[searchResultUnitIndex] = searchResultUnit; - } - - mse.context.setSearchResults(searchResultsCtx); + const mse = window.magentoStorefrontEvents; + if (!mse) { + // don't break search if events are broken/not loading + return; + } + const searchResultsCtx = mse.context.getSearchResults() ?? { units: [] }; + + // find search result unit index + const searchResultUnitIndex = searchResultsCtx.units.findIndex((unit) => unit.searchUnitId === searchUnitId); + + // create search result unit + const searchResultUnit: SearchResultUnit = { + searchUnitId, + searchRequestId, + products: createProducts(results.items), + categories: [], + suggestions: createSuggestions(results.suggestions), + page: results?.page_info?.current_page || 1, + perPage: results?.page_info?.page_size || 20, + facets: createFacets(results.facets), + }; + + // update search result unit + if (searchResultUnitIndex < 0) { + searchResultsCtx.units.push(searchResultUnit); + } else { + searchResultsCtx.units[searchResultUnitIndex] = searchResultUnit; + } + + mse.context.setSearchResults(searchResultsCtx); }; -const createProducts = ( - items: ProductSearchResponse['data']['productSearch']['items'] -): SearchResultProduct[] => { - if (!items) { - return []; - } - - const products: SearchResultProduct[] = items.map((item, index) => ({ - name: item?.product?.name, - sku: item?.product?.sku, - url: item?.product?.canonical_url ?? '', - imageUrl: item?.productView?.images?.length - ? item?.productView?.images[0].url ?? '' - : '', - price: - item?.productView?.price?.final?.amount?.value ?? - item?.product?.price_range?.minimum_price?.final_price?.value, - rank: index, - })); - - return products; +const createProducts = (items: ProductSearchResponse["data"]["productSearch"]["items"]): SearchResultProduct[] => { + if (!items) { + return []; + } + + const products: SearchResultProduct[] = items.map((item, index) => ({ + name: item?.product?.name, + sku: item?.product?.sku, + url: item?.product?.canonical_url ?? "", + imageUrl: item?.productView?.images?.length ? (item?.productView?.images[0].url ?? "") : "", + price: + item?.productView?.price?.final?.amount?.value ?? + item?.product?.price_range?.minimum_price?.final_price?.value, + rank: index, + })); + + return products; }; const createSuggestions = ( - items: ProductSearchResponse['data']['productSearch']['suggestions'] + items: ProductSearchResponse["data"]["productSearch"]["suggestions"], ): SearchResultSuggestion[] => { - if (!items) { - return []; - } - - const suggestions: SearchResultSuggestion[] = items.map( - (suggestion, index) => ({ - suggestion, - rank: index, - }) - ); - - return suggestions; + if (!items) { + return []; + } + + const suggestions: SearchResultSuggestion[] = items.map((suggestion, index) => ({ + suggestion, + rank: index, + })); + + return suggestions; }; -const createFacets = ( - items: ProductSearchResponse['data']['productSearch']['facets'] -): SearchFacet[] => { - if (!items) { - return []; - } - - const facets = items.map((item) => ({ - attribute: item?.attribute, - title: item?.title, - type: item?.type || 'PINNED', - buckets: item?.buckets.map((bucket) => bucket), - })); - - return facets; +const createFacets = (items: ProductSearchResponse["data"]["productSearch"]["facets"]): SearchFacet[] => { + if (!items) { + return []; + } + + const facets = items.map((item) => ({ + attribute: item?.attribute, + title: item?.title, + type: item?.type || "PINNED", + buckets: item?.buckets.map((bucket) => bucket), + })); + + return facets; }; export { updateSearchInputCtx, updateSearchResultsCtx }; diff --git a/src/context/index.ts b/src/context/index.ts index 8406a5d..9e9f2fe 100644 --- a/src/context/index.ts +++ b/src/context/index.ts @@ -7,13 +7,13 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -export * from './attributeMetadata'; -export * from './store'; -export * from './widgetConfig'; -export * from './search'; -export * from './products'; -export * from './displayChange'; -export * from './events'; -export * from './translation'; -export * from './cart'; -export * from './wishlist'; +export * from "./attributeMetadata"; +export * from "./store"; +export * from "./widgetConfig"; +export * from "./search"; +export * from "./products"; +export * from "./displayChange"; +export * from "./events"; +export * from "./translation"; +export * from "./cart"; +export * from "./wishlist"; diff --git a/src/context/products.tsx b/src/context/products.tsx index a7c8fbc..520f308 100644 --- a/src/context/products.tsx +++ b/src/context/products.tsx @@ -7,396 +7,347 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { createContext } from 'preact'; -import { useContext, useEffect, useMemo, useState } from 'preact/hooks'; +import { createContext } from "preact"; +import { useContext, useEffect, useMemo, useState } from "preact/hooks"; -import { getProductSearch, refineProductSearch } from '../api/search'; +import { getProductSearch, refineProductSearch } from "../api/search"; +import { Facet, FacetFilter, PageSizeOption, Product, ProductSearchQuery, RedirectRouteFunc } from "../types/interface"; import { - Facet, - FacetFilter, - PageSizeOption, - Product, - ProductSearchQuery, - RedirectRouteFunc, -} from '../types/interface'; -import { - CATEGORY_SORT_DEFAULT, - DEFAULT_MIN_QUERY_LENGTH, - DEFAULT_PAGE_SIZE, - DEFAULT_PAGE_SIZE_OPTIONS, - SEARCH_SORT_DEFAULT, -} from '../utils/constants'; -import { moveToTop } from '../utils/dom'; -import { - getFiltersFromUrl, - getValueFromUrl, - handleUrlPagination, -} from '../utils/handleUrlFilters'; -import { useAttributeMetadata } from './attributeMetadata'; -import { useSearch } from './search'; -import { useStore } from './store'; -import { useTranslation } from './translation'; + CATEGORY_SORT_DEFAULT, + DEFAULT_MIN_QUERY_LENGTH, + DEFAULT_PAGE_SIZE, + DEFAULT_PAGE_SIZE_OPTIONS, + SEARCH_SORT_DEFAULT, +} from "../utils/constants"; +import { moveToTop } from "../utils/dom"; +import { getFiltersFromUrl, getValueFromUrl, handleUrlPagination } from "../utils/handleUrlFilters"; +import { useAttributeMetadata } from "./attributeMetadata"; +import { useSearch } from "./search"; +import { useStore } from "./store"; +import { useTranslation } from "./translation"; interface WithChildrenProps { - children?: any; + children?: any; } const ProductsContext = createContext<{ - variables: ProductSearchQuery; - loading: boolean; - items: Product[]; - setItems: (items: Product[]) => void; - currentPage: number; - setCurrentPage: (page: number) => void; - pageSize: number; - setPageSize: (size: number) => void; - totalCount: number; - setTotalCount: (count: number) => void; - totalPages: number; - setTotalPages: (pages: number) => void; - facets: Facet[]; - setFacets: (facets: Facet[]) => void; - categoryName: string; - setCategoryName: (categoryName: string) => void; - currencySymbol: string; - setCurrencySymbol: (currencySymbol: string) => void; - currencyRate: string; - setCurrencyRate: (currencyRate: string) => void; - minQueryLength: string | number; - minQueryLengthReached: boolean; - setMinQueryLengthReached: (minQueryLengthReached: boolean) => void; - pageSizeOptions: PageSizeOption[]; - setRoute: RedirectRouteFunc | undefined; - refineProduct: (optionIds: string[], sku: string) => any; - pageLoading: boolean; - setPageLoading: (loading: boolean) => void; - categoryPath: string | undefined; - viewType: string; - setViewType: (viewType: string) => void; - listViewType: string; - setListViewType: (viewType: string) => void; - resolveCartId?: () => Promise; - refreshCart?: () => void; - addToCart?: ( - sku: string, - options: [], - quantity: number - ) => Promise; + variables: ProductSearchQuery; + loading: boolean; + items: Product[]; + setItems: (items: Product[]) => void; + currentPage: number; + setCurrentPage: (page: number) => void; + pageSize: number; + setPageSize: (size: number) => void; + totalCount: number; + setTotalCount: (count: number) => void; + totalPages: number; + setTotalPages: (pages: number) => void; + facets: Facet[]; + setFacets: (facets: Facet[]) => void; + categoryName: string; + setCategoryName: (categoryName: string) => void; + currencySymbol: string; + setCurrencySymbol: (currencySymbol: string) => void; + currencyRate: string; + setCurrencyRate: (currencyRate: string) => void; + minQueryLength: string | number; + minQueryLengthReached: boolean; + setMinQueryLengthReached: (minQueryLengthReached: boolean) => void; + pageSizeOptions: PageSizeOption[]; + setRoute: RedirectRouteFunc | undefined; + refineProduct: (optionIds: string[], sku: string) => any; + pageLoading: boolean; + setPageLoading: (loading: boolean) => void; + categoryPath: string | undefined; + viewType: string; + setViewType: (viewType: string) => void; + listViewType: string; + setListViewType: (viewType: string) => void; + resolveCartId?: () => Promise; + refreshCart?: () => void; + addToCart?: (sku: string, options: [], quantity: number) => Promise; }>({ - variables: { - phrase: '', - }, - loading: false, - items: [], - setItems: () => {}, - currentPage: 1, - setCurrentPage: () => {}, - pageSize: DEFAULT_PAGE_SIZE, - setPageSize: () => {}, - totalCount: 0, - setTotalCount: () => {}, - totalPages: 0, - setTotalPages: () => {}, - facets: [], - setFacets: () => {}, - categoryName: '', - setCategoryName: () => {}, - currencySymbol: '', - setCurrencySymbol: () => {}, - currencyRate: '', - setCurrencyRate: () => {}, - minQueryLength: DEFAULT_MIN_QUERY_LENGTH, - minQueryLengthReached: false, - setMinQueryLengthReached: () => {}, - pageSizeOptions: [], - setRoute: undefined, - refineProduct: () => {}, - pageLoading: false, - setPageLoading: () => {}, - categoryPath: undefined, - viewType: '', - setViewType: () => {}, - listViewType: '', - setListViewType: () => {}, - resolveCartId: () => Promise.resolve(''), - refreshCart: () => {}, - addToCart: () => Promise.resolve(), + variables: { + phrase: "", + }, + loading: false, + items: [], + setItems: () => {}, + currentPage: 1, + setCurrentPage: () => {}, + pageSize: DEFAULT_PAGE_SIZE, + setPageSize: () => {}, + totalCount: 0, + setTotalCount: () => {}, + totalPages: 0, + setTotalPages: () => {}, + facets: [], + setFacets: () => {}, + categoryName: "", + setCategoryName: () => {}, + currencySymbol: "", + setCurrencySymbol: () => {}, + currencyRate: "", + setCurrencyRate: () => {}, + minQueryLength: DEFAULT_MIN_QUERY_LENGTH, + minQueryLengthReached: false, + setMinQueryLengthReached: () => {}, + pageSizeOptions: [], + setRoute: undefined, + refineProduct: () => {}, + pageLoading: false, + setPageLoading: () => {}, + categoryPath: undefined, + viewType: "", + setViewType: () => {}, + listViewType: "", + setListViewType: () => {}, + resolveCartId: () => Promise.resolve(""), + refreshCart: () => {}, + addToCart: () => Promise.resolve(), }); const ProductsContextProvider = ({ children }: WithChildrenProps) => { - const urlValue = getValueFromUrl('p'); - const pageDefault = urlValue ? Number(urlValue) : 1; - - const searchCtx = useSearch(); - const storeCtx = useStore(); - const attributeMetadataCtx = useAttributeMetadata(); - - const pageSizeValue = getValueFromUrl('page_size'); - const defaultPageSizeOption = - Number(storeCtx?.config?.perPageConfig?.defaultPageSizeOption) || - DEFAULT_PAGE_SIZE; - const pageSizeDefault = pageSizeValue - ? Number(pageSizeValue) - : defaultPageSizeOption; - - const translation = useTranslation(); - - const showAllLabel = translation.ProductContainers.showAll; - - const [loading, setLoading] = useState(true); - const [pageLoading, setPageLoading] = useState(true); - const [items, setItems] = useState([]); - const [currentPage, setCurrentPage] = useState(pageDefault); - const [pageSize, setPageSize] = useState(pageSizeDefault); - const [totalCount, setTotalCount] = useState(0); - const [totalPages, setTotalPages] = useState(0); - const [facets, setFacets] = useState([]); - const [categoryName, setCategoryName] = useState( - storeCtx?.config?.categoryName ?? '' - ); - const [pageSizeOptions, setPageSizeOptions] = useState([]); - const [currencySymbol, setCurrencySymbol] = useState( - storeCtx?.config?.currencySymbol ?? '' - ); - const [currencyRate, setCurrencyRate] = useState( - storeCtx?.config?.currencyRate ?? '' - ); - const [minQueryLengthReached, setMinQueryLengthReached] = - useState(false); - const minQueryLength = useMemo(() => { - return storeCtx?.config?.minQueryLength || DEFAULT_MIN_QUERY_LENGTH; - }, [storeCtx?.config.minQueryLength]); - const categoryPath = storeCtx.config?.currentCategoryUrlPath; - - const viewTypeFromUrl = getValueFromUrl('view_type'); - const [viewType, setViewType] = useState( - viewTypeFromUrl ? viewTypeFromUrl : 'gridView' - ); - const [listViewType, setListViewType] = useState('default'); - - const variables = useMemo(() => { - return { - phrase: searchCtx.phrase, - filter: searchCtx.filters, - sort: searchCtx.sort, - context: storeCtx.context, - pageSize, - displayOutOfStock: storeCtx.config.displayOutOfStock, - currentPage, + const urlValue = getValueFromUrl("p"); + const pageDefault = urlValue ? Number(urlValue) : 1; + + const searchCtx = useSearch(); + const storeCtx = useStore(); + const attributeMetadataCtx = useAttributeMetadata(); + + const pageSizeValue = getValueFromUrl("page_size"); + const defaultPageSizeOption = Number(storeCtx?.config?.perPageConfig?.defaultPageSizeOption) || DEFAULT_PAGE_SIZE; + const pageSizeDefault = pageSizeValue ? Number(pageSizeValue) : defaultPageSizeOption; + + const translation = useTranslation(); + + const showAllLabel = translation.ProductContainers.showAll; + + const [loading, setLoading] = useState(true); + const [pageLoading, setPageLoading] = useState(true); + const [items, setItems] = useState([]); + const [currentPage, setCurrentPage] = useState(pageDefault); + const [pageSize, setPageSize] = useState(pageSizeDefault); + const [totalCount, setTotalCount] = useState(0); + const [totalPages, setTotalPages] = useState(0); + const [facets, setFacets] = useState([]); + const [categoryName, setCategoryName] = useState(storeCtx?.config?.categoryName ?? ""); + const [pageSizeOptions, setPageSizeOptions] = useState([]); + const [currencySymbol, setCurrencySymbol] = useState(storeCtx?.config?.currencySymbol ?? ""); + const [currencyRate, setCurrencyRate] = useState(storeCtx?.config?.currencyRate ?? ""); + const [minQueryLengthReached, setMinQueryLengthReached] = useState(false); + const minQueryLength = useMemo(() => { + return storeCtx?.config?.minQueryLength || DEFAULT_MIN_QUERY_LENGTH; + }, [storeCtx?.config.minQueryLength]); + const categoryPath = storeCtx.config?.currentCategoryUrlPath; + + const viewTypeFromUrl = getValueFromUrl("view_type"); + const [viewType, setViewType] = useState(viewTypeFromUrl ? viewTypeFromUrl : "gridView"); + const [listViewType, setListViewType] = useState("default"); + + const variables = useMemo(() => { + return { + phrase: searchCtx.phrase, + filter: searchCtx.filters, + sort: searchCtx.sort, + context: storeCtx.context, + pageSize, + displayOutOfStock: storeCtx.config.displayOutOfStock, + currentPage, + }; + }, [ + searchCtx.phrase, + searchCtx.filters, + searchCtx.sort, + storeCtx.context, + storeCtx.config.displayOutOfStock, + pageSize, + currentPage, + ]); + + const handleRefineProductSearch = async (optionIds: string[], sku: string) => { + const data = await refineProductSearch({ ...storeCtx, optionIds, sku }); + return data; }; - }, [ - searchCtx.phrase, - searchCtx.filters, - searchCtx.sort, - storeCtx.context, - storeCtx.config.displayOutOfStock, - pageSize, - currentPage, - ]); - - const handleRefineProductSearch = async ( - optionIds: string[], - sku: string - ) => { - const data = await refineProductSearch({ ...storeCtx, optionIds, sku }); - return data; - }; - - const context = { - variables, - loading, - items, - setItems, - currentPage, - setCurrentPage, - pageSize, - setPageSize, - totalCount, - setTotalCount, - totalPages, - setTotalPages, - facets, - setFacets, - categoryName, - setCategoryName, - currencySymbol, - setCurrencySymbol, - currencyRate, - setCurrencyRate, - minQueryLength, - minQueryLengthReached, - setMinQueryLengthReached, - pageSizeOptions, - setRoute: storeCtx.route, - refineProduct: handleRefineProductSearch, - pageLoading, - setPageLoading, - categoryPath, - viewType, - setViewType, - listViewType, - setListViewType, - cartId: storeCtx.config.resolveCartId, - refreshCart: storeCtx.config.refreshCart, - resolveCartId: storeCtx.config.resolveCartId, - addToCart: storeCtx.config.addToCart, - }; - - const searchProducts = async () => { - try { - setLoading(true); - moveToTop(); - if (checkMinQueryLength()) { - const filters = [...variables.filter]; - - handleCategorySearch(categoryPath, filters); - - const data = await getProductSearch({ - ...variables, - ...storeCtx, - apiUrl: storeCtx.apiUrl, - filter: filters, - categorySearch: !!categoryPath, + + const context = { + variables, + loading, + items, + setItems, + currentPage, + setCurrentPage, + pageSize, + setPageSize, + totalCount, + setTotalCount, + totalPages, + setTotalPages, + facets, + setFacets, + categoryName, + setCategoryName, + currencySymbol, + setCurrencySymbol, + currencyRate, + setCurrencyRate, + minQueryLength, + minQueryLengthReached, + setMinQueryLengthReached, + pageSizeOptions, + setRoute: storeCtx.route, + refineProduct: handleRefineProductSearch, + pageLoading, + setPageLoading, + categoryPath, + viewType, + setViewType, + listViewType, + setListViewType, + cartId: storeCtx.config.resolveCartId, + refreshCart: storeCtx.config.refreshCart, + resolveCartId: storeCtx.config.resolveCartId, + addToCart: storeCtx.config.addToCart, + }; + + const searchProducts = async () => { + try { + setLoading(true); + moveToTop(); + if (checkMinQueryLength()) { + const filters = [...variables.filter]; + + handleCategorySearch(categoryPath, filters); + + const data = await getProductSearch({ + ...variables, + ...storeCtx, + apiUrl: storeCtx.apiUrl, + filter: filters, + categorySearch: !!categoryPath, + }); + + setItems(data?.productSearch?.items || []); + setFacets(data?.productSearch?.facets || []); + setTotalCount(data?.productSearch?.total_count || 0); + setTotalPages(data?.productSearch?.page_info?.total_pages || 1); + handleCategoryNames(data?.productSearch?.facets || []); + + getPageSizeOptions(data?.productSearch?.total_count); + + paginationCheck(data?.productSearch?.total_count, data?.productSearch?.page_info?.total_pages); + } + setLoading(false); + setPageLoading(false); + } catch (error) { + setLoading(false); + setPageLoading(false); + } + }; + + const checkMinQueryLength = () => { + if ( + !storeCtx.config?.currentCategoryUrlPath && + searchCtx.phrase.trim().length < (Number(storeCtx.config.minQueryLength) || DEFAULT_MIN_QUERY_LENGTH) + ) { + setItems([]); + setFacets([]); + setTotalCount(0); + setTotalPages(1); + setMinQueryLengthReached(false); + return false; + } + setMinQueryLengthReached(true); + return true; + }; + + const getPageSizeOptions = (totalCount: number | null) => { + const optionsArray: PageSizeOption[] = []; + const pageSizeString = storeCtx?.config?.perPageConfig?.pageSizeOptions || DEFAULT_PAGE_SIZE_OPTIONS; + const pageSizeArray = pageSizeString.split(","); + pageSizeArray.forEach((option) => { + optionsArray.push({ + label: option, + value: parseInt(option, 10), + }); }); - setItems(data?.productSearch?.items || []); - setFacets(data?.productSearch?.facets || []); - setTotalCount(data?.productSearch?.total_count || 0); - setTotalPages(data?.productSearch?.page_info?.total_pages || 1); - handleCategoryNames(data?.productSearch?.facets || []); - - getPageSizeOptions(data?.productSearch?.total_count); - - paginationCheck( - data?.productSearch?.total_count, - data?.productSearch?.page_info?.total_pages - ); - } - setLoading(false); - setPageLoading(false); - } catch (error) { - setLoading(false); - setPageLoading(false); - } - }; - - const checkMinQueryLength = () => { - if ( - !storeCtx.config?.currentCategoryUrlPath && - searchCtx.phrase.trim().length < - (Number(storeCtx.config.minQueryLength) || DEFAULT_MIN_QUERY_LENGTH) - ) { - setItems([]); - setFacets([]); - setTotalCount(0); - setTotalPages(1); - setMinQueryLengthReached(false); - return false; - } - setMinQueryLengthReached(true); - return true; - }; - - const getPageSizeOptions = (totalCount: number | null) => { - const optionsArray: PageSizeOption[] = []; - const pageSizeString = - storeCtx?.config?.perPageConfig?.pageSizeOptions || - DEFAULT_PAGE_SIZE_OPTIONS; - const pageSizeArray = pageSizeString.split(','); - pageSizeArray.forEach((option) => { - optionsArray.push({ - label: option, - value: parseInt(option, 10), - }); - }); - - if (storeCtx?.config?.allowAllProducts == '1') { - // '==' is intentional for conversion - optionsArray.push({ - label: showAllLabel, - value: totalCount !== null ? (totalCount > 500 ? 500 : totalCount) : 0, - }); - } - setPageSizeOptions(optionsArray); - }; - - const paginationCheck = ( - totalCount: number | null, - totalPages: number | undefined - ) => { - if (totalCount && totalCount > 0 && totalPages === 1) { - setCurrentPage(1); - handleUrlPagination(1); - } - }; - - const handleCategorySearch = ( - categoryPath: string | undefined, - filters: FacetFilter[] - ) => { - if (categoryPath) { - //add category filter - const categoryFilter = { - attribute: 'categoryPath', - eq: categoryPath, - }; - filters.push(categoryFilter); - - //add default category sort - if (variables.sort.length < 1 || variables.sort === SEARCH_SORT_DEFAULT) { - variables.sort = CATEGORY_SORT_DEFAULT; - } - } - }; - - const handleCategoryNames = (facets: Facet[]) => { - facets.map((facet) => { - const bucketType = facet?.buckets[0]?.__typename; - if (bucketType === 'CategoryView') { - const names = facet.buckets.map((bucket) => { - if (bucket.__typename === 'CategoryView') - return { - name: bucket.name, - value: bucket.title, - attribute: facet.attribute, + if (storeCtx?.config?.allowAllProducts == "1") { + // '==' is intentional for conversion + optionsArray.push({ + label: showAllLabel, + value: totalCount !== null ? (totalCount > 500 ? 500 : totalCount) : 0, + }); + } + setPageSizeOptions(optionsArray); + }; + + const paginationCheck = (totalCount: number | null, totalPages: number | undefined) => { + if (totalCount && totalCount > 0 && totalPages === 1) { + setCurrentPage(1); + handleUrlPagination(1); + } + }; + + const handleCategorySearch = (categoryPath: string | undefined, filters: FacetFilter[]) => { + if (categoryPath) { + //add category filter + const categoryFilter = { + attribute: "categoryPath", + eq: categoryPath, }; + filters.push(categoryFilter); + + //add default category sort + if (variables.sort.length < 1 || variables.sort === SEARCH_SORT_DEFAULT) { + variables.sort = CATEGORY_SORT_DEFAULT; + } + } + }; + + const handleCategoryNames = (facets: Facet[]) => { + facets.map((facet) => { + const bucketType = facet?.buckets[0]?.__typename; + if (bucketType === "CategoryView") { + const names = facet.buckets.map((bucket) => { + if (bucket.__typename === "CategoryView") + return { + name: bucket.name, + value: bucket.title, + attribute: facet.attribute, + }; + }); + searchCtx.setCategoryNames(names); + } }); - searchCtx.setCategoryNames(names); - } - }); - }; - - useEffect(() => { - if (attributeMetadataCtx.filterableInSearch) { - searchProducts(); - } - }, [searchCtx.filters]); - - useEffect(() => { - if (attributeMetadataCtx.filterableInSearch) { - const filtersFromUrl = getFiltersFromUrl( - attributeMetadataCtx.filterableInSearch - ); - searchCtx.setFilters(filtersFromUrl); - } - }, [attributeMetadataCtx.filterableInSearch]); - - useEffect(() => { - if (!loading) { - searchProducts(); - } - }, [searchCtx.phrase, searchCtx.sort, currentPage, pageSize]); - - return ( - - {children} - - ); + }; + + useEffect(() => { + if (attributeMetadataCtx.filterableInSearch) { + searchProducts(); + } + }, [searchCtx.filters]); + + useEffect(() => { + if (attributeMetadataCtx.filterableInSearch) { + const filtersFromUrl = getFiltersFromUrl(attributeMetadataCtx.filterableInSearch); + searchCtx.setFilters(filtersFromUrl); + } + }, [attributeMetadataCtx.filterableInSearch]); + + useEffect(() => { + if (!loading) { + searchProducts(); + } + }, [searchCtx.phrase, searchCtx.sort, currentPage, pageSize]); + + return {children}; }; const useProducts = () => { - const productsCtx = useContext(ProductsContext); - return productsCtx; + const productsCtx = useContext(ProductsContext); + return productsCtx; }; export { ProductsContextProvider, useProducts }; diff --git a/src/context/search.tsx b/src/context/search.tsx index c6d7bbe..7579c1b 100644 --- a/src/context/search.tsx +++ b/src/context/search.tsx @@ -7,158 +7,138 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { createContext, FunctionComponent, useContext } from 'preact/compat'; -import { useState } from 'preact/hooks'; -import { useEffect } from 'react'; - -import { - FacetFilter, - ProductSearchSortInput, - SearchClauseInput, -} from '../types/interface'; -import { SEARCH_SORT_DEFAULT } from '../utils/constants'; -import { - addUrlFilter, - getValueFromUrl, - removeAllUrlFilters, - removeUrlFilter, -} from '../utils/handleUrlFilters'; -import { generateGQLSortInput } from '../utils/sort'; -import { useStore } from './store'; +import { createContext, FunctionComponent, useContext } from "preact/compat"; +import { useState } from "preact/hooks"; +import { useEffect } from "react"; + +import { FacetFilter, ProductSearchSortInput, SearchClauseInput } from "../types/interface"; +import { SEARCH_SORT_DEFAULT } from "../utils/constants"; +import { addUrlFilter, getValueFromUrl, removeAllUrlFilters, removeUrlFilter } from "../utils/handleUrlFilters"; +import { generateGQLSortInput } from "../utils/sort"; +import { useStore } from "./store"; interface SearchContextProps { - phrase: string; - categoryPath: string; - filters: FacetFilter[]; - sort: ProductSearchSortInput[]; - setPhrase: any; // FIXME: replace all any with type - setCategoryPath: any; - setFilters: any; - setSort: any; - setCategoryNames: any; - filterCount: number; - categoryNames: { name: string; value: string; attribute: string }[]; - createFilter: (filter: FacetFilter) => void; - updateFilter: (filter: FacetFilter) => void; - updateFilterOptions(filter: FacetFilter, option: string): void; - removeFilter: (name: string, option?: string) => void; - clearFilters: () => void; + phrase: string; + categoryPath: string; + filters: FacetFilter[]; + sort: ProductSearchSortInput[]; + setPhrase: any; // FIXME: replace all any with type + setCategoryPath: any; + setFilters: any; + setSort: any; + setCategoryNames: any; + filterCount: number; + categoryNames: { name: string; value: string; attribute: string }[]; + createFilter: (filter: FacetFilter) => void; + updateFilter: (filter: FacetFilter) => void; + updateFilterOptions(filter: FacetFilter, option: string): void; + removeFilter: (name: string, option?: string) => void; + clearFilters: () => void; } export const SearchContext = createContext({} as SearchContextProps); const SearchProvider: FunctionComponent = ({ children }) => { - const storeCtx = useStore(); - const phraseFromUrl = getValueFromUrl(storeCtx.searchQuery || 'q'); - - const sortFromUrl = getValueFromUrl('product_list_order'); - - const graphQLSort = generateGQLSortInput(sortFromUrl); - const sortDefault = graphQLSort - ? (graphQLSort as ProductSearchSortInput[]) - : SEARCH_SORT_DEFAULT; // default to "relevance" sort - - const [phrase, setPhrase] = useState(phraseFromUrl); - const [categoryPath, setCategoryPath] = useState(''); - const [filters, setFilters] = useState([]); - const [categoryNames, setCategoryNames] = useState< - { name: string; value: string; attribute: string }[] - >([]); - const [sort, setSort] = useState(sortDefault); - const [filterCount, setFilterCount] = useState(0); - - const createFilter = (filter: SearchClauseInput) => { - const newFilters = [...filters, filter]; - setFilters(newFilters); - addUrlFilter(filter); - }; - - const updateFilter = (filter: SearchClauseInput) => { - const newFilters = [...filters]; - const index = newFilters.findIndex((e) => e.attribute === filter.attribute); - newFilters[index] = filter; - setFilters(newFilters); - addUrlFilter(filter); - }; - - const removeFilter = (name: string, option?: string) => { - const newFilters = [...filters].filter((e) => { - return e.attribute !== name; - }); - setFilters(newFilters); - removeUrlFilter(name, option); - }; - - const clearFilters = () => { - removeAllUrlFilters(); - setFilters([]); - }; - - const updateFilterOptions = ( - facetFilter: SearchClauseInput, - option: string - ) => { - const newFilters = [...filters].filter( - (e) => e.attribute !== facetFilter.attribute - ); - const newOptions = facetFilter.in?.filter((e) => e !== option); - - newFilters.push({ - attribute: facetFilter.attribute, - in: newOptions, - }); - if (newOptions?.length) { - setFilters(newFilters); - removeUrlFilter(facetFilter.attribute, option); - } else { - removeFilter(facetFilter.attribute, option); - } - }; - - const getFilterCount = (filters: SearchClauseInput[]) => { - let count = 0; - filters.forEach((filter) => { - if (filter.in) { - count += filter.in.length; - } else { - count += 1; - } - }); - return count; - }; - - useEffect(() => { - const count = getFilterCount(filters); - setFilterCount(count); - }, [filters]); - - const context: SearchContextProps = { - phrase, - categoryPath, - filters, - sort, - categoryNames, - filterCount, - setPhrase, - setCategoryPath, - setFilters, - setCategoryNames, - setSort, - createFilter, - updateFilter, - updateFilterOptions, - removeFilter, - clearFilters, - }; - - return ( - {children} - ); + const storeCtx = useStore(); + const phraseFromUrl = getValueFromUrl(storeCtx.searchQuery || "q"); + + const sortFromUrl = getValueFromUrl("product_list_order"); + + const graphQLSort = generateGQLSortInput(sortFromUrl); + const sortDefault = graphQLSort ? (graphQLSort as ProductSearchSortInput[]) : SEARCH_SORT_DEFAULT; // default to "relevance" sort + + const [phrase, setPhrase] = useState(phraseFromUrl); + const [categoryPath, setCategoryPath] = useState(""); + const [filters, setFilters] = useState([]); + const [categoryNames, setCategoryNames] = useState<{ name: string; value: string; attribute: string }[]>([]); + const [sort, setSort] = useState(sortDefault); + const [filterCount, setFilterCount] = useState(0); + + const createFilter = (filter: SearchClauseInput) => { + const newFilters = [...filters, filter]; + setFilters(newFilters); + addUrlFilter(filter); + }; + + const updateFilter = (filter: SearchClauseInput) => { + const newFilters = [...filters]; + const index = newFilters.findIndex((e) => e.attribute === filter.attribute); + newFilters[index] = filter; + setFilters(newFilters); + addUrlFilter(filter); + }; + + const removeFilter = (name: string, option?: string) => { + const newFilters = [...filters].filter((e) => { + return e.attribute !== name; + }); + setFilters(newFilters); + removeUrlFilter(name, option); + }; + + const clearFilters = () => { + removeAllUrlFilters(); + setFilters([]); + }; + + const updateFilterOptions = (facetFilter: SearchClauseInput, option: string) => { + const newFilters = [...filters].filter((e) => e.attribute !== facetFilter.attribute); + const newOptions = facetFilter.in?.filter((e) => e !== option); + + newFilters.push({ + attribute: facetFilter.attribute, + in: newOptions, + }); + if (newOptions?.length) { + setFilters(newFilters); + removeUrlFilter(facetFilter.attribute, option); + } else { + removeFilter(facetFilter.attribute, option); + } + }; + + const getFilterCount = (filters: SearchClauseInput[]) => { + let count = 0; + filters.forEach((filter) => { + if (filter.in) { + count += filter.in.length; + } else { + count += 1; + } + }); + return count; + }; + + useEffect(() => { + const count = getFilterCount(filters); + setFilterCount(count); + }, [filters]); + + const context: SearchContextProps = { + phrase, + categoryPath, + filters, + sort, + categoryNames, + filterCount, + setPhrase, + setCategoryPath, + setFilters, + setCategoryNames, + setSort, + createFilter, + updateFilter, + updateFilterOptions, + removeFilter, + clearFilters, + }; + + return {children}; }; const useSearch = () => { - const searchCtx = useContext(SearchContext); - return searchCtx; + const searchCtx = useContext(SearchContext); + return searchCtx; }; export { SearchProvider, useSearch }; diff --git a/src/context/store.tsx b/src/context/store.tsx index 538ce33..0806eaf 100644 --- a/src/context/store.tsx +++ b/src/context/store.tsx @@ -7,97 +7,86 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { createContext } from 'preact'; -import { useContext, useMemo } from 'preact/hooks'; +import { createContext } from "preact"; +import { useContext, useMemo } from "preact/hooks"; -import { - QueryContextInput, - RedirectRouteFunc, - StoreDetailsConfig, -} from '../types/interface'; +import { QueryContextInput, RedirectRouteFunc, StoreDetailsConfig } from "../types/interface"; interface WithChildrenProps { - children?: any; + children?: any; } export interface StoreDetailsProps extends WithChildrenProps { - environmentId: string; - environmentType: string; - websiteCode: string; - storeCode: string; - storeViewCode: string; - config: StoreDetailsConfig; - context?: QueryContextInput; - apiUrl: string; - apiKey: string; - route?: RedirectRouteFunc; // optional product redirect func prop - searchQuery?: string; // 'q' default search query param if not provided. + environmentId: string; + environmentType: string; + websiteCode: string; + storeCode: string; + storeViewCode: string; + config: StoreDetailsConfig; + context?: QueryContextInput; + apiUrl: string; + apiKey: string; + route?: RedirectRouteFunc; // optional product redirect func prop + searchQuery?: string; // 'q' default search query param if not provided. } const StoreContext = createContext({ - environmentId: '', - environmentType: '', - websiteCode: '', - storeCode: '', - storeViewCode: '', - apiUrl: '', - apiKey: '', - config: {}, - context: {}, - route: undefined, - searchQuery: 'q', + environmentId: "", + environmentType: "", + websiteCode: "", + storeCode: "", + storeViewCode: "", + apiUrl: "", + apiKey: "", + config: {}, + context: {}, + route: undefined, + searchQuery: "q", }); const StoreContextProvider = ({ - children, - environmentId, - environmentType, - websiteCode, - storeCode, - storeViewCode, - config, - context, - apiKey, - route, - searchQuery, + children, + environmentId, + environmentType, + websiteCode, + storeCode, + storeViewCode, + config, + context, + apiKey, + route, + searchQuery, }: StoreDetailsProps) => { - const storeProps = useMemo( - () => ({ - environmentId, - environmentType, - websiteCode, - storeCode, - storeViewCode, - config, - context: { - customerGroup: context?.customerGroup ?? '', - userViewHistory: context?.userViewHistory ?? [], - }, - apiUrl: environmentType?.toLowerCase() === 'testing' ? TEST_URL : API_URL, - apiKey: - environmentType?.toLowerCase() === 'testing' && !apiKey - ? SANDBOX_KEY - : apiKey, - route, - searchQuery, - }), - [environmentId, websiteCode, storeCode, storeViewCode] - ); + const storeProps = useMemo( + () => ({ + environmentId, + environmentType, + websiteCode, + storeCode, + storeViewCode, + config, + context: { + customerGroup: context?.customerGroup ?? "", + userViewHistory: context?.userViewHistory ?? [], + }, + apiUrl: environmentType?.toLowerCase() === "testing" ? TEST_URL : API_URL, + apiKey: environmentType?.toLowerCase() === "testing" && !apiKey ? SANDBOX_KEY : apiKey, + route, + searchQuery, + }), + [environmentId, websiteCode, storeCode, storeViewCode], + ); - const storeContext = { - ...storeProps, - }; + const storeContext = { + ...storeProps, + }; - return ( - - {children} - - ); + return {children}; }; const useStore = () => { - const storeCtx = useContext(StoreContext); - return storeCtx; + const storeCtx = useContext(StoreContext); + return storeCtx; }; export { StoreContextProvider, useStore }; diff --git a/src/context/translation.tsx b/src/context/translation.tsx index eb8be7b..8ac9a7f 100644 --- a/src/context/translation.tsx +++ b/src/context/translation.tsx @@ -7,111 +7,107 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { createContext, FunctionComponent, useContext } from 'preact/compat'; +import { createContext, FunctionComponent, useContext } from "preact/compat"; import { - bg_BG, - ca_ES, - cs_CZ, - da_DK, - de_DE, - el_GR, - en_GB, - en_US, - es_ES, - et_EE, - eu_ES, - fa_IR, - fi_FI, - fr_FR, - gl_ES, - hi_IN, - hu_HU, - id_ID, - it_IT, - ja_JP, - ko_KR, - lt_LT, - lv_LV, - nb_NO, - nl_NL, - pt_BR, - pt_PT, - ro_RO, - ru_RU, - sv_SE, - th_TH, - tr_TR, - zh_Hans_CN, - zh_Hant_TW, -} from '../i18n'; -import { useStore } from './store'; + bg_BG, + ca_ES, + cs_CZ, + da_DK, + de_DE, + el_GR, + en_GB, + en_US, + es_ES, + et_EE, + eu_ES, + fa_IR, + fi_FI, + fr_FR, + gl_ES, + hi_IN, + hu_HU, + id_ID, + it_IT, + ja_JP, + ko_KR, + lt_LT, + lv_LV, + nb_NO, + nl_NL, + pt_BR, + pt_PT, + ro_RO, + ru_RU, + sv_SE, + th_TH, + tr_TR, + zh_Hans_CN, + zh_Hant_TW, +} from "../i18n"; +import { useStore } from "./store"; export type Language = { [key: string]: any }; export type Languages = { [key: string]: Language }; export const languages: Languages = { - default: en_US, - bg_BG, - ca_ES, - cs_CZ, - da_DK, - de_DE, - el_GR, - en_GB, - en_US, - es_ES, - et_EE, - eu_ES, - fa_IR, - fi_FI, - fr_FR, - gl_ES, - hi_IN, - hu_HU, - id_ID, - it_IT, - ja_JP, - ko_KR, - lt_LT, - lv_LV, - nb_NO, - nl_NL, - pt_BR, - pt_PT, - ro_RO, - ru_RU, - sv_SE, - th_TH, - tr_TR, - zh_Hans_CN, - zh_Hant_TW, + default: en_US, + bg_BG, + ca_ES, + cs_CZ, + da_DK, + de_DE, + el_GR, + en_GB, + en_US, + es_ES, + et_EE, + eu_ES, + fa_IR, + fi_FI, + fr_FR, + gl_ES, + hi_IN, + hu_HU, + id_ID, + it_IT, + ja_JP, + ko_KR, + lt_LT, + lv_LV, + nb_NO, + nl_NL, + pt_BR, + pt_PT, + ro_RO, + ru_RU, + sv_SE, + th_TH, + tr_TR, + zh_Hans_CN, + zh_Hant_TW, }; export const TranslationContext = createContext(languages.default); const useTranslation = () => { - const translation = useContext(TranslationContext); - return translation; + const translation = useContext(TranslationContext); + return translation; }; const getCurrLanguage = (languageDetected: string) => { - const langKeys = Object.keys(languages); - if (langKeys.includes(languageDetected)) { - return languageDetected; - } - return 'default'; + const langKeys = Object.keys(languages); + if (langKeys.includes(languageDetected)) { + return languageDetected; + } + return "default"; }; const Translation: FunctionComponent = ({ children }) => { - const storeCtx = useStore(); + const storeCtx = useStore(); - const currLanguage = getCurrLanguage(storeCtx?.config?.locale ?? ''); + const currLanguage = getCurrLanguage(storeCtx?.config?.locale ?? ""); - return ( - - {children} - - ); + return {children}; }; export default Translation; export { getCurrLanguage, useTranslation }; diff --git a/src/context/widgetConfig.tsx b/src/context/widgetConfig.tsx index 88a8dfe..b84c69e 100644 --- a/src/context/widgetConfig.tsx +++ b/src/context/widgetConfig.tsx @@ -7,127 +7,119 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { createContext } from 'preact'; -import { useContext, useEffect, useState } from 'preact/hooks'; +import { createContext } from "preact"; +import { useContext, useEffect, useState } from "preact/hooks"; -import { WidgetConfigOptions } from '../types/interface'; -import { useStore } from './store'; +import { WidgetConfigOptions } from "../types/interface"; +import { useStore } from "./store"; interface WidgetConfigProps extends WidgetConfigOptions {} const defaultWidgetConfigState = { - badge: { - enabled: false, - label: '', - attributeCode: '', - backgroundColor: '', - }, - price: { - showNoPrice: false, - showRange: true, - showRegularPrice: true, - showStrikethruPrice: true, - }, - attributeSlot: { - enabled: false, - attributeCode: '', - backgroundColor: '', - }, - addToWishlist: { - enabled: true, - placement: 'inLineWithName' as const, - }, - layout: { - defaultLayout: 'grid' as const, - allowedLayouts: [], - showToggle: true, - }, - addToCart: { enabled: true }, - stockStatusFilterLook: 'radio' as const, - swatches: { - enabled: false, - swatchAttributes: [], - swatchesOnPage: 10, - }, - multipleImages: { - enabled: true, - limit: 10, - }, - compare: { - enabled: true, - }, + badge: { + enabled: false, + label: "", + attributeCode: "", + backgroundColor: "", + }, + price: { + showNoPrice: false, + showRange: true, + showRegularPrice: true, + showStrikethruPrice: true, + }, + attributeSlot: { + enabled: false, + attributeCode: "", + backgroundColor: "", + }, + addToWishlist: { + enabled: true, + placement: "inLineWithName" as const, + }, + layout: { + defaultLayout: "grid" as const, + allowedLayouts: [], + showToggle: true, + }, + addToCart: { enabled: true }, + stockStatusFilterLook: "radio" as const, + swatches: { + enabled: false, + swatchAttributes: [], + swatchesOnPage: 10, + }, + multipleImages: { + enabled: true, + limit: 10, + }, + compare: { + enabled: true, + }, }; -const WidgetConfigContext = createContext( - defaultWidgetConfigState -); +const WidgetConfigContext = createContext(defaultWidgetConfigState); const WidgetConfigContextProvider = ({ children }: { children?: any }) => { - const storeCtx = useStore(); - const { environmentId, storeCode } = storeCtx; - - const [widgetConfig, setWidgetConfig] = useState( - defaultWidgetConfigState - ); - // widgetConfigFetched is to prevent configs flashing with default setting - // incase of there's slowness of widget config API - const [widgetConfigFetched, setWidgetConfigFetched] = - useState(false); - - useEffect(() => { - if (!environmentId || !storeCode) { - return; - } - - !widgetConfigFetched && - getWidgetConfig(environmentId, storeCode) - .then((results) => { - const newWidgetConfig = { - // new merchant config could have some missing node config, so it needs to merge with default config for missing nodes - ...defaultWidgetConfigState, - ...results, - }; - setWidgetConfig(newWidgetConfig); - setWidgetConfigFetched(true); - }) - .finally(() => { - setWidgetConfigFetched(true); + const storeCtx = useStore(); + const { environmentId, storeCode } = storeCtx; + + const [widgetConfig, setWidgetConfig] = useState(defaultWidgetConfigState); + // widgetConfigFetched is to prevent configs flashing with default setting + // incase of there's slowness of widget config API + const [widgetConfigFetched, setWidgetConfigFetched] = useState(false); + + useEffect(() => { + if (!environmentId || !storeCode) { + return; + } + + !widgetConfigFetched && + getWidgetConfig(environmentId, storeCode) + .then((results) => { + const newWidgetConfig = { + // new merchant config could have some missing node config, so it needs to merge with default config for missing nodes + ...defaultWidgetConfigState, + ...results, + }; + setWidgetConfig(newWidgetConfig); + setWidgetConfigFetched(true); + }) + .finally(() => { + setWidgetConfigFetched(true); + }); + }, [environmentId, storeCode]); + + const getWidgetConfig = async (envId: string, storeCode: string): Promise => { + const fileName = "widgets-config.json"; + const S3path = `/${envId}/${storeCode}/${fileName}`; + const widgetConfigUrl = `${WIDGET_CONFIG_URL}${S3path}`; + + const response = await fetch(widgetConfigUrl, { + method: "GET", }); - }, [environmentId, storeCode]); - - const getWidgetConfig = async ( - envId: string, - storeCode: string - ): Promise => { - const fileName = 'widgets-config.json'; - const S3path = `/${envId}/${storeCode}/${fileName}`; - const widgetConfigUrl = `${WIDGET_CONFIG_URL}${S3path}`; - - const response = await fetch(widgetConfigUrl, { - method: 'GET', - }); - - if (response.status !== 200) { - return defaultWidgetConfigState; - } - const results = await response?.json(); - return results; - }; - - const widgetConfigCtx = { - ...widgetConfig, - }; - - return ( - - {widgetConfigFetched && children} - - ); + + if (response.status !== 200) { + return defaultWidgetConfigState; + } + const results = await response?.json(); + return results; + }; + + const widgetConfigCtx = { + ...widgetConfig, + }; + + return ( + + {widgetConfigFetched && children} + + ); }; const useWidgetConfig = () => { - const widgetConfigCtx = useContext(WidgetConfigContext); - return widgetConfigCtx; + const widgetConfigCtx = useContext(WidgetConfigContext); + return widgetConfigCtx; }; export { WidgetConfigContextProvider, useWidgetConfig }; diff --git a/src/context/wishlist.tsx b/src/context/wishlist.tsx index ec8d802..b7f7593 100644 --- a/src/context/wishlist.tsx +++ b/src/context/wishlist.tsx @@ -7,118 +7,94 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { createContext, FunctionComponent } from 'preact'; -import { useContext, useEffect, useState } from 'preact/hooks'; +import { createContext, FunctionComponent } from "preact"; +import { useContext, useEffect, useState } from "preact/hooks"; -import { getGraphQL } from '../api/graphql'; -import { ADD_TO_WISHLIST, REMOVE_FROM_WISHLIST } from '../api/mutations'; -import { GET_CUSTOMER_WISHLISTS } from '../api/queries'; -import { - Wishlist, - WishlistAddItemInput, - WishlistResponse, -} from '../types/interface'; -import { useStore } from './store'; +import { getGraphQL } from "../api/graphql"; +import { ADD_TO_WISHLIST, REMOVE_FROM_WISHLIST } from "../api/mutations"; +import { GET_CUSTOMER_WISHLISTS } from "../api/queries"; +import { Wishlist, WishlistAddItemInput, WishlistResponse } from "../types/interface"; +import { useStore } from "./store"; export interface WishlistAttributesContext { - isAuthorized: boolean; - wishlist: Wishlist | undefined; - allWishlist: Wishlist[] | []; - addItemToWishlist: ( - wishlistId: string, - wishlistItem: WishlistAddItemInput - ) => void; - removeItemFromWishlist: (wishlistId: string, wishlistItemIds: string) => void; + isAuthorized: boolean; + wishlist: Wishlist | undefined; + allWishlist: Wishlist[] | []; + addItemToWishlist: (wishlistId: string, wishlistItem: WishlistAddItemInput) => void; + removeItemFromWishlist: (wishlistId: string, wishlistItemIds: string) => void; } const WishlistContext = createContext({} as WishlistAttributesContext); const useWishlist = (): WishlistAttributesContext => { - return useContext(WishlistContext); + return useContext(WishlistContext); }; const WishlistProvider: FunctionComponent = ({ children }) => { - const [isAuthorized, setIsAuthorized] = useState(false); - const [allWishlist, setAllWishlist] = useState([]); - const [wishlist, setWishlist] = useState(); - const { storeViewCode, config } = useStore(); + const [isAuthorized, setIsAuthorized] = useState(false); + const [allWishlist, setAllWishlist] = useState([]); + const [wishlist, setWishlist] = useState(); + const { storeViewCode, config } = useStore(); - useEffect(() => { - getWishlists(); - }, []); + useEffect(() => { + getWishlists(); + }, []); - const getWishlists = async () => { - const { data } = - (await getGraphQL( - GET_CUSTOMER_WISHLISTS, - {}, - storeViewCode, - config?.baseUrl - )) || {}; - const wishlistResponse: WishlistResponse = data?.customer; - const isAuthorized = !!wishlistResponse; + const getWishlists = async () => { + const { data } = (await getGraphQL(GET_CUSTOMER_WISHLISTS, {}, storeViewCode, config?.baseUrl)) || {}; + const wishlistResponse: WishlistResponse = data?.customer; + const isAuthorized = !!wishlistResponse; - setIsAuthorized(isAuthorized); - if (isAuthorized) { - // TODO: MSRCH-4278 - // We'll need to add a way to select a wishlist - // // FIXME: first Wishlist is temporary solution for QA as working concept - const firstWishlist = wishlistResponse.wishlists[0]; - setWishlist(firstWishlist); - setAllWishlist(wishlistResponse.wishlists); - } - }; + setIsAuthorized(isAuthorized); + if (isAuthorized) { + // TODO: MSRCH-4278 + // We'll need to add a way to select a wishlist + // // FIXME: first Wishlist is temporary solution for QA as working concept + const firstWishlist = wishlistResponse.wishlists[0]; + setWishlist(firstWishlist); + setAllWishlist(wishlistResponse.wishlists); + } + }; - const addItemToWishlist = async ( - wishlistId: string, - wishlistItem: WishlistAddItemInput - ) => { - const { data } = - (await getGraphQL( - ADD_TO_WISHLIST, - { - wishlistId, - wishlistItems: [wishlistItem], - }, - storeViewCode, - config?.baseUrl - )) || {}; - const wishlistResponse: Wishlist = data?.addProductsToWishlist.wishlist; - setWishlist(wishlistResponse); - }; + const addItemToWishlist = async (wishlistId: string, wishlistItem: WishlistAddItemInput) => { + const { data } = + (await getGraphQL( + ADD_TO_WISHLIST, + { + wishlistId, + wishlistItems: [wishlistItem], + }, + storeViewCode, + config?.baseUrl, + )) || {}; + const wishlistResponse: Wishlist = data?.addProductsToWishlist.wishlist; + setWishlist(wishlistResponse); + }; - const removeItemFromWishlist = async ( - wishlistId: string, - wishlistItemsIds: string - ) => { - const { data } = - (await getGraphQL( - REMOVE_FROM_WISHLIST, - { - wishlistId, - wishlistItemsIds: [wishlistItemsIds], - }, - storeViewCode, - config?.baseUrl - )) || {}; - const wishlistResponse: Wishlist = - data?.removeProductsFromWishlist.wishlist; - setWishlist(wishlistResponse); - }; + const removeItemFromWishlist = async (wishlistId: string, wishlistItemsIds: string) => { + const { data } = + (await getGraphQL( + REMOVE_FROM_WISHLIST, + { + wishlistId, + wishlistItemsIds: [wishlistItemsIds], + }, + storeViewCode, + config?.baseUrl, + )) || {}; + const wishlistResponse: Wishlist = data?.removeProductsFromWishlist.wishlist; + setWishlist(wishlistResponse); + }; - const wishlistContext: WishlistAttributesContext = { - isAuthorized, - wishlist, - allWishlist, - addItemToWishlist, - removeItemFromWishlist, - }; + const wishlistContext: WishlistAttributesContext = { + isAuthorized, + wishlist, + allWishlist, + addItemToWishlist, + removeItemFromWishlist, + }; - return ( - - {children} - - ); + return {children}; }; export { useWishlist, WishlistProvider }; diff --git a/src/hooks/useAccessibleDropdown.ts b/src/hooks/useAccessibleDropdown.ts index 500ca35..556e687 100644 --- a/src/hooks/useAccessibleDropdown.ts +++ b/src/hooks/useAccessibleDropdown.ts @@ -7,155 +7,151 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { useEffect, useRef, useState } from 'preact/hooks'; +import { useEffect, useRef, useState } from "preact/hooks"; -import { PageSizeOption, SortOption } from '../types/interface'; +import { PageSizeOption, SortOption } from "../types/interface"; const registerOpenDropdownHandlers = ({ - options, - activeIndex, - setActiveIndex, - select, + options, + activeIndex, + setActiveIndex, + select, }: { - options: SortOption[] | PageSizeOption[]; - activeIndex: number; - setActiveIndex: (index: number) => void; - select: (value: string | number | null) => void; + options: SortOption[] | PageSizeOption[]; + activeIndex: number; + setActiveIndex: (index: number) => void; + select: (value: string | number | null) => void; }) => { - const optionsLength = options.length; - const keyDownCallback = (e: KeyboardEvent) => { - e.preventDefault(); - - switch (e.key) { - case 'Up': - case 'ArrowUp': - e.preventDefault(); - setActiveIndex(activeIndex <= 0 ? optionsLength - 1 : activeIndex - 1); - return; - case 'Down': - case 'ArrowDown': + const optionsLength = options.length; + const keyDownCallback = (e: KeyboardEvent) => { e.preventDefault(); - setActiveIndex(activeIndex + 1 === optionsLength ? 0 : activeIndex + 1); - return; - case 'Enter': - case ' ': // Space - e.preventDefault(); - select(options[activeIndex].value); - return; - case 'Esc': - case 'Escape': - e.preventDefault(); - select(null); - return; - case 'PageUp': - case 'Home': - e.preventDefault(); - setActiveIndex(0); - return; - case 'PageDown': - case 'End': - e.preventDefault(); - setActiveIndex(options.length - 1); - return; - } - }; - document.addEventListener('keydown', keyDownCallback); - return () => { - document.removeEventListener('keydown', keyDownCallback); - }; + + switch (e.key) { + case "Up": + case "ArrowUp": + e.preventDefault(); + setActiveIndex(activeIndex <= 0 ? optionsLength - 1 : activeIndex - 1); + return; + case "Down": + case "ArrowDown": + e.preventDefault(); + setActiveIndex(activeIndex + 1 === optionsLength ? 0 : activeIndex + 1); + return; + case "Enter": + case " ": // Space + e.preventDefault(); + select(options[activeIndex].value); + return; + case "Esc": + case "Escape": + e.preventDefault(); + select(null); + return; + case "PageUp": + case "Home": + e.preventDefault(); + setActiveIndex(0); + return; + case "PageDown": + case "End": + e.preventDefault(); + setActiveIndex(options.length - 1); + return; + } + }; + document.addEventListener("keydown", keyDownCallback); + return () => { + document.removeEventListener("keydown", keyDownCallback); + }; }; -const registerClosedDropdownHandlers = ({ - setIsDropdownOpen, -}: { - setIsDropdownOpen: (value: boolean) => void; -}) => { - const keyDownCallback = (e: KeyboardEvent) => { - switch (e.key) { - case 'Up': - case 'ArrowUp': - case 'Down': - case 'ArrowDown': - case ' ': // Space - case 'Enter': - e.preventDefault(); - setIsDropdownOpen(true); - } - }; - document.addEventListener('keydown', keyDownCallback); - return () => { - document.removeEventListener('keydown', keyDownCallback); - }; +const registerClosedDropdownHandlers = ({ setIsDropdownOpen }: { setIsDropdownOpen: (value: boolean) => void }) => { + const keyDownCallback = (e: KeyboardEvent) => { + switch (e.key) { + case "Up": + case "ArrowUp": + case "Down": + case "ArrowDown": + case " ": // Space + case "Enter": + e.preventDefault(); + setIsDropdownOpen(true); + } + }; + document.addEventListener("keydown", keyDownCallback); + return () => { + document.removeEventListener("keydown", keyDownCallback); + }; }; const isSafari = () => { - const chromeInAgent = navigator.userAgent.indexOf('Chrome') > -1; - const safariInAgent = navigator.userAgent.indexOf('Safari') > -1; - return safariInAgent && !chromeInAgent; + const chromeInAgent = navigator.userAgent.indexOf("Chrome") > -1; + const safariInAgent = navigator.userAgent.indexOf("Safari") > -1; + return safariInAgent && !chromeInAgent; }; export const useAccessibleDropdown = ({ - options, - value, - onChange, + options, + value, + onChange, }: { - options: SortOption[] | PageSizeOption[]; - value: string | number; - onChange: (value: any) => void; + options: SortOption[] | PageSizeOption[]; + value: string | number; + onChange: (value: any) => void; }) => { - const [isDropdownOpen, setIsDropdownOpenInternal] = useState(false); - const listRef = useRef(null); - const [activeIndex, setActiveIndex] = useState(0); - const [isFocus, setIsFocus] = useState(false); - const select = (value: any) => { - if (value) { - onChange && onChange(value); - } - setIsDropdownOpen(false); - setIsFocus(false); - }; + const [isDropdownOpen, setIsDropdownOpenInternal] = useState(false); + const listRef = useRef(null); + const [activeIndex, setActiveIndex] = useState(0); + const [isFocus, setIsFocus] = useState(false); + const select = (value: any) => { + if (value) { + onChange && onChange(value); + } + setIsDropdownOpen(false); + setIsFocus(false); + }; - const setIsDropdownOpen = (v: boolean) => { - if (v) { - const selected = options?.findIndex((o) => o.value === value); + const setIsDropdownOpen = (v: boolean) => { + if (v) { + const selected = options?.findIndex((o) => o.value === value); - setActiveIndex(selected < 0 ? 0 : selected); - if (listRef.current && isSafari()) { - requestAnimationFrame(() => { - listRef?.current?.focus(); - }); - } - } else if (listRef.current && isSafari()) { - requestAnimationFrame(() => { - (listRef?.current?.previousSibling as HTMLUListElement)?.focus(); - }); - } - setIsDropdownOpenInternal(v); - }; + setActiveIndex(selected < 0 ? 0 : selected); + if (listRef.current && isSafari()) { + requestAnimationFrame(() => { + listRef?.current?.focus(); + }); + } + } else if (listRef.current && isSafari()) { + requestAnimationFrame(() => { + (listRef?.current?.previousSibling as HTMLUListElement)?.focus(); + }); + } + setIsDropdownOpenInternal(v); + }; - useEffect(() => { - if (isDropdownOpen) { - return registerOpenDropdownHandlers({ + useEffect(() => { + if (isDropdownOpen) { + return registerOpenDropdownHandlers({ + activeIndex, + setActiveIndex, + options, + select, + }); + } + if (isFocus) { + return registerClosedDropdownHandlers({ + setIsDropdownOpen, + }); + } + }, [isDropdownOpen, activeIndex, isFocus]); + + return { + isDropdownOpen, + setIsDropdownOpen, activeIndex, setActiveIndex, - options, select, - }); - } - if (isFocus) { - return registerClosedDropdownHandlers({ - setIsDropdownOpen, - }); - } - }, [isDropdownOpen, activeIndex, isFocus]); - - return { - isDropdownOpen, - setIsDropdownOpen, - activeIndex, - setActiveIndex, - select, - setIsFocus, - listRef, - }; + setIsFocus, + listRef, + }; }; diff --git a/src/hooks/usePagination.ts b/src/hooks/usePagination.ts index 998bd35..fdd7e30 100644 --- a/src/hooks/usePagination.ts +++ b/src/hooks/usePagination.ts @@ -7,73 +7,63 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { useMemo } from 'preact/compat'; +import { useMemo } from "preact/compat"; -export const ELLIPSIS = '...'; +export const ELLIPSIS = "..."; const getRange = (start: number, end: number) => { - const length = end - start + 1; - return Array.from({ length }, (_, index) => start + index); + const length = end - start + 1; + return Array.from({ length }, (_, index) => start + index); }; type PaginationType = { - currentPage: number; - totalPages: number; - siblingCount?: number; // defaults to 1 + currentPage: number; + totalPages: number; + siblingCount?: number; // defaults to 1 }; -export const usePagination = ({ - currentPage, - totalPages, - siblingCount = 1, -}: PaginationType) => { - const paginationRange: (string | number)[] | undefined = useMemo(() => { - const firstPageIndex = 1; - const lastPageIndex = totalPages; - const totalPagePills = siblingCount + 5; // siblingCount + firstPage + lastPage + currentPage + 2 * ellipsis(...) - const leftSiblingIndex = Math.max(currentPage - siblingCount, 1); - const rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages); +export const usePagination = ({ currentPage, totalPages, siblingCount = 1 }: PaginationType) => { + const paginationRange: (string | number)[] | undefined = useMemo(() => { + const firstPageIndex = 1; + const lastPageIndex = totalPages; + const totalPagePills = siblingCount + 5; // siblingCount + firstPage + lastPage + currentPage + 2 * ellipsis(...) + const leftSiblingIndex = Math.max(currentPage - siblingCount, 1); + const rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages); - // We do not show the left/right dots(...) if there is just one page left to be inserted between the extremes of sibling and the page limits. - const showLeftDots = leftSiblingIndex > 2; - const showRightDots = rightSiblingIndex < totalPages - 2; + // We do not show the left/right dots(...) if there is just one page left to be inserted between the extremes of sibling and the page limits. + const showLeftDots = leftSiblingIndex > 2; + const showRightDots = rightSiblingIndex < totalPages - 2; - // Case 1 - the total page count is less than the page pills we want to show. - // < 1 2 3 4 5 6 > - if (totalPages <= totalPagePills) { - return getRange(1, totalPages); - } + // Case 1 - the total page count is less than the page pills we want to show. + // < 1 2 3 4 5 6 > + if (totalPages <= totalPagePills) { + return getRange(1, totalPages); + } - // Case 2 - the total page count is greater than the page pills and only the dots on the right are shown - // < 1 2 3 4 ... 25 > - if (!showLeftDots && showRightDots) { - const leftItemCount = 3 + 2 * siblingCount; - const leftRange = getRange(1, leftItemCount); + // Case 2 - the total page count is greater than the page pills and only the dots on the right are shown + // < 1 2 3 4 ... 25 > + if (!showLeftDots && showRightDots) { + const leftItemCount = 3 + 2 * siblingCount; + const leftRange = getRange(1, leftItemCount); - return [...leftRange, ELLIPSIS, totalPages]; - } + return [...leftRange, ELLIPSIS, totalPages]; + } - // Case 3 - the total page count is greater than the page pills and only the dots on the left are shown - // < 1 ... 22 23 24 25 > - if (showLeftDots && !showRightDots) { - const rightItemCount = 3 + 2 * siblingCount; - const rightRange = getRange(totalPages - rightItemCount + 1, totalPages); - return [firstPageIndex, ELLIPSIS, ...rightRange]; - } + // Case 3 - the total page count is greater than the page pills and only the dots on the left are shown + // < 1 ... 22 23 24 25 > + if (showLeftDots && !showRightDots) { + const rightItemCount = 3 + 2 * siblingCount; + const rightRange = getRange(totalPages - rightItemCount + 1, totalPages); + return [firstPageIndex, ELLIPSIS, ...rightRange]; + } - // Case 4 - the total page count is greater than the page pills and both the right and left dots are shown - // < 1 ... 19 20 21 ... 25 > - if (showLeftDots && showRightDots) { - const middleRange = getRange(leftSiblingIndex, rightSiblingIndex); - return [ - firstPageIndex, - ELLIPSIS, - ...middleRange, - ELLIPSIS, - lastPageIndex, - ]; - } - }, [currentPage, totalPages, siblingCount]); + // Case 4 - the total page count is greater than the page pills and both the right and left dots are shown + // < 1 ... 19 20 21 ... 25 > + if (showLeftDots && showRightDots) { + const middleRange = getRange(leftSiblingIndex, rightSiblingIndex); + return [firstPageIndex, ELLIPSIS, ...middleRange, ELLIPSIS, lastPageIndex]; + } + }, [currentPage, totalPages, siblingCount]); - return paginationRange; + return paginationRange; }; diff --git a/src/hooks/useRangeFacet.ts b/src/hooks/useRangeFacet.ts index d5c60f2..9cec967 100644 --- a/src/hooks/useRangeFacet.ts +++ b/src/hooks/useRangeFacet.ts @@ -7,62 +7,59 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { useSearch } from '../context'; -import { FacetFilter, PriceFacet } from '../types/interface'; +import { useSearch } from "../context"; +import { FacetFilter, PriceFacet } from "../types/interface"; type ProcessedBucket = { from: number; to: number }; const useRangeFacet = ({ attribute, buckets }: PriceFacet) => { - const processedBuckets: { - [key: string]: ProcessedBucket; - } = {}; + const processedBuckets: { + [key: string]: ProcessedBucket; + } = {}; - buckets.forEach( - (bucket) => - (processedBuckets[bucket.title] = { - from: bucket.from, - to: bucket.to, - }) - ); + buckets.forEach( + (bucket) => + (processedBuckets[bucket.title] = { + from: bucket.from, + to: bucket.to, + }), + ); - const searchCtx = useSearch(); + const searchCtx = useSearch(); - const filter = searchCtx?.filters?.find( - (e: FacetFilter) => e.attribute === attribute - ); + const filter = searchCtx?.filters?.find((e: FacetFilter) => e.attribute === attribute); - const isSelected = (title: string) => { - const selected = filter - ? processedBuckets[title].from === filter.range?.from && - processedBuckets[title].to === filter.range?.to - : false; - return selected; - }; + const isSelected = (title: string) => { + const selected = filter + ? processedBuckets[title].from === filter.range?.from && processedBuckets[title].to === filter.range?.to + : false; + return selected; + }; - const onChange = (value: string) => { - if (!filter) { - const newFilter = { - attribute, - range: { - from: processedBuckets[value].from, - to: processedBuckets[value].to, - }, - }; - searchCtx.createFilter(newFilter); - return; - } + const onChange = (value: string) => { + if (!filter) { + const newFilter = { + attribute, + range: { + from: processedBuckets[value].from, + to: processedBuckets[value].to, + }, + }; + searchCtx.createFilter(newFilter); + return; + } - const newFilter = { - ...filter, - range: { - from: processedBuckets[value].from, - to: processedBuckets[value].to, - }, + const newFilter = { + ...filter, + range: { + from: processedBuckets[value].from, + to: processedBuckets[value].to, + }, + }; + searchCtx.updateFilter(newFilter); }; - searchCtx.updateFilter(newFilter); - }; - return { isSelected, onChange }; + return { isSelected, onChange }; }; export default useRangeFacet; diff --git a/src/hooks/useScalarFacet.ts b/src/hooks/useScalarFacet.ts index c749e82..a27a3ad 100644 --- a/src/hooks/useScalarFacet.ts +++ b/src/hooks/useScalarFacet.ts @@ -7,65 +7,55 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { useSearch } from '../context'; -import { - Facet as FacetType, - FacetFilter, - PriceFacet, -} from '../types/interface'; +import { useSearch } from "../context"; +import { Facet as FacetType, FacetFilter, PriceFacet } from "../types/interface"; export const useScalarFacet = (facet: FacetType | PriceFacet) => { - const searchCtx = useSearch(); - const filter = searchCtx?.filters?.find( - (e: FacetFilter) => e.attribute === facet.attribute - ); - - const isSelected = (attribute: string) => { - const selected = filter ? filter.in?.includes(attribute) : false; - return selected; - }; - - const onChange = (value: string, selected?: boolean) => { - // create filter - if (!filter) { - const newFilter: FacetFilter = { - attribute: facet.attribute, - in: [value], - }; - - searchCtx.createFilter(newFilter); - return; - } - - const newFilter = { ...filter }; - - const currentFilterIn = filter.in ? filter.in : []; - - newFilter.in = selected - ? [...currentFilterIn, value] - : filter.in?.filter((e: string) => e !== value); - - const filterUnselected = filter.in?.filter( - (x) => !newFilter.in?.includes(x) - ); - - // update filter - if (newFilter.in?.length) { - if (filterUnselected?.length) { - searchCtx.removeFilter(facet.attribute, filterUnselected[0]); - } - searchCtx.updateFilter(newFilter); - return; - } - - // remove filter - if (!newFilter.in?.length) { - searchCtx.removeFilter(facet.attribute); - return; - } - }; - - return { isSelected, onChange }; + const searchCtx = useSearch(); + const filter = searchCtx?.filters?.find((e: FacetFilter) => e.attribute === facet.attribute); + + const isSelected = (attribute: string) => { + const selected = filter ? filter.in?.includes(attribute) : false; + return selected; + }; + + const onChange = (value: string, selected?: boolean) => { + // create filter + if (!filter) { + const newFilter: FacetFilter = { + attribute: facet.attribute, + in: [value], + }; + + searchCtx.createFilter(newFilter); + return; + } + + const newFilter = { ...filter }; + + const currentFilterIn = filter.in ? filter.in : []; + + newFilter.in = selected ? [...currentFilterIn, value] : filter.in?.filter((e: string) => e !== value); + + const filterUnselected = filter.in?.filter((x) => !newFilter.in?.includes(x)); + + // update filter + if (newFilter.in?.length) { + if (filterUnselected?.length) { + searchCtx.removeFilter(facet.attribute, filterUnselected[0]); + } + searchCtx.updateFilter(newFilter); + return; + } + + // remove filter + if (!newFilter.in?.length) { + searchCtx.removeFilter(facet.attribute); + return; + } + }; + + return { isSelected, onChange }; }; export default useScalarFacet; diff --git a/src/hooks/useSliderFacet.ts b/src/hooks/useSliderFacet.ts index 2736253..26c3052 100644 --- a/src/hooks/useSliderFacet.ts +++ b/src/hooks/useSliderFacet.ts @@ -7,40 +7,38 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { useSearch } from '../context'; -import { FacetFilter, PriceFacet } from '../types/interface'; +import { useSearch } from "../context"; +import { FacetFilter, PriceFacet } from "../types/interface"; const useSliderFacet = ({ attribute }: PriceFacet) => { - const searchCtx = useSearch(); - - const onChange = (from: number, to: number) => { - const filter = searchCtx?.filters?.find( - (e: FacetFilter) => e.attribute === attribute - ); - - if (!filter) { - const newFilter = { - attribute, - range: { - from, - to, - }, - }; - searchCtx.createFilter(newFilter); - return; - } - - const newFilter = { - ...filter, - range: { - from, - to, - }, + const searchCtx = useSearch(); + + const onChange = (from: number, to: number) => { + const filter = searchCtx?.filters?.find((e: FacetFilter) => e.attribute === attribute); + + if (!filter) { + const newFilter = { + attribute, + range: { + from, + to, + }, + }; + searchCtx.createFilter(newFilter); + return; + } + + const newFilter = { + ...filter, + range: { + from, + to, + }, + }; + searchCtx.updateFilter(newFilter); }; - searchCtx.updateFilter(newFilter); - }; - return { onChange }; + return { onChange }; }; export default useSliderFacet; diff --git a/src/i18n/Sorani.ts b/src/i18n/Sorani.ts index 980593a..865f5fb 100644 --- a/src/i18n/Sorani.ts +++ b/src/i18n/Sorani.ts @@ -8,53 +8,52 @@ it. */ export const Sorani = { - Filter: { - title: 'فلتەرەکان', - showTitle: 'پیشاندانی فلتەرەکان', - hideTitle: 'شاردنەوەی فلتەرەکان', - clearAll: 'سڕینەوەی هەمووان', - }, - InputButtonGroup: { - title: 'پۆلەکان', - price: 'نرخ', - customPrice: 'نرخی بەکەسیکراو', - priceIncluded: 'بەڵێ', - priceExcluded: 'نەخێر', - priceExcludedMessage: 'نا {title}', - priceRange: ' و سەرووتر', - showmore: 'بینینی زیاتر', - }, - Loading: { - title: 'بارکردن', - }, - NoResults: { - heading: 'هیچ ئەنجامێک بۆ گەڕانەکەت نییە.', - subheading: 'تكایە دیسان هەوڵ بدەوە...', - }, - SortDropdown: { - title: 'پۆلێنکردن بەگوێرەی', - option: 'پۆلێنکردن بەگوێرەی: {selectedOption}', - relevanceLabel: 'پەیوەندیدارترین', - positionLabel: 'شوێن', - }, - CategoryFilters: { - results: 'ئەنجامەکان بۆ {phrase}', - products: '{totalCount} بەرهەمەکان', - }, - ProductCard: { - asLowAs: 'بەقەد نزمیی {discountPrice}', - startingAt: 'دەستپێدەکات لە {productPrice}', - bundlePrice: 'لە {fromBundlePrice} بۆ {toBundlePrice}', - from: 'لە {productPrice}', - }, - ProductContainers: { - minquery: - 'زاراوەی گەڕانەکەت {variables.phrase} بەلانی کەم نەگەیشتۆتە {minQueryLength} پیت.', - noresults: 'گەڕانەکەت هیچ ئەنجامێکی نەبوو.', - pagePicker: 'پیشاندانی {pageSize} لە هەر لاپەڕەیەکدا', - showAll: 'هەموو', - }, - SearchBar: { - placeholder: 'گەڕان...', - }, + Filter: { + title: "فلتەرەکان", + showTitle: "پیشاندانی فلتەرەکان", + hideTitle: "شاردنەوەی فلتەرەکان", + clearAll: "سڕینەوەی هەمووان", + }, + InputButtonGroup: { + title: "پۆلەکان", + price: "نرخ", + customPrice: "نرخی بەکەسیکراو", + priceIncluded: "بەڵێ", + priceExcluded: "نەخێر", + priceExcludedMessage: "نا {title}", + priceRange: " و سەرووتر", + showmore: "بینینی زیاتر", + }, + Loading: { + title: "بارکردن", + }, + NoResults: { + heading: "هیچ ئەنجامێک بۆ گەڕانەکەت نییە.", + subheading: "تكایە دیسان هەوڵ بدەوە...", + }, + SortDropdown: { + title: "پۆلێنکردن بەگوێرەی", + option: "پۆلێنکردن بەگوێرەی: {selectedOption}", + relevanceLabel: "پەیوەندیدارترین", + positionLabel: "شوێن", + }, + CategoryFilters: { + results: "ئەنجامەکان بۆ {phrase}", + products: "{totalCount} بەرهەمەکان", + }, + ProductCard: { + asLowAs: "بەقەد نزمیی {discountPrice}", + startingAt: "دەستپێدەکات لە {productPrice}", + bundlePrice: "لە {fromBundlePrice} بۆ {toBundlePrice}", + from: "لە {productPrice}", + }, + ProductContainers: { + minquery: "زاراوەی گەڕانەکەت {variables.phrase} بەلانی کەم نەگەیشتۆتە {minQueryLength} پیت.", + noresults: "گەڕانەکەت هیچ ئەنجامێکی نەبوو.", + pagePicker: "پیشاندانی {pageSize} لە هەر لاپەڕەیەکدا", + showAll: "هەموو", + }, + SearchBar: { + placeholder: "گەڕان...", + }, }; diff --git a/src/i18n/ar_AE.ts b/src/i18n/ar_AE.ts index 7e3170b..ef166fe 100644 --- a/src/i18n/ar_AE.ts +++ b/src/i18n/ar_AE.ts @@ -8,53 +8,52 @@ it. */ export const ar_AE = { - Filter: { - title: 'عوامل التصفية', - showTitle: 'إظهار عوامل التصفية', - hideTitle: 'إخفاء عوامل التصفية', - clearAll: 'مسح الكل', - }, - InputButtonGroup: { - title: 'الفئات', - price: 'السعر', - customPrice: 'السعر المخصص', - priceIncluded: 'نعم.', - priceExcluded: 'لا', - priceExcludedMessage: 'ليس {title}', - priceRange: ' وما بعده', - showmore: 'إظهار أكثر', - }, - Loading: { - title: 'تحميل', - }, - NoResults: { - heading: 'لا يوجد نتائج لبحثك.', - subheading: 'الرجاء المحاولة مرة أخرى...', - }, - SortDropdown: { - title: 'فرز حسب', - option: 'فرز حسب: {selectedOption}', - relevanceLabel: 'الأكثر صلة', - positionLabel: 'الموضع', - }, - CategoryFilters: { - results: 'النتائج لـ {phrase}', - products: 'منتجات {totalCount}', - }, - ProductCard: { - asLowAs: 'بقيمة {discountPrice} فقط', - startingAt: 'بدءًا من {productPrice}', - bundlePrice: 'من {fromBundlePrice} إلى {toBundlePrice}', - from: 'من {productPrice}', - }, - ProductContainers: { - minquery: - 'مصطلح البحث الخاص بك {variables.phrase} لم يصل إلى {minQueryLength} من الأحرف كحد أدنى.', - noresults: 'لا يوجد لبحثك أي نتائج.', - pagePicker: 'إظهار {pageSize} لكل صفحة', - showAll: 'الكل', - }, - SearchBar: { - placeholder: 'بحث...', - }, + Filter: { + title: "عوامل التصفية", + showTitle: "إظهار عوامل التصفية", + hideTitle: "إخفاء عوامل التصفية", + clearAll: "مسح الكل", + }, + InputButtonGroup: { + title: "الفئات", + price: "السعر", + customPrice: "السعر المخصص", + priceIncluded: "نعم.", + priceExcluded: "لا", + priceExcludedMessage: "ليس {title}", + priceRange: " وما بعده", + showmore: "إظهار أكثر", + }, + Loading: { + title: "تحميل", + }, + NoResults: { + heading: "لا يوجد نتائج لبحثك.", + subheading: "الرجاء المحاولة مرة أخرى...", + }, + SortDropdown: { + title: "فرز حسب", + option: "فرز حسب: {selectedOption}", + relevanceLabel: "الأكثر صلة", + positionLabel: "الموضع", + }, + CategoryFilters: { + results: "النتائج لـ {phrase}", + products: "منتجات {totalCount}", + }, + ProductCard: { + asLowAs: "بقيمة {discountPrice} فقط", + startingAt: "بدءًا من {productPrice}", + bundlePrice: "من {fromBundlePrice} إلى {toBundlePrice}", + from: "من {productPrice}", + }, + ProductContainers: { + minquery: "مصطلح البحث الخاص بك {variables.phrase} لم يصل إلى {minQueryLength} من الأحرف كحد أدنى.", + noresults: "لا يوجد لبحثك أي نتائج.", + pagePicker: "إظهار {pageSize} لكل صفحة", + showAll: "الكل", + }, + SearchBar: { + placeholder: "بحث...", + }, }; diff --git a/src/i18n/bg_BG.ts b/src/i18n/bg_BG.ts index 1cf6153..c003429 100644 --- a/src/i18n/bg_BG.ts +++ b/src/i18n/bg_BG.ts @@ -8,53 +8,52 @@ it. */ export const bg_BG = { - Filter: { - title: 'Филтри', - showTitle: 'Показване на филтри', - hideTitle: 'Скриване на филтри', - clearAll: 'Изчистване на всичко', - }, - InputButtonGroup: { - title: 'Категории', - price: 'Цена', - customPrice: 'Персонализирана цена', - priceIncluded: 'да', - priceExcluded: 'не', - priceExcludedMessage: 'Не {title}', - priceRange: ' и по-висока', - showmore: 'Показване на повече', - }, - Loading: { - title: 'Зареждане', - }, - NoResults: { - heading: 'Няма резултати за вашето търсене.', - subheading: 'Моля, опитайте отново...', - }, - SortDropdown: { - title: 'Сортиране по', - option: 'Сортиране по: {selectedOption}', - relevanceLabel: 'Най-подходящи', - positionLabel: 'Позиция', - }, - CategoryFilters: { - results: 'резултати за {phrase}', - products: '{totalCount} продукта', - }, - ProductCard: { - asLowAs: 'Само {discountPrice}', - startingAt: 'От {productPrice}', - bundlePrice: 'От {fromBundlePrice} до {toBundlePrice}', - from: 'От {productPrice}', - }, - ProductContainers: { - minquery: - 'Вашата дума за търсене {variables.phrase} не достига минимума от {minQueryLength} знака.', - noresults: 'Вашето търсене не даде резултати.', - pagePicker: 'Показване на {pageSize} на страница', - showAll: 'всички', - }, - SearchBar: { - placeholder: 'Търсене...', - }, + Filter: { + title: "Филтри", + showTitle: "Показване на филтри", + hideTitle: "Скриване на филтри", + clearAll: "Изчистване на всичко", + }, + InputButtonGroup: { + title: "Категории", + price: "Цена", + customPrice: "Персонализирана цена", + priceIncluded: "да", + priceExcluded: "не", + priceExcludedMessage: "Не {title}", + priceRange: " и по-висока", + showmore: "Показване на повече", + }, + Loading: { + title: "Зареждане", + }, + NoResults: { + heading: "Няма резултати за вашето търсене.", + subheading: "Моля, опитайте отново...", + }, + SortDropdown: { + title: "Сортиране по", + option: "Сортиране по: {selectedOption}", + relevanceLabel: "Най-подходящи", + positionLabel: "Позиция", + }, + CategoryFilters: { + results: "резултати за {phrase}", + products: "{totalCount} продукта", + }, + ProductCard: { + asLowAs: "Само {discountPrice}", + startingAt: "От {productPrice}", + bundlePrice: "От {fromBundlePrice} до {toBundlePrice}", + from: "От {productPrice}", + }, + ProductContainers: { + minquery: "Вашата дума за търсене {variables.phrase} не достига минимума от {minQueryLength} знака.", + noresults: "Вашето търсене не даде резултати.", + pagePicker: "Показване на {pageSize} на страница", + showAll: "всички", + }, + SearchBar: { + placeholder: "Търсене...", + }, }; diff --git a/src/i18n/bn_IN.ts b/src/i18n/bn_IN.ts index c365994..2a8150a 100644 --- a/src/i18n/bn_IN.ts +++ b/src/i18n/bn_IN.ts @@ -8,53 +8,53 @@ it. */ export const bn_IN = { - Filter: { - title: 'ফিল্টারগুলি', - showTitle: 'ফিল্টারগুলি দেখান', - hideTitle: 'ফিল্টারগুলি লুকান', - clearAll: 'সব ক্লিয়ার করুন', - }, - InputButtonGroup: { - title: 'ক্যাটেগরি', - price: 'মূল্য', - customPrice: 'কাস্টম প্রাইস', - priceIncluded: 'হ্যাঁ', - priceExcluded: 'না', - priceExcludedMessage: 'না {title}', - priceRange: ' এবং উর্দ্ধে', - showmore: 'আরো দেখান', - }, - Loading: { - title: 'লোডিং হচ্ছে', - }, - NoResults: { - heading: 'আপনার অনুসন্ধানের কোনো ফলাফল নেই।', - subheading: 'অনুগ্রহ করে পুনরায় চেষ্টা করুন...', - }, - SortDropdown: { - title: 'ক্রমানুসারে সাজান', - option: 'ক্রমানুসারে সাজান: {selectedOption}', - relevanceLabel: 'সবচেয়ে প্রাসঙ্গিক', - positionLabel: 'অবস্থান', - }, - CategoryFilters: { - results: '{phrase} এর জন্য ফলাফল', - products: '{totalCount} প্রোডাক্টগুলি', - }, - ProductCard: { - asLowAs: 'এত কম যে {discountPrice}', - startingAt: 'শুরু হচ্ছে {productPrice}', - bundlePrice: '{fromBundlePrice} থেকে {toBundlePrice} পর্যন্ত', - from: '{productPrice} থেকে', - }, - ProductContainers: { - minquery: - 'আপনার অনুসন্ধান করা শব্দটি {variables.phrase} ন্যূনতম অক্ষরসীমা {minQueryLength} পর্যন্ত পৌঁছাতে পারেনি।', - noresults: 'আপনার অনুসন্ধান থেকে কোনো ফলাফল পাওয়া যায়নি।', - pagePicker: 'পৃষ্ঠা {pageSize} অনুযায়ী দেখান', - showAll: 'সবগুলি', - }, - SearchBar: { - placeholder: 'অনুসন্ধান করুন...', - }, + Filter: { + title: "ফিল্টারগুলি", + showTitle: "ফিল্টারগুলি দেখান", + hideTitle: "ফিল্টারগুলি লুকান", + clearAll: "সব ক্লিয়ার করুন", + }, + InputButtonGroup: { + title: "ক্যাটেগরি", + price: "মূল্য", + customPrice: "কাস্টম প্রাইস", + priceIncluded: "হ্যাঁ", + priceExcluded: "না", + priceExcludedMessage: "না {title}", + priceRange: " এবং উর্দ্ধে", + showmore: "আরো দেখান", + }, + Loading: { + title: "লোডিং হচ্ছে", + }, + NoResults: { + heading: "আপনার অনুসন্ধানের কোনো ফলাফল নেই।", + subheading: "অনুগ্রহ করে পুনরায় চেষ্টা করুন...", + }, + SortDropdown: { + title: "ক্রমানুসারে সাজান", + option: "ক্রমানুসারে সাজান: {selectedOption}", + relevanceLabel: "সবচেয়ে প্রাসঙ্গিক", + positionLabel: "অবস্থান", + }, + CategoryFilters: { + results: "{phrase} এর জন্য ফলাফল", + products: "{totalCount} প্রোডাক্টগুলি", + }, + ProductCard: { + asLowAs: "এত কম যে {discountPrice}", + startingAt: "শুরু হচ্ছে {productPrice}", + bundlePrice: "{fromBundlePrice} থেকে {toBundlePrice} পর্যন্ত", + from: "{productPrice} থেকে", + }, + ProductContainers: { + minquery: + "আপনার অনুসন্ধান করা শব্দটি {variables.phrase} ন্যূনতম অক্ষরসীমা {minQueryLength} পর্যন্ত পৌঁছাতে পারেনি।", + noresults: "আপনার অনুসন্ধান থেকে কোনো ফলাফল পাওয়া যায়নি।", + pagePicker: "পৃষ্ঠা {pageSize} অনুযায়ী দেখান", + showAll: "সবগুলি", + }, + SearchBar: { + placeholder: "অনুসন্ধান করুন...", + }, }; diff --git a/src/i18n/ca_ES.ts b/src/i18n/ca_ES.ts index 6c71764..fec4c75 100644 --- a/src/i18n/ca_ES.ts +++ b/src/i18n/ca_ES.ts @@ -8,53 +8,52 @@ it. */ export const ca_ES = { - Filter: { - title: 'Filtres', - showTitle: 'Mostra els filtres', - hideTitle: 'Amaga els filtres', - clearAll: 'Esborra-ho tot', - }, - InputButtonGroup: { - title: 'Categories', - price: 'Preu', - customPrice: 'Preu personalitzat', - priceIncluded: 'sí', - priceExcluded: 'no', - priceExcludedMessage: 'No {title}', - priceRange: ' i superior', - showmore: 'Mostra més', - }, - Loading: { - title: 'Carregant', - }, - NoResults: { - heading: 'No hi ha resultats per a la vostra cerca.', - subheading: 'Siusplau torna-ho a provar...', - }, - SortDropdown: { - title: 'Ordenar per', - option: 'Ordena per: {selectedOption}', - relevanceLabel: 'El més rellevant', - positionLabel: 'Posició', - }, - CategoryFilters: { - results: 'Resultats per a {phrase}', - products: '{totalCount}productes', - }, - ProductCard: { - asLowAs: 'Mínim de {discountPrice}', - startingAt: 'A partir de {productPrice}', - bundlePrice: 'Des de {fromBundlePrice} A {toBundlePrice}', - from: 'Des de {productPrice}', - }, - ProductContainers: { - minquery: - 'El vostre terme de cerca {variables.phrase} no ha arribat al mínim de {minQueryLength} caràcters.', - noresults: 'La vostra cerca no ha retornat cap resultat.', - pagePicker: 'Mostra {pageSize} per pàgina', - showAll: 'tots', - }, - SearchBar: { - placeholder: 'Cerca...', - }, + Filter: { + title: "Filtres", + showTitle: "Mostra els filtres", + hideTitle: "Amaga els filtres", + clearAll: "Esborra-ho tot", + }, + InputButtonGroup: { + title: "Categories", + price: "Preu", + customPrice: "Preu personalitzat", + priceIncluded: "sí", + priceExcluded: "no", + priceExcludedMessage: "No {title}", + priceRange: " i superior", + showmore: "Mostra més", + }, + Loading: { + title: "Carregant", + }, + NoResults: { + heading: "No hi ha resultats per a la vostra cerca.", + subheading: "Siusplau torna-ho a provar...", + }, + SortDropdown: { + title: "Ordenar per", + option: "Ordena per: {selectedOption}", + relevanceLabel: "El més rellevant", + positionLabel: "Posició", + }, + CategoryFilters: { + results: "Resultats per a {phrase}", + products: "{totalCount}productes", + }, + ProductCard: { + asLowAs: "Mínim de {discountPrice}", + startingAt: "A partir de {productPrice}", + bundlePrice: "Des de {fromBundlePrice} A {toBundlePrice}", + from: "Des de {productPrice}", + }, + ProductContainers: { + minquery: "El vostre terme de cerca {variables.phrase} no ha arribat al mínim de {minQueryLength} caràcters.", + noresults: "La vostra cerca no ha retornat cap resultat.", + pagePicker: "Mostra {pageSize} per pàgina", + showAll: "tots", + }, + SearchBar: { + placeholder: "Cerca...", + }, }; diff --git a/src/i18n/cs_CZ.ts b/src/i18n/cs_CZ.ts index 5c1c796..564fc66 100644 --- a/src/i18n/cs_CZ.ts +++ b/src/i18n/cs_CZ.ts @@ -8,53 +8,52 @@ it. */ export const cs_CZ = { - Filter: { - title: 'Filtry', - showTitle: 'Zobrazit filtry', - hideTitle: 'Skrýt filtry', - clearAll: 'Vymazat vše', - }, - InputButtonGroup: { - title: 'Kategorie', - price: 'Cena', - customPrice: 'Vlastní cena', - priceIncluded: 'ano', - priceExcluded: 'ne', - priceExcludedMessage: 'Ne {title}', - priceRange: ' a výše', - showmore: 'Zobrazit více', - }, - Loading: { - title: 'Načítá se', - }, - NoResults: { - heading: 'Nebyly nalezeny žádné výsledky.', - subheading: 'Zkuste to znovu...', - }, - SortDropdown: { - title: 'Seřadit podle', - option: 'Seřadit podle: {selectedOption}', - relevanceLabel: 'Nejrelevantnější', - positionLabel: 'Umístění', - }, - CategoryFilters: { - results: 'výsledky pro {phrase}', - products: 'Produkty: {totalCount}', - }, - ProductCard: { - asLowAs: 'Pouze za {discountPrice}', - startingAt: 'Cena od {productPrice}', - bundlePrice: 'Z {fromBundlePrice} na {toBundlePrice}', - from: 'Z {productPrice}', - }, - ProductContainers: { - minquery: - 'Hledaný výraz {variables.phrase} nedosáhl minima počtu znaků ({minQueryLength}).', - noresults: 'Při hledání nebyly nalezeny žádné výsledky.', - pagePicker: 'Zobrazit {pageSize} na stránku', - showAll: 'vše', - }, - SearchBar: { - placeholder: 'Hledat...', - }, + Filter: { + title: "Filtry", + showTitle: "Zobrazit filtry", + hideTitle: "Skrýt filtry", + clearAll: "Vymazat vše", + }, + InputButtonGroup: { + title: "Kategorie", + price: "Cena", + customPrice: "Vlastní cena", + priceIncluded: "ano", + priceExcluded: "ne", + priceExcludedMessage: "Ne {title}", + priceRange: " a výše", + showmore: "Zobrazit více", + }, + Loading: { + title: "Načítá se", + }, + NoResults: { + heading: "Nebyly nalezeny žádné výsledky.", + subheading: "Zkuste to znovu...", + }, + SortDropdown: { + title: "Seřadit podle", + option: "Seřadit podle: {selectedOption}", + relevanceLabel: "Nejrelevantnější", + positionLabel: "Umístění", + }, + CategoryFilters: { + results: "výsledky pro {phrase}", + products: "Produkty: {totalCount}", + }, + ProductCard: { + asLowAs: "Pouze za {discountPrice}", + startingAt: "Cena od {productPrice}", + bundlePrice: "Z {fromBundlePrice} na {toBundlePrice}", + from: "Z {productPrice}", + }, + ProductContainers: { + minquery: "Hledaný výraz {variables.phrase} nedosáhl minima počtu znaků ({minQueryLength}).", + noresults: "Při hledání nebyly nalezeny žádné výsledky.", + pagePicker: "Zobrazit {pageSize} na stránku", + showAll: "vše", + }, + SearchBar: { + placeholder: "Hledat...", + }, }; diff --git a/src/i18n/da_DK.ts b/src/i18n/da_DK.ts index 3f9863b..c996661 100644 --- a/src/i18n/da_DK.ts +++ b/src/i18n/da_DK.ts @@ -8,53 +8,52 @@ it. */ export const da_DK = { - Filter: { - title: 'Filtre', - showTitle: 'Vis filtre', - hideTitle: 'Skjul filtre', - clearAll: 'Ryd alt', - }, - InputButtonGroup: { - title: 'Kategorier', - price: 'Pris', - customPrice: 'Brugerdefineret pris', - priceIncluded: 'ja', - priceExcluded: 'nej', - priceExcludedMessage: 'Ikke {title}', - priceRange: ' og over', - showmore: 'Vis mere', - }, - Loading: { - title: 'Indlæser', - }, - NoResults: { - heading: 'Ingen søgeresultater for din søgning', - subheading: 'Prøv igen...', - }, - SortDropdown: { - title: 'Sortér efter', - option: 'Sortér efter: {selectedOption}', - relevanceLabel: 'Mest relevant', - positionLabel: 'Position', - }, - CategoryFilters: { - results: 'resultater for {phrase}', - products: '{totalCount} produkter', - }, - ProductCard: { - asLowAs: 'Så lav som {discountPrice}', - startingAt: 'Fra {productPrice}', - bundlePrice: 'Fra {fromBundlePrice} til {toBundlePrice}', - from: 'Fra {productPrice}', - }, - ProductContainers: { - minquery: - 'Dit søgeord {variables.phrase} har ikke minimum på {minQueryLength} tegn.', - noresults: 'Din søgning gav ingen resultater.', - pagePicker: 'Vis {pageSize} pr. side', - showAll: 'alle', - }, - SearchBar: { - placeholder: 'Søg...', - }, + Filter: { + title: "Filtre", + showTitle: "Vis filtre", + hideTitle: "Skjul filtre", + clearAll: "Ryd alt", + }, + InputButtonGroup: { + title: "Kategorier", + price: "Pris", + customPrice: "Brugerdefineret pris", + priceIncluded: "ja", + priceExcluded: "nej", + priceExcludedMessage: "Ikke {title}", + priceRange: " og over", + showmore: "Vis mere", + }, + Loading: { + title: "Indlæser", + }, + NoResults: { + heading: "Ingen søgeresultater for din søgning", + subheading: "Prøv igen...", + }, + SortDropdown: { + title: "Sortér efter", + option: "Sortér efter: {selectedOption}", + relevanceLabel: "Mest relevant", + positionLabel: "Position", + }, + CategoryFilters: { + results: "resultater for {phrase}", + products: "{totalCount} produkter", + }, + ProductCard: { + asLowAs: "Så lav som {discountPrice}", + startingAt: "Fra {productPrice}", + bundlePrice: "Fra {fromBundlePrice} til {toBundlePrice}", + from: "Fra {productPrice}", + }, + ProductContainers: { + minquery: "Dit søgeord {variables.phrase} har ikke minimum på {minQueryLength} tegn.", + noresults: "Din søgning gav ingen resultater.", + pagePicker: "Vis {pageSize} pr. side", + showAll: "alle", + }, + SearchBar: { + placeholder: "Søg...", + }, }; diff --git a/src/i18n/de_DE.ts b/src/i18n/de_DE.ts index 62c8265..618ae69 100644 --- a/src/i18n/de_DE.ts +++ b/src/i18n/de_DE.ts @@ -8,53 +8,52 @@ it. */ export const de_DE = { - Filter: { - title: 'Filter', - showTitle: 'Filter einblenden', - hideTitle: 'Filter ausblenden', - clearAll: 'Alle löschen', - }, - InputButtonGroup: { - title: 'Kategorien', - price: 'Preis', - customPrice: 'Benutzerdefinierter Preis', - priceIncluded: 'ja', - priceExcluded: 'nein', - priceExcludedMessage: 'Nicht {title}', - priceRange: ' und höher', - showmore: 'Mehr anzeigen', - }, - Loading: { - title: 'Ladevorgang läuft', - }, - NoResults: { - heading: 'Keine Ergebnisse zu Ihrer Suche.', - subheading: 'Versuchen Sie es erneut...', - }, - SortDropdown: { - title: 'Sortieren nach', - option: 'Sortieren nach: {selectedOption}', - relevanceLabel: 'Höchste Relevanz', - positionLabel: 'Position', - }, - CategoryFilters: { - results: 'Ergebnisse für {phrase}', - products: '{totalCount} Produkte', - }, - ProductCard: { - asLowAs: 'Schon ab {discountPrice}', - startingAt: 'Ab {productPrice}', - bundlePrice: 'Aus {fromBundlePrice} zu {toBundlePrice}', - from: 'Ab {productPrice}', - }, - ProductContainers: { - minquery: - 'Ihr Suchbegriff {variables.phrase} ist kürzer als das Minimum von {minQueryLength} Zeichen.', - noresults: 'Zu Ihrer Suche wurden keine Ergebnisse zurückgegeben.', - pagePicker: '{pageSize} pro Seite anzeigen', - showAll: 'alle', - }, - SearchBar: { - placeholder: 'Suchen...', - }, + Filter: { + title: "Filter", + showTitle: "Filter einblenden", + hideTitle: "Filter ausblenden", + clearAll: "Alle löschen", + }, + InputButtonGroup: { + title: "Kategorien", + price: "Preis", + customPrice: "Benutzerdefinierter Preis", + priceIncluded: "ja", + priceExcluded: "nein", + priceExcludedMessage: "Nicht {title}", + priceRange: " und höher", + showmore: "Mehr anzeigen", + }, + Loading: { + title: "Ladevorgang läuft", + }, + NoResults: { + heading: "Keine Ergebnisse zu Ihrer Suche.", + subheading: "Versuchen Sie es erneut...", + }, + SortDropdown: { + title: "Sortieren nach", + option: "Sortieren nach: {selectedOption}", + relevanceLabel: "Höchste Relevanz", + positionLabel: "Position", + }, + CategoryFilters: { + results: "Ergebnisse für {phrase}", + products: "{totalCount} Produkte", + }, + ProductCard: { + asLowAs: "Schon ab {discountPrice}", + startingAt: "Ab {productPrice}", + bundlePrice: "Aus {fromBundlePrice} zu {toBundlePrice}", + from: "Ab {productPrice}", + }, + ProductContainers: { + minquery: "Ihr Suchbegriff {variables.phrase} ist kürzer als das Minimum von {minQueryLength} Zeichen.", + noresults: "Zu Ihrer Suche wurden keine Ergebnisse zurückgegeben.", + pagePicker: "{pageSize} pro Seite anzeigen", + showAll: "alle", + }, + SearchBar: { + placeholder: "Suchen...", + }, }; diff --git a/src/i18n/el_GR.ts b/src/i18n/el_GR.ts index 7700389..5ddb134 100644 --- a/src/i18n/el_GR.ts +++ b/src/i18n/el_GR.ts @@ -8,53 +8,52 @@ it. */ export const el_GR = { - Filter: { - title: 'Φίλτρα', - showTitle: 'Εμφάνιση φίλτρων', - hideTitle: 'Απόκρυψη φίλτρων', - clearAll: 'Απαλοιφή όλων', - }, - InputButtonGroup: { - title: 'Κατηγορίες', - price: 'Τιμή', - customPrice: 'Προσαρμοσμένη τιμή', - priceIncluded: 'ναι', - priceExcluded: 'όχι', - priceExcludedMessage: 'Όχι {title}', - priceRange: ' και παραπάνω', - showmore: 'Εμφάνιση περισσότερων', - }, - Loading: { - title: 'Γίνεται φόρτωση', - }, - NoResults: { - heading: 'Δεν υπάρχουν αποτελέσματα για την αναζήτησή σας.', - subheading: 'Προσπαθήστε ξανά...', - }, - SortDropdown: { - title: 'Ταξινόμηση κατά', - option: 'Ταξινόμηση κατά: {selectedOption}', - relevanceLabel: 'Το πιο σχετικό', - positionLabel: 'Θέση', - }, - CategoryFilters: { - results: 'αποτελέσματα για {phrase}', - products: '{totalCount} προϊόντα', - }, - ProductCard: { - asLowAs: 'Τόσο χαμηλά όσο {discountPrice}', - startingAt: 'Έναρξη από {productPrice}', - bundlePrice: 'Από {fromBundlePrice} Προς {toBundlePrice}', - from: 'Από {productPrice}', - }, - ProductContainers: { - minquery: - 'Ο όρος αναζήτησής σας {variables.phrase} δεν έχει φτάσει στο ελάχιστο {minQueryLength} χαρακτήρες.', - noresults: 'Η αναζήτηση δεν επέστρεψε κανένα αποτέλεσμα.', - pagePicker: 'Προβολή {pageSize} ανά σελίδα', - showAll: 'όλα', - }, - SearchBar: { - placeholder: 'Αναζήτηση...', - }, + Filter: { + title: "Φίλτρα", + showTitle: "Εμφάνιση φίλτρων", + hideTitle: "Απόκρυψη φίλτρων", + clearAll: "Απαλοιφή όλων", + }, + InputButtonGroup: { + title: "Κατηγορίες", + price: "Τιμή", + customPrice: "Προσαρμοσμένη τιμή", + priceIncluded: "ναι", + priceExcluded: "όχι", + priceExcludedMessage: "Όχι {title}", + priceRange: " και παραπάνω", + showmore: "Εμφάνιση περισσότερων", + }, + Loading: { + title: "Γίνεται φόρτωση", + }, + NoResults: { + heading: "Δεν υπάρχουν αποτελέσματα για την αναζήτησή σας.", + subheading: "Προσπαθήστε ξανά...", + }, + SortDropdown: { + title: "Ταξινόμηση κατά", + option: "Ταξινόμηση κατά: {selectedOption}", + relevanceLabel: "Το πιο σχετικό", + positionLabel: "Θέση", + }, + CategoryFilters: { + results: "αποτελέσματα για {phrase}", + products: "{totalCount} προϊόντα", + }, + ProductCard: { + asLowAs: "Τόσο χαμηλά όσο {discountPrice}", + startingAt: "Έναρξη από {productPrice}", + bundlePrice: "Από {fromBundlePrice} Προς {toBundlePrice}", + from: "Από {productPrice}", + }, + ProductContainers: { + minquery: "Ο όρος αναζήτησής σας {variables.phrase} δεν έχει φτάσει στο ελάχιστο {minQueryLength} χαρακτήρες.", + noresults: "Η αναζήτηση δεν επέστρεψε κανένα αποτέλεσμα.", + pagePicker: "Προβολή {pageSize} ανά σελίδα", + showAll: "όλα", + }, + SearchBar: { + placeholder: "Αναζήτηση...", + }, }; diff --git a/src/i18n/en_GA.ts b/src/i18n/en_GA.ts index 4c2127a..b44723f 100644 --- a/src/i18n/en_GA.ts +++ b/src/i18n/en_GA.ts @@ -8,53 +8,52 @@ it. */ export const en_GA = { - Filter: { - title: 'Scagairí', - showTitle: 'Taispeáin scagairí', - hideTitle: 'Folaigh scagairí', - clearAll: 'Glan gach', - }, - InputButtonGroup: { - title: 'Catagóirí', - price: 'Praghas', - customPrice: 'Saincheap Praghas', - priceIncluded: 'tá', - priceExcluded: 'níl', - priceExcludedMessage: 'Ní {title}', - priceRange: ' agus níos costasaí', - showmore: 'Taispeáin níos mó', - }, - Loading: { - title: 'Lódáil', - }, - NoResults: { - heading: 'Níl aon torthaí ar do chuardach.', - subheading: 'Bain triail eile as...', - }, - SortDropdown: { - title: 'Sórtáil de réir', - option: 'Sórtáil de réir: {selectedOption}', - relevanceLabel: 'Is Ábhartha', - positionLabel: 'Post', - }, - CategoryFilters: { - results: 'torthaí do {phrase}', - products: '{totalCount} táirge', - }, - ProductCard: { - asLowAs: 'Chomh híseal le {discountPrice}', - startingAt: 'Ag tosú ag {productPrice}', - bundlePrice: 'Ó {fromBundlePrice} go {toBundlePrice}', - from: 'Ó {productPrice}', - }, - ProductContainers: { - minquery: - 'Níor shroich do théarma cuardaigh {variables.phrase} íosmhéid {minQueryLength} carachtar.', - noresults: 'Níl aon torthaí ar do chuardach.', - pagePicker: 'Taispeáin {pageSize} in aghaidh an leathanaigh', - showAll: 'gach', - }, - SearchBar: { - placeholder: 'Cuardaigh...', - }, + Filter: { + title: "Scagairí", + showTitle: "Taispeáin scagairí", + hideTitle: "Folaigh scagairí", + clearAll: "Glan gach", + }, + InputButtonGroup: { + title: "Catagóirí", + price: "Praghas", + customPrice: "Saincheap Praghas", + priceIncluded: "tá", + priceExcluded: "níl", + priceExcludedMessage: "Ní {title}", + priceRange: " agus níos costasaí", + showmore: "Taispeáin níos mó", + }, + Loading: { + title: "Lódáil", + }, + NoResults: { + heading: "Níl aon torthaí ar do chuardach.", + subheading: "Bain triail eile as...", + }, + SortDropdown: { + title: "Sórtáil de réir", + option: "Sórtáil de réir: {selectedOption}", + relevanceLabel: "Is Ábhartha", + positionLabel: "Post", + }, + CategoryFilters: { + results: "torthaí do {phrase}", + products: "{totalCount} táirge", + }, + ProductCard: { + asLowAs: "Chomh híseal le {discountPrice}", + startingAt: "Ag tosú ag {productPrice}", + bundlePrice: "Ó {fromBundlePrice} go {toBundlePrice}", + from: "Ó {productPrice}", + }, + ProductContainers: { + minquery: "Níor shroich do théarma cuardaigh {variables.phrase} íosmhéid {minQueryLength} carachtar.", + noresults: "Níl aon torthaí ar do chuardach.", + pagePicker: "Taispeáin {pageSize} in aghaidh an leathanaigh", + showAll: "gach", + }, + SearchBar: { + placeholder: "Cuardaigh...", + }, }; diff --git a/src/i18n/en_GB.ts b/src/i18n/en_GB.ts index b71d160..a1f15f4 100644 --- a/src/i18n/en_GB.ts +++ b/src/i18n/en_GB.ts @@ -8,53 +8,52 @@ it. */ export const en_GB = { - Filter: { - title: 'Filters', - showTitle: 'Show filters', - hideTitle: 'Hide filters', - clearAll: 'Clear all', - }, - InputButtonGroup: { - title: 'Categories', - price: 'Price', - customPrice: 'Custom Price', - priceIncluded: 'yes', - priceExcluded: 'no', - priceExcludedMessage: 'Not {title}', - priceRange: ' and above', - showmore: 'Show more', - }, - Loading: { - title: 'Loading', - }, - NoResults: { - heading: 'No results for your search.', - subheading: 'Please try again...', - }, - SortDropdown: { - title: 'Sort by', - option: 'Sort by: {selectedOption}', - relevanceLabel: 'Most Relevant', - positionLabel: 'Position', - }, - CategoryFilters: { - results: 'results for {phrase}', - products: '{totalCount} products', - }, - ProductCard: { - asLowAs: 'As low as {discountPrice}', - startingAt: 'Starting at {productPrice}', - bundlePrice: 'From {fromBundlePrice} To {toBundlePrice}', - from: 'From {productPrice}', - }, - ProductContainers: { - minquery: - 'Your search term {variables.phrase} has not reached the minimum of {minQueryLength} characters.', - noresults: 'Your search returned no results.', - pagePicker: 'Show {pageSize} per page', - showAll: 'all', - }, - SearchBar: { - placeholder: 'Search...', - }, + Filter: { + title: "Filters", + showTitle: "Show filters", + hideTitle: "Hide filters", + clearAll: "Clear all", + }, + InputButtonGroup: { + title: "Categories", + price: "Price", + customPrice: "Custom Price", + priceIncluded: "yes", + priceExcluded: "no", + priceExcludedMessage: "Not {title}", + priceRange: " and above", + showmore: "Show more", + }, + Loading: { + title: "Loading", + }, + NoResults: { + heading: "No results for your search.", + subheading: "Please try again...", + }, + SortDropdown: { + title: "Sort by", + option: "Sort by: {selectedOption}", + relevanceLabel: "Most Relevant", + positionLabel: "Position", + }, + CategoryFilters: { + results: "results for {phrase}", + products: "{totalCount} products", + }, + ProductCard: { + asLowAs: "As low as {discountPrice}", + startingAt: "Starting at {productPrice}", + bundlePrice: "From {fromBundlePrice} To {toBundlePrice}", + from: "From {productPrice}", + }, + ProductContainers: { + minquery: "Your search term {variables.phrase} has not reached the minimum of {minQueryLength} characters.", + noresults: "Your search returned no results.", + pagePicker: "Show {pageSize} per page", + showAll: "all", + }, + SearchBar: { + placeholder: "Search...", + }, }; diff --git a/src/i18n/en_US.ts b/src/i18n/en_US.ts index d750f3d..1cbee01 100644 --- a/src/i18n/en_US.ts +++ b/src/i18n/en_US.ts @@ -8,63 +8,62 @@ it. */ export const en_US = { - Filter: { - title: 'Filters', - showTitle: 'Show filters', - hideTitle: 'Hide filters', - clearAll: 'Clear all', - }, - InputButtonGroup: { - title: 'Categories', - price: 'Price', - customPrice: 'Custom Price', - priceIncluded: 'yes', - priceExcluded: 'no', - priceExcludedMessage: 'Not {title}', - priceRange: ' and above', - showmore: 'Show more', - }, - Loading: { - title: 'Loading', - }, - NoResults: { - heading: 'No results for your search.', - subheading: 'Please try again...', - }, - SortDropdown: { - title: 'Sort by', - option: 'Sort by: {selectedOption}', - relevanceLabel: 'Most Relevant', - positionLabel: 'Position', - sortAttributeASC: '{label}: Low to High', - sortAttributeDESC: '{label}: High to Low', - sortASC: 'Price: Low to High', - sortDESC: 'Price: High to Low', - productName: 'Product Name', - productInStock: 'In Stock', - productLowStock: 'Low Stock', - }, - CategoryFilters: { - results: 'results for {phrase}', - products: '{totalCount} products', - }, - ProductCard: { - asLowAs: 'As low as {discountPrice}', - startingAt: 'Starting at {productPrice}', - bundlePrice: 'From {fromBundlePrice} To {toBundlePrice}', - from: 'From {productPrice}', - }, - ProductContainers: { - minquery: - 'Your search term {variables.phrase} has not reached the minimum of {minQueryLength} characters.', - noresults: 'Your search returned no results.', - pagePicker: 'Show {pageSize} per page', - showAll: 'all', - }, - SearchBar: { - placeholder: 'Search...', - }, - ListView: { - viewDetails: 'View details', - }, + Filter: { + title: "Filters", + showTitle: "Show filters", + hideTitle: "Hide filters", + clearAll: "Clear all", + }, + InputButtonGroup: { + title: "Categories", + price: "Price", + customPrice: "Custom Price", + priceIncluded: "yes", + priceExcluded: "no", + priceExcludedMessage: "Not {title}", + priceRange: " and above", + showmore: "Show more", + }, + Loading: { + title: "Loading", + }, + NoResults: { + heading: "No results for your search.", + subheading: "Please try again...", + }, + SortDropdown: { + title: "Sort by", + option: "Sort by: {selectedOption}", + relevanceLabel: "Most Relevant", + positionLabel: "Position", + sortAttributeASC: "{label}: Low to High", + sortAttributeDESC: "{label}: High to Low", + sortASC: "Price: Low to High", + sortDESC: "Price: High to Low", + productName: "Product Name", + productInStock: "In Stock", + productLowStock: "Low Stock", + }, + CategoryFilters: { + results: "results for {phrase}", + products: "{totalCount} products", + }, + ProductCard: { + asLowAs: "As low as {discountPrice}", + startingAt: "Starting at {productPrice}", + bundlePrice: "From {fromBundlePrice} To {toBundlePrice}", + from: "From {productPrice}", + }, + ProductContainers: { + minquery: "Your search term {variables.phrase} has not reached the minimum of {minQueryLength} characters.", + noresults: "Your search returned no results.", + pagePicker: "Show {pageSize} per page", + showAll: "all", + }, + SearchBar: { + placeholder: "Search...", + }, + ListView: { + viewDetails: "View details", + }, }; diff --git a/src/i18n/es_ES.ts b/src/i18n/es_ES.ts index 2f7efaf..71d87b7 100644 --- a/src/i18n/es_ES.ts +++ b/src/i18n/es_ES.ts @@ -8,53 +8,52 @@ it. */ export const es_ES = { - Filter: { - title: 'Filtros', - showTitle: 'Mostrar filtros', - hideTitle: 'Ocultar filtros', - clearAll: 'Borrar todo', - }, - InputButtonGroup: { - title: 'Categorías', - price: 'Precio', - customPrice: 'Precio personalizado', - priceIncluded: 'sí', - priceExcluded: 'no', - priceExcludedMessage: 'No es {title}', - priceRange: ' y más', - showmore: 'Mostrar más', - }, - Loading: { - title: 'Cargando', - }, - NoResults: { - heading: 'No hay resultados para tu búsqueda.', - subheading: 'Inténtalo de nuevo...', - }, - SortDropdown: { - title: 'Ordenar por', - option: 'Ordenar por: {selectedOption}', - relevanceLabel: 'Más relevantes', - positionLabel: 'Posición', - }, - CategoryFilters: { - results: 'resultados de {phrase}', - products: '{totalCount} productos', - }, - ProductCard: { - asLowAs: 'Por solo {discountPrice}', - startingAt: 'A partir de {productPrice}', - bundlePrice: 'Desde {fromBundlePrice} hasta {toBundlePrice}', - from: 'Desde {productPrice}', - }, - ProductContainers: { - minquery: - 'El término de búsqueda {variables.phrase} no llega al mínimo de {minQueryLength} caracteres.', - noresults: 'Tu búsqueda no ha dado resultados.', - pagePicker: 'Mostrar {pageSize} por página', - showAll: 'todo', - }, - SearchBar: { - placeholder: 'Buscar...', - }, + Filter: { + title: "Filtros", + showTitle: "Mostrar filtros", + hideTitle: "Ocultar filtros", + clearAll: "Borrar todo", + }, + InputButtonGroup: { + title: "Categorías", + price: "Precio", + customPrice: "Precio personalizado", + priceIncluded: "sí", + priceExcluded: "no", + priceExcludedMessage: "No es {title}", + priceRange: " y más", + showmore: "Mostrar más", + }, + Loading: { + title: "Cargando", + }, + NoResults: { + heading: "No hay resultados para tu búsqueda.", + subheading: "Inténtalo de nuevo...", + }, + SortDropdown: { + title: "Ordenar por", + option: "Ordenar por: {selectedOption}", + relevanceLabel: "Más relevantes", + positionLabel: "Posición", + }, + CategoryFilters: { + results: "resultados de {phrase}", + products: "{totalCount} productos", + }, + ProductCard: { + asLowAs: "Por solo {discountPrice}", + startingAt: "A partir de {productPrice}", + bundlePrice: "Desde {fromBundlePrice} hasta {toBundlePrice}", + from: "Desde {productPrice}", + }, + ProductContainers: { + minquery: "El término de búsqueda {variables.phrase} no llega al mínimo de {minQueryLength} caracteres.", + noresults: "Tu búsqueda no ha dado resultados.", + pagePicker: "Mostrar {pageSize} por página", + showAll: "todo", + }, + SearchBar: { + placeholder: "Buscar...", + }, }; diff --git a/src/i18n/et_EE.ts b/src/i18n/et_EE.ts index 7679232..8f999d5 100644 --- a/src/i18n/et_EE.ts +++ b/src/i18n/et_EE.ts @@ -8,53 +8,52 @@ it. */ export const et_EE = { - Filter: { - title: 'Filtrid', - showTitle: 'Kuva filtrid', - hideTitle: 'Peida filtrid', - clearAll: 'Tühjenda kõik', - }, - InputButtonGroup: { - title: 'Kategooriad', - price: 'Hind', - customPrice: 'Kohandatud hind', - priceIncluded: 'jah', - priceExcluded: 'ei', - priceExcludedMessage: 'Mitte {title}', - priceRange: ' ja üleval', - showmore: 'Kuva rohkem', - }, - Loading: { - title: 'Laadimine', - }, - NoResults: { - heading: 'Teie otsingule pole tulemusi.', - subheading: 'Proovige uuesti…', - }, - SortDropdown: { - title: 'Sortimisjärjekord', - option: 'Sortimisjärjekord: {selectedOption}', - relevanceLabel: 'Kõige asjakohasem', - positionLabel: 'Asukoht', - }, - CategoryFilters: { - results: '{phrase} tulemused', - products: '{totalCount} toodet', - }, - ProductCard: { - asLowAs: 'Ainult {discountPrice}', - startingAt: 'Alates {productPrice}', - bundlePrice: 'Alates {fromBundlePrice} kuni {toBundlePrice}', - from: 'Alates {productPrice}', - }, - ProductContainers: { - minquery: - 'Teie otsingutermin {variables.phrase} ei sisalda vähemalt {minQueryLength} tähemärki.', - noresults: 'Teie otsing ei andnud tulemusi.', - pagePicker: 'Näita {pageSize} lehekülje kohta', - showAll: 'kõik', - }, - SearchBar: { - placeholder: 'Otsi…', - }, + Filter: { + title: "Filtrid", + showTitle: "Kuva filtrid", + hideTitle: "Peida filtrid", + clearAll: "Tühjenda kõik", + }, + InputButtonGroup: { + title: "Kategooriad", + price: "Hind", + customPrice: "Kohandatud hind", + priceIncluded: "jah", + priceExcluded: "ei", + priceExcludedMessage: "Mitte {title}", + priceRange: " ja üleval", + showmore: "Kuva rohkem", + }, + Loading: { + title: "Laadimine", + }, + NoResults: { + heading: "Teie otsingule pole tulemusi.", + subheading: "Proovige uuesti…", + }, + SortDropdown: { + title: "Sortimisjärjekord", + option: "Sortimisjärjekord: {selectedOption}", + relevanceLabel: "Kõige asjakohasem", + positionLabel: "Asukoht", + }, + CategoryFilters: { + results: "{phrase} tulemused", + products: "{totalCount} toodet", + }, + ProductCard: { + asLowAs: "Ainult {discountPrice}", + startingAt: "Alates {productPrice}", + bundlePrice: "Alates {fromBundlePrice} kuni {toBundlePrice}", + from: "Alates {productPrice}", + }, + ProductContainers: { + minquery: "Teie otsingutermin {variables.phrase} ei sisalda vähemalt {minQueryLength} tähemärki.", + noresults: "Teie otsing ei andnud tulemusi.", + pagePicker: "Näita {pageSize} lehekülje kohta", + showAll: "kõik", + }, + SearchBar: { + placeholder: "Otsi…", + }, }; diff --git a/src/i18n/eu_ES.ts b/src/i18n/eu_ES.ts index c1ab5ff..5069a93 100644 --- a/src/i18n/eu_ES.ts +++ b/src/i18n/eu_ES.ts @@ -8,53 +8,52 @@ it. */ export const eu_ES = { - Filter: { - title: 'Iragazkiak', - showTitle: 'Erakutsi iragazkiak', - hideTitle: 'Ezkutatu iragazkiak', - clearAll: 'Garbitu dena', - }, - InputButtonGroup: { - title: 'Kategoriak', - price: 'Prezioa', - customPrice: 'Prezio pertsonalizatua', - priceIncluded: 'bai', - priceExcluded: 'ez', - priceExcludedMessage: 'Ez da {title}', - priceRange: ' eta gorago', - showmore: 'Erakutsi gehiago', - }, - Loading: { - title: 'Kargatzen', - }, - NoResults: { - heading: 'Ez dago emaitzarik zure bilaketarako.', - subheading: 'Saiatu berriro mesedez...', - }, - SortDropdown: { - title: 'Ordenatu', - option: 'Ordenatu honen arabera: {selectedOption}', - relevanceLabel: 'Garrantzitsuena', - positionLabel: 'Posizioa', - }, - CategoryFilters: { - results: '{phrase} bilaketaren emaitzak', - products: '{totalCount} produktu', - }, - ProductCard: { - asLowAs: '{discountPrice} bezain baxua', - startingAt: '{productPrice}-tatik hasita', - bundlePrice: '{fromBundlePrice} eta {toBundlePrice} artean', - from: '{productPrice}-tatik hasita', - }, - ProductContainers: { - minquery: - 'Zure bilaketa-terminoa ({variables.phrase}) ez da iritsi gutxieneko {minQueryLength} karakteretara.', - noresults: 'Zure bilaketak ez du emaitzarik eman.', - pagePicker: 'Erakutsi {pageSize} orriko', - showAll: 'guztiak', - }, - SearchBar: { - placeholder: 'Bilatu...', - }, + Filter: { + title: "Iragazkiak", + showTitle: "Erakutsi iragazkiak", + hideTitle: "Ezkutatu iragazkiak", + clearAll: "Garbitu dena", + }, + InputButtonGroup: { + title: "Kategoriak", + price: "Prezioa", + customPrice: "Prezio pertsonalizatua", + priceIncluded: "bai", + priceExcluded: "ez", + priceExcludedMessage: "Ez da {title}", + priceRange: " eta gorago", + showmore: "Erakutsi gehiago", + }, + Loading: { + title: "Kargatzen", + }, + NoResults: { + heading: "Ez dago emaitzarik zure bilaketarako.", + subheading: "Saiatu berriro mesedez...", + }, + SortDropdown: { + title: "Ordenatu", + option: "Ordenatu honen arabera: {selectedOption}", + relevanceLabel: "Garrantzitsuena", + positionLabel: "Posizioa", + }, + CategoryFilters: { + results: "{phrase} bilaketaren emaitzak", + products: "{totalCount} produktu", + }, + ProductCard: { + asLowAs: "{discountPrice} bezain baxua", + startingAt: "{productPrice}-tatik hasita", + bundlePrice: "{fromBundlePrice} eta {toBundlePrice} artean", + from: "{productPrice}-tatik hasita", + }, + ProductContainers: { + minquery: "Zure bilaketa-terminoa ({variables.phrase}) ez da iritsi gutxieneko {minQueryLength} karakteretara.", + noresults: "Zure bilaketak ez du emaitzarik eman.", + pagePicker: "Erakutsi {pageSize} orriko", + showAll: "guztiak", + }, + SearchBar: { + placeholder: "Bilatu...", + }, }; diff --git a/src/i18n/fa_IR.ts b/src/i18n/fa_IR.ts index e77aad3..543ad0e 100644 --- a/src/i18n/fa_IR.ts +++ b/src/i18n/fa_IR.ts @@ -8,53 +8,53 @@ it. */ export const fa_IR = { - Filter: { - title: 'فیلترها', - showTitle: 'نمایش فیلترها', - hideTitle: 'محو فیلترها', - clearAll: 'پاک کردن همه', - }, - InputButtonGroup: { - title: 'دسته‌ها', - price: 'قیمت', - customPrice: 'قیمت سفارشی', - priceIncluded: 'بله', - priceExcluded: 'خیر', - priceExcludedMessage: 'نه {title}', - priceRange: ' و بالاتر', - showmore: 'نمایش بیشتر', - }, - Loading: { - title: 'درحال بارگیری', - }, - NoResults: { - heading: 'جستجوی شما نتیجه‌ای دربر نداشت.', - subheading: 'لطفاً دوباره امتحان کنید...', - }, - SortDropdown: { - title: 'مرتب‌سازی براساس', - option: 'مرتب‌سازی براساس: {selectedOption}', - relevanceLabel: 'مرتبط‌ترین', - positionLabel: 'موقعیت', - }, - CategoryFilters: { - results: 'نتایج برای {phrase}', - products: '{totalCount} محصولات', - }, - ProductCard: { - asLowAs: 'برابر با {discountPrice}', - startingAt: 'شروع از {productPrice}', - bundlePrice: 'از {fromBundlePrice} تا {toBundlePrice}', - from: 'از {productPrice}', - }, - ProductContainers: { - minquery: - 'عبارت جستجوی شما {variables.phrase} به حداقل تعداد کاراکترهای لازم یعنی {minQueryLength} کاراکتر نرسیده است.', - noresults: 'جستجوی شما نتیجه‌ای را حاصل نکرد.', - pagePicker: 'نمایش {pageSize} در هر صفحه', - showAll: 'همه', - }, - SearchBar: { - placeholder: 'جستجو...', - }, + Filter: { + title: "فیلترها", + showTitle: "نمایش فیلترها", + hideTitle: "محو فیلترها", + clearAll: "پاک کردن همه", + }, + InputButtonGroup: { + title: "دسته‌ها", + price: "قیمت", + customPrice: "قیمت سفارشی", + priceIncluded: "بله", + priceExcluded: "خیر", + priceExcludedMessage: "نه {title}", + priceRange: " و بالاتر", + showmore: "نمایش بیشتر", + }, + Loading: { + title: "درحال بارگیری", + }, + NoResults: { + heading: "جستجوی شما نتیجه‌ای دربر نداشت.", + subheading: "لطفاً دوباره امتحان کنید...", + }, + SortDropdown: { + title: "مرتب‌سازی براساس", + option: "مرتب‌سازی براساس: {selectedOption}", + relevanceLabel: "مرتبط‌ترین", + positionLabel: "موقعیت", + }, + CategoryFilters: { + results: "نتایج برای {phrase}", + products: "{totalCount} محصولات", + }, + ProductCard: { + asLowAs: "برابر با {discountPrice}", + startingAt: "شروع از {productPrice}", + bundlePrice: "از {fromBundlePrice} تا {toBundlePrice}", + from: "از {productPrice}", + }, + ProductContainers: { + minquery: + "عبارت جستجوی شما {variables.phrase} به حداقل تعداد کاراکترهای لازم یعنی {minQueryLength} کاراکتر نرسیده است.", + noresults: "جستجوی شما نتیجه‌ای را حاصل نکرد.", + pagePicker: "نمایش {pageSize} در هر صفحه", + showAll: "همه", + }, + SearchBar: { + placeholder: "جستجو...", + }, }; diff --git a/src/i18n/fi_FI.ts b/src/i18n/fi_FI.ts index ddd45b3..df3350a 100644 --- a/src/i18n/fi_FI.ts +++ b/src/i18n/fi_FI.ts @@ -8,53 +8,52 @@ it. */ export const fi_FI = { - Filter: { - title: 'Suodattimet', - showTitle: 'Näytä suodattimet', - hideTitle: 'Piilota suodattimet', - clearAll: 'Poista kaikki', - }, - InputButtonGroup: { - title: 'Luokat', - price: 'Hinta', - customPrice: 'Mukautettu hinta', - priceIncluded: 'kyllä', - priceExcluded: 'ei', - priceExcludedMessage: 'Ei {title}', - priceRange: ' ja enemmän', - showmore: 'Näytä enemmän', - }, - Loading: { - title: 'Ladataan', - }, - NoResults: { - heading: 'Haullasi ei löytynyt tuloksia.', - subheading: 'Yritä uudelleen...', - }, - SortDropdown: { - title: 'Lajitteluperuste', - option: 'Lajitteluperuste: {selectedOption}', - relevanceLabel: 'Olennaisimmat', - positionLabel: 'Sijainti', - }, - CategoryFilters: { - results: 'tulosta ilmaukselle {phrase}', - products: '{totalCount} tuotetta', - }, - ProductCard: { - asLowAs: 'Parhaimmillaan {discountPrice}', - startingAt: 'Alkaen {productPrice}', - bundlePrice: '{fromBundlePrice} alkaen {toBundlePrice} asti', - from: '{productPrice} alkaen', - }, - ProductContainers: { - minquery: - 'Hakusanasi {variables.phrase} ei ole saavuttanut {minQueryLength} merkin vähimmäismäärää.', - noresults: 'Hakusi ei palauttanut tuloksia.', - pagePicker: 'Näytä {pageSize} sivua kohti', - showAll: 'kaikki', - }, - SearchBar: { - placeholder: 'Hae...', - }, + Filter: { + title: "Suodattimet", + showTitle: "Näytä suodattimet", + hideTitle: "Piilota suodattimet", + clearAll: "Poista kaikki", + }, + InputButtonGroup: { + title: "Luokat", + price: "Hinta", + customPrice: "Mukautettu hinta", + priceIncluded: "kyllä", + priceExcluded: "ei", + priceExcludedMessage: "Ei {title}", + priceRange: " ja enemmän", + showmore: "Näytä enemmän", + }, + Loading: { + title: "Ladataan", + }, + NoResults: { + heading: "Haullasi ei löytynyt tuloksia.", + subheading: "Yritä uudelleen...", + }, + SortDropdown: { + title: "Lajitteluperuste", + option: "Lajitteluperuste: {selectedOption}", + relevanceLabel: "Olennaisimmat", + positionLabel: "Sijainti", + }, + CategoryFilters: { + results: "tulosta ilmaukselle {phrase}", + products: "{totalCount} tuotetta", + }, + ProductCard: { + asLowAs: "Parhaimmillaan {discountPrice}", + startingAt: "Alkaen {productPrice}", + bundlePrice: "{fromBundlePrice} alkaen {toBundlePrice} asti", + from: "{productPrice} alkaen", + }, + ProductContainers: { + minquery: "Hakusanasi {variables.phrase} ei ole saavuttanut {minQueryLength} merkin vähimmäismäärää.", + noresults: "Hakusi ei palauttanut tuloksia.", + pagePicker: "Näytä {pageSize} sivua kohti", + showAll: "kaikki", + }, + SearchBar: { + placeholder: "Hae...", + }, }; diff --git a/src/i18n/fr_FR.ts b/src/i18n/fr_FR.ts index 783a701..ef93f13 100644 --- a/src/i18n/fr_FR.ts +++ b/src/i18n/fr_FR.ts @@ -8,53 +8,53 @@ it. */ export const fr_FR = { - Filter: { - title: 'Filtres', - showTitle: 'Afficher les filtres', - hideTitle: 'Masquer les filtres', - clearAll: 'Tout effacer', - }, - InputButtonGroup: { - title: 'Catégories', - price: 'Prix', - customPrice: 'Prix personnalisé', - priceIncluded: 'oui', - priceExcluded: 'non', - priceExcludedMessage: 'Exclure {title}', - priceRange: ' et plus', - showmore: 'Plus', - }, - Loading: { - title: 'Chargement', - }, - NoResults: { - heading: 'Votre recherche n’a renvoyé aucun résultat', - subheading: 'Veuillez réessayer…', - }, - SortDropdown: { - title: 'Trier par', - option: 'Trier par : {selectedOption}', - relevanceLabel: 'Pertinence', - positionLabel: 'Position', - }, - CategoryFilters: { - results: 'résultats trouvés pour {phrase}', - products: '{totalCount} produits', - }, - ProductCard: { - asLowAs: 'Prix descendant jusqu’à {discountPrice}', - startingAt: 'À partir de {productPrice}', - bundlePrice: 'De {fromBundlePrice} à {toBundlePrice}', - from: 'De {productPrice}', - }, - ProductContainers: { - minquery: - 'Votre terme de recherche « {variables.phrase} » est en dessous de la limite minimale de {minQueryLength} caractères.', - noresults: 'Votre recherche n’a renvoyé aucun résultat.', - pagePicker: 'Affichage : {pageSize} par page', - showAll: 'tout', - }, - SearchBar: { - placeholder: 'Rechercher…', - }, + Filter: { + title: "Filtres", + showTitle: "Afficher les filtres", + hideTitle: "Masquer les filtres", + clearAll: "Tout effacer", + }, + InputButtonGroup: { + title: "Catégories", + price: "Prix", + customPrice: "Prix personnalisé", + priceIncluded: "oui", + priceExcluded: "non", + priceExcludedMessage: "Exclure {title}", + priceRange: " et plus", + showmore: "Plus", + }, + Loading: { + title: "Chargement", + }, + NoResults: { + heading: "Votre recherche n’a renvoyé aucun résultat", + subheading: "Veuillez réessayer…", + }, + SortDropdown: { + title: "Trier par", + option: "Trier par : {selectedOption}", + relevanceLabel: "Pertinence", + positionLabel: "Position", + }, + CategoryFilters: { + results: "résultats trouvés pour {phrase}", + products: "{totalCount} produits", + }, + ProductCard: { + asLowAs: "Prix descendant jusqu’à {discountPrice}", + startingAt: "À partir de {productPrice}", + bundlePrice: "De {fromBundlePrice} à {toBundlePrice}", + from: "De {productPrice}", + }, + ProductContainers: { + minquery: + "Votre terme de recherche « {variables.phrase} » est en dessous de la limite minimale de {minQueryLength} caractères.", + noresults: "Votre recherche n’a renvoyé aucun résultat.", + pagePicker: "Affichage : {pageSize} par page", + showAll: "tout", + }, + SearchBar: { + placeholder: "Rechercher…", + }, }; diff --git a/src/i18n/gl_ES.ts b/src/i18n/gl_ES.ts index 10c5bb1..8c35565 100644 --- a/src/i18n/gl_ES.ts +++ b/src/i18n/gl_ES.ts @@ -8,53 +8,52 @@ it. */ export const gl_ES = { - Filter: { - title: 'Filtros', - showTitle: 'Mostrar filtros', - hideTitle: 'Ocultar filtros', - clearAll: 'Borrar todo', - }, - InputButtonGroup: { - title: 'Categorías', - price: 'Prezo', - customPrice: 'Prezo personalizado', - priceIncluded: 'si', - priceExcluded: 'non', - priceExcludedMessage: 'Non {title}', - priceRange: ' e superior', - showmore: 'Mostrar máis', - }, - Loading: { - title: 'Cargando', - }, - NoResults: { - heading: 'Non hai resultados para a súa busca.', - subheading: 'Ténteo de novo...', - }, - SortDropdown: { - title: 'Ordenar por', - option: 'Ordenar por: {selectedOption}', - relevanceLabel: 'Máis relevante', - positionLabel: 'Posición', - }, - CategoryFilters: { - results: 'resultados para {phrase}', - products: '{totalCount} produtos', - }, - ProductCard: { - asLowAs: 'A partir de só {discountPrice}', - startingAt: 'A partir de {productPrice}', - bundlePrice: 'Desde {fromBundlePrice} ata {toBundlePrice}', - from: 'Desde {productPrice}', - }, - ProductContainers: { - minquery: - 'O seu termo de busca {variables.phrase} non alcanzou o mínimo de {minQueryLength} caracteres.', - noresults: 'A súa busca non obtivo resultados.', - pagePicker: 'Mostrar {pageSize} por páxina', - showAll: 'todos', - }, - SearchBar: { - placeholder: 'Buscar...', - }, + Filter: { + title: "Filtros", + showTitle: "Mostrar filtros", + hideTitle: "Ocultar filtros", + clearAll: "Borrar todo", + }, + InputButtonGroup: { + title: "Categorías", + price: "Prezo", + customPrice: "Prezo personalizado", + priceIncluded: "si", + priceExcluded: "non", + priceExcludedMessage: "Non {title}", + priceRange: " e superior", + showmore: "Mostrar máis", + }, + Loading: { + title: "Cargando", + }, + NoResults: { + heading: "Non hai resultados para a súa busca.", + subheading: "Ténteo de novo...", + }, + SortDropdown: { + title: "Ordenar por", + option: "Ordenar por: {selectedOption}", + relevanceLabel: "Máis relevante", + positionLabel: "Posición", + }, + CategoryFilters: { + results: "resultados para {phrase}", + products: "{totalCount} produtos", + }, + ProductCard: { + asLowAs: "A partir de só {discountPrice}", + startingAt: "A partir de {productPrice}", + bundlePrice: "Desde {fromBundlePrice} ata {toBundlePrice}", + from: "Desde {productPrice}", + }, + ProductContainers: { + minquery: "O seu termo de busca {variables.phrase} non alcanzou o mínimo de {minQueryLength} caracteres.", + noresults: "A súa busca non obtivo resultados.", + pagePicker: "Mostrar {pageSize} por páxina", + showAll: "todos", + }, + SearchBar: { + placeholder: "Buscar...", + }, }; diff --git a/src/i18n/hi_IN.ts b/src/i18n/hi_IN.ts index 5ff13d4..fe1a9ea 100644 --- a/src/i18n/hi_IN.ts +++ b/src/i18n/hi_IN.ts @@ -8,53 +8,52 @@ it. */ export const hi_IN = { - Filter: { - title: 'फिल्टर', - showTitle: 'फ़िल्टर दिखाएं', - hideTitle: 'फ़िल्टर छुपाएं', - clearAll: 'सभी साफ करें', - }, - InputButtonGroup: { - title: 'श्रेणियाँ', - price: 'कीमत', - customPrice: 'कस्टम कीमत', - priceIncluded: 'हां', - priceExcluded: 'नहीं', - priceExcludedMessage: 'नहीं {title}', - priceRange: ' और ऊपर', - showmore: 'और दिखाएं', - }, - Loading: { - title: 'लोड हो रहा है', - }, - NoResults: { - heading: 'आपकी खोज के लिए कोई परिणाम नहीं.', - subheading: 'कृपया फिर कोशिश करें...', - }, - SortDropdown: { - title: 'इसके अनुसार क्रमबद्ध करें', - option: 'इसके अनुसार क्रमबद्ध करें: {selectedOption}', - relevanceLabel: 'सबसे अधिक प्रासंगिक', - positionLabel: 'पद', - }, - CategoryFilters: { - results: '{phrase} के लिए परिणाम', - products: '{totalCount} प्रोडक्ट्स', - }, - ProductCard: { - asLowAs: '{discountPrice} जितना कम ', - startingAt: '{productPrice} से शुरू', - bundlePrice: '{fromBundlePrice} से {toBundlePrice} तक', - from: '{productPrice} से ', - }, - ProductContainers: { - minquery: - 'आपका खोज शब्द {variables.phrase} न्यूनतम {minQueryLength} वर्ण तक नहीं पहुंच पाया है।', - noresults: 'आपकी खोज का कोई परिणाम नहीं निकला।', - pagePicker: 'प्रति पृष्ठ {pageSize}दिखाओ', - showAll: 'सब', - }, - SearchBar: { - placeholder: 'खोज...', - }, + Filter: { + title: "फिल्टर", + showTitle: "फ़िल्टर दिखाएं", + hideTitle: "फ़िल्टर छुपाएं", + clearAll: "सभी साफ करें", + }, + InputButtonGroup: { + title: "श्रेणियाँ", + price: "कीमत", + customPrice: "कस्टम कीमत", + priceIncluded: "हां", + priceExcluded: "नहीं", + priceExcludedMessage: "नहीं {title}", + priceRange: " और ऊपर", + showmore: "और दिखाएं", + }, + Loading: { + title: "लोड हो रहा है", + }, + NoResults: { + heading: "आपकी खोज के लिए कोई परिणाम नहीं.", + subheading: "कृपया फिर कोशिश करें...", + }, + SortDropdown: { + title: "इसके अनुसार क्रमबद्ध करें", + option: "इसके अनुसार क्रमबद्ध करें: {selectedOption}", + relevanceLabel: "सबसे अधिक प्रासंगिक", + positionLabel: "पद", + }, + CategoryFilters: { + results: "{phrase} के लिए परिणाम", + products: "{totalCount} प्रोडक्ट्स", + }, + ProductCard: { + asLowAs: "{discountPrice} जितना कम ", + startingAt: "{productPrice} से शुरू", + bundlePrice: "{fromBundlePrice} से {toBundlePrice} तक", + from: "{productPrice} से ", + }, + ProductContainers: { + minquery: "आपका खोज शब्द {variables.phrase} न्यूनतम {minQueryLength} वर्ण तक नहीं पहुंच पाया है।", + noresults: "आपकी खोज का कोई परिणाम नहीं निकला।", + pagePicker: "प्रति पृष्ठ {pageSize}दिखाओ", + showAll: "सब", + }, + SearchBar: { + placeholder: "खोज...", + }, }; diff --git a/src/i18n/hu_HU.ts b/src/i18n/hu_HU.ts index 350299a..60eea74 100644 --- a/src/i18n/hu_HU.ts +++ b/src/i18n/hu_HU.ts @@ -8,53 +8,52 @@ it. */ export const hu_HU = { - Filter: { - title: 'Szűrők', - showTitle: 'Szűrők megjelenítése', - hideTitle: 'Szűrők elrejtése', - clearAll: 'Összes törlése', - }, - InputButtonGroup: { - title: 'Kategóriák', - price: 'Ár', - customPrice: 'Egyedi ár', - priceIncluded: 'igen', - priceExcluded: 'nem', - priceExcludedMessage: 'Nem {title}', - priceRange: ' és fölötte', - showmore: 'További információk megjelenítése', - }, - Loading: { - title: 'Betöltés', - }, - NoResults: { - heading: 'Nincs találat a keresésre.', - subheading: 'Kérjük, próbálja meg újra...', - }, - SortDropdown: { - title: 'Rendezési szempont', - option: 'Rendezési szempont: {selectedOption}', - relevanceLabel: 'Legrelevánsabb', - positionLabel: 'Pozíció', - }, - CategoryFilters: { - results: 'eredmények a következőre: {phrase}', - products: '{totalCount} termék', - }, - ProductCard: { - asLowAs: 'Ennyire alacsony: {discountPrice}', - startingAt: 'Kezdő ár: {productPrice}', - bundlePrice: 'Ettől: {fromBundlePrice} Eddig: {toBundlePrice}', - from: 'Ettől: {productPrice}', - }, - ProductContainers: { - minquery: - 'A keresett kifejezés: {variables.phrase} nem érte el a minimum {minQueryLength} karaktert.', - noresults: 'A keresés nem hozott eredményt.', - pagePicker: '{pageSize} megjelenítése oldalanként', - showAll: 'összes', - }, - SearchBar: { - placeholder: 'Keresés...', - }, + Filter: { + title: "Szűrők", + showTitle: "Szűrők megjelenítése", + hideTitle: "Szűrők elrejtése", + clearAll: "Összes törlése", + }, + InputButtonGroup: { + title: "Kategóriák", + price: "Ár", + customPrice: "Egyedi ár", + priceIncluded: "igen", + priceExcluded: "nem", + priceExcludedMessage: "Nem {title}", + priceRange: " és fölötte", + showmore: "További információk megjelenítése", + }, + Loading: { + title: "Betöltés", + }, + NoResults: { + heading: "Nincs találat a keresésre.", + subheading: "Kérjük, próbálja meg újra...", + }, + SortDropdown: { + title: "Rendezési szempont", + option: "Rendezési szempont: {selectedOption}", + relevanceLabel: "Legrelevánsabb", + positionLabel: "Pozíció", + }, + CategoryFilters: { + results: "eredmények a következőre: {phrase}", + products: "{totalCount} termék", + }, + ProductCard: { + asLowAs: "Ennyire alacsony: {discountPrice}", + startingAt: "Kezdő ár: {productPrice}", + bundlePrice: "Ettől: {fromBundlePrice} Eddig: {toBundlePrice}", + from: "Ettől: {productPrice}", + }, + ProductContainers: { + minquery: "A keresett kifejezés: {variables.phrase} nem érte el a minimum {minQueryLength} karaktert.", + noresults: "A keresés nem hozott eredményt.", + pagePicker: "{pageSize} megjelenítése oldalanként", + showAll: "összes", + }, + SearchBar: { + placeholder: "Keresés...", + }, }; diff --git a/src/i18n/hy_AM.ts b/src/i18n/hy_AM.ts index 8a9f91e..5fd0055 100644 --- a/src/i18n/hy_AM.ts +++ b/src/i18n/hy_AM.ts @@ -8,53 +8,52 @@ it. */ export const hy_AM = { - Filter: { - title: 'Ֆիլտրեր', - showTitle: 'Ցույց տալ ֆիլտրերը', - hideTitle: 'Թաքցնել ֆիլտրերը', - clearAll: 'Մաքրել բոլորը', - }, - InputButtonGroup: { - title: 'Կատեգորիաներ', - price: 'Գինը', - customPrice: 'Սովորական գինը', - priceIncluded: 'այո', - priceExcluded: 'ոչ', - priceExcludedMessage: 'Ոչ {title}', - priceRange: ' և վերևում', - showmore: 'Ցույց տալ ավելին', - }, - Loading: { - title: 'Բեռնվում է', - }, - NoResults: { - heading: 'Ձեր որոնման համար արդյունքներ չկան:', - subheading: 'Խնդրում եմ փորձել կրկին...', - }, - SortDropdown: { - title: 'Դասավորել ըստ', - option: 'Դասավորել ըստ՝ {selectedOption}', - relevanceLabel: 'Ամենակարևորը', - positionLabel: 'Դիրք', - }, - CategoryFilters: { - results: 'արդյունքներ {phrase}-ի համար', - products: '{totalCount} ապրանքներ', - }, - ProductCard: { - asLowAs: '{discountPrice}-ի չափ ցածր', - startingAt: 'Սկսած {productPrice}-ից', - bundlePrice: '{fromBundlePrice}-ից մինչև {toBundlePrice}', - from: '{productPrice}-ից', - }, - ProductContainers: { - minquery: - 'Ձեր որոնման բառը {variables.phrase} չի հասել նվազագույն {minQueryLength} նիշերի:', - noresults: 'Ձեր որոնումը արդյունք չտվեց:', - pagePicker: 'Ցույց տալ {pageSize} յուրաքանչյուր էջի համար', - showAll: 'բոլորը', - }, - SearchBar: { - placeholder: 'Որոնել...', - }, + Filter: { + title: "Ֆիլտրեր", + showTitle: "Ցույց տալ ֆիլտրերը", + hideTitle: "Թաքցնել ֆիլտրերը", + clearAll: "Մաքրել բոլորը", + }, + InputButtonGroup: { + title: "Կատեգորիաներ", + price: "Գինը", + customPrice: "Սովորական գինը", + priceIncluded: "այո", + priceExcluded: "ոչ", + priceExcludedMessage: "Ոչ {title}", + priceRange: " և վերևում", + showmore: "Ցույց տալ ավելին", + }, + Loading: { + title: "Բեռնվում է", + }, + NoResults: { + heading: "Ձեր որոնման համար արդյունքներ չկան:", + subheading: "Խնդրում եմ փորձել կրկին...", + }, + SortDropdown: { + title: "Դասավորել ըստ", + option: "Դասավորել ըստ՝ {selectedOption}", + relevanceLabel: "Ամենակարևորը", + positionLabel: "Դիրք", + }, + CategoryFilters: { + results: "արդյունքներ {phrase}-ի համար", + products: "{totalCount} ապրանքներ", + }, + ProductCard: { + asLowAs: "{discountPrice}-ի չափ ցածր", + startingAt: "Սկսած {productPrice}-ից", + bundlePrice: "{fromBundlePrice}-ից մինչև {toBundlePrice}", + from: "{productPrice}-ից", + }, + ProductContainers: { + minquery: "Ձեր որոնման բառը {variables.phrase} չի հասել նվազագույն {minQueryLength} նիշերի:", + noresults: "Ձեր որոնումը արդյունք չտվեց:", + pagePicker: "Ցույց տալ {pageSize} յուրաքանչյուր էջի համար", + showAll: "բոլորը", + }, + SearchBar: { + placeholder: "Որոնել...", + }, }; diff --git a/src/i18n/id_ID.ts b/src/i18n/id_ID.ts index a02b129..e567510 100644 --- a/src/i18n/id_ID.ts +++ b/src/i18n/id_ID.ts @@ -8,53 +8,52 @@ it. */ export const id_ID = { - Filter: { - title: 'Filter', - showTitle: 'Tampilkan filter', - hideTitle: 'Sembunyikan filter', - clearAll: 'Bersihkan semua', - }, - InputButtonGroup: { - title: 'Kategori', - price: 'Harga', - customPrice: 'Harga Kustom', - priceIncluded: 'ya', - priceExcluded: 'tidak', - priceExcludedMessage: 'Bukan {title}', - priceRange: ' ke atas', - showmore: 'Tampilkan lainnya', - }, - Loading: { - title: 'Memuat', - }, - NoResults: { - heading: 'Tidak ada hasil untuk pencarian Anda.', - subheading: 'Coba lagi...', - }, - SortDropdown: { - title: 'Urut berdasarkan', - option: 'Urut berdasarkan: {selectedOption}', - relevanceLabel: 'Paling Relevan', - positionLabel: 'Posisi', - }, - CategoryFilters: { - results: 'hasil untuk {phrase}', - products: '{totalCount} produk', - }, - ProductCard: { - asLowAs: 'Paling rendah {discountPrice}', - startingAt: 'Mulai dari {productPrice}', - bundlePrice: 'Mulai {fromBundlePrice} hingga {toBundlePrice}', - from: 'Mulai {productPrice}', - }, - ProductContainers: { - minquery: - 'Istilah pencarian {variables.phrase} belum mencapai batas minimum {minQueryLength} karakter.', - noresults: 'Pencarian Anda tidak memberikan hasil.', - pagePicker: 'Menampilkan {pageSize} per halaman', - showAll: 'semua', - }, - SearchBar: { - placeholder: 'Cari...', - }, + Filter: { + title: "Filter", + showTitle: "Tampilkan filter", + hideTitle: "Sembunyikan filter", + clearAll: "Bersihkan semua", + }, + InputButtonGroup: { + title: "Kategori", + price: "Harga", + customPrice: "Harga Kustom", + priceIncluded: "ya", + priceExcluded: "tidak", + priceExcludedMessage: "Bukan {title}", + priceRange: " ke atas", + showmore: "Tampilkan lainnya", + }, + Loading: { + title: "Memuat", + }, + NoResults: { + heading: "Tidak ada hasil untuk pencarian Anda.", + subheading: "Coba lagi...", + }, + SortDropdown: { + title: "Urut berdasarkan", + option: "Urut berdasarkan: {selectedOption}", + relevanceLabel: "Paling Relevan", + positionLabel: "Posisi", + }, + CategoryFilters: { + results: "hasil untuk {phrase}", + products: "{totalCount} produk", + }, + ProductCard: { + asLowAs: "Paling rendah {discountPrice}", + startingAt: "Mulai dari {productPrice}", + bundlePrice: "Mulai {fromBundlePrice} hingga {toBundlePrice}", + from: "Mulai {productPrice}", + }, + ProductContainers: { + minquery: "Istilah pencarian {variables.phrase} belum mencapai batas minimum {minQueryLength} karakter.", + noresults: "Pencarian Anda tidak memberikan hasil.", + pagePicker: "Menampilkan {pageSize} per halaman", + showAll: "semua", + }, + SearchBar: { + placeholder: "Cari...", + }, }; diff --git a/src/i18n/index.ts b/src/i18n/index.ts index 4144622..cf1b370 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -7,83 +7,83 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { ar_AE } from './ar_AE'; -import { bg_BG } from './bg_BG'; -import { bn_IN } from './bn_IN'; -import { ca_ES } from './ca_ES'; -import { cs_CZ } from './cs_CZ'; -import { da_DK } from './da_DK'; -import { de_DE } from './de_DE'; -import { el_GR } from './el_GR'; -import { en_GA } from './en_GA'; -import { en_GB } from './en_GB'; -import { en_US } from './en_US'; -import { es_ES } from './es_ES'; -import { et_EE } from './et_EE'; -import { eu_ES } from './eu_ES'; -import { fa_IR } from './fa_IR'; -import { fi_FI } from './fi_FI'; -import { fr_FR } from './fr_FR'; -import { gl_ES } from './gl_ES'; -import { hi_IN } from './hi_IN'; -import { hu_HU } from './hu_HU'; -import { hy_AM } from './hy_AM'; -import { id_ID } from './id_ID'; -import { it_IT } from './it_IT'; -import { ja_JP } from './ja_JP'; -import { ko_KR } from './ko_KR'; -import { lt_LT } from './lt_LT'; -import { lv_LV } from './lv_LV'; -import { nb_NO } from './nb_NO'; -import { nl_NL } from './nl_NL'; -import { pt_BR } from './pt_BR'; -import { pt_PT } from './pt_PT'; -import { ro_RO } from './ro_RO'; -import { ru_RU } from './ru_RU'; -import { Sorani } from './Sorani'; -import { sv_SE } from './sv_SE'; -import { th_TH } from './th_TH'; -import { tr_TR } from './tr_TR'; -import { zh_Hans_CN } from './zh_Hans_CN'; -import { zh_Hant_TW } from './zh_Hant_TW'; +import { ar_AE } from "./ar_AE"; +import { bg_BG } from "./bg_BG"; +import { bn_IN } from "./bn_IN"; +import { ca_ES } from "./ca_ES"; +import { cs_CZ } from "./cs_CZ"; +import { da_DK } from "./da_DK"; +import { de_DE } from "./de_DE"; +import { el_GR } from "./el_GR"; +import { en_GA } from "./en_GA"; +import { en_GB } from "./en_GB"; +import { en_US } from "./en_US"; +import { es_ES } from "./es_ES"; +import { et_EE } from "./et_EE"; +import { eu_ES } from "./eu_ES"; +import { fa_IR } from "./fa_IR"; +import { fi_FI } from "./fi_FI"; +import { fr_FR } from "./fr_FR"; +import { gl_ES } from "./gl_ES"; +import { hi_IN } from "./hi_IN"; +import { hu_HU } from "./hu_HU"; +import { hy_AM } from "./hy_AM"; +import { id_ID } from "./id_ID"; +import { it_IT } from "./it_IT"; +import { ja_JP } from "./ja_JP"; +import { ko_KR } from "./ko_KR"; +import { lt_LT } from "./lt_LT"; +import { lv_LV } from "./lv_LV"; +import { nb_NO } from "./nb_NO"; +import { nl_NL } from "./nl_NL"; +import { pt_BR } from "./pt_BR"; +import { pt_PT } from "./pt_PT"; +import { ro_RO } from "./ro_RO"; +import { ru_RU } from "./ru_RU"; +import { Sorani } from "./Sorani"; +import { sv_SE } from "./sv_SE"; +import { th_TH } from "./th_TH"; +import { tr_TR } from "./tr_TR"; +import { zh_Hans_CN } from "./zh_Hans_CN"; +import { zh_Hant_TW } from "./zh_Hant_TW"; export { - ar_AE, - bg_BG, - bn_IN, - ca_ES, - cs_CZ, - da_DK, - de_DE, - el_GR, - en_GA, - en_GB, - en_US, - es_ES, - et_EE, - eu_ES, - fa_IR, - fi_FI, - fr_FR, - gl_ES, - hi_IN, - hu_HU, - hy_AM, - id_ID, - it_IT, - ja_JP, - ko_KR, - lt_LT, - lv_LV, - nb_NO, - nl_NL, - pt_BR, - pt_PT, - ro_RO, - ru_RU, - Sorani, - sv_SE, - th_TH, - tr_TR, - zh_Hans_CN, - zh_Hant_TW, + ar_AE, + bg_BG, + bn_IN, + ca_ES, + cs_CZ, + da_DK, + de_DE, + el_GR, + en_GA, + en_GB, + en_US, + es_ES, + et_EE, + eu_ES, + fa_IR, + fi_FI, + fr_FR, + gl_ES, + hi_IN, + hu_HU, + hy_AM, + id_ID, + it_IT, + ja_JP, + ko_KR, + lt_LT, + lv_LV, + nb_NO, + nl_NL, + pt_BR, + pt_PT, + ro_RO, + ru_RU, + Sorani, + sv_SE, + th_TH, + tr_TR, + zh_Hans_CN, + zh_Hant_TW, }; diff --git a/src/i18n/it_IT.ts b/src/i18n/it_IT.ts index 5cb1e2e..f1bf9af 100644 --- a/src/i18n/it_IT.ts +++ b/src/i18n/it_IT.ts @@ -8,53 +8,52 @@ it. */ export const it_IT = { - Filter: { - title: 'Filtri', - showTitle: 'Mostra filtri', - hideTitle: 'Nascondi filtri', - clearAll: 'Cancella tutto', - }, - InputButtonGroup: { - title: 'Categorie', - price: 'Prezzo', - customPrice: 'Prezzo personalizzato', - priceIncluded: 'sì', - priceExcluded: 'no', - priceExcludedMessage: 'Non {title}', - priceRange: ' e superiore', - showmore: 'Mostra altro', - }, - Loading: { - title: 'Caricamento', - }, - NoResults: { - heading: 'Nessun risultato per la ricerca.', - subheading: 'Riprova...', - }, - SortDropdown: { - title: 'Ordina per', - option: 'Ordina per: {selectedOption}', - relevanceLabel: 'Più rilevante', - positionLabel: 'Posizione', - }, - CategoryFilters: { - results: 'risultati per {phrase}', - products: '{totalCount} prodotti', - }, - ProductCard: { - asLowAs: 'A partire da {discountPrice}', - startingAt: 'A partire da {productPrice}', - bundlePrice: 'Da {fromBundlePrice} a {toBundlePrice}', - from: 'Da {productPrice}', - }, - ProductContainers: { - minquery: - 'Il termine di ricerca {variables.phrase} non ha raggiunto il minimo di {minQueryLength} caratteri.', - noresults: 'La ricerca non ha prodotto risultati.', - pagePicker: 'Mostra {pageSize} per pagina', - showAll: 'tutto', - }, - SearchBar: { - placeholder: 'Cerca...', - }, + Filter: { + title: "Filtri", + showTitle: "Mostra filtri", + hideTitle: "Nascondi filtri", + clearAll: "Cancella tutto", + }, + InputButtonGroup: { + title: "Categorie", + price: "Prezzo", + customPrice: "Prezzo personalizzato", + priceIncluded: "sì", + priceExcluded: "no", + priceExcludedMessage: "Non {title}", + priceRange: " e superiore", + showmore: "Mostra altro", + }, + Loading: { + title: "Caricamento", + }, + NoResults: { + heading: "Nessun risultato per la ricerca.", + subheading: "Riprova...", + }, + SortDropdown: { + title: "Ordina per", + option: "Ordina per: {selectedOption}", + relevanceLabel: "Più rilevante", + positionLabel: "Posizione", + }, + CategoryFilters: { + results: "risultati per {phrase}", + products: "{totalCount} prodotti", + }, + ProductCard: { + asLowAs: "A partire da {discountPrice}", + startingAt: "A partire da {productPrice}", + bundlePrice: "Da {fromBundlePrice} a {toBundlePrice}", + from: "Da {productPrice}", + }, + ProductContainers: { + minquery: "Il termine di ricerca {variables.phrase} non ha raggiunto il minimo di {minQueryLength} caratteri.", + noresults: "La ricerca non ha prodotto risultati.", + pagePicker: "Mostra {pageSize} per pagina", + showAll: "tutto", + }, + SearchBar: { + placeholder: "Cerca...", + }, }; diff --git a/src/i18n/ja_JP.ts b/src/i18n/ja_JP.ts index 2f23ed2..195737a 100644 --- a/src/i18n/ja_JP.ts +++ b/src/i18n/ja_JP.ts @@ -8,53 +8,52 @@ it. */ export const ja_JP = { - Filter: { - title: 'フィルター', - showTitle: 'フィルターを表示', - hideTitle: 'フィルターを隠す', - clearAll: 'すべて消去', - }, - InputButtonGroup: { - title: 'カテゴリ', - price: '価格', - customPrice: 'カスタム価格', - priceIncluded: 'はい', - priceExcluded: 'いいえ', - priceExcludedMessage: '{title}ではない', - priceRange: ' 以上', - showmore: 'すべてを表示', - }, - Loading: { - title: '読み込み中', - }, - NoResults: { - heading: '検索結果はありません。', - subheading: '再試行してください', - }, - SortDropdown: { - title: '並べ替え条件', - option: '{selectedOption}に並べ替え', - relevanceLabel: '最も関連性が高い', - positionLabel: '配置', - }, - CategoryFilters: { - results: '{phrase}の検索結果', - products: '{totalCount}製品', - }, - ProductCard: { - asLowAs: '割引料金 : {discountPrice}', - startingAt: '初年度価格 : {productPrice}', - bundlePrice: '{fromBundlePrice} から {toBundlePrice}', - from: '{productPrice} から', - }, - ProductContainers: { - minquery: - 'ご入力の検索語{variables.phrase}は、最低文字数 {minQueryLength} 文字に達していません。', - noresults: '検索結果はありませんでした。', - pagePicker: '1 ページあたり {pageSize} を表示', - showAll: 'すべて', - }, - SearchBar: { - placeholder: '検索', - }, + Filter: { + title: "フィルター", + showTitle: "フィルターを表示", + hideTitle: "フィルターを隠す", + clearAll: "すべて消去", + }, + InputButtonGroup: { + title: "カテゴリ", + price: "価格", + customPrice: "カスタム価格", + priceIncluded: "はい", + priceExcluded: "いいえ", + priceExcludedMessage: "{title}ではない", + priceRange: " 以上", + showmore: "すべてを表示", + }, + Loading: { + title: "読み込み中", + }, + NoResults: { + heading: "検索結果はありません。", + subheading: "再試行してください", + }, + SortDropdown: { + title: "並べ替え条件", + option: "{selectedOption}に並べ替え", + relevanceLabel: "最も関連性が高い", + positionLabel: "配置", + }, + CategoryFilters: { + results: "{phrase}の検索結果", + products: "{totalCount}製品", + }, + ProductCard: { + asLowAs: "割引料金 : {discountPrice}", + startingAt: "初年度価格 : {productPrice}", + bundlePrice: "{fromBundlePrice} から {toBundlePrice}", + from: "{productPrice} から", + }, + ProductContainers: { + minquery: "ご入力の検索語{variables.phrase}は、最低文字数 {minQueryLength} 文字に達していません。", + noresults: "検索結果はありませんでした。", + pagePicker: "1 ページあたり {pageSize} を表示", + showAll: "すべて", + }, + SearchBar: { + placeholder: "検索", + }, }; diff --git a/src/i18n/ko_KR.ts b/src/i18n/ko_KR.ts index 4fc809c..147d5c7 100644 --- a/src/i18n/ko_KR.ts +++ b/src/i18n/ko_KR.ts @@ -8,53 +8,52 @@ it. */ export const ko_KR = { - Filter: { - title: '필터', - showTitle: '필터 표시', - hideTitle: '필터 숨기기', - clearAll: '모두 지우기', - }, - InputButtonGroup: { - title: '범주', - price: '가격', - customPrice: '맞춤 가격', - priceIncluded: '예', - priceExcluded: '아니요', - priceExcludedMessage: '{title} 아님', - priceRange: ' 이상', - showmore: '자세히 표시', - }, - Loading: { - title: '로드 중', - }, - NoResults: { - heading: '현재 검색에 대한 결과가 없습니다.', - subheading: '다시 시도해 주십시오.', - }, - SortDropdown: { - title: '정렬 기준', - option: '정렬 기준: {selectedOption}', - relevanceLabel: '관련성 가장 높음', - positionLabel: '위치', - }, - CategoryFilters: { - results: '{phrase}에 대한 검색 결과', - products: '{totalCount}개 제품', - }, - ProductCard: { - asLowAs: '최저 {discountPrice}', - startingAt: '최저가: {productPrice}', - bundlePrice: '{fromBundlePrice} ~ {toBundlePrice}', - from: '{productPrice}부터', - }, - ProductContainers: { - minquery: - '검색어 “{variables.phrase}”이(가) 최소 문자 길이인 {minQueryLength}자 미만입니다.', - noresults: '검색 결과가 없습니다.', - pagePicker: '페이지당 {pageSize}개 표시', - showAll: '모두', - }, - SearchBar: { - placeholder: '검색...', - }, + Filter: { + title: "필터", + showTitle: "필터 표시", + hideTitle: "필터 숨기기", + clearAll: "모두 지우기", + }, + InputButtonGroup: { + title: "범주", + price: "가격", + customPrice: "맞춤 가격", + priceIncluded: "예", + priceExcluded: "아니요", + priceExcludedMessage: "{title} 아님", + priceRange: " 이상", + showmore: "자세히 표시", + }, + Loading: { + title: "로드 중", + }, + NoResults: { + heading: "현재 검색에 대한 결과가 없습니다.", + subheading: "다시 시도해 주십시오.", + }, + SortDropdown: { + title: "정렬 기준", + option: "정렬 기준: {selectedOption}", + relevanceLabel: "관련성 가장 높음", + positionLabel: "위치", + }, + CategoryFilters: { + results: "{phrase}에 대한 검색 결과", + products: "{totalCount}개 제품", + }, + ProductCard: { + asLowAs: "최저 {discountPrice}", + startingAt: "최저가: {productPrice}", + bundlePrice: "{fromBundlePrice} ~ {toBundlePrice}", + from: "{productPrice}부터", + }, + ProductContainers: { + minquery: "검색어 “{variables.phrase}”이(가) 최소 문자 길이인 {minQueryLength}자 미만입니다.", + noresults: "검색 결과가 없습니다.", + pagePicker: "페이지당 {pageSize}개 표시", + showAll: "모두", + }, + SearchBar: { + placeholder: "검색...", + }, }; diff --git a/src/i18n/lt_LT.ts b/src/i18n/lt_LT.ts index d7f9467..c133de9 100644 --- a/src/i18n/lt_LT.ts +++ b/src/i18n/lt_LT.ts @@ -8,53 +8,52 @@ it. */ export const lt_LT = { - Filter: { - title: 'Filtrai', - showTitle: 'Rodyti filtrus', - hideTitle: 'Slėpti filtrus', - clearAll: 'Išvalyti viską', - }, - InputButtonGroup: { - title: 'Kategorijos', - price: 'Kaina', - customPrice: 'Individualizuota kaina', - priceIncluded: 'taip', - priceExcluded: 'ne', - priceExcludedMessage: 'Ne {title}', - priceRange: ' ir aukščiau', - showmore: 'Rodyti daugiau', - }, - Loading: { - title: 'Įkeliama', - }, - NoResults: { - heading: 'Nėra jūsų ieškos rezultatų.', - subheading: 'Bandykite dar kartą...', - }, - SortDropdown: { - title: 'Rikiuoti pagal', - option: 'Rikiuoti pagal: {selectedOption}', - relevanceLabel: 'Svarbiausias', - positionLabel: 'Padėtis', - }, - CategoryFilters: { - results: 'rezultatai {phrase}', - products: 'Produktų: {totalCount}', - }, - ProductCard: { - asLowAs: 'Žema kaip {discountPrice}', - startingAt: 'Pradedant nuo {productPrice}', - bundlePrice: 'Nuo {fromBundlePrice} iki {toBundlePrice}', - from: 'Nuo {productPrice}', - }, - ProductContainers: { - minquery: - 'Jūsų ieškos sąlyga {variables.phrase} nesiekia minimalaus skaičiaus simbolių: {minQueryLength}.', - noresults: 'Jūsų ieška nedavė jokių rezultatų.', - pagePicker: 'Rodyti {pageSize} psl.', - showAll: 'viskas', - }, - SearchBar: { - placeholder: 'Ieška...', - }, + Filter: { + title: "Filtrai", + showTitle: "Rodyti filtrus", + hideTitle: "Slėpti filtrus", + clearAll: "Išvalyti viską", + }, + InputButtonGroup: { + title: "Kategorijos", + price: "Kaina", + customPrice: "Individualizuota kaina", + priceIncluded: "taip", + priceExcluded: "ne", + priceExcludedMessage: "Ne {title}", + priceRange: " ir aukščiau", + showmore: "Rodyti daugiau", + }, + Loading: { + title: "Įkeliama", + }, + NoResults: { + heading: "Nėra jūsų ieškos rezultatų.", + subheading: "Bandykite dar kartą...", + }, + SortDropdown: { + title: "Rikiuoti pagal", + option: "Rikiuoti pagal: {selectedOption}", + relevanceLabel: "Svarbiausias", + positionLabel: "Padėtis", + }, + CategoryFilters: { + results: "rezultatai {phrase}", + products: "Produktų: {totalCount}", + }, + ProductCard: { + asLowAs: "Žema kaip {discountPrice}", + startingAt: "Pradedant nuo {productPrice}", + bundlePrice: "Nuo {fromBundlePrice} iki {toBundlePrice}", + from: "Nuo {productPrice}", + }, + ProductContainers: { + minquery: "Jūsų ieškos sąlyga {variables.phrase} nesiekia minimalaus skaičiaus simbolių: {minQueryLength}.", + noresults: "Jūsų ieška nedavė jokių rezultatų.", + pagePicker: "Rodyti {pageSize} psl.", + showAll: "viskas", + }, + SearchBar: { + placeholder: "Ieška...", + }, }; diff --git a/src/i18n/lv_LV.ts b/src/i18n/lv_LV.ts index 94708d7..5960a96 100644 --- a/src/i18n/lv_LV.ts +++ b/src/i18n/lv_LV.ts @@ -8,53 +8,52 @@ it. */ export const lv_LV = { - Filter: { - title: 'Filtri', - showTitle: 'Rādīt filtrus', - hideTitle: 'Slēpt filtrus', - clearAll: 'Notīrīt visus', - }, - InputButtonGroup: { - title: 'Kategorijas', - price: 'Cena', - customPrice: 'Pielāgot cenu', - priceIncluded: 'jā', - priceExcluded: 'nē', - priceExcludedMessage: 'Nav {title}', - priceRange: ' un augstāk', - showmore: 'Rādīt vairāk', - }, - Loading: { - title: 'Notiek ielāde', - }, - NoResults: { - heading: 'Jūsu meklēšanai nav rezultātu.', - subheading: 'Mēģiniet vēlreiz…', - }, - SortDropdown: { - title: 'Kārtot pēc', - option: 'Kārtot pēc: {selectedOption}', - relevanceLabel: 'Visatbilstošākais', - positionLabel: 'Pozīcija', - }, - CategoryFilters: { - results: '{phrase} rezultāti', - products: '{totalCount} produkti', - }, - ProductCard: { - asLowAs: 'Tik zemu kā {discountPrice}', - startingAt: 'Sākot no {productPrice}', - bundlePrice: 'No {fromBundlePrice} uz{toBundlePrice}', - from: 'No {productPrice}', - }, - ProductContainers: { - minquery: - 'Jūsu meklēšanas vienums {variables.phrase} nav sasniedzis minimumu {minQueryLength} rakstzīmes.', - noresults: 'Jūsu meklēšana nedeva nekādus rezultātus.', - pagePicker: 'Rādīt {pageSize} vienā lapā', - showAll: 'viss', - }, - SearchBar: { - placeholder: 'Meklēt…', - }, + Filter: { + title: "Filtri", + showTitle: "Rādīt filtrus", + hideTitle: "Slēpt filtrus", + clearAll: "Notīrīt visus", + }, + InputButtonGroup: { + title: "Kategorijas", + price: "Cena", + customPrice: "Pielāgot cenu", + priceIncluded: "jā", + priceExcluded: "nē", + priceExcludedMessage: "Nav {title}", + priceRange: " un augstāk", + showmore: "Rādīt vairāk", + }, + Loading: { + title: "Notiek ielāde", + }, + NoResults: { + heading: "Jūsu meklēšanai nav rezultātu.", + subheading: "Mēģiniet vēlreiz…", + }, + SortDropdown: { + title: "Kārtot pēc", + option: "Kārtot pēc: {selectedOption}", + relevanceLabel: "Visatbilstošākais", + positionLabel: "Pozīcija", + }, + CategoryFilters: { + results: "{phrase} rezultāti", + products: "{totalCount} produkti", + }, + ProductCard: { + asLowAs: "Tik zemu kā {discountPrice}", + startingAt: "Sākot no {productPrice}", + bundlePrice: "No {fromBundlePrice} uz{toBundlePrice}", + from: "No {productPrice}", + }, + ProductContainers: { + minquery: "Jūsu meklēšanas vienums {variables.phrase} nav sasniedzis minimumu {minQueryLength} rakstzīmes.", + noresults: "Jūsu meklēšana nedeva nekādus rezultātus.", + pagePicker: "Rādīt {pageSize} vienā lapā", + showAll: "viss", + }, + SearchBar: { + placeholder: "Meklēt…", + }, }; diff --git a/src/i18n/nb_NO.ts b/src/i18n/nb_NO.ts index 079d145..120b7e1 100644 --- a/src/i18n/nb_NO.ts +++ b/src/i18n/nb_NO.ts @@ -8,53 +8,52 @@ it. */ export const nb_NO = { - Filter: { - title: 'Filtre', - showTitle: 'Vis filtre', - hideTitle: 'Skjul filtre', - clearAll: 'Fjern alle', - }, - InputButtonGroup: { - title: 'Kategorier', - price: 'Pris', - customPrice: 'Egendefinert pris', - priceIncluded: 'ja', - priceExcluded: 'nei', - priceExcludedMessage: 'Ikke {title}', - priceRange: ' og over', - showmore: 'Vis mer', - }, - Loading: { - title: 'Laster inn', - }, - NoResults: { - heading: 'Finner ingen resultater for søket.', - subheading: 'Prøv igjen.', - }, - SortDropdown: { - title: 'Sorter etter', - option: 'Sorter etter: {selectedOption}', - relevanceLabel: 'Mest aktuelle', - positionLabel: 'Plassering', - }, - CategoryFilters: { - results: 'resultater for {phrase}', - products: '{totalCount} produkter', - }, - ProductCard: { - asLowAs: 'Så lavt som {discountPrice}', - startingAt: 'Fra {productPrice}', - bundlePrice: 'Fra {fromBundlePrice} til {toBundlePrice}', - from: 'Fra {productPrice}', - }, - ProductContainers: { - minquery: - 'Søkeordet {variables.phrase} har ikke de påkrevde {minQueryLength} tegnene.', - noresults: 'Søket ditt ga ingen resultater.', - pagePicker: 'Vis {pageSize} per side', - showAll: 'alle', - }, - SearchBar: { - placeholder: 'Søk …', - }, + Filter: { + title: "Filtre", + showTitle: "Vis filtre", + hideTitle: "Skjul filtre", + clearAll: "Fjern alle", + }, + InputButtonGroup: { + title: "Kategorier", + price: "Pris", + customPrice: "Egendefinert pris", + priceIncluded: "ja", + priceExcluded: "nei", + priceExcludedMessage: "Ikke {title}", + priceRange: " og over", + showmore: "Vis mer", + }, + Loading: { + title: "Laster inn", + }, + NoResults: { + heading: "Finner ingen resultater for søket.", + subheading: "Prøv igjen.", + }, + SortDropdown: { + title: "Sorter etter", + option: "Sorter etter: {selectedOption}", + relevanceLabel: "Mest aktuelle", + positionLabel: "Plassering", + }, + CategoryFilters: { + results: "resultater for {phrase}", + products: "{totalCount} produkter", + }, + ProductCard: { + asLowAs: "Så lavt som {discountPrice}", + startingAt: "Fra {productPrice}", + bundlePrice: "Fra {fromBundlePrice} til {toBundlePrice}", + from: "Fra {productPrice}", + }, + ProductContainers: { + minquery: "Søkeordet {variables.phrase} har ikke de påkrevde {minQueryLength} tegnene.", + noresults: "Søket ditt ga ingen resultater.", + pagePicker: "Vis {pageSize} per side", + showAll: "alle", + }, + SearchBar: { + placeholder: "Søk …", + }, }; diff --git a/src/i18n/nl_NL.ts b/src/i18n/nl_NL.ts index c93b45c..7446a06 100644 --- a/src/i18n/nl_NL.ts +++ b/src/i18n/nl_NL.ts @@ -8,53 +8,52 @@ it. */ export const nl_NL = { - Filter: { - title: 'Filters', - showTitle: 'Filters weergeven', - hideTitle: 'Filters verbergen', - clearAll: 'Alles wissen', - }, - InputButtonGroup: { - title: 'Categorieën', - price: 'Prijs', - customPrice: 'Aangepaste prijs', - priceIncluded: 'ja', - priceExcluded: 'nee', - priceExcludedMessage: 'Niet {title}', - priceRange: ' en meer', - showmore: 'Meer tonen', - }, - Loading: { - title: 'Laden', - }, - NoResults: { - heading: 'Geen resultaten voor je zoekopdracht.', - subheading: 'Probeer het opnieuw...', - }, - SortDropdown: { - title: 'Sorteren op', - option: 'Sorteren op: {selectedOption}', - relevanceLabel: 'Meest relevant', - positionLabel: 'Positie', - }, - CategoryFilters: { - results: 'resultaten voor {phrase}', - products: '{totalCount} producten', - }, - ProductCard: { - asLowAs: 'Slechts {discountPrice}', - startingAt: 'Vanaf {productPrice}', - bundlePrice: 'Van {fromBundlePrice} tot {toBundlePrice}', - from: 'Vanaf {productPrice}', - }, - ProductContainers: { - minquery: - 'Je zoekterm {variables.phrase} bevat niet het minimumaantal van {minQueryLength} tekens.', - noresults: 'Geen resultaten gevonden voor je zoekopdracht.', - pagePicker: '{pageSize} weergeven per pagina', - showAll: 'alles', - }, - SearchBar: { - placeholder: 'Zoeken...', - }, + Filter: { + title: "Filters", + showTitle: "Filters weergeven", + hideTitle: "Filters verbergen", + clearAll: "Alles wissen", + }, + InputButtonGroup: { + title: "Categorieën", + price: "Prijs", + customPrice: "Aangepaste prijs", + priceIncluded: "ja", + priceExcluded: "nee", + priceExcludedMessage: "Niet {title}", + priceRange: " en meer", + showmore: "Meer tonen", + }, + Loading: { + title: "Laden", + }, + NoResults: { + heading: "Geen resultaten voor je zoekopdracht.", + subheading: "Probeer het opnieuw...", + }, + SortDropdown: { + title: "Sorteren op", + option: "Sorteren op: {selectedOption}", + relevanceLabel: "Meest relevant", + positionLabel: "Positie", + }, + CategoryFilters: { + results: "resultaten voor {phrase}", + products: "{totalCount} producten", + }, + ProductCard: { + asLowAs: "Slechts {discountPrice}", + startingAt: "Vanaf {productPrice}", + bundlePrice: "Van {fromBundlePrice} tot {toBundlePrice}", + from: "Vanaf {productPrice}", + }, + ProductContainers: { + minquery: "Je zoekterm {variables.phrase} bevat niet het minimumaantal van {minQueryLength} tekens.", + noresults: "Geen resultaten gevonden voor je zoekopdracht.", + pagePicker: "{pageSize} weergeven per pagina", + showAll: "alles", + }, + SearchBar: { + placeholder: "Zoeken...", + }, }; diff --git a/src/i18n/pt_BR.ts b/src/i18n/pt_BR.ts index 368eeab..69bda21 100644 --- a/src/i18n/pt_BR.ts +++ b/src/i18n/pt_BR.ts @@ -8,53 +8,52 @@ it. */ export const pt_BR = { - Filter: { - title: 'Filtros', - showTitle: 'Mostrar filtros', - hideTitle: 'Ocultar filtros', - clearAll: 'Limpar tudo', - }, - InputButtonGroup: { - title: 'Categorias', - price: 'Preço', - customPrice: 'Preço personalizado', - priceIncluded: 'sim', - priceExcluded: 'não', - priceExcludedMessage: 'Não {title}', - priceRange: ' e acima', - showmore: 'Mostrar mais', - }, - Loading: { - title: 'Carregando', - }, - NoResults: { - heading: 'Nenhum resultado para sua busca.', - subheading: 'Tente novamente...', - }, - SortDropdown: { - title: 'Classificar por', - option: 'Classificar por: {selectedOption}', - relevanceLabel: 'Mais relevantes', - positionLabel: 'Posição', - }, - CategoryFilters: { - results: 'resultados para {phrase}', - products: '{totalCount} produtos', - }, - ProductCard: { - asLowAs: 'Por apenas {discountPrice}', - startingAt: 'A partir de {productPrice}', - bundlePrice: 'De {fromBundlePrice} por {toBundlePrice}', - from: 'De {productPrice}', - }, - ProductContainers: { - minquery: - 'Seu termo de pesquisa {variables.phrase} não atingiu o mínimo de {minQueryLength} caracteres.', - noresults: 'Sua busca não retornou resultados.', - pagePicker: 'Mostrar {pageSize} por página', - showAll: 'tudo', - }, - SearchBar: { - placeholder: 'Pesquisar...', - }, + Filter: { + title: "Filtros", + showTitle: "Mostrar filtros", + hideTitle: "Ocultar filtros", + clearAll: "Limpar tudo", + }, + InputButtonGroup: { + title: "Categorias", + price: "Preço", + customPrice: "Preço personalizado", + priceIncluded: "sim", + priceExcluded: "não", + priceExcludedMessage: "Não {title}", + priceRange: " e acima", + showmore: "Mostrar mais", + }, + Loading: { + title: "Carregando", + }, + NoResults: { + heading: "Nenhum resultado para sua busca.", + subheading: "Tente novamente...", + }, + SortDropdown: { + title: "Classificar por", + option: "Classificar por: {selectedOption}", + relevanceLabel: "Mais relevantes", + positionLabel: "Posição", + }, + CategoryFilters: { + results: "resultados para {phrase}", + products: "{totalCount} produtos", + }, + ProductCard: { + asLowAs: "Por apenas {discountPrice}", + startingAt: "A partir de {productPrice}", + bundlePrice: "De {fromBundlePrice} por {toBundlePrice}", + from: "De {productPrice}", + }, + ProductContainers: { + minquery: "Seu termo de pesquisa {variables.phrase} não atingiu o mínimo de {minQueryLength} caracteres.", + noresults: "Sua busca não retornou resultados.", + pagePicker: "Mostrar {pageSize} por página", + showAll: "tudo", + }, + SearchBar: { + placeholder: "Pesquisar...", + }, }; diff --git a/src/i18n/pt_PT.ts b/src/i18n/pt_PT.ts index 9cae2e3..385f682 100644 --- a/src/i18n/pt_PT.ts +++ b/src/i18n/pt_PT.ts @@ -8,53 +8,52 @@ it. */ export const pt_PT = { - Filter: { - title: 'Filtros', - showTitle: 'Mostrar filtros', - hideTitle: 'Ocultar filtros', - clearAll: 'Limpar tudo', - }, - InputButtonGroup: { - title: 'Categorias', - price: 'Preço', - customPrice: 'Preço Personalizado', - priceIncluded: 'sim', - priceExcluded: 'não', - priceExcludedMessage: 'Não {title}', - priceRange: ' e acima', - showmore: 'Mostrar mais', - }, - Loading: { - title: 'A carregar', - }, - NoResults: { - heading: 'Não existem resultados para a sua pesquisa.', - subheading: 'Tente novamente...', - }, - SortDropdown: { - title: 'Ordenar por', - option: 'Ordenar por: {selectedOption}', - relevanceLabel: 'Mais Relevantes', - positionLabel: 'Posição', - }, - CategoryFilters: { - results: 'resultados para {phrase}', - products: '{totalCount} produtos', - }, - ProductCard: { - asLowAs: 'A partir de {discountPrice}', - startingAt: 'A partir de {productPrice}', - bundlePrice: 'De {fromBundlePrice} a {toBundlePrice}', - from: 'A partir de {productPrice}', - }, - ProductContainers: { - minquery: - 'O seu termo de pesquisa {variables.phrase} não atingiu o mínimo de {minQueryLength} carateres.', - noresults: 'A sua pesquisa não devolveu resultados.', - pagePicker: 'Mostrar {pageSize} por página', - showAll: 'tudo', - }, - SearchBar: { - placeholder: 'Procurar...', - }, + Filter: { + title: "Filtros", + showTitle: "Mostrar filtros", + hideTitle: "Ocultar filtros", + clearAll: "Limpar tudo", + }, + InputButtonGroup: { + title: "Categorias", + price: "Preço", + customPrice: "Preço Personalizado", + priceIncluded: "sim", + priceExcluded: "não", + priceExcludedMessage: "Não {title}", + priceRange: " e acima", + showmore: "Mostrar mais", + }, + Loading: { + title: "A carregar", + }, + NoResults: { + heading: "Não existem resultados para a sua pesquisa.", + subheading: "Tente novamente...", + }, + SortDropdown: { + title: "Ordenar por", + option: "Ordenar por: {selectedOption}", + relevanceLabel: "Mais Relevantes", + positionLabel: "Posição", + }, + CategoryFilters: { + results: "resultados para {phrase}", + products: "{totalCount} produtos", + }, + ProductCard: { + asLowAs: "A partir de {discountPrice}", + startingAt: "A partir de {productPrice}", + bundlePrice: "De {fromBundlePrice} a {toBundlePrice}", + from: "A partir de {productPrice}", + }, + ProductContainers: { + minquery: "O seu termo de pesquisa {variables.phrase} não atingiu o mínimo de {minQueryLength} carateres.", + noresults: "A sua pesquisa não devolveu resultados.", + pagePicker: "Mostrar {pageSize} por página", + showAll: "tudo", + }, + SearchBar: { + placeholder: "Procurar...", + }, }; diff --git a/src/i18n/ro_RO.ts b/src/i18n/ro_RO.ts index 795f370..cab72e6 100644 --- a/src/i18n/ro_RO.ts +++ b/src/i18n/ro_RO.ts @@ -8,53 +8,52 @@ it. */ export const ro_RO = { - Filter: { - title: 'Filtre', - showTitle: 'Afișați filtrele', - hideTitle: 'Ascundeți filtrele', - clearAll: 'Ștergeți tot', - }, - InputButtonGroup: { - title: 'Categorii', - price: 'Preț', - customPrice: 'Preț personalizat', - priceIncluded: 'da', - priceExcluded: 'nu', - priceExcludedMessage: 'Fără {title}', - priceRange: ' și mai mult', - showmore: 'Afișați mai multe', - }, - Loading: { - title: 'Se încarcă', - }, - NoResults: { - heading: 'Niciun rezultat pentru căutarea dvs.', - subheading: 'Încercați din nou...', - }, - SortDropdown: { - title: 'Sortați după', - option: 'Sortați după: {selectedOption}', - relevanceLabel: 'Cele mai relevante', - positionLabel: 'Poziție', - }, - CategoryFilters: { - results: 'rezultate pentru {phrase}', - products: '{totalCount} produse', - }, - ProductCard: { - asLowAs: 'Preț redus până la {discountPrice}', - startingAt: 'Începând de la {productPrice}', - bundlePrice: 'De la {fromBundlePrice} la {toBundlePrice}', - from: 'De la {productPrice}', - }, - ProductContainers: { - minquery: - 'Termenul căutat {variables.phrase} nu a atins numărul minim de {minQueryLength} caractere.', - noresults: 'Nu există rezultate pentru căutarea dvs.', - pagePicker: 'Afișați {pageSize} per pagină', - showAll: 'toate', - }, - SearchBar: { - placeholder: 'Căutare...', - }, + Filter: { + title: "Filtre", + showTitle: "Afișați filtrele", + hideTitle: "Ascundeți filtrele", + clearAll: "Ștergeți tot", + }, + InputButtonGroup: { + title: "Categorii", + price: "Preț", + customPrice: "Preț personalizat", + priceIncluded: "da", + priceExcluded: "nu", + priceExcludedMessage: "Fără {title}", + priceRange: " și mai mult", + showmore: "Afișați mai multe", + }, + Loading: { + title: "Se încarcă", + }, + NoResults: { + heading: "Niciun rezultat pentru căutarea dvs.", + subheading: "Încercați din nou...", + }, + SortDropdown: { + title: "Sortați după", + option: "Sortați după: {selectedOption}", + relevanceLabel: "Cele mai relevante", + positionLabel: "Poziție", + }, + CategoryFilters: { + results: "rezultate pentru {phrase}", + products: "{totalCount} produse", + }, + ProductCard: { + asLowAs: "Preț redus până la {discountPrice}", + startingAt: "Începând de la {productPrice}", + bundlePrice: "De la {fromBundlePrice} la {toBundlePrice}", + from: "De la {productPrice}", + }, + ProductContainers: { + minquery: "Termenul căutat {variables.phrase} nu a atins numărul minim de {minQueryLength} caractere.", + noresults: "Nu există rezultate pentru căutarea dvs.", + pagePicker: "Afișați {pageSize} per pagină", + showAll: "toate", + }, + SearchBar: { + placeholder: "Căutare...", + }, }; diff --git a/src/i18n/ru_RU.ts b/src/i18n/ru_RU.ts index 96b5f4b..6399910 100644 --- a/src/i18n/ru_RU.ts +++ b/src/i18n/ru_RU.ts @@ -8,53 +8,52 @@ it. */ export const ru_RU = { - Filter: { - title: 'Фильтры', - showTitle: 'Показать фильтры', - hideTitle: 'Скрыть фильтры', - clearAll: 'Очистить все', - }, - InputButtonGroup: { - title: 'Категории', - price: 'Цена', - customPrice: 'Индивидуальная цена', - priceIncluded: 'да', - priceExcluded: 'нет', - priceExcludedMessage: 'Нет {title}', - priceRange: ' и выше', - showmore: 'Показать еще', - }, - Loading: { - title: 'Загрузка', - }, - NoResults: { - heading: 'Нет результатов по вашему поисковому запросу.', - subheading: 'Повторите попытку...', - }, - SortDropdown: { - title: 'Сортировка по', - option: 'Сортировать по: {selectedOption}', - relevanceLabel: 'Самые подходящие', - positionLabel: 'Положение', - }, - CategoryFilters: { - results: 'Результаты по запросу «{phrase}»', - products: 'Продукты: {totalCount}', - }, - ProductCard: { - asLowAs: 'Всего за {discountPrice}', - startingAt: 'От {productPrice}', - bundlePrice: 'От {fromBundlePrice} до {toBundlePrice}', - from: 'От {productPrice}', - }, - ProductContainers: { - minquery: - 'Поисковый запрос «{variables.phrase}» содержит меньше {minQueryLength} символов.', - noresults: 'Нет результатов по вашему запросу.', - pagePicker: 'Показывать {pageSize} на странице', - showAll: 'все', - }, - SearchBar: { - placeholder: 'Поиск...', - }, + Filter: { + title: "Фильтры", + showTitle: "Показать фильтры", + hideTitle: "Скрыть фильтры", + clearAll: "Очистить все", + }, + InputButtonGroup: { + title: "Категории", + price: "Цена", + customPrice: "Индивидуальная цена", + priceIncluded: "да", + priceExcluded: "нет", + priceExcludedMessage: "Нет {title}", + priceRange: " и выше", + showmore: "Показать еще", + }, + Loading: { + title: "Загрузка", + }, + NoResults: { + heading: "Нет результатов по вашему поисковому запросу.", + subheading: "Повторите попытку...", + }, + SortDropdown: { + title: "Сортировка по", + option: "Сортировать по: {selectedOption}", + relevanceLabel: "Самые подходящие", + positionLabel: "Положение", + }, + CategoryFilters: { + results: "Результаты по запросу «{phrase}»", + products: "Продукты: {totalCount}", + }, + ProductCard: { + asLowAs: "Всего за {discountPrice}", + startingAt: "От {productPrice}", + bundlePrice: "От {fromBundlePrice} до {toBundlePrice}", + from: "От {productPrice}", + }, + ProductContainers: { + minquery: "Поисковый запрос «{variables.phrase}» содержит меньше {minQueryLength} символов.", + noresults: "Нет результатов по вашему запросу.", + pagePicker: "Показывать {pageSize} на странице", + showAll: "все", + }, + SearchBar: { + placeholder: "Поиск...", + }, }; diff --git a/src/i18n/sv_SE.ts b/src/i18n/sv_SE.ts index 9a64140..6e89720 100644 --- a/src/i18n/sv_SE.ts +++ b/src/i18n/sv_SE.ts @@ -8,53 +8,52 @@ it. */ export const sv_SE = { - Filter: { - title: 'Filter', - showTitle: 'Visa filter', - hideTitle: 'Dölj filter', - clearAll: 'Rensa allt', - }, - InputButtonGroup: { - title: 'Kategorier', - price: 'Pris', - customPrice: 'Anpassat pris', - priceIncluded: 'ja', - priceExcluded: 'nej', - priceExcludedMessage: 'Inte {title}', - priceRange: ' eller mer', - showmore: 'Visa mer', - }, - Loading: { - title: 'Läser in', - }, - NoResults: { - heading: 'Inga sökresultat.', - subheading: 'Försök igen …', - }, - SortDropdown: { - title: 'Sortera på', - option: 'Sortera på: {selectedOption}', - relevanceLabel: 'Mest relevant', - positionLabel: 'Position', - }, - CategoryFilters: { - results: 'resultat för {phrase}', - products: '{totalCount} produkter', - }, - ProductCard: { - asLowAs: 'Så lite som {discountPrice}', - startingAt: 'Från {productPrice}', - bundlePrice: 'Från {fromBundlePrice} till {toBundlePrice}', - from: 'Från {productPrice}', - }, - ProductContainers: { - minquery: - 'Din sökterm {variables.phrase} har inte nått upp till minimiantalet tecken, {minQueryLength}.', - noresults: 'Sökningen gav inget resultat.', - pagePicker: 'Visa {pageSize} per sida', - showAll: 'alla', - }, - SearchBar: { - placeholder: 'Sök …', - }, + Filter: { + title: "Filter", + showTitle: "Visa filter", + hideTitle: "Dölj filter", + clearAll: "Rensa allt", + }, + InputButtonGroup: { + title: "Kategorier", + price: "Pris", + customPrice: "Anpassat pris", + priceIncluded: "ja", + priceExcluded: "nej", + priceExcludedMessage: "Inte {title}", + priceRange: " eller mer", + showmore: "Visa mer", + }, + Loading: { + title: "Läser in", + }, + NoResults: { + heading: "Inga sökresultat.", + subheading: "Försök igen …", + }, + SortDropdown: { + title: "Sortera på", + option: "Sortera på: {selectedOption}", + relevanceLabel: "Mest relevant", + positionLabel: "Position", + }, + CategoryFilters: { + results: "resultat för {phrase}", + products: "{totalCount} produkter", + }, + ProductCard: { + asLowAs: "Så lite som {discountPrice}", + startingAt: "Från {productPrice}", + bundlePrice: "Från {fromBundlePrice} till {toBundlePrice}", + from: "Från {productPrice}", + }, + ProductContainers: { + minquery: "Din sökterm {variables.phrase} har inte nått upp till minimiantalet tecken, {minQueryLength}.", + noresults: "Sökningen gav inget resultat.", + pagePicker: "Visa {pageSize} per sida", + showAll: "alla", + }, + SearchBar: { + placeholder: "Sök …", + }, }; diff --git a/src/i18n/th_TH.ts b/src/i18n/th_TH.ts index 166a7cb..80887bd 100644 --- a/src/i18n/th_TH.ts +++ b/src/i18n/th_TH.ts @@ -8,53 +8,52 @@ it. */ export const th_TH = { - Filter: { - title: 'ตัวกรอง', - showTitle: 'แสดงตัวกรอง', - hideTitle: 'ซ่อนตัวกรอง', - clearAll: 'ล้างทั้งหมด', - }, - InputButtonGroup: { - title: 'หมวดหมู่', - price: 'ราคา', - customPrice: 'ปรับแต่งราคา', - priceIncluded: 'ใช่', - priceExcluded: 'ไม่', - priceExcludedMessage: 'ไม่ใช่ {title}', - priceRange: ' และสูงกว่า', - showmore: 'แสดงมากขึ้น', - }, - Loading: { - title: 'กำลังโหลด', - }, - NoResults: { - heading: 'ไม่มีผลลัพธ์สำหรับการค้นหาของคุณ', - subheading: 'โปรดลองอีกครั้ง...', - }, - SortDropdown: { - title: 'เรียงตาม', - option: 'เรียงตาม: {selectedOption}', - relevanceLabel: 'เกี่ยวข้องมากที่สุด', - positionLabel: 'ตำแหน่ง', - }, - CategoryFilters: { - results: 'ผลลัพธ์สำหรับ {phrase}', - products: '{totalCount} ผลิตภัณฑ์', - }, - ProductCard: { - asLowAs: 'ต่ำสุดที่ {discountPrice}', - startingAt: 'เริ่มต้นที่ {productPrice}', - bundlePrice: 'ตั้งแต่ {fromBundlePrice} ถึง {toBundlePrice}', - from: 'ตั้งแต่ {productPrice}', - }, - ProductContainers: { - minquery: - 'คำว่า {variables.phrase} ที่คุณใช้ค้นหายังมีจำนวนอักขระไม่ถึงจำนวนขั้นต่ำ {minQueryLength} อักขระ', - noresults: 'การค้นหาของคุณไม่มีผลลัพธ์', - pagePicker: 'แสดง {pageSize} ต่อหน้า', - showAll: 'ทั้งหมด', - }, - SearchBar: { - placeholder: 'ค้นหา...', - }, + Filter: { + title: "ตัวกรอง", + showTitle: "แสดงตัวกรอง", + hideTitle: "ซ่อนตัวกรอง", + clearAll: "ล้างทั้งหมด", + }, + InputButtonGroup: { + title: "หมวดหมู่", + price: "ราคา", + customPrice: "ปรับแต่งราคา", + priceIncluded: "ใช่", + priceExcluded: "ไม่", + priceExcludedMessage: "ไม่ใช่ {title}", + priceRange: " และสูงกว่า", + showmore: "แสดงมากขึ้น", + }, + Loading: { + title: "กำลังโหลด", + }, + NoResults: { + heading: "ไม่มีผลลัพธ์สำหรับการค้นหาของคุณ", + subheading: "โปรดลองอีกครั้ง...", + }, + SortDropdown: { + title: "เรียงตาม", + option: "เรียงตาม: {selectedOption}", + relevanceLabel: "เกี่ยวข้องมากที่สุด", + positionLabel: "ตำแหน่ง", + }, + CategoryFilters: { + results: "ผลลัพธ์สำหรับ {phrase}", + products: "{totalCount} ผลิตภัณฑ์", + }, + ProductCard: { + asLowAs: "ต่ำสุดที่ {discountPrice}", + startingAt: "เริ่มต้นที่ {productPrice}", + bundlePrice: "ตั้งแต่ {fromBundlePrice} ถึง {toBundlePrice}", + from: "ตั้งแต่ {productPrice}", + }, + ProductContainers: { + minquery: "คำว่า {variables.phrase} ที่คุณใช้ค้นหายังมีจำนวนอักขระไม่ถึงจำนวนขั้นต่ำ {minQueryLength} อักขระ", + noresults: "การค้นหาของคุณไม่มีผลลัพธ์", + pagePicker: "แสดง {pageSize} ต่อหน้า", + showAll: "ทั้งหมด", + }, + SearchBar: { + placeholder: "ค้นหา...", + }, }; diff --git a/src/i18n/tr_TR.ts b/src/i18n/tr_TR.ts index 6be519c..72242ea 100644 --- a/src/i18n/tr_TR.ts +++ b/src/i18n/tr_TR.ts @@ -8,53 +8,52 @@ it. */ export const tr_TR = { - Filter: { - title: 'Filtreler', - showTitle: 'Filtreleri göster', - hideTitle: 'Filtreleri gizle', - clearAll: 'Tümünü temizle', - }, - InputButtonGroup: { - title: 'Kategoriler', - price: 'Fiyat', - customPrice: 'Özel Fiyat', - priceIncluded: 'evet', - priceExcluded: 'hayır', - priceExcludedMessage: 'Hariç: {title}', - priceRange: ' ve üzeri', - showmore: 'Diğerlerini göster', - }, - Loading: { - title: 'Yükleniyor', - }, - NoResults: { - heading: 'Aramanız hiç sonuç döndürmedi', - subheading: 'Lütfen tekrar deneyin...', - }, - SortDropdown: { - title: 'Sırala', - option: 'Sıralama ölçütü: {selectedOption}', - relevanceLabel: 'En Çok İlişkili', - positionLabel: 'Konum', - }, - CategoryFilters: { - results: '{phrase} için sonuçlar', - products: '{totalCount} ürün', - }, - ProductCard: { - asLowAs: 'En düşük: {discountPrice}', - startingAt: 'Başlangıç fiyatı: {productPrice}', - bundlePrice: '{fromBundlePrice} - {toBundlePrice} arası', - from: 'Başlangıç: {productPrice}', - }, - ProductContainers: { - minquery: - 'Arama teriminiz ({variables.phrase}) minimum {minQueryLength} karakter sınırlamasından daha kısa.', - noresults: 'Aramanız hiç sonuç döndürmedi.', - pagePicker: 'Sayfa başına {pageSize} göster', - showAll: 'tümü', - }, - SearchBar: { - placeholder: 'Ara...', - }, + Filter: { + title: "Filtreler", + showTitle: "Filtreleri göster", + hideTitle: "Filtreleri gizle", + clearAll: "Tümünü temizle", + }, + InputButtonGroup: { + title: "Kategoriler", + price: "Fiyat", + customPrice: "Özel Fiyat", + priceIncluded: "evet", + priceExcluded: "hayır", + priceExcludedMessage: "Hariç: {title}", + priceRange: " ve üzeri", + showmore: "Diğerlerini göster", + }, + Loading: { + title: "Yükleniyor", + }, + NoResults: { + heading: "Aramanız hiç sonuç döndürmedi", + subheading: "Lütfen tekrar deneyin...", + }, + SortDropdown: { + title: "Sırala", + option: "Sıralama ölçütü: {selectedOption}", + relevanceLabel: "En Çok İlişkili", + positionLabel: "Konum", + }, + CategoryFilters: { + results: "{phrase} için sonuçlar", + products: "{totalCount} ürün", + }, + ProductCard: { + asLowAs: "En düşük: {discountPrice}", + startingAt: "Başlangıç fiyatı: {productPrice}", + bundlePrice: "{fromBundlePrice} - {toBundlePrice} arası", + from: "Başlangıç: {productPrice}", + }, + ProductContainers: { + minquery: "Arama teriminiz ({variables.phrase}) minimum {minQueryLength} karakter sınırlamasından daha kısa.", + noresults: "Aramanız hiç sonuç döndürmedi.", + pagePicker: "Sayfa başına {pageSize} göster", + showAll: "tümü", + }, + SearchBar: { + placeholder: "Ara...", + }, }; diff --git a/src/i18n/zh_Hans_CN.ts b/src/i18n/zh_Hans_CN.ts index a82debb..9dfb985 100644 --- a/src/i18n/zh_Hans_CN.ts +++ b/src/i18n/zh_Hans_CN.ts @@ -8,53 +8,52 @@ it. */ export const zh_Hans_CN = { - Filter: { - title: '筛选条件', - showTitle: '显示筛选条件', - hideTitle: '隐藏筛选条件', - clearAll: '全部清除', - }, - InputButtonGroup: { - title: '类别', - price: '价格', - customPrice: '自定义价格', - priceIncluded: '是', - priceExcluded: '否', - priceExcludedMessage: '不是 {title}', - priceRange: ' 及以上', - showmore: '显示更多', - }, - Loading: { - title: '正在加载', - }, - NoResults: { - heading: '无搜索结果。', - subheading: '请重试...', - }, - SortDropdown: { - title: '排序依据', - option: '排序依据:{selectedOption}', - relevanceLabel: '最相关', - positionLabel: '位置', - }, - CategoryFilters: { - results: '{phrase} 的结果', - products: '{totalCount} 个产品', - }, - ProductCard: { - asLowAs: '低至 {discountPrice}', - startingAt: '起价为 {productPrice}', - bundlePrice: '从 {fromBundlePrice} 到 {toBundlePrice}', - from: '从 {productPrice} 起', - }, - ProductContainers: { - minquery: - '您的搜索词 {variables.phrase} 尚未达到最少 {minQueryLength} 个字符这一要求。', - noresults: '您的搜索未返回任何结果。', - pagePicker: '每页显示 {pageSize} 项', - showAll: '全部', - }, - SearchBar: { - placeholder: '搜索...', - }, + Filter: { + title: "筛选条件", + showTitle: "显示筛选条件", + hideTitle: "隐藏筛选条件", + clearAll: "全部清除", + }, + InputButtonGroup: { + title: "类别", + price: "价格", + customPrice: "自定义价格", + priceIncluded: "是", + priceExcluded: "否", + priceExcludedMessage: "不是 {title}", + priceRange: " 及以上", + showmore: "显示更多", + }, + Loading: { + title: "正在加载", + }, + NoResults: { + heading: "无搜索结果。", + subheading: "请重试...", + }, + SortDropdown: { + title: "排序依据", + option: "排序依据:{selectedOption}", + relevanceLabel: "最相关", + positionLabel: "位置", + }, + CategoryFilters: { + results: "{phrase} 的结果", + products: "{totalCount} 个产品", + }, + ProductCard: { + asLowAs: "低至 {discountPrice}", + startingAt: "起价为 {productPrice}", + bundlePrice: "从 {fromBundlePrice} 到 {toBundlePrice}", + from: "从 {productPrice} 起", + }, + ProductContainers: { + minquery: "您的搜索词 {variables.phrase} 尚未达到最少 {minQueryLength} 个字符这一要求。", + noresults: "您的搜索未返回任何结果。", + pagePicker: "每页显示 {pageSize} 项", + showAll: "全部", + }, + SearchBar: { + placeholder: "搜索...", + }, }; diff --git a/src/i18n/zh_Hant_TW.ts b/src/i18n/zh_Hant_TW.ts index 00c3680..cac947a 100644 --- a/src/i18n/zh_Hant_TW.ts +++ b/src/i18n/zh_Hant_TW.ts @@ -8,53 +8,52 @@ it. */ export const zh_Hant_TW = { - Filter: { - title: '篩選器', - showTitle: '顯示篩選器', - hideTitle: '隱藏篩選器', - clearAll: '全部清除', - }, - InputButtonGroup: { - title: '類別', - price: '價格', - customPrice: '自訂價格', - priceIncluded: '是', - priceExcluded: '否', - priceExcludedMessage: '不是 {title}', - priceRange: ' 以上', - showmore: '顯示更多', - }, - Loading: { - title: '載入中', - }, - NoResults: { - heading: '沒有符合搜尋的結果。', - subheading: '請再試一次…', - }, - SortDropdown: { - title: '排序依據', - option: '排序方式:{selectedOption}', - relevanceLabel: '最相關', - positionLabel: '位置', - }, - CategoryFilters: { - results: '{phrase} 的結果', - products: '{totalCount} 個產品', - }, - ProductCard: { - asLowAs: '低至 {discountPrice}', - startingAt: '起價為 {productPrice}', - bundlePrice: '從 {fromBundlePrice} 到 {toBundlePrice}', - from: '起價為 {productPrice}', - }, - ProductContainers: { - minquery: - '您的搜尋字詞 {variables.phrase} 未達到最少 {minQueryLength} 個字元。', - noresults: '您的搜尋未傳回任何結果。', - pagePicker: '顯示每頁 {pageSize}', - showAll: '全部', - }, - SearchBar: { - placeholder: '搜尋…', - }, + Filter: { + title: "篩選器", + showTitle: "顯示篩選器", + hideTitle: "隱藏篩選器", + clearAll: "全部清除", + }, + InputButtonGroup: { + title: "類別", + price: "價格", + customPrice: "自訂價格", + priceIncluded: "是", + priceExcluded: "否", + priceExcludedMessage: "不是 {title}", + priceRange: " 以上", + showmore: "顯示更多", + }, + Loading: { + title: "載入中", + }, + NoResults: { + heading: "沒有符合搜尋的結果。", + subheading: "請再試一次…", + }, + SortDropdown: { + title: "排序依據", + option: "排序方式:{selectedOption}", + relevanceLabel: "最相關", + positionLabel: "位置", + }, + CategoryFilters: { + results: "{phrase} 的結果", + products: "{totalCount} 個產品", + }, + ProductCard: { + asLowAs: "低至 {discountPrice}", + startingAt: "起價為 {productPrice}", + bundlePrice: "從 {fromBundlePrice} 到 {toBundlePrice}", + from: "起價為 {productPrice}", + }, + ProductContainers: { + minquery: "您的搜尋字詞 {variables.phrase} 未達到最少 {minQueryLength} 個字元。", + noresults: "您的搜尋未傳回任何結果。", + pagePicker: "顯示每頁 {pageSize}", + showAll: "全部", + }, + SearchBar: { + placeholder: "搜尋…", + }, }; diff --git a/src/index.tsx b/src/index.tsx index 930a594..ecd4b0f 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -7,67 +7,67 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { render } from 'preact'; +import { render } from "preact"; -import './styles/index.css'; +import "./styles/index.css"; -import { getUserViewHistory } from '../src/utils/getUserViewHistory'; -import App from './containers/App'; +import { getUserViewHistory } from "../src/utils/getUserViewHistory"; +import App from "./containers/App"; import { - AttributeMetadataProvider, - CartProvider, - ProductsContextProvider, - SearchProvider, - StoreContextProvider, - StoreDetailsProps, -} from './context/'; -import Resize from './context/displayChange'; -import Translation from './context/translation'; -import { validateStoreDetailsKeys } from './utils/validateStoreDetails'; + AttributeMetadataProvider, + CartProvider, + ProductsContextProvider, + SearchProvider, + StoreContextProvider, + StoreDetailsProps, +} from "./context/"; +import Resize from "./context/displayChange"; +import Translation from "./context/translation"; +import { validateStoreDetailsKeys } from "./utils/validateStoreDetails"; type MountSearchPlpProps = { - storeDetails: StoreDetailsProps; - root: HTMLElement; + storeDetails: StoreDetailsProps; + root: HTMLElement; }; const LiveSearchPLP = ({ storeDetails, root }: MountSearchPlpProps) => { - if (!storeDetails) { - throw new Error("Livesearch PLP's storeDetails prop was not provided"); - } - if (!root) { - throw new Error("Livesearch PLP's Root prop was not provided"); - } + if (!storeDetails) { + throw new Error("Livesearch PLP's storeDetails prop was not provided"); + } + if (!root) { + throw new Error("Livesearch PLP's Root prop was not provided"); + } - const userViewHistory = getUserViewHistory(); + const userViewHistory = getUserViewHistory(); - const updatedStoreDetails: StoreDetailsProps = { - ...storeDetails, - context: { - ...storeDetails.context, - userViewHistory, - }, - }; + const updatedStoreDetails: StoreDetailsProps = { + ...storeDetails, + context: { + ...storeDetails.context, + userViewHistory, + }, + }; - render( - - - - - - - - - - - - - - - , - root - ); + render( + + + + + + + + + + + + + + + , + root, + ); }; -if (typeof window !== 'undefined' && !window.LiveSearchPLP) { - window.LiveSearchPLP = LiveSearchPLP; +if (typeof window !== "undefined" && !window.LiveSearchPLP) { + window.LiveSearchPLP = LiveSearchPLP; } diff --git a/src/main.tsx b/src/main.tsx index ad82a27..c3c434f 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -19,9 +19,11 @@ const env = import.meta.env; mse.context.setMagentoExtension({ magentoExtensionVersion: "1.0.0", }); + mse.context.setSearchExtension({ version: "2.0.3", }); + mse.context.setShopper({ shopperId: "logged-in" }); mse.context.setPage({ @@ -50,7 +52,7 @@ mse.context.setStorefrontInstance({ storeViewName: env.CONFIG_STORE_VIEW_NAME ?? "", baseCurrencyCode: env.CONFIG_BASE_CURRENCY_CODE ?? "", storeViewCurrencyCode: env.CONFIG_STORE_VIEW_CURRENCY_CODE ?? "", - catalogExtensionVersion: '1.0.0', + catalogExtensionVersion: "1.0.0", }); // configure store details @@ -94,9 +96,9 @@ const storeDetails: StoreDetails = { // apiKey: "", // apiUrl: env.MODE === 'testing' ? TEST_URL : API_URL, // apiKey: env.MODE === "testing" && apiKey ? apiKey : env.VITE_SANDBOX_KEY, - // environmentType?.toLowerCase() === 'testing' && !apiKey - // ? SANDBOX_KEY - // : apiKey, + // environmentType?.toLowerCase() === 'testing' && !apiKey + // ? SANDBOX_KEY + // : apiKey, environmentType: env.MODE ?? "", // searchQuery: 'search_query', // Optional: providing searchQuery will override 'q' query param // route: ({ sku, urlKey }) => { diff --git a/src/types/custom.d.ts b/src/types/custom.d.ts index 568ac04..9e5df33 100644 --- a/src/types/custom.d.ts +++ b/src/types/custom.d.ts @@ -7,27 +7,27 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -declare module '*.svg' { - const content: any; - export default content; +declare module "*.svg" { + const content: any; + export default content; } -declare module '*.svg?inline' { - const content: any; - export default content; +declare module "*.svg?inline" { + const content: any; + export default content; } -declare module '*.jpg' { - const content: string; - export default content; +declare module "*.jpg" { + const content: string; + export default content; } -declare module '*.png' { - const content: string; - export default content; +declare module "*.png" { + const content: string; + export default content; } -declare module '*.json' { - const content: string; - export default content; +declare module "*.json" { + const content: string; + export default content; } diff --git a/src/types/globals.d.ts b/src/types/globals.d.ts index 2b74853..cf441b4 100644 --- a/src/types/globals.d.ts +++ b/src/types/globals.d.ts @@ -7,22 +7,22 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { MagentoStorefrontEvents } from '@adobe/magento-storefront-events-sdk'; +import { MagentoStorefrontEvents } from "@adobe/magento-storefront-events-sdk"; export {}; declare global { - interface Window { - LiveSearchPLP: typeof import('../index'); - magentoStorefrontEvents: MagentoStorefrontEvents; - } - const Sentry: any; - const API_URL: string; - const WIDGET_CONFIG_URL: string; - const LS_API_URL: string; - const API_KEY: string; - const SANDBOX_KEY: string; - const TEST_URL: string; - const FLOODGATE_CLIENT_ID: string; - const FLOODGATE_API_KEY: string; + interface Window { + LiveSearchPLP: typeof import("../index"); + magentoStorefrontEvents: MagentoStorefrontEvents; + } + const Sentry: any; + const API_URL: string; + const WIDGET_CONFIG_URL: string; + const LS_API_URL: string; + const API_KEY: string; + const SANDBOX_KEY: string; + const TEST_URL: string; + const FLOODGATE_CLIENT_ID: string; + const FLOODGATE_API_KEY: string; } diff --git a/src/types/interface.ts b/src/types/interface.ts index 2acf7ac..d2c4c6f 100644 --- a/src/types/interface.ts +++ b/src/types/interface.ts @@ -9,456 +9,442 @@ it. // API Specific Types export interface RequestError { - message: string; - locations: Array<{ line: number; column: number }>; - path: Array; - extensions: { - errorMessage: string; - classification: string; - }; + message: string; + locations: Array<{ line: number; column: number }>; + path: Array; + extensions: { + errorMessage: string; + classification: string; + }; } export interface ClientProps { - apiUrl: string; - environmentId: string; - websiteCode: string; - storeCode: string; - storeViewCode: string; - apiKey: string; - xRequestId?: string; + apiUrl: string; + environmentId: string; + websiteCode: string; + storeCode: string; + storeViewCode: string; + apiKey: string; + xRequestId?: string; } export interface StoreDetailsConfig { - allowAllProducts?: string | boolean; - perPageConfig?: { pageSizeOptions?: string; defaultPageSizeOption?: string }; - minQueryLength?: string | number; // string if used on magento, number if used on data-service-graphql - pageSize?: number; - currencySymbol?: string; - currencyRate?: string; - currentCategoryUrlPath?: string; - categoryName?: string; - displaySearchBox?: boolean; - displayOutOfStock?: string | boolean; // "1" will return from php escapeJs and boolean is returned if called from data-service-graphql - displayMode?: string; - locale?: string; - priceSlider?: boolean; - imageCarousel?: boolean; - listview?: boolean; - optimizeImages?: boolean; - imageBaseWidth?: number; - resolveCartId?: () => Promise; - refreshCart?: () => void; - baseUrl?: string; // base URL for store view - addToCart?: ( - sku: string, - options: [], - quantity: number - ) => Promise; + allowAllProducts?: string | boolean; + perPageConfig?: { pageSizeOptions?: string; defaultPageSizeOption?: string }; + minQueryLength?: string | number; // string if used on magento, number if used on data-service-graphql + pageSize?: number; + currencySymbol?: string; + currencyRate?: string; + currentCategoryUrlPath?: string; + categoryName?: string; + displaySearchBox?: boolean; + displayOutOfStock?: string | boolean; // "1" will return from php escapeJs and boolean is returned if called from data-service-graphql + displayMode?: string; + locale?: string; + priceSlider?: boolean; + imageCarousel?: boolean; + listview?: boolean; + optimizeImages?: boolean; + imageBaseWidth?: number; + resolveCartId?: () => Promise; + refreshCart?: () => void; + baseUrl?: string; // base URL for store view + addToCart?: (sku: string, options: [], quantity: number) => Promise; } // Types -export type BucketTypename = - | 'ScalarBucket' - | 'RangeBucket' - | 'StatsBucket' - | 'CategoryView'; - -export type RedirectRouteFunc = ({ - sku, - urlKey, -}: { - sku: string; - urlKey: null | string; -}) => string; +export type BucketTypename = "ScalarBucket" | "RangeBucket" | "StatsBucket" | "CategoryView"; + +export type RedirectRouteFunc = ({ sku, urlKey }: { sku: string; urlKey: null | string }) => string; export interface MagentoHeaders { - environmentId: string; - websiteCode: string; - storeCode: string; - storeViewCode: string; - apiKey: string; - xRequestId: string; - customerGroup: string; + environmentId: string; + websiteCode: string; + storeCode: string; + storeViewCode: string; + apiKey: string; + xRequestId: string; + customerGroup: string; } export interface ProductSearchQuery { - phrase: string; - pageSize?: number; - currentPage?: number; - displayOutOfStock?: string | boolean; - filter?: SearchClauseInput[]; - sort?: ProductSearchSortInput[]; - xRequestId?: string; - context?: QueryContextInput; - data?: QueryData; - categorySearch?: boolean; + phrase: string; + pageSize?: number; + currentPage?: number; + displayOutOfStock?: string | boolean; + filter?: SearchClauseInput[]; + sort?: ProductSearchSortInput[]; + xRequestId?: string; + context?: QueryContextInput; + data?: QueryData; + categorySearch?: boolean; } export interface RefineProductQuery { - optionIds: string[]; - sku: string; - context?: QueryContextInput; + optionIds: string[]; + sku: string; + context?: QueryContextInput; } export type QueryResponse = Promise; export interface SearchClauseInput { - attribute: string; - in?: string[]; - eq?: string; - range?: { - from: number; - to: number; - }; + attribute: string; + in?: string[]; + eq?: string; + range?: { + from: number; + to: number; + }; } export interface ProductSearchSortInput { - attribute: string; - direction: 'ASC' | 'DESC'; + attribute: string; + direction: "ASC" | "DESC"; } export interface QueryContextInput { - customerGroup?: string; - userViewHistory?: { sku: string; dateTime: string }[]; + customerGroup?: string; + userViewHistory?: { sku: string; dateTime: string }[]; } export interface QueryData { - products: boolean; - facets: boolean; - suggestions: boolean; + products: boolean; + facets: boolean; + suggestions: boolean; } export type ProductSearchPromise = QueryResponse; export type AttributeMetadata = { - attribute: string; - label: string; - numeric: boolean; + attribute: string; + label: string; + numeric: boolean; }; export interface ProductSearchResponse { - extensions: { - 'request-id': string; - }; - data: { - productSearch: { - total_count: null | number; - items: null | Array; - facets: null | Array; - suggestions?: null | Array; - related_terms?: null | Array; - page_info: null | PageInfo; + extensions: { + "request-id": string; }; - attributeMetadata: { - sortable: AttributeMetadata[]; + data: { + productSearch: { + total_count: null | number; + items: null | Array; + facets: null | Array; + suggestions?: null | Array; + related_terms?: null | Array; + page_info: null | PageInfo; + }; + attributeMetadata: { + sortable: AttributeMetadata[]; + }; }; - }; - errors: Array; + errors: Array; } export interface AttributeMetadataResponse { - extensions: { - 'request-id': string; - }; - data: { - attributeMetadata: { - sortable: AttributeMetadata[]; - filterableInSearch: AttributeMetadata[]; + extensions: { + "request-id": string; + }; + data: { + attributeMetadata: { + sortable: AttributeMetadata[]; + filterableInSearch: AttributeMetadata[]; + }; }; - }; } export interface Product { - product: { - __typename: string; - id: number; - uid: string; - name: string; - sku: string; - description: null | ComplexTextValue; - short_description: null | ComplexTextValue; - attribute_set_id: null | number; - meta_title: null | string; - meta_keyword: null | string; - meta_description: null | string; - image: null | ProductMedia; - small_image: null | ProductMedia; - thumbnail: null | ProductMedia; - new_from_date: null | string; - new_to_date: null | string; - created_at: null | string; - updated_at: null | string; - price_range: { - minimum_price: ProductPrice; - maximum_price: ProductPrice; - }; - gift_message_available: null | string; - canonical_url: null | string; - media_gallery: null | ProductMedia; - custom_attributes: null | CustomAttribute; - add_to_cart_allowed: null | boolean; - }; - productView: { - __typename: string; - id: number; - uid: string; - name: string; - sku: string; - description: null | ComplexTextValue; - short_description: null | ComplexTextValue; - attribute_set_id: null | number; - meta_title: null | string; - meta_keyword: null | string; - meta_description: null | string; - images: null | ProductViewMedia[]; - new_from_date: null | string; - new_to_date: null | string; - created_at: null | string; - updated_at: null | string; - price: { - final: ProductViewPrice; - regular: ProductViewPrice; + product: { + __typename: string; + id: number; + uid: string; + name: string; + sku: string; + description: null | ComplexTextValue; + short_description: null | ComplexTextValue; + attribute_set_id: null | number; + meta_title: null | string; + meta_keyword: null | string; + meta_description: null | string; + image: null | ProductMedia; + small_image: null | ProductMedia; + thumbnail: null | ProductMedia; + new_from_date: null | string; + new_to_date: null | string; + created_at: null | string; + updated_at: null | string; + price_range: { + minimum_price: ProductPrice; + maximum_price: ProductPrice; + }; + gift_message_available: null | string; + canonical_url: null | string; + media_gallery: null | ProductMedia; + custom_attributes: null | CustomAttribute; + add_to_cart_allowed: null | boolean; }; - priceRange: { - minimum: { - final: ProductViewPrice; - regular: ProductViewPrice; - }; - maximum: { - final: ProductViewPrice; - regular: ProductViewPrice; - }; + productView: { + __typename: string; + id: number; + uid: string; + name: string; + sku: string; + description: null | ComplexTextValue; + short_description: null | ComplexTextValue; + attribute_set_id: null | number; + meta_title: null | string; + meta_keyword: null | string; + meta_description: null | string; + images: null | ProductViewMedia[]; + new_from_date: null | string; + new_to_date: null | string; + created_at: null | string; + updated_at: null | string; + price: { + final: ProductViewPrice; + regular: ProductViewPrice; + }; + priceRange: { + minimum: { + final: ProductViewPrice; + regular: ProductViewPrice; + }; + maximum: { + final: ProductViewPrice; + regular: ProductViewPrice; + }; + }; + gift_message_available: null | string; + url: null | string; + urlKey: null | string; + media_gallery: null | ProductViewMedia; + custom_attributes: null | CustomAttribute; + add_to_cart_allowed: null | boolean; + options: + | null + | { + id: null | string; + title: null | string; + values: null | SwatchValues[]; + }[]; }; - gift_message_available: null | string; - url: null | string; - urlKey: null | string; - media_gallery: null | ProductViewMedia; - custom_attributes: null | CustomAttribute; - add_to_cart_allowed: null | boolean; - options: - | null - | { - id: null | string; - title: null | string; - values: null | SwatchValues[]; - }[]; - }; - highlights: Array; + highlights: Array; } export interface RefinedProduct { - refineProduct: { - __typename: string; - id: number; - uid: string; - name: string; - sku: string; - description: null | ComplexTextValue; - short_description: null | ComplexTextValue; - attribute_set_id: null | number; - meta_title: null | string; - meta_keyword: null | string; - meta_description: null | string; - images: null | ProductViewMedia[]; - new_from_date: null | string; - new_to_date: null | string; - created_at: null | string; - updated_at: null | string; - price: { - final: ProductViewPrice; - regular: ProductViewPrice; - }; - priceRange: { - minimum: { - final: ProductViewPrice; - regular: ProductViewPrice; - }; - maximum: { - final: ProductViewPrice; - regular: ProductViewPrice; - }; + refineProduct: { + __typename: string; + id: number; + uid: string; + name: string; + sku: string; + description: null | ComplexTextValue; + short_description: null | ComplexTextValue; + attribute_set_id: null | number; + meta_title: null | string; + meta_keyword: null | string; + meta_description: null | string; + images: null | ProductViewMedia[]; + new_from_date: null | string; + new_to_date: null | string; + created_at: null | string; + updated_at: null | string; + price: { + final: ProductViewPrice; + regular: ProductViewPrice; + }; + priceRange: { + minimum: { + final: ProductViewPrice; + regular: ProductViewPrice; + }; + maximum: { + final: ProductViewPrice; + regular: ProductViewPrice; + }; + }; + gift_message_available: null | string; + url: null | string; + media_gallery: null | ProductViewMedia; + custom_attributes: null | CustomAttribute; + add_to_cart_allowed: null | boolean; + options: + | null + | { + id: null | string; + title: null | string; + values: null | SwatchValues[]; + }[]; }; - gift_message_available: null | string; - url: null | string; - media_gallery: null | ProductViewMedia; - custom_attributes: null | CustomAttribute; - add_to_cart_allowed: null | boolean; - options: - | null - | { - id: null | string; - title: null | string; - values: null | SwatchValues[]; - }[]; - }; - highlights: Array; + highlights: Array; } export interface ComplexTextValue { - html: string; + html: string; } export interface Money { - value: number; - currency: string; + value: number; + currency: string; } export interface ProductPrice { - fixed_product_taxes: null | { amount: Money; label: string }; - regular_price: Money; - final_price: Money; - discount: null | { percent_off: number; amount_off: number }; + fixed_product_taxes: null | { amount: Money; label: string }; + regular_price: Money; + final_price: Money; + discount: null | { percent_off: number; amount_off: number }; } export interface ProductViewPrice { - adjustments: null | { amount: number; code: string }; - amount: Money; + adjustments: null | { amount: number; code: string }; + amount: Money; } -type ImageRoles = 'image' | 'small_image' | 'thumbnail' | 'swatch_image'; +type ImageRoles = "image" | "small_image" | "thumbnail" | "swatch_image"; export interface ProductMedia { - url: null | string; - label: null | string; - position: null | number; - disabled: null | boolean; + url: null | string; + label: null | string; + position: null | number; + disabled: null | boolean; } export interface ProductViewMedia { - url: null | string; - label: null | string; - position: null | number; - disabled: null | boolean; - roles: ImageRoles[]; + url: null | string; + label: null | string; + position: null | number; + disabled: null | boolean; + roles: ImageRoles[]; } export interface SwatchValues { - title: string; - id: string; - type: string; - value: string; + title: string; + id: string; + type: string; + value: string; } export interface CustomAttribute { - code: string; - value: string; + code: string; + value: string; } export interface Highlights { - attribute: string; - value: string; - matched_words: Array; + attribute: string; + value: string; + matched_words: Array; } export interface PageInfo { - current_page: number; - page_size: number; - total_pages: number; + current_page: number; + page_size: number; + total_pages: number; } export interface Facet { - __typename?: BucketTypename; - title: string; - attribute: string; - type?: 'PINNED' | 'INTELLIGENT' | 'POPULAR'; - buckets: Array; + __typename?: BucketTypename; + title: string; + attribute: string; + type?: "PINNED" | "INTELLIGENT" | "POPULAR"; + buckets: Array; } export interface RangeBucket { - __typename: 'RangeBucket'; - title: string; - from: number; - to: number; - count: number; + __typename: "RangeBucket"; + title: string; + from: number; + to: number; + count: number; } export interface ScalarBucket { - __typename: 'ScalarBucket'; - title: string; - id?: string; - count: number; + __typename: "ScalarBucket"; + title: string; + id?: string; + count: number; } export interface StatsBucket { - __typename: 'StatsBucket'; - title: string; - min: number; - max: number; + __typename: "StatsBucket"; + title: string; + min: number; + max: number; } export interface CategoryView { - __typename: 'CategoryView'; - title: string; - name: string; - path: string; - count: number; + __typename: "CategoryView"; + title: string; + name: string; + path: string; + count: number; } export interface PriceFacet extends Facet { - buckets: RangeBucket[]; + buckets: RangeBucket[]; } export interface FacetFilter { - attribute: string; - in?: string[]; - eq?: string; - range?: { - from: number; - to: number; - }; + attribute: string; + in?: string[]; + eq?: string; + range?: { + from: number; + to: number; + }; } export interface FeatureFlags { - [key: string]: boolean; + [key: string]: boolean; } export interface PageSizeOption { - label: string; - value: number; + label: string; + value: number; } export interface SortMetadata { - label: string; - attribute: string; - numeric: boolean; + label: string; + attribute: string; + numeric: boolean; } export interface SortOption { - label: string; - value: string; + label: string; + value: string; } export interface GQLSortInput { - direction: 'ASC' | 'DESC'; - attribute: string; + direction: "ASC" | "DESC"; + attribute: string; } export interface WishlistItem { - id: string; - product: { - uid: string; - name: string; - sku: string; - }; + id: string; + product: { + uid: string; + name: string; + sku: string; + }; } export interface Wishlist { - id: string; - name: string; - items_count: number; - items_v2: { - items: WishlistItem[]; - }; + id: string; + name: string; + items_count: number; + items_v2: { + items: WishlistItem[]; + }; } export interface WishlistResponse { - wishlists: Array; + wishlists: Array; } export interface WishlistAddItemInput { - quantity: number; - sku: string; - parent_sku?: string; - selected_options?: string[]; + quantity: number; + sku: string; + parent_sku?: string; + selected_options?: string[]; } -export { type WidgetConfigOptions } from './widget'; +export { type WidgetConfigOptions } from "./widget"; diff --git a/src/types/widget.ts b/src/types/widget.ts index 712300e..094e7f4 100644 --- a/src/types/widget.ts +++ b/src/types/widget.ts @@ -9,87 +9,87 @@ it. // Widget Configuration Options Specific Types export interface WidgetConfigOptions { - // pageSize: number; // TODO: phase-2 MSRCH-4164 - // minQueryLength: number; // TODO: phase-2 MSRCH-4164 - // currencySymbol: string; // TODO: phase-2 MSRCH-4164 - // currencyRate: number; // TODO: phase-2 MSRCH-4164 - // displayOutOfStock: boolean; // TODO: phase-2 MSRCH-4164 - // allowAllProducts: boolean; // TODO: phase-2 MSRCH-4164 - badge: Badge; - price: Price; - attributeSlot: AttributeSlot; - addToWishlist: AddToWishlist; - layout: Layout; - addToCart: AddToCart; - stockStatusFilterLook: StockStatusFilterLook; - swatches: Swatches; - multipleImages: MultipleImages; - compare: Compare; + // pageSize: number; // TODO: phase-2 MSRCH-4164 + // minQueryLength: number; // TODO: phase-2 MSRCH-4164 + // currencySymbol: string; // TODO: phase-2 MSRCH-4164 + // currencyRate: number; // TODO: phase-2 MSRCH-4164 + // displayOutOfStock: boolean; // TODO: phase-2 MSRCH-4164 + // allowAllProducts: boolean; // TODO: phase-2 MSRCH-4164 + badge: Badge; + price: Price; + attributeSlot: AttributeSlot; + addToWishlist: AddToWishlist; + layout: Layout; + addToCart: AddToCart; + stockStatusFilterLook: StockStatusFilterLook; + swatches: Swatches; + multipleImages: MultipleImages; + compare: Compare; } type Badge = { - enabled: boolean; - label: string; - attributeCode: string; - backgroundColor: string; + enabled: boolean; + label: string; + attributeCode: string; + backgroundColor: string; }; type Price = { - showNoPrice: boolean; - showRange: boolean; - showRegularPrice: boolean; - showStrikethruPrice: boolean; + showNoPrice: boolean; + showRange: boolean; + showRegularPrice: boolean; + showStrikethruPrice: boolean; }; type AttributeSlot = { - enabled: boolean; - attributeCode: string; - backgroundColor: string; + enabled: boolean; + attributeCode: string; + backgroundColor: string; }; type AddToWishlist = { - enabled: boolean; - placement: AddToWishlistPlacement; + enabled: boolean; + placement: AddToWishlistPlacement; }; export type AddToWishlistPlacement = - | 'inLineWithName' // default - | 'onCard'; + | "inLineWithName" // default + | "onCard"; type Layout = { - defaultLayout: LayoutType; - allowedLayouts: LayoutType[]; - showToggle: boolean; + defaultLayout: LayoutType; + allowedLayouts: LayoutType[]; + showToggle: boolean; }; type LayoutType = - | 'grid' // default - | 'list'; + | "grid" // default + | "list"; type AddToCart = { - enabled: boolean; + enabled: boolean; }; -type StockStatusFilterLook = 'radio' | 'checkbox' | 'toggle'; +type StockStatusFilterLook = "radio" | "checkbox" | "toggle"; type Swatches = { - enabled: boolean; - swatchAttributes: SwatchAttribute[]; - swatchesOnPage: number; + enabled: boolean; + swatchAttributes: SwatchAttribute[]; + swatchesOnPage: number; }; type SwatchAttribute = { - attributeCode: string; - swatchType: SwatchAttributeType; + attributeCode: string; + swatchType: SwatchAttributeType; }; -type SwatchAttributeType = 'color' | 'size'; +type SwatchAttributeType = "color" | "size"; type MultipleImages = { - enabled: boolean; - limit: number; + enabled: boolean; + limit: number; }; type Compare = { - enabled: boolean; + enabled: boolean; }; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 4c47b2e..7eb91a7 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -7,24 +7,20 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { ProductSearchSortInput } from '@/types/interface'; +import { ProductSearchSortInput } from "@/types/interface"; export const DEFAULT_PAGE_SIZE = 24; -export const DEFAULT_PAGE_SIZE_OPTIONS = '12,24,36'; +export const DEFAULT_PAGE_SIZE_OPTIONS = "12,24,36"; export const DEFAULT_MIN_QUERY_LENGTH = 3; export const PRODUCT_COLUMNS = { - desktop: 4, - tablet: 3, - mobile: 2, + desktop: 4, + tablet: 3, + mobile: 2, }; -export const SEARCH_SORT_DEFAULT: ProductSearchSortInput[] = [ - { attribute: 'relevance', direction: 'DESC' }, -]; -export const CATEGORY_SORT_DEFAULT: ProductSearchSortInput[] = [ - { attribute: 'position', direction: 'ASC' }, -]; +export const SEARCH_SORT_DEFAULT: ProductSearchSortInput[] = [{ attribute: "relevance", direction: "DESC" }]; +export const CATEGORY_SORT_DEFAULT: ProductSearchSortInput[] = [{ attribute: "position", direction: "ASC" }]; -export const SEARCH_UNIT_ID = 'livesearch-plp'; -export const BOOLEAN_YES = 'yes'; -export const BOOLEAN_NO = 'no'; +export const SEARCH_UNIT_ID = "livesearch-plp"; +export const BOOLEAN_YES = "yes"; +export const BOOLEAN_NO = "no"; diff --git a/src/utils/decodeHtmlString.ts b/src/utils/decodeHtmlString.ts index fa93229..c0b72d8 100644 --- a/src/utils/decodeHtmlString.ts +++ b/src/utils/decodeHtmlString.ts @@ -8,8 +8,8 @@ it. */ const decodeHtmlString = (input: string): string | null => { - const doc = new DOMParser().parseFromString(input, 'text/html'); - return doc.documentElement.textContent; + const doc = new DOMParser().parseFromString(input, "text/html"); + return doc.documentElement.textContent; }; export { decodeHtmlString }; diff --git a/src/utils/dom.ts b/src/utils/dom.ts index c0def50..e97e31e 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -8,9 +8,9 @@ it. */ export const moveToTop = (): void => { - window.scrollTo({ top: 0 }); + window.scrollTo({ top: 0 }); }; export const classNames = (...classes: string[]) => { - return classes.filter(Boolean).join(' '); + return classes.filter(Boolean).join(" "); }; diff --git a/src/utils/getProductImage.ts b/src/utils/getProductImage.ts index 9ffa31b..9717c80 100644 --- a/src/utils/getProductImage.ts +++ b/src/utils/getProductImage.ts @@ -7,93 +7,83 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { ProductViewMedia } from '../types/interface'; - -const getProductImageURLs = ( - images: ProductViewMedia[], - amount: number = 3, - topImageUrl?: string -): string[] => { - const imageUrlArray: Array = []; - const url = new URL(window.location.href); - const protocol = url.protocol; - - // const topImageUrl = "http://master-7rqtwti-wdxwuaerh4gbm.eu-4.magentosite.cloud/media/catalog/product/3/1/31t0a-sopll._ac_.jpg"; - for (const image of images) { - const imageUrl = image.url?.replace(/^https?:\/\//, ''); - if (imageUrl) { - imageUrlArray.push(`${protocol}//${imageUrl}`); - } - } - - if (topImageUrl) { - const topImageUrlFormatted = `${protocol}//${topImageUrl.replace( - /^https?:\/\//, - '' - )}`; - const index = topImageUrlFormatted.indexOf(topImageUrlFormatted); - if (index > -1) { - imageUrlArray.splice(index, 1); +import { ProductViewMedia } from "../types/interface"; + +const getProductImageURLs = (images: ProductViewMedia[], amount: number = 3, topImageUrl?: string): string[] => { + const imageUrlArray: Array = []; + const url = new URL(window.location.href); + const protocol = url.protocol; + + // const topImageUrl = "http://master-7rqtwti-wdxwuaerh4gbm.eu-4.magentosite.cloud/media/catalog/product/3/1/31t0a-sopll._ac_.jpg"; + for (const image of images) { + const imageUrl = image.url?.replace(/^https?:\/\//, ""); + if (imageUrl) { + imageUrlArray.push(`${protocol}//${imageUrl}`); + } } - imageUrlArray.unshift(topImageUrlFormatted); - } + if (topImageUrl) { + const topImageUrlFormatted = `${protocol}//${topImageUrl.replace(/^https?:\/\//, "")}`; + const index = topImageUrlFormatted.indexOf(topImageUrlFormatted); + if (index > -1) { + imageUrlArray.splice(index, 1); + } + + imageUrlArray.unshift(topImageUrlFormatted); + } - return imageUrlArray.slice(0, amount); + return imageUrlArray.slice(0, amount); }; export interface ResolveImageUrlOptions { - width: number; - height?: number; - auto?: string; - quality?: number; - crop?: boolean; - fit?: string; + width: number; + height?: number; + auto?: string; + quality?: number; + crop?: boolean; + fit?: string; } const resolveImageUrl = (url: string, opts: ResolveImageUrlOptions): string => { - const [base, query] = url.split('?'); - const params = new URLSearchParams(query); + const [base, query] = url.split("?"); + const params = new URLSearchParams(query); - Object.entries(opts).forEach(([key, value]) => { - if (value !== undefined && value !== null) { - params.set(key, String(value)); - } - }); + Object.entries(opts).forEach(([key, value]) => { + if (value !== undefined && value !== null) { + params.set(key, String(value)); + } + }); - return `${base}?${params.toString()}`; + return `${base}?${params.toString()}`; }; -const generateOptimizedImages = ( - imageUrls: string[], - baseImageWidth: number -): { src: string; srcset: any }[] => { - const baseOptions = { - fit: 'cover', - crop: false, - dpi: 1, - }; - - const imageUrlArray: Array<{ src: string; srcset: any }> = []; - - for (const imageUrl of imageUrls) { - const src = resolveImageUrl(imageUrl, { - ...baseOptions, - width: baseImageWidth, - }); - const dpiSet = [1, 2, 3]; - const srcset = dpiSet.map((dpi) => { - return `${resolveImageUrl(imageUrl, { - ...baseOptions, - auto: 'webp', - quality: 80, - width: baseImageWidth * dpi, - })} ${dpi}x`; - }); - imageUrlArray.push({ src, srcset }); - } +const generateOptimizedImages = (imageUrls: string[], baseImageWidth: number): { src: string; srcset: any }[] => { + const baseOptions = { + fit: "cover", + crop: false, + dpi: 1, + }; + + const imageUrlArray: Array<{ src: string; srcset: any }> = []; + + for (const imageUrl of imageUrls) { + const src = resolveImageUrl(imageUrl, { + ...baseOptions, + width: baseImageWidth, + }); + const dpiSet = [1, 2, 3]; + const srcset = dpiSet.map((dpi) => { + return `${resolveImageUrl(imageUrl, { + ...baseOptions, + auto: "webp", + quality: 80, + width: baseImageWidth * dpi, + })} ${dpi}x`; + }); + imageUrlArray.push({ src, srcset }); + } - return imageUrlArray; + return imageUrlArray; }; export { generateOptimizedImages, getProductImageURLs }; diff --git a/src/utils/getProductPrice.ts b/src/utils/getProductPrice.ts index 5ae52e9..3922f05 100644 --- a/src/utils/getProductPrice.ts +++ b/src/utils/getProductPrice.ts @@ -7,59 +7,55 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import getSymbolFromCurrency from 'currency-symbol-map'; +import getSymbolFromCurrency from "currency-symbol-map"; -import { Product, RefinedProduct } from '../types/interface'; +import { Product, RefinedProduct } from "../types/interface"; const getProductPrice = ( - product: Product | RefinedProduct, - currencySymbol: string, - currencyRate: string | undefined, - useMaximum = false, - useFinal = false + product: Product | RefinedProduct, + currencySymbol: string, + currencyRate: string | undefined, + useMaximum = false, + useFinal = false, ): string => { - let priceType; - let price; - if ('product' in product) { - priceType = product?.product?.price_range?.minimum_price; - - if (useMaximum) { - priceType = product?.product?.price_range?.maximum_price; - } - - price = priceType?.regular_price; - if (useFinal) { - price = priceType?.final_price; + let priceType; + let price; + if ("product" in product) { + priceType = product?.product?.price_range?.minimum_price; + + if (useMaximum) { + priceType = product?.product?.price_range?.maximum_price; + } + + price = priceType?.regular_price; + if (useFinal) { + price = priceType?.final_price; + } + } else { + priceType = product?.refineProduct?.priceRange?.minimum ?? product?.refineProduct?.price; + + if (useMaximum) { + priceType = product?.refineProduct?.priceRange?.maximum; + } + + price = priceType?.regular?.amount; + if (useFinal) { + price = priceType?.final?.amount; + } } - } else { - priceType = - product?.refineProduct?.priceRange?.minimum ?? - product?.refineProduct?.price; - if (useMaximum) { - priceType = product?.refineProduct?.priceRange?.maximum; - } + // if currency symbol is configurable within Commerce, that symbol is used + let currency = price?.currency; - price = priceType?.regular?.amount; - if (useFinal) { - price = priceType?.final?.amount; + if (currencySymbol) { + currency = currencySymbol; + } else { + currency = getSymbolFromCurrency(currency) ?? "$"; } - } - - // if currency symbol is configurable within Commerce, that symbol is used - let currency = price?.currency; - - if (currencySymbol) { - currency = currencySymbol; - } else { - currency = getSymbolFromCurrency(currency) ?? '$'; - } - const convertedPrice = currencyRate - ? price?.value * parseFloat(currencyRate) - : price?.value; + const convertedPrice = currencyRate ? price?.value * parseFloat(currencyRate) : price?.value; - return convertedPrice ? `${currency}${convertedPrice.toFixed(2)}` : ''; + return convertedPrice ? `${currency}${convertedPrice.toFixed(2)}` : ""; }; export { getProductPrice }; diff --git a/src/utils/getUserViewHistory.ts b/src/utils/getUserViewHistory.ts index 9c1647e..63590d6 100644 --- a/src/utils/getUserViewHistory.ts +++ b/src/utils/getUserViewHistory.ts @@ -10,23 +10,22 @@ it. type UserViewHistory = { sku: string; dateTime: string }; const getUserViewHistory = (): UserViewHistory[] => { - const userViewHistory: { sku: string; date: string }[] | null = - localStorage?.getItem('ds-view-history-time-decay') - ? JSON.parse(localStorage.getItem('ds-view-history-time-decay') as string) - : null; + const userViewHistory: { sku: string; date: string }[] | null = localStorage?.getItem("ds-view-history-time-decay") + ? JSON.parse(localStorage.getItem("ds-view-history-time-decay") as string) + : null; - if (userViewHistory && Array.isArray(userViewHistory)) { - // https://git.corp.adobe.com/magento-datalake/magento2-snowplow-js/blob/main/src/utils.js#L177 - // this shows localStorage is guaranteed sorted by unique by most recent timestamp as last index. + if (userViewHistory && Array.isArray(userViewHistory)) { + // https://git.corp.adobe.com/magento-datalake/magento2-snowplow-js/blob/main/src/utils.js#L177 + // this shows localStorage is guaranteed sorted by unique by most recent timestamp as last index. - // MSRCH-2740: send the top 200 most recently viewed unique SKUs - return userViewHistory.slice(-200).map((v) => ({ - sku: v.sku, - dateTime: v.date, - })); - } + // MSRCH-2740: send the top 200 most recently viewed unique SKUs + return userViewHistory.slice(-200).map((v) => ({ + sku: v.sku, + dateTime: v.date, + })); + } - return []; + return []; }; export { getUserViewHistory }; diff --git a/src/utils/handleUrlFilters.ts b/src/utils/handleUrlFilters.ts index 820d659..0a1b309 100644 --- a/src/utils/handleUrlFilters.ts +++ b/src/utils/handleUrlFilters.ts @@ -9,168 +9,161 @@ it. //Luma Specific URL handling -import { FacetFilter, SearchClauseInput } from '../types/interface'; -import { DEFAULT_PAGE_SIZE } from '../utils/constants'; +import { FacetFilter, SearchClauseInput } from "../types/interface"; +import { DEFAULT_PAGE_SIZE } from "../utils/constants"; // if you add custom search query params, add them to this object const nonFilterKeys = { - search: 'q', - search_query: 'search_query', - pagination: 'p', - sort: 'product_list_order', - page_size: 'page_size', + search: "q", + search_query: "search_query", + pagination: "p", + sort: "product_list_order", + page_size: "page_size", }; const addUrlFilter = (filter: SearchClauseInput) => { - const url = new URL(window.location.href); - const params = new URLSearchParams(url.searchParams); - const attribute = filter.attribute; - if (filter.range) { - const filt = filter.range; - if (getValueFromUrl(attribute)) { - params.delete(attribute); - params.append(attribute, `${filt.from}--${filt.to}`); + const url = new URL(window.location.href); + const params = new URLSearchParams(url.searchParams); + const attribute = filter.attribute; + if (filter.range) { + const filt = filter.range; + if (getValueFromUrl(attribute)) { + params.delete(attribute); + params.append(attribute, `${filt.from}--${filt.to}`); + } else { + params.append(attribute, `${filt.from}--${filt.to}`); + } } else { - params.append(attribute, `${filt.from}--${filt.to}`); + const filt = filter.in || []; + const filterParams = params.getAll(attribute); + filt.map((f) => { + if (!filterParams.includes(f)) { + params.append(attribute, f); + } + }); } - } else { - const filt = filter.in || []; - const filterParams = params.getAll(attribute); - filt.map((f) => { - if (!filterParams.includes(f)) { - params.append(attribute, f); - } - }); - } - setWindowHistory(url.pathname, params); + setWindowHistory(url.pathname, params); }; const removeUrlFilter = (name: string, option?: string) => { - const url = new URL(window.location.href); - const params = new URLSearchParams(url.searchParams); - const allValues = url.searchParams.getAll(name); - params.delete(name); - if (option) { - allValues.splice(allValues.indexOf(option), 1); - allValues.forEach((val) => params.append(name, val)); - } - setWindowHistory(url.pathname, params); + const url = new URL(window.location.href); + const params = new URLSearchParams(url.searchParams); + const allValues = url.searchParams.getAll(name); + params.delete(name); + if (option) { + allValues.splice(allValues.indexOf(option), 1); + allValues.forEach((val) => params.append(name, val)); + } + setWindowHistory(url.pathname, params); }; const removeAllUrlFilters = () => { - const url = new URL(window.location.href); - const params = new URLSearchParams(url.searchParams); - for (const key of url.searchParams.keys()) { - // if nonFilterKeys values includes a key from params (for customizing) - if (!Object.values(nonFilterKeys).includes(key)) { - params.delete(key); + const url = new URL(window.location.href); + const params = new URLSearchParams(url.searchParams); + for (const key of url.searchParams.keys()) { + // if nonFilterKeys values includes a key from params (for customizing) + if (!Object.values(nonFilterKeys).includes(key)) { + params.delete(key); + } } - } - setWindowHistory(url.pathname, params); + setWindowHistory(url.pathname, params); }; const handleUrlSort = (sortOption: string) => { - const url = new URL(window.location.href); - const params = new URLSearchParams(url.searchParams); - params.set('product_list_order', sortOption); - setWindowHistory(url.pathname, params); + const url = new URL(window.location.href); + const params = new URLSearchParams(url.searchParams); + params.set("product_list_order", sortOption); + setWindowHistory(url.pathname, params); }; const handleViewType = (viewType: string) => { - const url = new URL(window.location.href); - const params = new URLSearchParams(url.searchParams); - params.set('view_type', viewType); - setWindowHistory(url.pathname, params); + const url = new URL(window.location.href); + const params = new URLSearchParams(url.searchParams); + params.set("view_type", viewType); + setWindowHistory(url.pathname, params); }; const handleUrlPageSize = (pageSizeOption: number) => { - const url = new URL(window.location.href); - const params = new URLSearchParams(url.searchParams); - if (pageSizeOption === DEFAULT_PAGE_SIZE) { - params.delete('page_size'); - } else { - params.set('page_size', pageSizeOption.toString()); - } - setWindowHistory(url.pathname, params); + const url = new URL(window.location.href); + const params = new URLSearchParams(url.searchParams); + if (pageSizeOption === DEFAULT_PAGE_SIZE) { + params.delete("page_size"); + } else { + params.set("page_size", pageSizeOption.toString()); + } + setWindowHistory(url.pathname, params); }; const handleUrlPagination = (pageNumber: number) => { - const url = new URL(window.location.href); - const params = new URLSearchParams(url.searchParams); - if (pageNumber === 1) { - params.delete('p'); - } else { - params.set('p', pageNumber.toString()); - } - setWindowHistory(url.pathname, params); + const url = new URL(window.location.href); + const params = new URLSearchParams(url.searchParams); + if (pageNumber === 1) { + params.delete("p"); + } else { + params.set("p", pageNumber.toString()); + } + setWindowHistory(url.pathname, params); }; -const getFiltersFromUrl = ( - filterableAttributes: string[] -): SearchClauseInput[] => { - const params = getSearchParams(); - - const filters: FacetFilter[] = []; - for (const [key, value] of params.entries()) { - // if nonFilterKeys values includes a key from params (for customizing) - if ( - filterableAttributes.includes(key) && - !Object.values(nonFilterKeys).includes(key) - ) { - if (value.includes('--')) { - const range = value.split('--'); - const filter = { - attribute: key, - range: { from: Number(range[0]), to: Number(range[1]) }, - }; - filters.push(filter); - } else { - const attributeIndex = filters.findIndex( - (filter) => filter.attribute == key - ); - if (attributeIndex !== -1) { - filters[attributeIndex].in?.push(value); - } else { - const filter = { attribute: key, in: [value] }; - filters.push(filter); +const getFiltersFromUrl = (filterableAttributes: string[]): SearchClauseInput[] => { + const params = getSearchParams(); + + const filters: FacetFilter[] = []; + for (const [key, value] of params.entries()) { + // if nonFilterKeys values includes a key from params (for customizing) + if (filterableAttributes.includes(key) && !Object.values(nonFilterKeys).includes(key)) { + if (value.includes("--")) { + const range = value.split("--"); + const filter = { + attribute: key, + range: { from: Number(range[0]), to: Number(range[1]) }, + }; + filters.push(filter); + } else { + const attributeIndex = filters.findIndex((filter) => filter.attribute == key); + if (attributeIndex !== -1) { + filters[attributeIndex].in?.push(value); + } else { + const filter = { attribute: key, in: [value] }; + filters.push(filter); + } + } } - } } - } - return filters; + return filters; }; const getValueFromUrl = (param: string) => { - const params = getSearchParams(); - const filter = params.get(param); - if (filter) { - return filter; - } - return ''; + const params = getSearchParams(); + const filter = params.get(param); + if (filter) { + return filter; + } + return ""; }; const getSearchParams = () => { - const search = window.location.search; - return new URLSearchParams(search); + const search = window.location.search; + return new URLSearchParams(search); }; const setWindowHistory = (pathname: string, params: URLSearchParams) => { - if(params.toString() === '') { - window.history.pushState({}, '', `${pathname}`); - } else { - window.history.pushState({}, '', `${pathname}?${params.toString()}`); - } + if (params.toString() === "") { + window.history.pushState({}, "", `${pathname}`); + } else { + window.history.pushState({}, "", `${pathname}?${params.toString()}`); + } }; export { - addUrlFilter, - getFiltersFromUrl, - getValueFromUrl, - handleUrlPageSize, - handleUrlPagination, - handleUrlSort, - handleViewType, - removeAllUrlFilters, - removeUrlFilter, + addUrlFilter, + getFiltersFromUrl, + getValueFromUrl, + handleUrlPageSize, + handleUrlPagination, + handleUrlSort, + handleViewType, + removeAllUrlFilters, + removeUrlFilter, }; diff --git a/src/utils/htmlStringDecode.ts b/src/utils/htmlStringDecode.ts index fc6fbcb..49bf649 100644 --- a/src/utils/htmlStringDecode.ts +++ b/src/utils/htmlStringDecode.ts @@ -8,8 +8,8 @@ it. */ const htmlStringDecode = (input: string): string | null => { - const doc = new DOMParser().parseFromString(input, 'text/html'); - return doc.documentElement.textContent; + const doc = new DOMParser().parseFromString(input, "text/html"); + return doc.documentElement.textContent; }; export { htmlStringDecode }; diff --git a/src/utils/sort.ts b/src/utils/sort.ts index ad10ac8..96aa194 100644 --- a/src/utils/sort.ts +++ b/src/utils/sort.ts @@ -7,87 +7,85 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { Language } from '../context/translation'; -import { GQLSortInput, SortMetadata, SortOption } from '../types/interface'; +import { Language } from "../context/translation"; +import { GQLSortInput, SortMetadata, SortOption } from "../types/interface"; const defaultSortOptions = (): SortOption[] => { - return [ - { label: 'Most Relevant', value: 'relevance_DESC' }, - { label: 'Price: Low to High', value: 'price_ASC' }, - { label: 'Price: High to Low', value: 'price_DESC' }, - ]; + return [ + { label: "Most Relevant", value: "relevance_DESC" }, + { label: "Price: Low to High", value: "price_ASC" }, + { label: "Price: High to Low", value: "price_DESC" }, + ]; }; const getSortOptionsfromMetadata = ( - translation: Language, - sortMetadata: SortMetadata[], - displayOutOfStock?: string | boolean, - categoryPath?: string + translation: Language, + sortMetadata: SortMetadata[], + displayOutOfStock?: string | boolean, + categoryPath?: string, ): SortOption[] => { - const sortOptions = categoryPath - ? [ - { - label: translation.SortDropdown.positionLabel, - value: 'position_ASC', - }, - ] - : [ - { - label: translation.SortDropdown.relevanceLabel, - value: 'relevance_DESC', - }, - ]; - const displayInStockOnly = displayOutOfStock != '1'; // '!=' is intentional for conversion + const sortOptions = categoryPath + ? [ + { + label: translation.SortDropdown.positionLabel, + value: "position_ASC", + }, + ] + : [ + { + label: translation.SortDropdown.relevanceLabel, + value: "relevance_DESC", + }, + ]; + const displayInStockOnly = displayOutOfStock != "1"; // '!=' is intentional for conversion - if (sortMetadata && sortMetadata.length > 0) { - sortMetadata.forEach((e) => { - if ( - !e.attribute.includes('relevance') && - !(e.attribute.includes('inStock') && displayInStockOnly) && - !e.attribute.includes('position') - /* conditions for which we don't display the sorting option: + if (sortMetadata && sortMetadata.length > 0) { + sortMetadata.forEach((e) => { + if ( + !e.attribute.includes("relevance") && + !(e.attribute.includes("inStock") && displayInStockOnly) && + !e.attribute.includes("position") + /* conditions for which we don't display the sorting option: 1) if the option attribute is relevance 2) if the option attribute is "inStock" and display out of stock products is set to no 3) if the option attribute is "position" and there is not a categoryPath (we're not in category browse mode) -> the conditional part is handled in setting sortOptions */ - ) { - if (e.numeric && e.attribute.includes('price')) { - sortOptions.push({ - label: `${e.label}: Low to High`, - value: `${e.attribute}_ASC`, - }); - sortOptions.push({ - label: `${e.label}: High to Low`, - value: `${e.attribute}_DESC`, - }); - } else { - sortOptions.push({ - label: `${e.label}`, - value: `${e.attribute}_DESC`, - }); - } - } - }); - } - return sortOptions; + ) { + if (e.numeric && e.attribute.includes("price")) { + sortOptions.push({ + label: `${e.label}: Low to High`, + value: `${e.attribute}_ASC`, + }); + sortOptions.push({ + label: `${e.label}: High to Low`, + value: `${e.attribute}_DESC`, + }); + } else { + sortOptions.push({ + label: `${e.label}`, + value: `${e.attribute}_DESC`, + }); + } + } + }); + } + return sortOptions; }; -const generateGQLSortInput = ( - sortOption: string -): GQLSortInput[] | undefined => { - // results sorted by relevance or position by default - if (!sortOption) { - return undefined; - } +const generateGQLSortInput = (sortOption: string): GQLSortInput[] | undefined => { + // results sorted by relevance or position by default + if (!sortOption) { + return undefined; + } - // sort options are in format attribute_direction - const index = sortOption.lastIndexOf('_'); - return [ - { - attribute: sortOption.substring(0, index), - direction: sortOption.substring(index + 1) === 'ASC' ? 'ASC' : 'DESC', - }, - ]; + // sort options are in format attribute_direction + const index = sortOption.lastIndexOf("_"); + return [ + { + attribute: sortOption.substring(0, index), + direction: sortOption.substring(index + 1) === "ASC" ? "ASC" : "DESC", + }, + ]; }; export { defaultSortOptions, generateGQLSortInput, getSortOptionsfromMetadata }; diff --git a/src/utils/tests/translations.test.ts b/src/utils/tests/translations.test.ts index 406c76b..28a8d9d 100644 --- a/src/utils/tests/translations.test.ts +++ b/src/utils/tests/translations.test.ts @@ -7,74 +7,65 @@ accordance with the terms of the Adobe license agreement accompanying it. */ -import { getCurrLanguage } from '../../context/translation'; +import { getCurrLanguage } from "../../context/translation"; // Locales Widgets Support V1 const widgetsLocales = [ - 'bg_BG', - 'ca_ES', - 'cs_CZ', - 'da_DK', - 'de_DE', - 'el_GR', - 'en_GB', - 'en_US', - 'es_ES', - 'et_EE', - 'eu_ES', - 'fa_IR', - 'fi_FI', - 'fr_FR', - 'gl_ES', - 'hi_IN', - 'hu_HU', - 'id_ID', - 'it_IT', - 'ja_JP', - 'ko_KR', - 'lt_LT', - 'lv_LV', - 'nb_NO', - 'nl_NL', - 'pt_BR', - 'pt_PT', - 'ro_RO', - 'ru_RU', - 'sv_SE', - 'th_TH', - 'tr_TR', - 'zh_Hans_CN', - 'zh_Hant_TW', + "bg_BG", + "ca_ES", + "cs_CZ", + "da_DK", + "de_DE", + "el_GR", + "en_GB", + "en_US", + "es_ES", + "et_EE", + "eu_ES", + "fa_IR", + "fi_FI", + "fr_FR", + "gl_ES", + "hi_IN", + "hu_HU", + "id_ID", + "it_IT", + "ja_JP", + "ko_KR", + "lt_LT", + "lv_LV", + "nb_NO", + "nl_NL", + "pt_BR", + "pt_PT", + "ro_RO", + "ru_RU", + "sv_SE", + "th_TH", + "tr_TR", + "zh_Hans_CN", + "zh_Hant_TW", ]; //Locales Widgets does not support further info: https://wiki.corp.adobe.com/display/ACDS/Widgets+i18n+Translation -const mockLocales = [ - 'ar_AE', - 'ar_SA', - 'ar_MA', - 'ar_EG', - 'bn_IN', - 'hy_AM', - 'en_GA', - 'Sorani', -]; +const mockLocales = ["ar_AE", "ar_SA", "ar_MA", "ar_EG", "bn_IN", "hy_AM", "en_GA", "Sorani"]; -describe('Get language based on passed locale', () => { - it('returns the detected language from list of locales widgets supports', () => { - widgetsLocales.forEach((locale) => { - expect(getCurrLanguage(locale)).toBe(locale); +describe("Get language based on passed locale", () => { + it("returns the detected language from list of locales widgets supports", () => { + widgetsLocales.forEach((locale) => { + expect(getCurrLanguage(locale)).toBe(locale); + }); }); - }); - it('returns default when locale is not recognized', () => { - expect(getCurrLanguage('xr_XX')).toBe('default'); - }); + it("returns default when locale is not recognized", () => { + expect(getCurrLanguage("xr_XX")).toBe("default"); + }); }); -describe('Get language based on locales Widgets does not support', () => { - it('returns default when locale is not recognized', () => { - mockLocales.forEach((locale) => { - expect(getCurrLanguage(locale)).toBe('default'); +describe("Get language based on locales Widgets does not support", () => { + it("returns default when locale is not recognized", () => { + mockLocales.forEach((locale) => { + expect(getCurrLanguage(locale)).toBe("default"); + }); }); - }); }); diff --git a/src/utils/tests/utils.test.ts b/src/utils/tests/utils.test.ts index 0fb4bb0..01b15a7 100644 --- a/src/utils/tests/utils.test.ts +++ b/src/utils/tests/utils.test.ts @@ -1,131 +1,122 @@ -import { StoreDetailsProps } from '../../context'; -import { - sanitizeString, - validateStoreDetailsKeys, -} from '../validateStoreDetails'; -describe('should sanitize string', () => { - test('should remove special characters', () => { - const unsanitizedStr1 = sanitizeString( - 'hello
hello
' - ); - const unsanitizedStr2 = sanitizeString(''); - const expectedStr1 = 'helloscripthelloscriptdivhellodiv'; - const expectedStr2 = 'scripthelloscript'; +import { StoreDetailsProps } from "../../context"; +import { sanitizeString, validateStoreDetailsKeys } from "../validateStoreDetails"; +describe("should sanitize string", () => { + test("should remove special characters", () => { + const unsanitizedStr1 = sanitizeString("hello
hello
"); + const unsanitizedStr2 = sanitizeString(""); + const expectedStr1 = "helloscripthelloscriptdivhellodiv"; + const expectedStr2 = "scripthelloscript"; - expect(unsanitizedStr1).toEqual(expectedStr1); - expect(unsanitizedStr2).toEqual(expectedStr2); - }); - test('valid string should not change', () => { - const validStr1 = sanitizeString('storefront-catalog-apollo'); - const validStr2 = sanitizeString('12,24,36'); - const validStr3 = sanitizeString('main_website_store'); - const validStr4 = sanitizeString('b6589fc6ab0dc82cf1'); - const expectedStr1 = 'storefront-catalog-apollo'; - const expectedStr2 = '12,24,36'; - const expectedStr3 = 'main_website_store'; - const expectedStr4 = 'b6589fc6ab0dc82cf1'; + expect(unsanitizedStr1).toEqual(expectedStr1); + expect(unsanitizedStr2).toEqual(expectedStr2); + }); + test("valid string should not change", () => { + const validStr1 = sanitizeString("storefront-catalog-apollo"); + const validStr2 = sanitizeString("12,24,36"); + const validStr3 = sanitizeString("main_website_store"); + const validStr4 = sanitizeString("b6589fc6ab0dc82cf1"); + const expectedStr1 = "storefront-catalog-apollo"; + const expectedStr2 = "12,24,36"; + const expectedStr3 = "main_website_store"; + const expectedStr4 = "b6589fc6ab0dc82cf1"; - expect(validStr1).toEqual(expectedStr1); - expect(validStr2).toEqual(expectedStr2); - expect(validStr3).toEqual(expectedStr3); - expect(validStr4).toEqual(expectedStr4); - }); + expect(validStr1).toEqual(expectedStr1); + expect(validStr2).toEqual(expectedStr2); + expect(validStr3).toEqual(expectedStr3); + expect(validStr4).toEqual(expectedStr4); + }); }); -describe('test validating storeDetails.', () => { - test('valid storeDetails should remain unchanged', () => { - const storeDetails = { - environmentId: '22500baf-135e-4b8f-8f18-14276de7d356', - websiteCode: 'base', - storeCode: 'main_website_store', - storeViewCode: 'default', - config: { - minQueryLength: '2', - pageSize: 8, - perPageConfig: { - pageSizeOptions: '12,24,36', - defaultPageSizeOption: '24', - }, - currencySymbol: '$', - currencyRate: '1', - displaySearchBox: true, - displayOutOfStock: true, - allowAllProducts: false, - optimizeImages: true, - imageBaseWidth: 200, - }, - context: { - customerGroup: 'b6589fc6ab0dc82cf12099d1c2d40ab994e8410c', - }, - apiKey: 'storefront-catalog-apollo', - apiUrl: '', - environmentType: '', - } as StoreDetailsProps; - const expectedStoreDetails = JSON.parse(JSON.stringify(storeDetails)); +describe("test validating storeDetails.", () => { + test("valid storeDetails should remain unchanged", () => { + const storeDetails = { + environmentId: "22500baf-135e-4b8f-8f18-14276de7d356", + websiteCode: "base", + storeCode: "main_website_store", + storeViewCode: "default", + config: { + minQueryLength: "2", + pageSize: 8, + perPageConfig: { + pageSizeOptions: "12,24,36", + defaultPageSizeOption: "24", + }, + currencySymbol: "$", + currencyRate: "1", + displaySearchBox: true, + displayOutOfStock: true, + allowAllProducts: false, + optimizeImages: true, + imageBaseWidth: 200, + }, + context: { + customerGroup: "b6589fc6ab0dc82cf12099d1c2d40ab994e8410c", + }, + apiKey: "storefront-catalog-apollo", + apiUrl: "", + environmentType: "", + } as StoreDetailsProps; + const expectedStoreDetails = JSON.parse(JSON.stringify(storeDetails)); - expect(validateStoreDetailsKeys(storeDetails)).toEqual( - expectedStoreDetails - ); - }); - test('invalid storeDetails should remove unknown keys', () => { - const invalidStoreDetails = { - environmentId: '22500baf-135e-4b8f-8f18-14276de7d356', - websiteCode: 'base', - storeCode: 'main_website_store', - storeViewCode: 'default', - config: { - minQueryLength: '2', - pageSize: 8, - perPageConfig: { - pageSizeOptions: '12,24,36', - defaultPageSizeOption: '24', - }, - currencySymbol: '$', - currencyRate: '1', - displaySearchBox: true, - displayOutOfStock: true, - allowAllProducts: false, - optimizeImages: true, - imageBaseWidth: 200, - }, - context: { - customerGroup: 'b6589fc6ab0dc82cf12099d1c2d40ab994e8410c', - }, - apiKey: 'storefront-catalog-apollo', - apiUrl: '', - environmentType: '', - shouldGetRemoved: 'should not belong here', - } as StoreDetailsProps; - const expectedStoreDetails = { - environmentId: '22500baf-135e-4b8f-8f18-14276de7d356', - websiteCode: 'base', - storeCode: 'main_website_store', - storeViewCode: 'default', - config: { - minQueryLength: '2', - pageSize: 8, - perPageConfig: { - pageSizeOptions: '12,24,36', - defaultPageSizeOption: '24', - }, - currencySymbol: '$', - currencyRate: '1', - displaySearchBox: true, - displayOutOfStock: true, - allowAllProducts: false, - optimizeImages: true, - imageBaseWidth: 200, - }, - context: { - customerGroup: 'b6589fc6ab0dc82cf12099d1c2d40ab994e8410c', - }, - apiKey: 'storefront-catalog-apollo', - apiUrl: '', - environmentType: '', - } as StoreDetailsProps; + expect(validateStoreDetailsKeys(storeDetails)).toEqual(expectedStoreDetails); + }); + test("invalid storeDetails should remove unknown keys", () => { + const invalidStoreDetails = { + environmentId: "22500baf-135e-4b8f-8f18-14276de7d356", + websiteCode: "base", + storeCode: "main_website_store", + storeViewCode: "default", + config: { + minQueryLength: "2", + pageSize: 8, + perPageConfig: { + pageSizeOptions: "12,24,36", + defaultPageSizeOption: "24", + }, + currencySymbol: "$", + currencyRate: "1", + displaySearchBox: true, + displayOutOfStock: true, + allowAllProducts: false, + optimizeImages: true, + imageBaseWidth: 200, + }, + context: { + customerGroup: "b6589fc6ab0dc82cf12099d1c2d40ab994e8410c", + }, + apiKey: "storefront-catalog-apollo", + apiUrl: "", + environmentType: "", + shouldGetRemoved: "should not belong here", + } as StoreDetailsProps; + const expectedStoreDetails = { + environmentId: "22500baf-135e-4b8f-8f18-14276de7d356", + websiteCode: "base", + storeCode: "main_website_store", + storeViewCode: "default", + config: { + minQueryLength: "2", + pageSize: 8, + perPageConfig: { + pageSizeOptions: "12,24,36", + defaultPageSizeOption: "24", + }, + currencySymbol: "$", + currencyRate: "1", + displaySearchBox: true, + displayOutOfStock: true, + allowAllProducts: false, + optimizeImages: true, + imageBaseWidth: 200, + }, + context: { + customerGroup: "b6589fc6ab0dc82cf12099d1c2d40ab994e8410c", + }, + apiKey: "storefront-catalog-apollo", + apiUrl: "", + environmentType: "", + } as StoreDetailsProps; - expect(validateStoreDetailsKeys(invalidStoreDetails)).toEqual( - expectedStoreDetails - ); - }); + expect(validateStoreDetailsKeys(invalidStoreDetails)).toEqual(expectedStoreDetails); + }); }); diff --git a/src/utils/useIntersectionObserver.ts b/src/utils/useIntersectionObserver.ts index 7a99edb..e7efb9e 100644 --- a/src/utils/useIntersectionObserver.ts +++ b/src/utils/useIntersectionObserver.ts @@ -1,28 +1,27 @@ -import { useEffect, useState } from 'preact/hooks'; +import { useEffect, useState } from "preact/hooks"; export const useIntersectionObserver = (ref: any, options: any) => { - const { rootMargin } = options; - const [observerEntry, setObserverEntry] = - useState(null); + const { rootMargin } = options; + const [observerEntry, setObserverEntry] = useState(null); - useEffect(() => { - if (!ref?.current) return; - const observer = new IntersectionObserver( - ([entry]) => { - setObserverEntry(entry); - if (entry.isIntersecting) { - observer.unobserve(entry.target); - } - }, - { rootMargin } - ); + useEffect(() => { + if (!ref?.current) return; + const observer = new IntersectionObserver( + ([entry]) => { + setObserverEntry(entry); + if (entry.isIntersecting) { + observer.unobserve(entry.target); + } + }, + { rootMargin }, + ); - observer.observe(ref.current); + observer.observe(ref.current); - return () => { - observer.disconnect(); - }; - }, [ref, rootMargin]); + return () => { + observer.disconnect(); + }; + }, [ref, rootMargin]); - return observerEntry; + return observerEntry; }; diff --git a/src/utils/validateStoreDetails.ts b/src/utils/validateStoreDetails.ts index a971044..4548800 100644 --- a/src/utils/validateStoreDetails.ts +++ b/src/utils/validateStoreDetails.ts @@ -1,41 +1,38 @@ -import { StoreDetailsProps } from '../context'; +import { StoreDetailsProps } from "../context"; const validStoreDetailsKeys: Array = [ - 'environmentId', - 'environmentType', - 'websiteCode', - 'storeCode', - 'storeViewCode', - 'config', - 'context', - 'apiUrl', - 'apiKey', - 'route', - 'searchQuery', + "environmentId", + "environmentType", + "websiteCode", + "storeCode", + "storeViewCode", + "config", + "context", + "apiUrl", + "apiKey", + "route", + "searchQuery", ]; export const sanitizeString = (value: any) => { - // just incase, https://stackoverflow.com/a/23453651 - if (typeof value === 'string') { - // eslint-disable-next-line no-useless-escape - value = value.replace(/[^a-z0-9áéíóúñü \.,_-]/gim, ''); - return value.trim(); - } - return value; + // just incase, https://stackoverflow.com/a/23453651 + if (typeof value === "string") { + // eslint-disable-next-line no-useless-escape + value = value.replace(/[^a-z0-9áéíóúñü \.,_-]/gim, ""); + return value.trim(); + } + return value; }; -export const validateStoreDetailsKeys = ( - storeDetails: StoreDetailsProps -): StoreDetailsProps => { - Object.keys(storeDetails).forEach((key: string) => { - if (!validStoreDetailsKeys.includes(key as keyof StoreDetailsProps)) { - // eslint-disable-next-line no-console - console.error(`Invalid key ${key} in StoreDetailsProps`); - // filter out invalid keys/value - delete (storeDetails as any)[key]; - return; - } - (storeDetails as any)[key] = sanitizeString((storeDetails as any)[key]); - }); - return storeDetails; +export const validateStoreDetailsKeys = (storeDetails: StoreDetailsProps): StoreDetailsProps => { + Object.keys(storeDetails).forEach((key: string) => { + if (!validStoreDetailsKeys.includes(key as keyof StoreDetailsProps)) { + console.error(`Invalid key ${key} in StoreDetailsProps`); + // filter out invalid keys/value + delete (storeDetails as any)[key]; + return; + } + (storeDetails as any)[key] = sanitizeString((storeDetails as any)[key]); + }); + return storeDetails; }; diff --git a/storybook-stories.js b/storybook-stories.js index 3a9c5e7..1dbdba4 100644 --- a/storybook-stories.js +++ b/storybook-stories.js @@ -1,8 +1,8 @@ -const path = require('path'); +const path = require("path"); module.exports = { - stories: [ - path.resolve(__dirname, './src/**/*.mdx'), - path.resolve(__dirname, './src/**/*.stories.@(js|jsx|ts|tsx|mdx)'), - ], + stories: [ + path.resolve(__dirname, "./src/**/*.mdx"), + path.resolve(__dirname, "./src/**/*.stories.@(js|jsx|ts|tsx|mdx)"), + ], }; diff --git a/tsconfig.app.json b/tsconfig.app.json index 1714b50..6bb7565 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -1,30 +1,30 @@ { - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - "paths": { - "react": ["./node_modules/preact/compat/"], - "react-dom": ["./node_modules/preact/compat/"], - "@/*": ["./src/*"] - }, + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "paths": { + "react": ["./node_modules/preact/compat/"], + "react-dom": ["./node_modules/preact/compat/"], + "@/*": ["./src/*"] + }, - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - "jsxImportSource": "preact", + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + "jsxImportSource": "preact", - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"] + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] } diff --git a/tsconfig.json b/tsconfig.json index c309037..ef5f155 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,6 @@ { "files": [], - "references": [ - { "path": "./tsconfig.app.json" }, - { "path": "./tsconfig.node.json" } - ], + "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }], "exclude": ["**/*.test.js"] } diff --git a/vite.config.ts b/vite.config.ts index e483ccc..e2b3c01 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-console */ import preact from "@preact/preset-vite"; import path, { resolve } from "node:path"; import { defineConfig, loadEnv } from "vite"; @@ -7,7 +6,7 @@ import svgr from "vite-plugin-svgr"; import pkg from "./package.json"; // const _banner = `${pkg.name}@v${pkg.version}`; -const MAJOR_VERSION = `v${pkg.version.split('.')[0]}`; +const MAJOR_VERSION = `v${pkg.version.split(".")[0]}`; // https://vitejs.dev/config/ export default defineConfig(({ mode }) => { @@ -17,15 +16,12 @@ export default defineConfig(({ mode }) => { const envDir = path.resolve(process.cwd(), "config"); const envPrefix = ["VITE", "CONFIG"]; // load all .env files here so we have access to non `VITE_` variables in the config - const env = loadEnv(mode, envDir, ''); + const env = loadEnv(mode, envDir, ""); const PORT = env.LUMA_PORT; return { - plugins: [ - svgr(), - preact(), - ], + plugins: [svgr(), preact()], envDir, envPrefix, // only allow CONFIG on dev ??? resolve: { @@ -36,16 +32,16 @@ export default defineConfig(({ mode }) => { server: { port: parseInt(PORT), strictPort: true, - open: `http://localhost:${PORT}/${MAJOR_VERSION}/index.html` + open: `http://localhost:${PORT}/${MAJOR_VERSION}/index.html`, // proxy: { // [`/v${MAJOR_VERSION}`]: `http://localhost:${PORT}/` // } }, define: { __APP_VERSION__: JSON.stringify(env.npm_package_version), - __API_URL__: JSON.stringify(env.VITE_API_URL ?? ''), + __API_URL__: JSON.stringify(env.VITE_API_URL ?? ""), // for backwards compatability - "API_URL": JSON.stringify(env.VITE_API_URL ?? ''), + API_URL: JSON.stringify(env.VITE_API_URL ?? ""), }, // https://vitejs.dev/guide/build#library-mode build: { @@ -53,7 +49,7 @@ export default defineConfig(({ mode }) => { entry: resolve(__dirname, "src/LiveSearchPLP.tsx"), name: "LiveSearchPLP", fileName: "search", - } - } + }, + }, }; }); diff --git a/webpack.common.js b/webpack.common.js index a7ed15d..c169c8d 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -1,122 +1,108 @@ -const path = require('path'); -const pkg = require('./package.json'); -const webpack = require('webpack'); -const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); -const TerserPlugin = require('terser-webpack-plugin'); +const path = require("path"); +const pkg = require("./package.json"); +const webpack = require("webpack"); +const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin"); +const TerserPlugin = require("terser-webpack-plugin"); const lumaPort = 8081; const PORT = process.env.PORT || lumaPort; const banner = `${pkg.name}@v${pkg.version}`; -const MAJOR_VERSION = `v${pkg.version.split('.')[0]}`; +const MAJOR_VERSION = `v${pkg.version.split(".")[0]}`; const publicPaths = { - DEV: `http://localhost:${PORT}/${MAJOR_VERSION}/`, - QA: ``, - PROD: ``, + DEV: `http://localhost:${PORT}/${MAJOR_VERSION}/`, + QA: ``, + PROD: ``, }; const commonConfig = { - experiments: { - outputModule: true, - }, - entry: { - search: './src', - }, - output: { - path: path.resolve(__dirname, 'dist'), - filename: '[name].js', - libraryTarget: 'module', - }, - watchOptions: { - aggregateTimeout: 100, // delay before reloading - }, - devServer: { - compress: true, - // host: '', - port: PORT, - static: { - directory: path.join(__dirname, 'dist'), + experiments: { + outputModule: true, }, - headers: { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS', - 'Access-Control-Allow-Headers': - 'X-Requested-With, content-type, Authorization', + entry: { + search: "./src", }, - open: publicPaths.DEV, - allowedHosts: ['all'], - watchFiles: ['src/**/*', 'public/**/*', 'dist/**/*'], - hot: true, - liveReload: false, - host: '0.0.0.0', - client: { - webSocketURL: `ws://localhost:${PORT}/ws`, + output: { + path: path.resolve(__dirname, "dist"), + filename: "[name].js", + libraryTarget: "module", }, - }, - module: { - rules: [ - { - test: /\.[jt]sx?$/, - use: [ - { - loader: require.resolve('ts-loader'), - options: { - transpileOnly: true, + watchOptions: { + aggregateTimeout: 100, // delay before reloading + }, + devServer: { + compress: true, + // host: '', + port: PORT, + static: { + directory: path.join(__dirname, "dist"), + }, + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS", + "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization", + }, + open: publicPaths.DEV, + allowedHosts: ["all"], + watchFiles: ["src/**/*", "public/**/*", "dist/**/*"], + hot: true, + liveReload: false, + host: "0.0.0.0", + client: { + webSocketURL: `ws://localhost:${PORT}/ws`, + }, + }, + module: { + rules: [ + { + test: /\.[jt]sx?$/, + use: [ + { + loader: require.resolve("ts-loader"), + options: { + transpileOnly: true, + }, + }, + ], + exclude: /node_modules/, + }, + { + test: /\.css$/, + exclude: /node_modules/, + use: ["style-loader", "css-loader", "postcss-loader"], + }, + { + test: /\.svg$/, + use: ["preact-svg-loader"], }, - }, ], - exclude: /node_modules/, - }, - { - test: /\.css$/, - exclude: /node_modules/, - use: ['style-loader', 'css-loader', 'postcss-loader'], - }, - { - test: /\.svg$/, - use: ['preact-svg-loader'], - }, - ], - }, - resolve: { - extensions: [ - '.tsx', - '.ts', - '.js', - '.jsx', - '.svg', - '.css', - '.json', - '.mdx', - '.mjs', - ], - alias: { - react: 'preact/compat', - 'react-dom/test-utils': 'preact/test-utils', - 'react-dom': 'preact/compat', // Must be below test-utils - 'react/jsx-runtime': 'preact/jsx-runtime', }, - plugins: [ - new TsconfigPathsPlugin({ - /* options: */ - configFile: 'tsconfig.json', - }), - - ], - }, - plugins: [ - new webpack.BannerPlugin(banner), - ], - optimization: { - minimizer: [ - new TerserPlugin({ - extractComments: { - banner, + resolve: { + extensions: [".tsx", ".ts", ".js", ".jsx", ".svg", ".css", ".json", ".mdx", ".mjs"], + alias: { + react: "preact/compat", + "react-dom/test-utils": "preact/test-utils", + "react-dom": "preact/compat", // Must be below test-utils + "react/jsx-runtime": "preact/jsx-runtime", }, - }), - ], - }, + plugins: [ + new TsconfigPathsPlugin({ + /* options: */ + configFile: "tsconfig.json", + }), + ], + }, + plugins: [new webpack.BannerPlugin(banner)], + optimization: { + minimizer: [ + new TerserPlugin({ + extractComments: { + banner, + }, + }), + ], + }, }; module.exports = { commonConfig, publicPaths }; diff --git a/webpack.dev.js b/webpack.dev.js index 99ea926..45279f1 100644 --- a/webpack.dev.js +++ b/webpack.dev.js @@ -1,28 +1,26 @@ -const { merge } = require('webpack-merge'); -const webpack = require('webpack'); -const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); +const { merge } = require("webpack-merge"); +const webpack = require("webpack"); +const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); +const HtmlWebpackPlugin = require("html-webpack-plugin"); -const { commonConfig, publicPaths } = require('./webpack.common.js'); +const { commonConfig, publicPaths } = require("./webpack.common.js"); module.exports = merge(commonConfig, { - mode: 'development', - output: { - publicPath: publicPaths.DEV, - }, - plugins: [ - new webpack.DefinePlugin({ - API_URL: JSON.stringify('https://catalog-service.adobe.io/graphql'), - TEST_URL: JSON.stringify( - 'https://catalog-service-sandbox.adobe.io/graphql' - ), - SANDBOX_KEY: JSON.stringify('storefront-widgets'), - }), - new HtmlWebpackPlugin({ - title: 'LiveSearch PLP', - template: './dev-template.html', - }), - new webpack.HotModuleReplacementPlugin(), - new ForkTsCheckerWebpackPlugin(), - ], + mode: "development", + output: { + publicPath: publicPaths.DEV, + }, + plugins: [ + new webpack.DefinePlugin({ + API_URL: JSON.stringify("https://catalog-service.adobe.io/graphql"), + TEST_URL: JSON.stringify("https://catalog-service-sandbox.adobe.io/graphql"), + SANDBOX_KEY: JSON.stringify("storefront-widgets"), + }), + new HtmlWebpackPlugin({ + title: "LiveSearch PLP", + template: "./dev-template.html", + }), + new webpack.HotModuleReplacementPlugin(), + new ForkTsCheckerWebpackPlugin(), + ], }); diff --git a/webpack.prod.js b/webpack.prod.js index 218cc91..8df59c8 100644 --- a/webpack.prod.js +++ b/webpack.prod.js @@ -1,24 +1,22 @@ -const { merge } = require('webpack-merge'); -const webpack = require('webpack'); -const { commonConfig, publicPaths } = require('./webpack.common.js'); +const { merge } = require("webpack-merge"); +const webpack = require("webpack"); +const { commonConfig, publicPaths } = require("./webpack.common.js"); module.exports = merge(commonConfig, { - mode: 'production', - output: { - publicPath: publicPaths.PROD, - }, - plugins: [ - ...commonConfig.plugins, - new webpack.DefinePlugin({ - API_URL: JSON.stringify('https://catalog-service.adobe.io/graphql'), - TEST_URL: JSON.stringify( - 'https://catalog-service-sandbox.adobe.io/graphql' - ), - SANDBOX_KEY: JSON.stringify('storefront-widgets'), - 'process.env.NODE_ENV': JSON.stringify('production'), - }), - ], - optimization: { - minimize: true, - }, + mode: "production", + output: { + publicPath: publicPaths.PROD, + }, + plugins: [ + ...commonConfig.plugins, + new webpack.DefinePlugin({ + API_URL: JSON.stringify("https://catalog-service.adobe.io/graphql"), + TEST_URL: JSON.stringify("https://catalog-service-sandbox.adobe.io/graphql"), + SANDBOX_KEY: JSON.stringify("storefront-widgets"), + "process.env.NODE_ENV": JSON.stringify("production"), + }), + ], + optimization: { + minimize: true, + }, });