@riosst100/pwa-marketplace 2.8.0 → 2.8.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.
package/i18n/en_US.json CHANGED
@@ -368,6 +368,12 @@
368
368
  "productFullDetail.outOfStockProduct": "This item is currently out of stock",
369
369
  "productFullDetail.addToCartSuccess": "Product successfully added to cart!",
370
370
  "productFullDetail.addToCartError": "Failed to add product to cart.",
371
+ "favoriteSeller.toastRemoveSuccess": "Successfully removed favorite seller.",
372
+ "favoriteSeller.toastRemoveError": "Failed to remove favorite seller.",
373
+ "favoriteSeller.removing": "Removing...",
374
+ "favoriteSeller.toastUnfollowSuccess": "Successfully unfollowed seller.",
375
+ "favoriteSeller.toastUnfollowError": "Failed to unfollow seller.",
376
+ "favoriteSeller.unfollowing": "Unfollowing...",
371
377
  "productImageCarousel.previousButtonAriaLabel": "Previous Image",
372
378
  "productImageCarousel.nextButtonAriaLabel": "Next Image",
373
379
  "productList.each": " ea.",
package/i18n/id_ID.json CHANGED
@@ -369,6 +369,12 @@
369
369
  "productFullDetail.outOfStockProduct": "This item is currently out of stock",
370
370
  "productFullDetail.addToCartSuccess": "Produk berhasil ditambahkan ke keranjang!",
371
371
  "productFullDetail.addToCartError": "Gagal menambahkan produk ke keranjang.",
372
+ "favoriteSeller.toastRemoveSuccess": "Berhasil menghapus penjual favorit.",
373
+ "favoriteSeller.toastRemoveError": "Gagal menghapus penjual favorit.",
374
+ "favoriteSeller.removing": "Menghapus...",
375
+ "favoriteSeller.toastUnfollowSuccess": "Berhasil berhenti mengikuti penjual.",
376
+ "favoriteSeller.toastUnfollowError": "Gagal berhenti mengikuti penjual.",
377
+ "favoriteSeller.unfollowing": "Sedang berhenti mengikuti...",
372
378
  "productImageCarousel.previousButtonAriaLabel": "Previous Image",
373
379
  "productImageCarousel.nextButtonAriaLabel": "Next Image",
374
380
  "productList.each": " ea.",
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.8.0",
4
+ "version": "2.8.1",
5
5
  "main": "src/index.js",
