@riosst100/pwa-marketplace 3.0.0 → 3.0.1

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.
Files changed (50) hide show
  1. package/i18n/en_US.json +1 -1
  2. package/i18n/id_ID.json +1 -1
  3. package/package.json +1 -1
  4. package/src/componentOverrideMapping.js +1 -0
  5. package/src/components/CheckoutHeader/checkoutHeader.js +162 -0
  6. package/src/components/CheckoutHeader/checkoutHeader.module.css +171 -0
  7. package/src/components/CheckoutHeader/index.js +1 -0
  8. package/src/components/FavoriteSeller/AddToListButton/addToListButton.module.css +2 -2
  9. package/src/components/FilterTop/FilterBlockList/filterTopItem.module.css +2 -0
  10. package/src/components/SellerCoupon/index.js +1 -0
  11. package/src/components/SellerCoupon/sellerCoupon.js +84 -0
  12. package/src/components/SellerCoupon/sellerCoupon.module.css +110 -0
  13. package/src/components/SellerCoupon/sellerCouponCheckout.js +147 -0
  14. package/src/components/SellerCoupon/sellerCouponCheckout.module.css +85 -0
  15. package/src/components/SellerDetail/sellerDetail.js +10 -2
  16. package/src/components/SellerProducts/sellerProducts.js +4 -2
  17. package/src/overwrites/peregrine/lib/talons/CartPage/PriceSummary/usePriceSummary.js +10 -1
  18. package/src/overwrites/peregrine/lib/talons/CheckoutPage/checkoutPage.extended.gql.js +17 -1
  19. package/src/overwrites/peregrine/lib/talons/Header/useCartTrigger.js +82 -0
  20. package/src/overwrites/peregrine/lib/talons/ProductFullDetail/useProductFullDetail.js +17 -1
  21. package/src/overwrites/venia-ui/lib/components/Breadcrumbs/breadcrumbs.js +11 -11
  22. package/src/overwrites/venia-ui/lib/components/CartPage/PriceSummary/priceSummary.js +24 -6
  23. package/src/overwrites/venia-ui/lib/components/CartPage/ProductListing/productListing.js +6 -2
  24. package/src/overwrites/venia-ui/lib/components/CartPage/ProductListingBySeller/productListingBySeller.js +3 -1
  25. package/src/overwrites/venia-ui/lib/components/CartPage/cartPage.js +20 -4
  26. package/src/overwrites/venia-ui/lib/components/CheckoutPage/OrderSummary/orderSummary.js +1 -1
  27. package/src/overwrites/venia-ui/lib/components/CheckoutPage/PaymentInformation/paymentInformation.js +1 -1
  28. package/src/overwrites/venia-ui/lib/components/CheckoutPage/PaymentInformation/paymentMethods.js +1 -1
  29. package/src/overwrites/venia-ui/lib/components/CheckoutPage/PriceAdjustments/priceAdjustments.js +74 -6
  30. package/src/overwrites/venia-ui/lib/components/CheckoutPage/ShippingInformation/shippingInformation.js +3 -3
  31. package/src/overwrites/venia-ui/lib/components/CheckoutPage/checkoutPage.js +53 -2
  32. package/src/overwrites/venia-ui/lib/components/CheckoutPage/checkoutPage.module.css +1 -1
  33. package/src/overwrites/venia-ui/lib/components/FilterModal/FilterList/filterItemRadio.js +1 -2
  34. package/src/overwrites/venia-ui/lib/components/FilterModal/FilterList/filterItemRadioGroup.js +10 -27
  35. package/src/overwrites/venia-ui/lib/components/FilterModal/FilterList/subFilterItemRadioGroup.js +1 -1
  36. package/src/overwrites/venia-ui/lib/components/Footer/footer.js +14 -4
  37. package/src/overwrites/venia-ui/lib/components/Footer/footer.module.css +16 -4
  38. package/src/overwrites/venia-ui/lib/components/Gallery/item.js +9 -8
  39. package/src/overwrites/venia-ui/lib/components/Header/accountTrigger.js +3 -3
  40. package/src/overwrites/venia-ui/lib/components/Header/cartTrigger.js +9 -6
  41. package/src/overwrites/venia-ui/lib/components/Header/cartTrigger.module.css +1 -1
  42. package/src/overwrites/venia-ui/lib/components/Header/header.js +2 -0
  43. package/src/overwrites/venia-ui/lib/components/Header/wishlistTrigger.js +4 -4
  44. package/src/overwrites/venia-ui/lib/components/Main/main.js +9 -4
  45. package/src/overwrites/venia-ui/lib/components/Main/main.module.css +2 -2
  46. package/src/overwrites/venia-ui/lib/components/ProductFullDetail/productFullDetail.js +100 -72
  47. package/src/overwrites/venia-ui/lib/components/ToastContainer/toast.module.css +3 -3
  48. package/src/talons/Header/useCartTrigger.js +82 -0
  49. package/src/talons/Seller/seller.gql.js +42 -1
  50. package/src/talons/Seller/useSeller.js +25 -2
