@riosst100/pwa-marketplace 2.1.5 → 2.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@riosst100/pwa-marketplace",
3
3
  "author": "riosst100@gmail.com",
4
- "version": "2.1.5",
4
+ "version": "2.1.7",
5
5
  "main": "src/index.js",
6
6
  "pwa-studio": {
7
7
  "targets": {
@@ -15,11 +15,13 @@ module.exports = componentOverrideMapping = {
15
15
  [`@magento/peregrine/lib/talons/AccountMenu/useAccountMenuItems.js`]: '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/AccountMenu/useAccountMenuItems.js',
16
16
  [`@magento/peregrine/lib/talons/MegaMenu/megaMenu.gql.js`]: '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/MegaMenu/megaMenu.gql.js',
17
17
  [`@magento/peregrine/lib/talons/RootComponents/Product/productDetailFragment.gql.js`]: '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/RootComponents/Product/productDetailFragment.gql.js',
18
+ [`@magento/peregrine/lib/talons/RootComponents/Product/useProduct.js`]: '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/RootComponents/Product/useProduct.js',
18
19
  [`@magento/peregrine/lib/talons/ProductFullDetail/useProductFullDetail.js`]: '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/ProductFullDetail/useProductFullDetail.js',
19
20
  [`@magento/peregrine/lib/util/deriveErrorMessage.js`]: '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/util/deriveErrorMessage.js',
20
21
  [`@magento/venia-ui/lib/components/MegaMenu/megaMenu.js`]: '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/MegaMenu/megaMenu.js',
21
22
  [`@magento/venia-ui/lib/components/FilterModal/FilterList/filterDefault.js`]: '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/FilterModal/FilterList/filterDefault.js',
22
23
  [`@magento/venia-ui/lib/RootComponents/Category/categoryContent.js`]: '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/RootComponents/Category/categoryContent.js',
24
+ [`@magento/venia-ui/lib/RootComponents/Product/product.js`]: '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/RootComponents/Product/product.js',
23
25
  [`@magento/peregrine/lib/talons/RootComponents/Category/useCategoryContent.js`]: '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/RootComponents/Category/useCategoryContent.js',
24
26
  [`@magento/peregrine/lib/talons/RootComponents/Category/useCategory.js`]: '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/RootComponents/Category/useCategory.js',
25
27
  [`@magento/peregrine/lib/talons/Breadcrumbs/useBreadcrumbs.js`]: '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/Breadcrumbs/useBreadcrumbs.js',
@@ -193,9 +193,17 @@ const getConfigPrice = (product, optionCodes, optionSelections) => {
193
193
  variants
194
194
  });
195
195
 
196
+ const minPrice = product.price_range?.minimum_price.final_price.value;
197
+ const maxPrice = product.price_range?.maximum_price.final_price.value;
198
+
199
+ let val = minPrice;
200
+ if (minPrice != maxPrice) {
201
+ val = minPrice + ' - ' + maxPrice;
202
+ }
203
+
196
204
  const priceRange = {
197
205
  final_price: {
198
- value: product.price_range?.minimum_price.final_price.value + ' - ' + product.price_range?.maximum_price.final_price.value,
206
+ value: val,
199
207
  currency: product.price_range?.minimum_price.final_price.currency
200
208
  }
201
209
  };
@@ -205,9 +213,6 @@ const getConfigPrice = (product, optionCodes, optionSelections) => {
205
213
  : priceRange;
206
214
  }
207
215
 
208
- console.log('value----=====')
209
- console.log(value)
210
-
211
216
  return value;
212
217
  };
213
218
 
@@ -266,7 +271,8 @@ export const useProductFullDetail = props => {
266
271
  const {
267
272
  addConfigurableProductToCartMutation,
268
273
  addSimpleProductToCartMutation,
269
- product
274
+ product,
275
+ isPreview
270
276
  } = props;
271
277
 
272
278
  const [, { dispatch }] = useEventingContext();
@@ -651,7 +657,7 @@ export const useProductFullDetail = props => {
651
657
  isEverythingOutOfStock,
652
658
  outOfStockVariants,
653
659
  isAddToCartDisabled:
654
- isOutOfStock ||
660
+ isPreview || isOutOfStock ||
655
661
  isEverythingOutOfStock ||
656
662
  isMissingOptions ||
657
663
  isAddConfigurableLoading ||
@@ -13,8 +13,11 @@ export const GET_STORE_CONFIG_DATA = gql`
13
13
  `;
14
14
 
15
15
  export const GET_PRODUCT_DETAIL_QUERY = gql`
16
- query getProductDetailForProductPage($urlKey: String!) {
17
- products(filter: { url_key: { eq: $urlKey } }) {
16
+ query getProductDetailForProductPage($urlKey: String!, $productPreviewToken: String) {
17
+ products(
18
+ product_preview_token: $productPreviewToken,
19
+ filter: { url_key: { eq: $urlKey } }
20
+ ) {
18
21
  items {
19
22
  id
20
23
  uid
@@ -0,0 +1,121 @@
1
+ import { useQuery } from '@apollo/client';
2
+ import { useEffect, useMemo } from 'react';
3
+ import { useLocation } from 'react-router-dom';
4
+ import { useAppContext } from '@magento/peregrine/lib/context/app';
5
+
6
+ import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
7
+ import DEFAULT_OPERATIONS from './product.gql';
8
+ import { useEventingContext } from '@magento/peregrine/lib/context/eventing';
9
+
10
+ /**
11
+ * A [React Hook]{@link https://reactjs.org/docs/hooks-intro.html} that
12
+ * controls the logic for the Product Root Component.
13
+ *
14
+ * @kind function
15
+ *
16
+ * @param {object} props
17
+ * @param {Function} props.mapProduct - A function for updating products to the proper shape.
18
+ * @param {GraphQLAST} props.queries.getStoreConfigData - Fetches storeConfig product url suffix using a server query
19
+ * @param {GraphQLAST} props.queries.getProductQuery - Fetches product using a server query
20
+ *
21
+ * @returns {object} result
22
+ * @returns {Bool} result.error - Indicates a network error occurred.
23
+ * @returns {Bool} result.loading - Indicates the query is in flight.
24
+ * @returns {Bool} result.product - The product's details.
25
+ */
26
+ export const useProduct = props => {
27
+ const { mapProduct } = props;
28
+
29
+ const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
30
+ const { getStoreConfigData, getProductDetailQuery } = operations;
31
+ const { pathname, search } = useLocation();
32
+ const [
33
+ ,
34
+ {
35
+ actions: { setPageLoading }
36
+ }
37
+ ] = useAppContext();
38
+
39
+ const { data: storeConfigData } = useQuery(getStoreConfigData, {
40
+ fetchPolicy: 'cache-and-network',
41
+ nextFetchPolicy: 'cache-first'
42
+ });
43
+
44
+ const slug = pathname.split('/').pop();
45
+ const productUrlSuffix = storeConfigData?.storeConfig?.product_url_suffix;
46
+ const urlKey = productUrlSuffix ? slug.replace(productUrlSuffix, '') : slug;
47
+
48
+ const params = new URLSearchParams(search);
49
+ const productPreviewToken = params.get('preview');
50
+
51
+ const { error, loading, data } = useQuery(getProductDetailQuery, {
52
+ fetchPolicy: 'cache-and-network',
53
+ nextFetchPolicy: 'cache-first',
54
+ skip: !storeConfigData,
55
+ variables: {
56
+ urlKey,
57
+ productPreviewToken
58
+ }
59
+ });
60
+
61
+ const isBackgroundLoading = !!data && loading;
62
+
63
+ const product = useMemo(() => {
64
+ if (!data) {
65
+ // The product isn't in the cache and we don't have a response from GraphQL yet.
66
+ return null;
67
+ }
68
+
69
+ // Note: if a product is out of stock _and_ the backend specifies not to
70
+ // display OOS items, the items array will be empty.
71
+
72
+ // Only return the product that we queried for.
73
+ const product = data.products.items.find(
74
+ item => item.url_key === urlKey
75
+ );
76
+
77
+ if (!product) {
78
+ return null;
79
+ }
80
+
81
+ return mapProduct(product);
82
+ }, [data, mapProduct, urlKey]);
83
+
84
+ const [, { dispatch }] = useEventingContext();
85
+
86
+ // Update the page indicator if the GraphQL query is in flight.
87
+ useEffect(() => {
88
+ setPageLoading(isBackgroundLoading);
89
+ }, [isBackgroundLoading, setPageLoading]);
90
+
91
+ useEffect(() => {
92
+ if (!error && !loading && product) {
93
+ dispatch({
94
+ type: 'PRODUCT_PAGE_VIEW',
95
+ payload: {
96
+ id: product.id,
97
+ name: product.name,
98
+ sku: product.sku,
99
+ currency_code:
100
+ product?.price_range?.maximum_price?.final_price
101
+ ?.currency,
102
+ price: product.price,
103
+ price_range: {
104
+ maximum_price: {
105
+ final_price:
106
+ product?.price_range?.maximum_price?.final_price
107
+ ?.value
108
+ }
109
+ },
110
+ url_key: product.url_key
111
+ }
112
+ });
113
+ }
114
+ }, [error, loading, product, dispatch]);
115
+
116
+ return {
117
+ error,
118
+ loading,
119
+ product
120
+ };
121
+ };
@@ -0,0 +1,58 @@
1
+ import React, { Fragment } from 'react';
2
+ import { FormattedMessage } from 'react-intl';
3
+ import { string } from 'prop-types';
4
+ import { useProduct } from '@magento/peregrine/lib/talons/RootComponents/Product/useProduct';
5
+
6
+ import ErrorView from '@magento/venia-ui/lib/components/ErrorView';
7
+ import { StoreTitle, Meta } from '@magento/venia-ui/lib/components/Head';
8
+ import ProductFullDetail from '@magento/venia-ui/lib/components/ProductFullDetail';
9
+ import mapProduct from '@magento/venia-ui/lib/util/mapProduct';
10
+ import ProductShimmer from './product.shimmer';
11
+
12
+ /*
13
+ * As of this writing, there is no single Product query type in the M2.3 schema.
14
+ * The recommended solution is to use filter criteria on a Products query.
15
+ * However, the `id` argument is not supported. See
16
+ * https://github.com/magento/graphql-ce/issues/86
17
+ * TODO: Replace with a single product query when possible.
18
+ */
19
+
20
+ const Product = props => {
21
+ const { __typename: productType } = props;
22
+ const talonProps = useProduct({
23
+ mapProduct
24
+ });
25
+
26
+ const { error, loading, product } = talonProps;
27
+
28
+ if (loading && !product)
29
+ return <ProductShimmer productType={productType} />;
30
+ if (error && !product) return <ErrorView />;
31
+ if (!product) {
32
+ return <ErrorView />;
33
+ return (
34
+ <h1>
35
+ <FormattedMessage
36
+ id={'product.outOfStockTryAgain'}
37
+ defaultMessage={
38
+ 'This Product is currently out of stock. Please try again later.'
39
+ }
40
+ />
41
+ </h1>
42
+ );
43
+ }
44
+
45
+ return (
46
+ <Fragment>
47
+ <StoreTitle>{product.name}</StoreTitle>
48
+ <Meta name="description" content={product.meta_description} />
49
+ <ProductFullDetail product={product} />
50
+ </Fragment>
51
+ );
52
+ };
53
+
54
+ Product.propTypes = {
55
+ __typename: string.isRequired
56
+ };
57
+
58
+ export default Product;
@@ -38,6 +38,7 @@ import ProductLabel from '@riosst100/pwa-marketplace/src/components/ProductLabel
38
38
  import RFQ from '@riosst100/pwa-marketplace/src/components/RFQ';
39
39
  import LinkToOtherStores from '@riosst100/pwa-marketplace/src/components/LinkToOtherStores';
40
40
  import Collapsible from '@riosst100/pwa-marketplace/src/components/commons/Collapsible';
41
+ import { useLocation } from 'react-router-dom';
41
42
 
42
43
  // Correlate a GQL error message to a field. GQL could return a longer error
43
44
  // string but it may contain contextual info such as product id. We can use
@@ -75,7 +76,12 @@ const ProductDetailsCollapsible = (props) => {
75
76
  const ProductFullDetail = props => {
76
77
  const { product } = props;
77
78
 
78
- const talonProps = useProductFullDetail({ product });
79
+ const { search } = useLocation();
80
+
81
+ const params = new URLSearchParams(search);
82
+ const isPreview = params.get('preview');
83
+
84
+ const talonProps = useProductFullDetail({ product, isPreview });
79
85
 
80
86
  const {
81
87
  breadcrumbCategoryId,
@@ -438,9 +444,32 @@ const ProductFullDetail = props => {
438
444
  return result;
439
445
  }
440
446
 
447
+ const productPreviewMessages = isPreview ? (
448
+ <div
449
+ style={{
450
+ backgroundColor: "white", // Light gray background
451
+ border: "1px solid rgb(242 101 102)", // Subtle border
452
+ borderRadius: "5px", // Rounded corners
453
+ padding: "10px 15px", // Space inside the box
454
+ margin: "10px 0px 20px 0", // Space outside the box
455
+ fontSize: "14px", // Readable text size
456
+ color: "rgb(242 101 102)", // Dark gray text
457
+ }}
458
+ >
459
+ <span
460
+ style={{
461
+ fontWeight: "500", // Slightly bold text
462
+ }}
463
+ >
464
+ This is a preview of your product. Only you can see this page.
465
+ </span>
466
+ </div>
467
+ ) : null;
468
+
441
469
  return (
442
470
  <Fragment>
443
471
  {breadcrumbs}
472
+ {productPreviewMessages}
444
473
  <Form
445
474
  className={classes.root}
446
475
  data-cy="ProductFullDetail-root"