6
6
  "pwa-studio": {
7
7
  "targets": {
@@ -11,6 +11,7 @@ import { useCommonToasts } from '@magento/venia-ui/lib/components/Wishlist/AddTo
11
11
 
12
12
  const HeartIcon = <Heart color='#f76b1c' size={14} variant="Outline" className='stroke-[#f76b1c]' />;
13
13
 
14
+
14
15
  const AddToFavoriteListButton = props => {
15
16
  const talonProps = useAddToFavoriteListButton(props);
16
17
  const buttonRef = useRef();
@@ -21,7 +22,8 @@ const AddToFavoriteListButton = props => {
21
22
  errorToastProps,
22
23
  isSelected,
23
24
  loginToastProps,
24
- successToastProps
25
+ successToastProps,
26
+ isLoading
25
27
  } = talonProps;
26
28
 
27
29
  useCommonToasts({ errorToastProps, loginToastProps, successToastProps });
@@ -30,10 +32,15 @@ const AddToFavoriteListButton = props => {
30
32
  const classes = useStyle(defaultClasses, props.classes);
31
33
  const buttonClass = isSelected ? classes.root_selected : classes.root;
32
34
 
35
+ // Only hide text on mobile for follow, always show for unfollow
36
+ const textClass = isSelected
37
+ ? 'text-[#f76b1c] text-[14px] font-medium whitespace-nowrap'
38
+ : `text-[#f76b1c] text-[14px] font-medium whitespace-nowrap ${props.hideTextOnMobile ? 'md_block xs_hidden' : ''}`;
39
+
33
40
  return (
34
- <button ref={buttonRef} className={buttonClass} {...ariaButtonProps}>
35
- {props.icon}
36
- {buttonText && <span className={`text-[#f76b1c] text-[14px] font-medium whitespace-nowrap ${props.hideTextOnMobile ? 'md_block xs_hidden' : ''}`}>{buttonText}</span>}
41
+ <button ref={buttonRef} className={buttonClass} {...ariaButtonProps} disabled={isLoading}>
42
+ {!isSelected && props.icon}
43
+ {buttonText && <span className={textClass}>{buttonText}</span>}
37
44
  </button>
38
45
  );
39
46
  };
@@ -1,17 +1,22 @@
1
+
1
2
  .root {
2
3
  composes: gap-x-2xs from global;
3
4
  composes: inline-flex from global;
4
5
  composes: items-center from global;
5
- min-height: 3rem;
6
+ /* min-height: 3rem; */
6
7
  composes: min-w-[3rem] from global;
8
+ border: 1px solid #f76b1c;
9
+ border-radius: 30px;
10
+ background: #fff;
11
+ color: #f76b1c;
12
+ box-sizing: border-box;
13
+ padding: 8px 14px;
14
+ font-weight: 500;
15
+ font-size: 14px;
16
+ transition: background 0.2s, color 0.2s;
7
17
  }
8
18
 
9
19
  .root_selected {
10
20
  composes: root;
11
-
12
- --selectedColor: rgb(var(--venia-global-color-red-400));
13
- --fill: var(--selectedColor);
14
- --stroke: var(--selectedColor);
15
-
16
21
  composes: no-underline from global;
17
22
  }
@@ -2,31 +2,40 @@ import React from 'react';
2
2
  import { StoreTitle } from '@magento/venia-ui/lib/components/Head';
3
3
  import { useIntl } from 'react-intl';
4
4
  import Item from './item';
5
+ import useFavoriteSellerList from '@riosst100/pwa-marketplace/src/talons/FavoriteSeller/FavoriteSellerList/useFavoriteSellerList';
5
6
 
6
- const favoriteSeller = () => {
7
-
7
+ const FavoriteSeller = () => {
8
8
  const { formatMessage } = useIntl();
9
9
  const PAGE_TITLE = formatMessage({
10
10
  id: 'favoriteSellerPage.pageTitleText',
11
11
  defaultMessage: 'Favorite Seller'
12
12
  });
13
13
 
14
+ // Fetch favorite seller list
15
+ const { data, loading, error, refetch } = useFavoriteSellerList();
16
+
14
17
  return (
15
18
  <div className='relative'>
16
19
  <StoreTitle>{PAGE_TITLE}</StoreTitle>
17
20
  <div aria-live="polite" className="text-xl font-medium text-left mb-[30px]">
18
21
  {PAGE_TITLE}
19
22
  </div>
20
-
21
- <div className='flex flex-col gap-5'>
22
- {
23
- [...Array(5)].map(() => (
24
- <Item />
25
- ))
26
- }
27
- </div>
23
+ {loading ? (
24
+ <div>Loading...</div>
25
+ ) : (
26
+ <div className='flex flex-col gap-5'>
27
+ {error && <div>Error loading favorite sellers.</div>}
28
+ {data && data.items && data.items.length > 0 ? (
29
+ data.items.map(sellerItem => (
30
+ <Item key={sellerItem.id} sellerItem={sellerItem} refetchFavoriteSellerList={refetch} />
31
+ ))
32
+ ) : !error ? (
33
+ <div>No favorite sellers found.</div>
34
+ ) : null}
35
+ </div>
36
+ )}
28
37
  </div>
29
- )
30
- }
38
+ );
39
+ };
31
40
 
32
- export default favoriteSeller
41
+ export default FavoriteSeller;
@@ -5,81 +5,82 @@ import Image from '@magento/venia-ui/lib/components/Image';
5
5
  import Verify from '@riosst100/pwa-marketplace/src/components/CrossSeller/verifyIcon';
6
6
  import Star from '@riosst100/pwa-marketplace/src/components/CrossSeller/starIcon';
7
7
  import logoImage from '@riosst100/pwa-marketplace/src/components/CrossSeller/logo_seller.png';
8
- import { Share, Trash } from 'iconsax-react';
8
+ import { Share } from 'iconsax-react';
9
9
  import SocialShare from '@riosst100/pwa-marketplace/src/components/SocialMediaShare';
10
10
  import { X } from 'react-feather';
11
11
  import Modal from '@riosst100/pwa-marketplace/src/components/Modal';
12
12
  import cn from 'classnames';
13
13
  import { primary900 } from '@riosst100/pwa-marketplace/src/theme/vars';
14
- import { FormattedMessage } from 'react-intl';
14
+ import { FormattedMessage, useIntl } from 'react-intl';
15
+ import useRemoveFavoriteSeller from '@riosst100/pwa-marketplace/src/talons/FavoriteSeller/FavoriteSellerList/useRemoveFavoriteSeller';
16
+ import { useState } from 'react';
17
+ import { useToasts } from '@magento/peregrine';
15
18
 
16
- const item = () => {
17
- const [open, setOpen] = React.useState(false);
19
+ const Item = ({ sellerItem, refetchFavoriteSellerList }) => {
20
+ const [open, setOpen] = useState(false);
21
+ const { remove, loading: removing } = useRemoveFavoriteSeller();
22
+ const [, { addToast }] = useToasts();
23
+ const { formatMessage } = useIntl();
18
24
 
19
- const handleRemoveFromFavorite = () => {
20
- alert('remove fav seller')
21
- }
25
+ const handleRemoveFromFavorite = async () => {
26
+ try {
27
+ await remove([sellerItem.seller.seller_id]);
28
+ addToast({
29
+ type: 'success',
30
+ message: formatMessage({
31
+ id: 'favoriteSeller.toastUnfollowSuccess',
32
+ defaultMessage: 'Successfully unfollowed seller.'
33
+ }),
34
+ timeout: 3000
35
+ });
36
+ if (typeof refetchFavoriteSellerList === 'function') {
37
+ await refetchFavoriteSellerList();
38
+ }
39
+ } catch (e) {
40
+ addToast({
41
+ type: 'error',
42
+ message: formatMessage({
43
+ id: 'favoriteSeller.toastUnfollowError',
44
+ defaultMessage: 'Failed to unfollow seller.'
45
+ }),
46
+ timeout: 3000
47
+ });
48
+ console.error('Failed to unfollow seller:', e);
49
+ }
50
+ };
22
51
 
23
52
  const handleGoToSellerPage = () => {
24
- alert('to seller page')
25
- }
53
+ if (sellerItem?.seller?.url) {
54
+ window.location.href = sellerItem.seller.url;
55
+ } else {
56
+ alert('to seller page');
57
+ }
58
+ };
26
59
 
27
60
  return (
28
61
  <>
29
- <Modal
30
- open={open}
31
- setOpen={setOpen}
32
- className={cn(
33
- 'max-w-max !min-h-auto px-[30px] pt-[30px] pb-10',
34
- )}
35
- >
36
- <div className='social_share-container flex flex-col gap-y-7'>
37
- <div className='flex justify-between'>
38
- <div className='text-lg font-medium'>
39
- Share to your friends
40
- </div>
41
- <button onClick={() => { setOpen(!open) }} >
42
- <X size={24} color={primary900} />
43
- </button>
44
- </div>
45
- <div className='flex flex-row border border-gray-100 rounded-md px-5 py-2.5 gap-x-2.5 items-center'>
46
- <div className='flex flex-col'>
47
- <div className='text-[14px] font-normal'>
48
- Zen Market.TCG
49
- </div>
50
- <div className='text-[12px] font-normal text-gray-200'>
51
- zenmarket-tcg.link
52
- </div>
53
- </div>
62
+ <div className='border border-gray-100 rounded-md p-5 flex flex-col md_flex-row justify-between gap-y-4 relative'>
63
+ {removing && (
64
+ <div className="absolute inset-0 bg-white bg-opacity-60 flex items-center justify-center z-10">
65
+ <span className="text-sm text-gray-700">
66
+ <FormattedMessage
67
+ id="favoriteSeller.unfollowing"
68
+ defaultMessage="Unfollowing..."
69
+ />
70
+ </span>
54
71
  </div>
55
- <SocialShare rootClassName="justify-center" />
56
- </div>
57
- </Modal>
58
- <div className='border border-gray-100 rounded-md p-5 flex flex-col md_flex-row justify-between gap-y-4'>
72
+ )}
59
73
  <div className='seller_info-container flex flex-row gap-x-[15px]'>
60
- <div className='logo_wrapper w-[100px] h-[100px]'>
61
- <Image
62
- alt='seller name'
63
- className="relative mt-[-5px]"
64
- src={logoImage}
65
- />
66
- </div>
67
74
  <div className='flex flex-col gap-y-[15px]'>
68
75
  <div className='flex flex-col gap-[6px]'>
69
76
  <div className='seller_summary-wrapper flex flex-row gap-x-2.5 items-center'>
70
77
  <div className='seller_name text-lg font-medium leading-6'>
71
- Zen Market
72
- </div>
73
- <div className='seller_badge flex flex-row gap-x-[5px] items-center leading-6'>
74
- <Verify />
75
- <span className='text-xs font-medium text-gray-600-transparent capitalize'>
76
- Verified
77
- </span>
78
+ {sellerItem?.seller?.name || '-'}
78
79
  </div>
79
80
  </div>
80
81
  <div className='flex flex-row gap-x-[5px] items-center'>
81
82
  <span className='font-normal text-[12px] text-gray-200 '>
82
- Jurong West
83
+ {sellerItem?.seller?.description || '-'}
83
84
  </span>
84
85
  </div>
85
86
  </div>
@@ -87,54 +88,36 @@ const item = () => {
87
88
  <Button
88
89
  classes={{
89
90
  content: 'gap-1.5 grid-flow-col inline-grid items-center justify-center justify-items-center capitalize font-medium text-[14px]',
90
- rootClass: 'py-[0px] h-9 hover_border-blue-700'
91
+ rootClass: 'py-[0px] h-9 hover_border-orange-500 border-orange-500 text-[#f76b1c]'
91
92
  }}
92
93
  onClick={handleGoToSellerPage}
94
+ variant="outlined"
93
95
  >
94
96
  <FormattedMessage
95
97
  id={'favoriteSeller.visitStore'}
96
98
  defaultMessage={'Visit Store'}
97
99
  />
98
100
  </Button>
99
- <div
100
- className='flex items-center justify-center gap-[5px] p-[9px] relative rounded-[30px] overflow-hidden border border-solid border-blue-600 hover_border-blue-700 cursor-pointer w-9 h-9'
101
- onClick={() => { setOpen(!open) }}
101
+ <Button
102
+ classes={{
103
+ content: 'gap-1.5 grid-flow-col inline-grid items-center justify-center justify-items-center capitalize font-medium text-[14px]',
104
+ rootClass: 'py-[0px] h-9 hover_border-orange-500 border-orange-500 text-[#f76b1c]'
105
+ }}
106
+ onClick={handleRemoveFromFavorite}
107
+ disabled={removing}
108
+ variant="outlined"
102
109
  >
103
- <Share
104
- size="15"
105
- className='text-blue-600 group-hover_text-blue-800 left-[-1px]'
110
+ <FormattedMessage
111
+ id={'favoriteSeller.unfollow'}
112
+ defaultMessage={'Unfollow'}
106
113
  />
107
- </div>
108
- </div>
109
- </div>
110
- </div>
111
- <div className='flex flex-row justify-between md_justify-center items-center gap-5'>
112
- <div className='flex flex-col gap-y-2'>
113
- <div className='rating_sales flex flex-row gap-x-[5px] items-center'>
114
- <Star width={18} height={18} />
115
- <p className='font-medium text-[18px] text-gray-600'>
116
- 4.7
117
- </p>
114
+ </Button>
118
115
  </div>
119
- <span className='text-gray-800 text-xs'>
120
- <FormattedMessage
121
- id={'favoriteSeller.RatingAndReviews'}
122
- defaultMessage={'Rating & Reviews'}
123
- />
124
- </span>
125
-
126
116
  </div>
127
- <Button
128
- data-cy="Product-Section-removeFavorite"
129
- onClick={handleRemoveFromFavorite}
130
- className="min-w-min border border-gray-200 rounded-full border-solid w-7 h-7 flex items-center justify-center hover_border-gray-600"
131
- >
132
- <Trash size="16" color="#999999" />
133
- </Button>
134
117
  </div>
135
118
  </div>
136
119
  </>
137
- )
138
- }
120
+ );
121
+ };
139
122
 
140
- export default item
123
+ export default Item;
@@ -22,17 +22,23 @@ import Image from '@magento/venia-ui/lib/components/Image';
22
22
  import Button from '@magento/venia-ui/lib/components/Button';
23
23
  import cn from 'classnames';
24
24
  import Rating from '@riosst100/pwa-marketplace/src/components/commons/Rating';
25
+
25
26
  const FavoriteSellerButton = React.lazy(() => import('@riosst100/pwa-marketplace/src/components/FavoriteSeller/AddToListButton'));
26
27
 
28
+
29
+ import { useHistory } from 'react-router-dom';
30
+
27
31
  const SellerDetail = props => {
28
32
  const talonProps = useSeller({
29
33
  mapSeller
30
34
  });
31
35
 
32
36
  const { error, loading, seller, favoriteSellerButtonProps } = talonProps;
37
+ const history = useHistory();
38
+
33
39
  if (loading && !seller)
34
40
  return '';
35
- // return <SellerShimmer />;
41
+
36
42
  if (error && !seller) return <ErrorView />;
37
43
  if (!seller) {
38
44
  return (
@@ -162,6 +168,9 @@ const SellerDetail = props => {
162
168
  {...favoriteSellerButtonProps}
163
169
  buttonText={'Follow Seller'}
164
170
  hideTextOnMobile={true}
171
+ afterAdd={isSelected => {
172
+ if (!isSelected) history.push('/favorite-seller');
173
+ }}
165
174
  />
166
175
  </Suspense>
167
176
  <button className='flex items-center justify-center gap-[8px] px-[14px] py-[8px] bg-white rounded-[30px] border border-solid border-[#f76b1c] min-w-[44px]'>
@@ -182,3 +191,4 @@ const SellerDetail = props => {
182
191
  }
183
192
 
184
193
  export default SellerDetail;
194
+
@@ -1,17 +1,19 @@
1
- import { useCallback, useMemo, useState } from 'react';
1
+
2
+ import { useCallback, useMemo, useState, useRef } from 'react';
2
3
  import { useIntl } from 'react-intl';
3
4
  import { useMutation, useQuery } from '@apollo/client';
4
-
5
5
  import { useUserContext } from '@magento/peregrine/lib/context/user';
6
6
  import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
7
-
8
7
  import defaultOperations from './addToListButton.gql';
8
+ import favoriteSellerListGqls from '@riosst100/pwa-marketplace/src/talons/FavoriteSeller/FavoriteSellerList/favoriteSellerList.gql';
9
+
9
10
 
10
11
  export const useAddToFavoriteListButton = props => {
12
+ const unfollowedRef = useRef(false);
11
13
  const { afterAdd, beforeAdd, item } = props;
12
-
13
14
  const operations = mergeOperations(defaultOperations, props.operations);
14
15
 
16
+ // Mutation for add
15
17
  const [
16
18
  addToFavoriteSeller,
17
19
  {
@@ -21,19 +23,28 @@ export const useAddToFavoriteListButton = props => {
21
23
  }
22
24
  ] = useMutation(operations.addToFavoriteSellerMutation);
23
25
 
24
- // const {
25
- // client,
26
- // data: { customerFavoriteSellers }
27
- // } = useQuery(operations.getSellerInFavoriteListsQuery);
26
+ // Mutation for remove
27
+ const [removeSeller, { loading: isRemoving }] = useMutation(
28
+ favoriteSellerListGqls.removeSellerFromFavoriteListMutation
29
+ );
30
+
31
+ // Query to get current favorite sellers
32
+ const { data: favoriteListData, refetch: refetchFavoriteList } = useQuery(
33
+ favoriteSellerListGqls.getFavoriteSellerListQuery,
34
+ {
35
+ variables: { pageSize: 100, currentPage: 1 },
36
+ fetchPolicy: 'cache-and-network',
37
+ }
38
+ );
28
39
 
29
- // const isSelected = useMemo(() => {
30
- // return (
31
- // customerFavoriteSellers.includes(item.seller_id) || isAddingToList
32
- // );
33
- // }, [customerFavoriteSellers, isAddingToList, item.seller_id]);
34
- const isSelected = false;
40
+ // Determine if this seller is already in favorite list
41
+ const isSelected = useMemo(() => {
42
+ const items = favoriteListData?.favoritelist?.items || [];
43
+ return items.some(i => i.seller?.seller_id == item.seller_id);
44
+ }, [favoriteListData, item.seller_id]);
35
45
 
36
46
  const [showLoginToast, setShowLoginToast] = useState(0);
47
+ const [showUnfollowToast, setShowUnfollowToast] = useState(0);
37
48
 
38
49
  const { formatMessage } = useIntl();
39
50
  const [{ isSignedIn }] = useUserContext();
@@ -46,37 +57,35 @@ export const useAddToFavoriteListButton = props => {
46
57
  if (beforeAdd) {
47
58
  await beforeAdd();
48
59
  }
49
-
50
- await addToFavoriteSeller({
51
- variables: { sellerId: item.seller_id }
52
- });
53
-
54
- // client.writeQuery({
55
- // query: operations.getSellerInFavoriteListsQuery,
56
- // data: {
57
- // customerFavoriteSellers: [
58
- // ...customerFavoriteSellers,
59
- // item.seller_id
60
- // ]
61
- // }
62
- // });
63
-
64
- // if (afterAdd) {
65
- // afterAdd();
66
- // }
60
+ const wasSelected = isSelected;
61
+ unfollowedRef.current = false;
62
+ if (isSelected) {
63
+ // Unfollow
64
+ unfollowedRef.current = true;
65
+ await removeSeller({ variables: { sellerIds: [item.seller_id] } });
66
+ } else {
67
+ // Follow
68
+ await addToFavoriteSeller({ variables: { sellerId: item.seller_id } });
69
+ }
70
+ await refetchFavoriteList();
71
+ if (unfollowedRef.current) {
72
+ setShowUnfollowToast(current => current + 1);
73
+ unfollowedRef.current = false;
74
+ }
75
+ if (afterAdd) afterAdd(wasSelected);
67
76
  } catch (error) {
68
77
  console.error(error);
69
78
  }
70
79
  }
71
80
  }, [
72
81
  addToFavoriteSeller,
82
+ removeSeller,
73
83
  afterAdd,
74
84
  beforeAdd,
75
- // client,
76
- // customerFavoriteSellers,
77
85
  isSignedIn,
78
86
  item,
79
- // operations.getSellerInFavoriteListsQuery
87
+ isSelected,
88
+ refetchFavoriteList
80
89
  ]);
81
90
 
82
91
  const loginToastProps = useMemo(() => {
@@ -107,9 +116,18 @@ export const useAddToFavoriteListButton = props => {
107
116
  timeout: 5000
108
117
  };
109
118
  }
110
-
119
+ if (showUnfollowToast) {
120
+ return {
121
+ type: 'success',
122
+ message: formatMessage({
123
+ id: 'favoriteSeller.galleryButton.unfollowSuccessMessage',
124
+ defaultMessage: 'Seller removed from your favorites list.'
125
+ }),
126
+ timeout: 5000
127
+ };
128
+ }
111
129
  return null;
112
- }, [addSellerData, formatMessage]);
130
+ }, [addSellerData, formatMessage, showUnfollowToast]);
113
131
 
114
132
  const errorToastProps = useMemo(() => {
115
133
  if (errorAddingProduct) {
@@ -129,15 +147,20 @@ export const useAddToFavoriteListButton = props => {
129
147
 
130
148
  const buttonProps = useMemo(
131
149
  () => ({
132
- 'aria-label': formatMessage({
133
- id: 'favoriteSellerButton.addText',
134
- defaultMessage: 'Add to Favorites'
135
- }),
136
- isDisabled: false,
150
+ 'aria-label': isSelected
151
+ ? formatMessage({
152
+ id: 'favoriteSellerButton.unfollowText',
153
+ defaultMessage: 'Unfollow Seller'
154
+ })
155
+ : formatMessage({
156
+ id: 'favoriteSellerButton.addText',
157
+ defaultMessage: 'Follow Seller'
158
+ }),
159
+ isDisabled: isAddingToList || isRemoving,
137
160
  onPress: handleClick,
138
161
  type: 'button'
139
162
  }),
140
- [formatMessage, handleClick]
163
+ [formatMessage, handleClick, isSelected, isAddingToList, isRemoving]
141
164
  );
142
165
 
143
166
  return {
@@ -145,12 +168,12 @@ export const useAddToFavoriteListButton = props => {
145
168
  buttonText:
146
169
  typeof props.buttonText === 'function'
147
170
  ? props.buttonText(isSelected)
148
- : props.buttonText,
149
- // customerFavoriteSellers,
171
+ : (isSelected ? 'Unfollow Seller' : 'Follow Seller'),
150
172
  errorToastProps,
151
173
  handleClick,
152
174
  isSelected,
153
175
  loginToastProps,
154
- successToastProps
176
+ successToastProps,
177
+ isLoading: isAddingToList || isRemoving
155
178
  };
156
179
  };
@@ -0,0 +1,49 @@
1
+ import { gql } from '@apollo/client';
2
+
3
+ export const GET_FAVORITE_SELLER_LIST = gql`
4
+ query GetFavoriteSellerList($filter: FavoriteFilterInput, $pageSize: Int, $currentPage: Int) {
5
+ favoritelist(filter: $filter, pageSize: $pageSize, currentPage: $currentPage) {
6
+ items {
7
+ creation_time
8
+ customer_id
9
+ id
10
+ seller {
11
+ description
12
+ name
13
+ seller_id
14
+ url
15
+ }
16
+ status
17
+ }
18
+ page_info {
19
+ current_page
20
+ page_size
21
+ total_pages
22
+ }
23
+ total_count
24
+ }
25
+ }
26
+ `;
27
+
28
+ export const REMOVE_SELLER_FROM_FAVORITE_LIST = gql`
29
+ mutation RemoveSellerFromFavoriteList($sellerIds: [ID]!) {
30
+ removeSellerToFavoritelist(sellerIds: $sellerIds) {
31
+ error
32
+ favorite {
33
+ creation_time
34
+ customer {
35
+ customer_id
36
+ name
37
+ }
38
+ customer_id
39
+ id
40
+ status
41
+ }
42
+ }
43
+ }
44
+ `;
45
+
46
+ export default {
47
+ getFavoriteSellerListQuery: GET_FAVORITE_SELLER_LIST,
48
+ removeSellerFromFavoriteListMutation: REMOVE_SELLER_FROM_FAVORITE_LIST
49
+ };
@@ -0,0 +1,30 @@
1
+ import { useQuery } from '@apollo/client';
2
+ import gqls from './favoriteSellerList.gql';
3
+
4
+ /**
5
+ * Custom hook untuk mengambil daftar seller yang di-follow user
6
+ * @param {Object} options - Opsi query Apollo (filter, pageSize, currentPage)
7
+ */
8
+ const useFavoriteSellerList = (options = {}) => {
9
+ const { filter = {}, pageSize = 20, currentPage = 1 } = options;
10
+ const { data, loading, error, refetch } = useQuery(
11
+ gqls.getFavoriteSellerListQuery,
12
+ {
13
+ variables: {
14
+ filter,
15
+ pageSize,
16
+ currentPage
17
+ },
18
+ fetchPolicy: 'cache-and-network'
19
+ }
20
+ );
21
+
22
+ return {
23
+ data: data?.favoritelist,
24
+ loading,
25
+ error,
26
+ refetch
27
+ };
28
+ };
29
+
30
+ export default useFavoriteSellerList;
@@ -0,0 +1,31 @@
1
+ import { useMutation } from '@apollo/client';
2
+ import gqls from './favoriteSellerList.gql';
3
+
4
+ /**
5
+ * Custom hook untuk menghapus seller dari favorite list
6
+ * @returns { removeSeller, loading, error, data }
7
+ */
8
+ const useRemoveFavoriteSeller = () => {
9
+ const [removeSeller, { loading, error, data }] = useMutation(
10
+ gqls.removeSellerFromFavoriteListMutation
11
+ );
12
+
13
+ /**
14
+ * @param {Array<string|number>} sellerIds - Array of seller_id yang ingin dihapus
15
+ * @returns {Promise}
16
+ */
17
+ const remove = (sellerIds) => {
18
+ return removeSeller({
19
+ variables: { sellerIds }
20
+ });
21
+ };
22
+
23
+ return {
24
+ remove,
25
+ loading,
26
+ error,
27
+ data
28
+ };
29
+ };
30
+
31
+ export default useRemoveFavoriteSeller;