@@ -3,7 +3,9 @@ import { shape, string } from 'prop-types';
3
3
  import { Link, Route } from 'react-router-dom';
4
4
 
5
5
  import AccountTrigger from '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/Header/accountTrigger';
6
+
6
7
  import CartTrigger from '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/Header/cartTrigger';
8
+
7
9
  import WishlistTrigger from '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/Header/wishlistTrigger';
8
10
  import NavTrigger from '@magento/venia-ui/lib/components/Header/navTrigger';
9
11
  import SearchTrigger from '@magento/venia-ui/lib/components/Header/searchTrigger';
@@ -1,9 +1,8 @@
1
1
  import React from 'react'
2
2
  import { Link } from 'react-router-dom';
3
+ import Icon from '@magento/venia-ui/lib/components/Icon';
3
4
  import resourceUrl from '@magento/peregrine/lib/util/makeUrl';
4
- import { Heart } from 'iconsax-react';
5
- import { darkBlue } from '@riosst100/pwa-marketplace/src/theme/vars';
6
- import cn from 'classnames';
5
+ import { Heart as HeartIcon } from 'react-feather';
7
6
 
8
7
  const wishlistTrigger = () => {
9
8
  return (
@@ -14,7 +13,8 @@ const wishlistTrigger = () => {
14
13
  className={''}
15
14
  data-cy="wishlistLink"
16
15
  >
17
- <Heart size="20" color={darkBlue} className={cn('stroke-0')} variant="Outline" />
16
+ <Icon src={HeartIcon} attrs={{ width: 20 }} />
17
+ {/* <Heart size="20" color={darkBlue} className={cn('stroke-0')} variant="Outline" /> */}
18
18
  </Link>
19
19
  </div>
20
20
  )
@@ -6,6 +6,7 @@ import { useScrollLock } from '@magento/peregrine';
6
6
  import { useStyle } from '@magento/venia-ui/lib/classify';
7
7
  import Footer from '@magento/venia-ui/lib/components/Footer';
8
8
  import Header from '@magento/venia-ui/lib/components/Header';
9
+ import CheckoutHeader from '@riosst100/pwa-marketplace/src/components/CheckoutHeader';
9
10
  import defaultClasses from './main.module.css';
10
11
  import cn from 'classnames';
11
12
 
@@ -21,10 +22,14 @@ const Main = props => {
21
22
  useScrollLock(isMasked);
22
23
 
23
24
  return (
24
- <main className={rootClass}>
25
- {!isCheckoutPage && <Header />}
26
- <div className={cn(pageClass, 'main-content-container pb-16 !min-h-[50vh]')}>{children}</div>
27
- {!isCheckoutPage && <Footer />}
25
+ <main className={rootClass} style={{
26
+ "minHeight": "100vh",
27
+ "display": "flex",
28
+ "flexDirection": "column"
29
+ }}>
30
+ {isCheckoutPage ? <CheckoutHeader /> : <Header />}
31
+ <div style={{"flex": 1}} className={cn(pageClass, isCheckoutPage ? 'max-w-[1000px] main-content-container pb-16 !min-h-[50vh]' : 'max-w-[1300px] main-content-container pb-16 !min-h-[50vh]')}>{children}</div>
32
+ <Footer />
28
33
  </main>
29
34
  );
30
35
  };
@@ -10,9 +10,9 @@
10
10
  }
11
11
 
12
12
  .page {
13
- composes: md_max-w-screen-md from global;
14
- composes: lg_max-w-[1300px] from global;
13
+ /* composes: md_max-w-screen-md from global; */
15
14
  composes: mx-auto from global;
15
+ composes: w-full from global;
16
16
  composes: my-0 from global;
17
17
  composes: px-[15px] from global;
18
18
  min-height: 40rem;
@@ -38,6 +38,8 @@ import RFQ from '@riosst100/pwa-marketplace/src/components/RFQ';
38
38
  import LinkToOtherStores from '@riosst100/pwa-marketplace/src/components/LinkToOtherStores';
39
39
  import Collapsible from '@riosst100/pwa-marketplace/src/components/commons/Collapsible';
40
40
  import { useLocation } from 'react-router-dom';
41
+ import Icon from '@magento/venia-ui/lib/components/Icon';
42
+ import { ShoppingCart } from 'react-feather';
41
43
 
42
44
  import { totalListings, lowestPrice } from '@riosst100/pwa-marketplace/src/components/CrossSeller/crossSellerBuy';
43
45
 
@@ -57,6 +59,7 @@ const ERROR_FIELD_TO_MESSAGE_MAPPING = {
57
59
 
58
60
  const ProductDetailsCollapsible = (props) => {
59
61
  const { data } = props;
62
+
60
63
  return (
61
64
  <>
62
65
  {data.map((_data) => (
@@ -99,13 +102,10 @@ const ProductFullDetail = props => {
99
102
  customAttributes,
100
103
  wishlistButtonProps,
101
104
  sellerDetails,
102
- productReviewData,
103
- loadingProductReview,
104
- errorProductReview,
105
- ratingsMetadataData,
106
- loadingRatingsMetadata,
107
- handleSubmitReview,
108
- defaultNickname
105
+ handleToastAction,
106
+ addToCartResponseData,
107
+ errorAddingProductToCart,
108
+ isAddProductLoading,
109
109
  } = talonProps;
110
110
 
111
111
  const [, { addToast }] = useToasts();
@@ -135,59 +135,69 @@ const ProductFullDetail = props => {
135
135
  currentProduct={productDetails.name}
136
136
  />
137
137
  ) : null;
138
+
138
139
  // Fill a map with field/section -> error.
139
140
  const errors = new Map();
140
- if (errorMessage) {
141
- Object.keys(ERROR_MESSAGE_TO_FIELD_MAPPING).forEach(key => {
142
- if (errorMessage.includes(key)) {
143
- const target = ERROR_MESSAGE_TO_FIELD_MAPPING[key];
144
- const message = ERROR_FIELD_TO_MESSAGE_MAPPING[target];
145
- errors.set(target, message);
146
- }
147
- });
148
141
 
149
- // Handle cases where a user token is invalid or expired. Preferably
150
- // this would be handled elsewhere with an error code and not a string.
151
- if (errorMessage.includes('The current user cannot')) {
152
- errors.set('form', [
153
- new Error(
154
- formatMessage({
155
- id: 'productFullDetail.errorToken',
156
- defaultMessage:
157
- 'There was a problem with your cart. Please sign in again and try adding the item once more.'
158
- })
159
- )
160
- ]);
161
- }
142
+ useEffect(() => {
143
+ if (errorMessage) {
144
+ Object.keys(ERROR_MESSAGE_TO_FIELD_MAPPING).forEach(key => {
145
+ if (errorMessage.includes(key)) {
146
+ const target = ERROR_MESSAGE_TO_FIELD_MAPPING[key];
147
+ const message = ERROR_FIELD_TO_MESSAGE_MAPPING[target];
148
+ errors.set(target, message);
149
+ }
150
+ });
162
151
 
163
- // Handle cases where a cart wasn't created properly.
164
- if (
165
- errorMessage.includes('Variable "$cartId" got invalid value null')
166
- ) {
167
- errors.set('form', [
168
- new Error(
169
- formatMessage({
170
- id: 'productFullDetail.errorCart',
171
- defaultMessage:
172
- 'There was a problem with your cart. Please refresh the page and try adding the item once more.'
173
- })
174
- )
175
- ]);
176
- }
152
+ addToast({
153
+ type: 'error',
154
+ message: 'Desired quantity not available. You already have all of these in your cart.',
155
+ timeout: 3000
156
+ });
177
157
 
178
- // An unknown error should still present a readable message.
179
- if (!errors.size) {
180
- errors.set('form', [
181
- new Error(
182
- formatMessage({
183
- id: 'productFullDetail.errorUnknown',
184
- defaultMessage:
185
- 'Could not add item to cart. Please check required options and try again.'
186
- })
187
- )
188
- ]);
158
+ // Handle cases where a user token is invalid or expired. Preferably
159
+ // this would be handled elsewhere with an error code and not a string.
160
+ // if (errorMessage.includes('The current user cannot')) {
161
+ // errors.set('form', [
162
+ // new Error(
163
+ // formatMessage({
164
+ // id: 'productFullDetail.errorToken',
165
+ // defaultMessage:
166
+ // 'There was a problem with your cart. Please sign in again and try adding the item once more.'
167
+ // })
168
+ // )
169
+ // ]);
170
+ // }
171
+
172
+ // Handle cases where a cart wasn't created properly.
173
+ // if (
174
+ // errorMessage.includes('Variable "$cartId" got invalid value null')
175
+ // ) {
176
+ // errors.set('form', [
177
+ // new Error(
178
+ // formatMessage({
179
+ // id: 'productFullDetail.errorCart',
180
+ // defaultMessage:
181
+ // 'There was a problem with your cart. Please refresh the page and try adding the item once more.'
182
+ // })
183
+ // )
184
+ // ]);
185
+ // }
186
+
187
+ // An unknown error should still present a readable message.
188
+ // if (!errors.size) {
189
+ // errors.set('form', [
190
+ // new Error(
191
+ // formatMessage({
192
+ // id: 'productFullDetail.errorUnknown',
193
+ // defaultMessage:
194
+ // 'Could not add item to cart. Please check required options and try again.'
195
+ // })
196
+ // )
197
+ // ]);
198
+ // }
189
199
  }
190
- }
200
+ }, [errorMessage]);
191
201
 
192
202
  const customAttributesDetails = useMemo(() => {
193
203
  const list = [];
@@ -499,17 +509,7 @@ const ProductFullDetail = props => {
499
509
  {
500
510
  id: 'product-reviews',
501
511
  title: 'Reviews',
502
- content: <ProductReviews
503
- className={cn(contentContainerClass, classes.contentContainerTabOverride)}
504
- productReviewData={productReviewData}
505
- loadingProductReview={loadingProductReview}
506
- errorProductReview={errorProductReview}
507
- ratingsMetadataData={ratingsMetadataData}
508
- loadingRatingsMetadata={loadingRatingsMetadata}
509
- handleSubmitReview={handleSubmitReview}
510
- defaultNickname={defaultNickname}
511
- product={product}
512
- />
512
+ content: <ProductReviews className={cn(contentContainerClass, classes.contentContainerTabOverride)} />
513
513
  }
514
514
  ];
515
515
 
@@ -552,16 +552,11 @@ const ProductFullDetail = props => {
552
552
  </div>
553
553
  ) : null;
554
554
 
555
+ const AlertCircleIcon = <Icon src={ShoppingCart} attrs={{ width: 20 }} />;
556
+
555
557
  const handleAddToCart = async (...args) => {
556
558
  try {
557
559
  await originalHandleAddToCart(...args);
558
- addToast({
559
- type: 'success',
560
- message: formatMessage({
561
- id: 'productFullDetail.addToCartSuccess',
562
- defaultMessage: 'Product successfully added to cart!'
563
- })
564
- });
565
560
  } catch (e) {
566
561
  addToast({
567
562
  type: 'error',
@@ -573,6 +568,39 @@ const ProductFullDetail = props => {
573
568
  }
574
569
  };
575
570
 
571
+ useEffect(() => {
572
+ if (
573
+ addToCartResponseData
574
+ && !addToCartResponseData?.addProductsToCart?.user_errors.length
575
+ && !isAddProductLoading
576
+ && !errorAddingProductToCart
577
+ ) {
578
+ addToast({
579
+ type: 'success',
580
+ icon: AlertCircleIcon,
581
+ message: formatMessage({
582
+ id: 'productFullDetail.addToCartSuccess',
583
+ defaultMessage: '1 item added to cart.'
584
+ }),
585
+ timeout: 5000,
586
+ dismissable: true,
587
+ hasDismissAction: true,
588
+ dismissActionText: formatMessage({
589
+ id: 'productFullDetail.addToCartContinueShipping',
590
+ defaultMessage: 'Continue Shopping'
591
+ }),
592
+ actionText: formatMessage({
593
+ id: 'productFullDetail.addToCartViewCart',
594
+ defaultMessage: 'View Shopping Cart'
595
+ }),
596
+ onAction: removeToast =>
597
+ handleToastAction(
598
+ removeToast
599
+ )
600
+ });
601
+ }
602
+ }, [addToCartResponseData, errorAddingProductToCart, isAddProductLoading]);
603
+
576
604
  useEffect(() => {
577
605
  const toastRoot = document.getElementById('toast-root');
578
606
  if (toastRoot) {
@@ -26,7 +26,7 @@
26
26
  grid-auto-columns: min-content auto min-content;
27
27
  width: 100%;
28
28
  box-shadow: none;
29
- border-bottom-width: 3px !important;
29
+ border-bottom-width: 2px !important;
30
30
  border-radius: 10px;
31
31
  }
32
32
 
@@ -89,11 +89,11 @@
89
89
  composes: root;
90
90
 
91
91
  background-color: #f1f9f4;
92
- border: 2px solid #51dc6b;
92
+ border: 1px solid #51dc6b;
93
93
  }
94
94
 
95
95
  .successToast > .icon {
96
- --stroke: #51dc6b;
96
+ /* --stroke: #51dc6b; */
97
97
  }
98
98
 
99
99
  .message {
@@ -0,0 +1,82 @@
1
+ import { useCallback, useState, useEffect } from 'react';
2
+ import { useQuery } from '@apollo/client';
3
+ import { useHistory, useLocation } from 'react-router-dom';
4
+
5
+ import { useCartContext } from '@magento/peregrine/lib/context/cart';
6
+ import { useDropdown } from '@magento/peregrine/lib/hooks/useDropdown';
7
+
8
+ /**
9
+ * Routes to hide the mini cart on.
10
+ */
11
+ // const DENIED_MINI_CART_ROUTES = ['/checkout'];
12
+ const DENIED_MINI_CART_ROUTES = [];
13
+
14
+ /**
15
+ *
16
+ * @param {DocumentNode} props.queries.getItemCountQuery query to get the total cart items count
17
+ *
18
+ * @returns {
19
+ * itemCount: Number,
20
+ * miniCartIsOpen: Boolean,
21
+ * handleLinkClick: Function,
22
+ * handleTriggerClick: Function,
23
+ * miniCartRef: Function,
24
+ * hideCartTrigger: Function,
25
+ * setMiniCartIsOpen: Function
26
+ * }
27
+ */
28
+ export const useCartTrigger = props => {
29
+ const {
30
+ queries: { getItemCountQuery }
31
+ } = props;
32
+
33
+ const [{ cartId }] = useCartContext();
34
+ const history = useHistory();
35
+ const location = useLocation();
36
+ const [isHidden, setIsHidden] = useState(() =>
37
+ DENIED_MINI_CART_ROUTES.includes(location.pathname)
38
+ );
39
+
40
+ const {
41
+ elementRef: miniCartRef,
42
+ expanded: miniCartIsOpen,
43
+ setExpanded: setMiniCartIsOpen,
44
+ triggerRef: miniCartTriggerRef
45
+ } = useDropdown();
46
+
47
+ const { data } = useQuery(getItemCountQuery, {
48
+ fetchPolicy: 'cache-and-network',
49
+ variables: {
50
+ cartId
51
+ },
52
+ skip: !cartId,
53
+ errorPolicy: 'all'
54
+ });
55
+
56
+ const itemCount = data?.cart?.total_summary_quantity_including_config || 0;
57
+
58
+ const handleTriggerClick = useCallback(() => {
59
+ // Open the mini cart.
60
+ setMiniCartIsOpen(isOpen => !isOpen);
61
+ }, [setMiniCartIsOpen]);
62
+
63
+ const handleLinkClick = useCallback(() => {
64
+ // Send the user to the cart page.
65
+ history.push('/cart');
66
+ }, [history]);
67
+
68
+ useEffect(() => {
69
+ setIsHidden(DENIED_MINI_CART_ROUTES.includes(location.pathname));
70
+ }, [location]);
71
+
72
+ return {
73
+ handleLinkClick,
74
+ handleTriggerClick,
75
+ itemCount,
76
+ miniCartIsOpen,
77
+ miniCartRef,
78
+ hideCartTrigger: isHidden,
79
+ setMiniCartIsOpen,
80
+ miniCartTriggerRef
81
+ };
82
+ };
@@ -162,7 +162,48 @@ export const GET_SELLER_DETAIL_QUERY = gql`
162
162
  }
163
163
  `;
164
164
 
165
+ export const GET_COUPON_CODE_QUERY = gql`
166
+ query getSellerCoupons(
167
+ $sellerUrl: String!
168
+ $pageSize: Int
169
+ $currentPage: Int
170
+ $filters: CouponCodeFilterInput
171
+ ) {
172
+ sellerCoupons(
173
+ sellerUrl: $sellerUrl
174
+ pageSize: $pageSize
175
+ currentPage: $currentPage
176
+ filters: $filters
177
+ ) {
178
+ items {
179
+ code
180
+ coupon_id
181
+ couponcode_id
182
+ created_at
183
+ description
184
+ discount_amount
185
+ expiration_date
186
+ from_date
187
+ is_active
188
+ name
189
+ seller_id
190
+ times_used
191
+ to_date
192
+ type
193
+ uses_per_customer
194
+ }
195
+ page_info {
196
+ current_page
197
+ page_size
198
+ total_pages
199
+ }
200
+ total_count
201
+ }
202
+ }
203
+ `;
204
+
165
205
  export default {
166
206
  getStoreConfigData: GET_STORE_CONFIG_DATA,
167
- getSellerDetailQuery: GET_SELLER_DETAIL_QUERY
207
+ getSellerDetailQuery: GET_SELLER_DETAIL_QUERY,
208
+ getCouponCodeQuery: GET_COUPON_CODE_QUERY,
168
209
  };
@@ -13,7 +13,7 @@ export const useSeller = props => {
13
13
  const { formatMessage } = useIntl();
14
14
 
15
15
  const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
16
- const { getStoreConfigData, getSellerDetailQuery } = operations;
16
+ const { getStoreConfigData, getSellerDetailQuery, getCouponCodeQuery } = operations;
17
17
  const { pathname } = useLocation();
18
18
  const [
19
19
  ,
@@ -45,6 +45,26 @@ export const useSeller = props => {
45
45
  }
46
46
  });
47
47
 
48
+ const {
49
+ data: couponData,
50
+ error: couponError,
51
+ loading: couponLoading
52
+ } = useQuery(getCouponCodeQuery, {
53
+ fetchPolicy: 'cache-and-network',
54
+ nextFetchPolicy: 'cache-first',
55
+ variables: {
56
+ sellerUrl: urlKey,
57
+ pageSize: 20,
58
+ currentPage: 1,
59
+ filters: {
60
+ is_public: {
61
+ eq: '1'
62
+ }
63
+ }
64
+ },
65
+ skip: !urlKey
66
+ });
67
+
48
68
  const isBackgroundLoading = !!data && loading;
49
69
 
50
70
  const seller = useMemo(() => {
@@ -84,6 +104,9 @@ export const useSeller = props => {
84
104
  error,
85
105
  loading,
86
106
  seller,
87
- favoriteSellerButtonProps
107
+ favoriteSellerButtonProps,
108
+ couponData,
109
+ couponError,
110
+ couponLoading
88
111
  };
89
112
  };