@riosst100/pwa-marketplace 3.0.6 → 3.0.8

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": "3.0.6",
4
+ "version": "3.0.8",
5
5
  "main": "src/index.js",
6
6
  "pwa-studio": {
7
7
  "targets": {
@@ -1,4 +1,5 @@
1
1
  module.exports = componentOverrideMapping = {
2
+ ['@magento/peregrine/lib/talons/CreateAccount/useCreateAccount.js']: '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/CreateAccount/useCreateAccount.js',
2
3
  ['@magento/peregrine/lib/talons/CheckoutPage/PaymentInformation/usePaymentMethods.js']: '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/CheckoutPage/PaymentInformation/usePaymentMethods.js',
3
4
  ['@magento/venia-ui/lib/components/CartPage/PriceAdjustments/CouponCode/couponCode.js']: '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/CartPage/PriceAdjustments/CouponCode/couponCode.js',
4
5
  ['@magento/peregrine/lib/talons/Header/useCartTrigger.js']: '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/Header/useCartTrigger.js',
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ import Item from './item';
3
+
4
+ export const listings = [
5
+ { id: 1, sellerName: 'SuperGamesInc', sales: 3329, condition: 'Near Mint 1st Edition', price: 34.19 },
6
+ { id: 2, sellerName: 'GameWorld', sales: 1520, condition: 'Near Mint 1st Edition', price: 28.49 },
7
+ { id: 3, sellerName: 'MegaPlay', sales: 980, condition: 'Near Mint 1st Edition', price: 31.00 }
8
+ ];
9
+
10
+ export const totalListings = listings.length;
11
+ export const lowestPrice = Math.min(...listings.map(item => item.price));
12
+
13
+ const CrossSeller = () => {
14
+ return (
15
+ <>
16
+ <h3 className="font-semibold text-sm sm_text-base md_text-lg lg_text-xl xl_text-2xl mb-1">{totalListings} Listings</h3>
17
+ <p className="text-[16px] mb-6">As low as ${lowestPrice.toFixed(2)}</p>
18
+
19
+ <div className="flex flex-col gap-y-4">
20
+ {listings.map(item => (
21
+ <Item key={item.id} {...item} />
22
+ ))}
23
+ </div>
24
+ </>
25
+ );
26
+ };
27
+
28
+ export default CrossSeller;
@@ -1,15 +1 @@
1
- import React from 'react';
2
- import Content from './crossSellerBuy';
3
-
4
- const index = () => {
5
-
6
- const contentProps = {
7
-
8
- }
9
-
10
- return (
11
- <Content {...contentProps} />
12
- )
13
- }
14
-
15
- export default index
1
+ export { default } from './crossSeller';
@@ -95,13 +95,6 @@ const FilterTop = props => {
95
95
  [handleApply, filterRef]
96
96
  );
97
97
 
98
- // const allowedFiltersArr = [];
99
-
100
- // allowedFilters.length && allowedFilters.map((val, index) => {
101
- // allowedFiltersArr.push(val.code);
102
- // });
103
- // const allowedFiltersArr = ['card_rarity','card_print_version','card_set', 'card_product_type'];
104
-
105
98
  const filtersList = useMemo(
106
99
  () =>
107
100
  Array.from(filterItems, ([group, items], iteration) => {
@@ -339,7 +339,6 @@ const ShowMore = props => {
339
339
  <StoreTitle>{title}</StoreTitle>
340
340
  <Breadcrumbs categoryId={categoryId} customPage={title} currentFilter={activeFilters} />
341
341
  {category?.url_path.includes('model-railway') && <FilterTop shopby={shopby} filters={[]} category={category} children={[]} allowedFilters={category ? category.allowed_filters : []} />}
342
- {/* <ShopByFilters handleActiveFilter={handleActiveFilter} activeFilter={activeFilter} category={category} /> */}
343
342
  {availableFilterOption.length ?
344
343
  <ul className={classes.nav}>
345
344
  {availableFilterOption.map((filter, index) => (
@@ -0,0 +1,303 @@
1
+ import { useCallback, useMemo, useState } from 'react';
2
+ import { useApolloClient, useMutation } from '@apollo/client';
3
+
4
+ import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
5
+ import { useUserContext } from '@magento/peregrine/lib/context/user';
6
+ import { useCartContext } from '@magento/peregrine/lib/context/cart';
7
+ import { useAwaitQuery } from '@magento/peregrine/lib/hooks/useAwaitQuery';
8
+ import { retrieveCartId } from '@magento/peregrine/lib/store/actions/cart';
9
+ import { useGoogleReCaptcha } from '@magento/peregrine/lib/hooks/useGoogleReCaptcha';
10
+
11
+ import DEFAULT_OPERATIONS from '@magento/peregrine/lib/talons/CreateAccount/createAccount.gql';
12
+ import { useEventingContext } from '@magento/peregrine/lib/context/eventing';
13
+
14
+ import { useHistory } from 'react-router-dom';
15
+ import { BrowserPersistence } from '@magento/peregrine/lib/util';
16
+
17
+ const storage = new BrowserPersistence();
18
+
19
+ /**
20
+ * Returns props necessary to render CreateAccount component. In particular this
21
+ * talon handles the submission flow by first doing a pre-submisson validation
22
+ * and then, on success, invokes the `onSubmit` prop, which is usually the action.
23
+ *
24
+ * @param {CreateAccountQueries} props.queries queries used by the talon
25
+ * @param {CreateAccountMutations} props.mutations mutations used by the talon
26
+ * @param {InitialValues} props.initialValues initial values to sanitize and seed the form
27
+ * @param {Function} props.onSubmit the post submit callback
28
+ * @param {Function} props.onCancel the cancel callback
29
+ *
30
+ * @returns {CreateAccountProps}
31
+ *
32
+ * @example <caption>Importing into your project</caption>
33
+ * import { useForgotPassword } from '@magento/peregrine/lib/talons/CreateAccount/useCreateAccount.js';
34
+ */
35
+ export const useCreateAccount = props => {
36
+ const { initialValues = {}, onSubmit, onCancel } = props;
37
+
38
+ const operations = mergeOperations(DEFAULT_OPERATIONS, props.operations);
39
+ const {
40
+ createAccountMutation,
41
+ createCartMutation,
42
+ getCartDetailsQuery,
43
+ getCustomerQuery,
44
+ mergeCartsMutation,
45
+ signInMutation
46
+ } = operations;
47
+ const apolloClient = useApolloClient();
48
+ const [isSubmitting, setIsSubmitting] = useState(false);
49
+ const [
50
+ { cartId },
51
+ { createCart, removeCart, getCartDetails }
52
+ ] = useCartContext();
53
+ const [
54
+ { isGettingDetails },
55
+ { getUserDetails, setToken }
56
+ ] = useUserContext();
57
+
58
+ const [, { dispatch }] = useEventingContext();
59
+
60
+ const history = useHistory();
61
+
62
+ const [fetchCartId] = useMutation(createCartMutation);
63
+
64
+ const [mergeCarts] = useMutation(mergeCartsMutation);
65
+
66
+ // For create account and sign in mutations, we don't want to cache any
67
+ // personally identifiable information (PII). So we set fetchPolicy to 'no-cache'.
68
+ const [createAccount, { error: createAccountError }] = useMutation(
69
+ createAccountMutation,
70
+ {
71
+ fetchPolicy: 'no-cache'
72
+ }
73
+ );
74
+
75
+ const [signIn, { error: signInError }] = useMutation(signInMutation, {
76
+ fetchPolicy: 'no-cache'
77
+ });
78
+
79
+ const fetchUserDetails = useAwaitQuery(getCustomerQuery);
80
+ const fetchCartDetails = useAwaitQuery(getCartDetailsQuery);
81
+
82
+ const {
83
+ generateReCaptchaData,
84
+ recaptchaLoading,
85
+ recaptchaWidgetProps
86
+ } = useGoogleReCaptcha({
87
+ currentForm: 'CUSTOMER_CREATE',
88
+ formAction: 'createAccount'
89
+ });
90
+
91
+ const handleCancel = useCallback(() => {
92
+ onCancel();
93
+ }, [onCancel]);
94
+
95
+ const handleCancelKeyPress = useCallback(() => {
96
+ event => {
97
+ if (event.key === 'Enter') {
98
+ handleCancel();
99
+ }
100
+ };
101
+ }, [handleCancel]);
102
+
103
+ const handleSubmit = useCallback(
104
+ async formValues => {
105
+ setIsSubmitting(true);
106
+ try {
107
+ // Get source cart id (guest cart id).
108
+ const sourceCartId = cartId;
109
+
110
+ // Get reCaptchaV3 Data for createAccount mutation
111
+ const recaptchaDataForCreateAccount = await generateReCaptchaData();
112
+
113
+ // Create the account and then sign in.
114
+ await createAccount({
115
+ variables: {
116
+ email: formValues.customer.email,
117
+ firstname: formValues.customer.firstname,
118
+ lastname: formValues.customer.lastname,
119
+ password: formValues.password,
120
+ is_subscribed: !!formValues.subscribe
121
+ },
122
+ ...recaptchaDataForCreateAccount
123
+ });
124
+
125
+ dispatch({
126
+ type: 'USER_CREATE_ACCOUNT',
127
+ payload: {
128
+ email: formValues.customer.email,
129
+ firstName: formValues.customer.firstname,
130
+ lastName: formValues.customer.lastname,
131
+ isSubscribed: !!formValues.subscribe
132
+ }
133
+ });
134
+
135
+ storage.setItem('confirm_email', formValues.customer.email);
136
+
137
+ console.log(formValues.customer.email)
138
+
139
+ history.push('/verify-email');
140
+
141
+ // Get reCaptchaV3 Data for signIn mutation
142
+ // const recaptchaDataForSignIn = await generateReCaptchaData();
143
+
144
+ // const signInResponse = await signIn({
145
+ // variables: {
146
+ // email: formValues.customer.email,
147
+ // password: formValues.password
148
+ // },
149
+ // ...recaptchaDataForSignIn
150
+ // });
151
+ // const token = signInResponse.data.generateCustomerToken.token;
152
+ // await setToken(token);
153
+
154
+ // // Clear all cart/customer data from cache and redux.
155
+ // await apolloClient.clearCacheData(apolloClient, 'cart');
156
+ // await apolloClient.clearCacheData(apolloClient, 'customer');
157
+ // await removeCart();
158
+
159
+ // // Create and get the customer's cart id.
160
+ // await createCart({
161
+ // fetchCartId
162
+ // });
163
+ // const destinationCartId = await retrieveCartId();
164
+
165
+ // // Merge the guest cart into the customer cart.
166
+ // await mergeCarts({
167
+ // variables: {
168
+ // destinationCartId,
169
+ // sourceCartId
170
+ // }
171
+ // });
172
+
173
+ // // Ensure old stores are updated with any new data.
174
+ // await getUserDetails({ fetchUserDetails });
175
+ // await getCartDetails({
176
+ // fetchCartId,
177
+ // fetchCartDetails
178
+ // });
179
+
180
+ // Finally, invoke the post-submission callback.
181
+ if (onSubmit) {
182
+ onSubmit();
183
+ }
184
+ } catch (error) {
185
+ if (process.env.NODE_ENV !== 'production') {
186
+ console.error(error);
187
+ }
188
+ setIsSubmitting(false);
189
+ }
190
+ },
191
+
192
+ [
193
+ cartId,
194
+ generateReCaptchaData,
195
+ createAccount,
196
+ signIn,
197
+ setToken,
198
+ apolloClient,
199
+ removeCart,
200
+ createCart,
201
+ fetchCartId,
202
+ mergeCarts,
203
+ getUserDetails,
204
+ fetchUserDetails,
205
+ getCartDetails,
206
+ fetchCartDetails,
207
+ onSubmit,
208
+ dispatch,
209
+ history,
210
+ storage
211
+ ]
212
+ );
213
+
214
+ const sanitizedInitialValues = useMemo(() => {
215
+ const { email, firstName, lastName, ...rest } = initialValues;
216
+
217
+ return {
218
+ customer: { email, firstname: firstName, lastname: lastName },
219
+ ...rest
220
+ };
221
+ }, [initialValues]);
222
+
223
+ const errors = useMemo(
224
+ () =>
225
+ new Map([
226
+ ['createAccountQuery', createAccountError],
227
+ ['signInMutation', signInError]
228
+ ]),
229
+ [createAccountError, signInError]
230
+ );
231
+
232
+ return {
233
+ errors,
234
+ handleCancel,
235
+ handleSubmit,
236
+ handleCancelKeyPress,
237
+ initialValues: sanitizedInitialValues,
238
+ isDisabled: isSubmitting || isGettingDetails || recaptchaLoading,
239
+ recaptchaWidgetProps
240
+ };
241
+ };
242
+
243
+ /** JSDocs type definitions */
244
+
245
+ /**
246
+ * GraphQL queries for the create account form.
247
+ * This is a type used by the {@link useCreateAccount} talon.
248
+ *
249
+ * @typedef {Object} CreateAccountQueries
250
+ *
251
+ * @property {GraphQLAST} customerQuery query to fetch customer details
252
+ * @property {GraphQLAST} getCartDetailsQuery query to get cart details
253
+ */
254
+
255
+ /**
256
+ * GraphQL mutations for the create account form.
257
+ * This is a type used by the {@link useCreateAccount} talon.
258
+ *
259
+ * @typedef {Object} CreateAccountMutations
260
+ *
261
+ * @property {GraphQLAST} createAccountMutation mutation for creating new account
262
+ * @property {GraphQLAST} createCartMutation mutation for creating new cart
263
+ * @property {GraphQLAST} mergeCartsMutation mutation for merging carts
264
+ * @property {GraphQLAST} signInMutation mutation for signing
265
+ */
266
+
267
+ /**
268
+ * Initial values for the create account form.
269
+ * This is a type used by the {@link useCreateAccount} talon.
270
+ *
271
+ * @typedef {Object} InitialValues
272
+ *
273
+ * @property {String} email email id of the user
274
+ * @property {String} firstName first name of the user
275
+ * @property {String} lastName last name of the user
276
+ */
277
+
278
+ /**
279
+ * Sanitized initial values for the create account form.
280
+ * This is a type used by the {@link useCreateAccount} talon.
281
+ *
282
+ * @typedef {Object} SanitizedInitialValues
283
+ *
284
+ * @property {String} email email id of the user
285
+ * @property {String} firstname first name of the user
286
+ * @property {String} lastname last name of the user
287
+ */
288
+
289
+ /**
290
+ * Object type returned by the {@link useCreateAccount} talon.
291
+ * It provides props data to use when rendering the create account form component.
292
+ *
293
+ * @typedef {Object} CreateAccountProps
294
+ *
295
+ * @property {Map} errors a map of errors to their respective mutations
296
+ * @property {Function} handleCancel callback function to handle form cancellations
297
+ * @property {Function} handleSubmit callback function to handle form submission
298
+ * @property {SanitizedInitialValues} initialValues initial values for the create account form
299
+ * @property {Boolean} isDisabled true if either details are being fetched or form is being submitted. False otherwise.
300
+ * @property {Object} recaptchaWidgetProps - Props for the GoogleReCaptcha component.
301
+ * @property {Function} recaptchaWidgetProps.containerElement - Container reference callback.
302
+ * @property {Boolean} recaptchaWidgetProps.shouldRender - Checks if component should be rendered.
303
+ */
@@ -20,6 +20,9 @@ const CustomerOrdersFragment = gql`
20
20
  }
21
21
  items {
22
22
  id
23
+ is_preorder
24
+ pre_order_deposit
25
+ pre_order_payment_type
23
26
  product_image_url
24
27
  product_name
25
28
  product_sale_price {
@@ -112,6 +115,17 @@ export const GET_CUSTOMER_ORDERS = gql`
112
115
  ${CustomerOrdersFragment}
113
116
  `;
114
117
 
118
+ export const COMPLETE_PREORDER = gql`
119
+ mutation CompletePreorder($input: CompletePreorderInput!) {
120
+ completePreorder(input: $input) {
121
+ cart_id
122
+ message
123
+ success
124
+ }
125
+ }
126
+ `;
127
+
115
128
  export default {
116
- getCustomerOrdersQuery: GET_CUSTOMER_ORDERS
129
+ getCustomerOrdersQuery: GET_CUSTOMER_ORDERS,
130
+ completePreorderMutation: COMPLETE_PREORDER
117
131
  };
@@ -44,3 +44,14 @@ export default {
44
44
  getProductThumbnailsQuery: GET_PRODUCT_THUMBNAILS,
45
45
  getConfigurableThumbnailSource: GET_CONFIGURABLE_THUMBNAIL_SOURCE
46
46
  };
47
+
48
+ // Mutation to complete preorder
49
+ export const COMPLETE_PREORDER = gql`
50
+ mutation CompletePreorder($input: CompletePreorderInput!) {
51
+ completePreorder(input: $input) {
52
+ cart_id
53
+ message
54
+ success
55
+ }
56
+ }
57
+ `;
@@ -720,6 +720,7 @@ export const useProductFullDetail = props => {
720
720
  sku: productSku,
721
721
  publish_status: product.publish_status,
722
722
  custom_table_metadata: product.custom_table_metadata,
723
+ related_products: product.related_products,
723
724
  term_and_conditions: product.term_and_conditions,
724
725
  link_to_other_stores: product.link_to_other_stores,
725
726
  shipping_policy: product.shipping_policy,
@@ -43,6 +43,7 @@ export const GET_CATEGORY_CONTENT = gql`
43
43
  allowed_filters {
44
44
  code
45
45
  }
46
+ prefixes
46
47
  custom_subcategory {
47
48
  name
48
49
  path
@@ -17,6 +17,10 @@ export const ProductDetailsFragment = gql`
17
17
  city
18
18
  country
19
19
  }
20
+ related_products {
21
+ uid
22
+ name
23
+ }
20
24
  description {
21
25
  html
22
26
  }
@@ -76,38 +80,6 @@ export const ProductDetailsFragment = gql`
76
80
  }
77
81
  publish_status
78
82
  sku
79
- auction_data {
80
- is_auction
81
- status
82
- customer_id
83
- starting_price
84
- reserve_price
85
- days
86
- min_qty
87
- max_qty
88
- start_auction_time
89
- stop_auction_time
90
- auction_status
91
- increment_opt
92
- increment_price
93
- auto_auction_opt
94
- featured_auction
95
- buy_it_now
96
- max_amount
97
- min_amount
98
- current_time_stamp
99
- continue_time
100
- limit_bids
101
- time_zone
102
- stop_auction_utc_time
103
- start_auction_utc_time
104
- today_time
105
- start_auction_time_stamp
106
- stop_auction_time_stamp
107
- new_auction_start
108
- customer_name
109
- max_bids
110
- }
111
83
  preorder {
112
84
  is_preorder
113
85
  pre_order_payment_type
@@ -165,7 +165,7 @@ const CategoryContent = props => {
165
165
  ) : null;
166
166
 
167
167
  const sidebar = shouldShowFilterButtons ? (
168
- <FilterSidebar hideFilters={category && category.hide_filters ? true : false} children={children} filters={filters} allowedFilters={category ? category.allowed_filters : []} />
168
+ <FilterSidebar hideFilters={category && category.hide_filters ? true : false} children={children} filters={filters} allowedFilters={category ? category.allowed_filters : []} prefixes={category ? category.prefixes : []} />
169
169
  ) : shouldShowFilterShimmer ? (
170
170
  <FilterSidebarShimmer />
171
171
  ) : null;
@@ -21,7 +21,7 @@ const SCROLL_OFFSET = 150;
21
21
  * @param {Object} props.filters - filters to display
22
22
  */
23
23
  const FilterSidebar = props => {
24
- const { filters, filterCountToOpen, allowedFilters, hideFilters } = props;
24
+ const { filters, filterCountToOpen, allowedFilters, prefixes, hideFilters } = props;
25
25
  const talonProps = useFilterSidebar({ filters });
26
26
  const {
27
27
  filterApi,
@@ -116,7 +116,15 @@ const FilterSidebar = props => {
116
116
  // // console.log([...sorted.entries()]);
117
117
  // const filterItems = [...sorted.entries()];
118
118
 
119
- // console.log('filterItems',filterItems)
119
+ const removePrefix = (attrCode) => {
120
+ if (prefixes) {
121
+ return prefixes.reduce((s, p) =>
122
+ s.startsWith(p + "_") ? s.replace(p + "_", "") : s
123
+ , attrCode);
124
+ }
125
+
126
+ return attrCode;
127
+ };
120
128
 
121
129
  const filtersList = useMemo(
122
130
  () =>
@@ -124,10 +132,10 @@ const FilterSidebar = props => {
124
132
  const blockState = filterState.get(group);
125
133
  const groupName = filterNames.get(group);
126
134
  const frontendInput = filterFrontendInput.get(group);
127
-
128
- const hideFilters = ['card_game','bricks_categories','sc_sports_categories','trains','trains_locomotives','trains_supplies_type','lof_preorder','card_pre_orders','auction','special_price','sc_baseball_inserts','sc_baseball_parallel','sale','sc_set_type','sc_brands'];
129
- if (!allowedFiltersArr?.length || filterState.size && allowedFiltersArr.length || !filterState.size && allowedFiltersArr.length && allowedFiltersArr.includes(group)) {
130
- if (!hideFilters.includes(group) && groupName && !group.includes('card_release') && !group.includes('card_set') && !group.includes('sc_set_name')) {
135
+
136
+ if (!allowedFiltersArr.length || allowedFiltersArr.length && allowedFiltersArr.includes(removePrefix(group))) {
137
+ console.log('removePrefix(group)',removePrefix(group))
138
+ // if (!hideFilters.includes(group) && groupName && !group.includes('card_release') && !group.includes('card_set') && !group.includes('sc_set_name')) {
131
139
 
132
140
  // if (!allowedFiltersArr?.length && group != "category_uid" || allowedFiltersArr?.length && allowedFiltersArr.includes(group)) {
133
141
  let subFilter = null;
@@ -177,7 +185,7 @@ const FilterSidebar = props => {
177
185
  initialOpen={true}
178
186
  />
179
187
  );
180
- }
188
+ // }
181
189
  }
182
190
  }),
183
191
  [
@@ -254,6 +262,7 @@ FilterSidebar.propTypes = {
254
262
  root: string,
255
263
  root_open: string
256
264
  }),
265
+ prefixes: [],
257
266
  filters: arrayOf(
258
267
  shape({
259
268
  attribute_code: string,
@@ -129,7 +129,7 @@ const GalleryItem = props => {
129
129
  {ratingAverage}
130
130
  </span>
131
131
  </div>
132
- <div className={cn('item-info px-[15px] pb-[20px]')}>
132
+ <div className={cn('item-info px-[15px] pb-[15px]')}>
133
133
  {/* <Link
134
134
  onClick={handleLinkClick}
135
135
  to={productLink}
@@ -76,8 +76,6 @@ const ReviewModal = (props) => {
76
76
  // if (onSubmit) {
77
77
  // onSubmit({ ...formState, ratings });
78
78
  // }
79
- console.log('formState',formState)
80
- console.log('e',e)
81
79
  setSubmitting(true);
82
80
  const input = {
83
81
  nickname: formState.nickname,
@@ -119,24 +117,18 @@ const ReviewModal = (props) => {
119
117
  return { url, label };
120
118
  };
121
119
 
122
- console.log('ratings',ratings)
123
-
124
120
  const ratingStars = useMemo(() => {
125
- console.log('ratingsMetadata22',ratingsMetadata)
126
121
  if (!ratingsMetadata) {
127
122
  return '';
128
123
  }
129
124
 
130
125
  // Find value (1-5) for selected value_id
131
126
  const selectedValue = ratings && ratingsMetadata.values.find(v => v.value_id === ratings) || '';
132
- console.log('selectedValue',selectedValue)
133
127
 
134
128
  let starButtons = [];
135
129
 
136
130
  [1,2,3,4,5].map(star => {
137
131
  const valObj = ratingsMetadata.values.find(v => v.value === String(star));
138
- console.log('String(star)',String(star))
139
- console.log('valObj',valObj)
140
132
  if (valObj) {
141
133
  starButtons.push(
142
134
  <button
@@ -26,6 +26,7 @@ import { SearchNormal } from 'iconsax-react';
26
26
  import cn from 'classnames';
27
27
  import Pagination from '@riosst100/pwa-marketplace/src/overwrites/venia-ui/lib/components/Pagination';
28
28
  import { ReviewModal } from './Reviews'
29
+ import { useCartContext } from '@magento/peregrine/lib/context/cart';
29
30
 
30
31
  const errorIcon = (
31
32
  <Icon
@@ -38,7 +39,7 @@ const errorIcon = (
38
39
  const searchIcon = <Icon src={SearchIcon} size={24} />;
39
40
 
40
41
  const OrderHistoryPage = props => {
41
- const talonProps = useOrderHistoryPage();
42
+ const talonProps = useOrderHistoryPage();
42
43
  const {
43
44
  errorMessage,
44
45
  loadMoreOrders,
@@ -51,6 +52,7 @@ const OrderHistoryPage = props => {
51
52
  searchText,
52
53
  pageControl
53
54
  } = talonProps;
55
+
54
56
  const [, { addToast }] = useToasts();
55
57
  const { formatMessage } = useIntl();
56
58
  const [reviewOrder, setReviewOrder] = useState(null);
@@ -166,8 +168,6 @@ const OrderHistoryPage = props => {
166
168
  }
167
169
  }, [addToast, errorMessage]);
168
170
 
169
- console.log('reviewOrder',reviewOrder)
170
-
171
171
  return (
172
172
  <OrderHistoryContextProvider>
173
173
  <ReviewModal
@@ -1,9 +1,13 @@
1
- import React, { useCallback, useState } from 'react';
1
+ import React, { useCallback, useMemo, useState } from 'react';
2
+ import { useMutation } from '@apollo/client';
2
3
  import { arrayOf, number, shape, string } from 'prop-types';
3
4
  import { ChevronDown, ChevronUp } from 'react-feather';
4
5
  import { FormattedMessage, useIntl } from 'react-intl';
5
6
  import Price from '@magento/venia-ui/lib/components/Price';
6
7
  import { useOrderRow } from '@magento/peregrine/lib/talons/OrderHistoryPage/useOrderRow';
8
+ import { COMPLETE_PREORDER } from '@riosst100/pwa-marketplace/src/overwrites/peregrine/lib/talons/OrderHistoryPage/orderRow.gql';
9
+ import { useCartContext } from '@magento/peregrine/lib/context/cart';
10
+ import { useToasts } from '@magento/peregrine/lib/Toasts';
7
11
 
8
12
  import { useStyle } from '@magento/venia-ui/lib/classify';
9
13
  import Icon from '@magento/venia-ui/lib/components/Icon';
@@ -19,6 +23,8 @@ import { Link, useHistory } from 'react-router-dom';
19
23
  const OrderRow = props => {
20
24
  const { order, setReviewOrder } = props;
21
25
  const { formatMessage } = useIntl();
26
+ const [{ cartId }] = useCartContext();
27
+ const [, { addToast }] = useToasts();
22
28
  const history = useHistory();
23
29
  const {
24
30
  invoices,
@@ -29,7 +35,7 @@ const OrderRow = props => {
29
35
  status,
30
36
  total
31
37
  } = order;
32
-
38
+
33
39
  const { grand_total: grandTotal } = total;
34
40
  const { currency, value: orderTotal } = grandTotal;
35
41
 
@@ -47,7 +53,12 @@ const OrderRow = props => {
47
53
  const hasInvoice = !!invoices.length;
48
54
  const hasShipment = !!shipments.length;
49
55
  let derivedStatus;
50
- if (status === 'Complete') {
56
+ if (status === 'Canceled') {
57
+ derivedStatus = formatMessage({
58
+ id: 'orderRow.canceledText',
59
+ defaultMessage: 'Canceled'
60
+ });
61
+ } else if (status === 'Complete') {
51
62
  derivedStatus = formatMessage({
52
63
  id: 'orderRow.deliveredText',
53
64
  defaultMessage: 'Delivered'
@@ -101,6 +112,9 @@ const OrderRow = props => {
101
112
  );
102
113
 
103
114
  const badgeStatusStyle = () => {
115
+ if (status === 'Canceled') {
116
+ return 'text-red-600 text-[14px] font-medium py-[5px] border-none';
117
+ }
104
118
  return 'text-blue-700 text-[14px] font-medium py-[5px] border-none';
105
119
  }
106
120
 
@@ -138,6 +152,58 @@ const OrderRow = props => {
138
152
 
139
153
  const showNewReturnButton = status === 'Complete' || derivedStatus === formatMessage({ id: 'orderRow.deliveredText', defaultMessage: 'Delivered' });
140
154
 
155
+ // Find a preorder item eligible for completion (deposit type)
156
+ const preorderItem = useMemo(() => {
157
+ if (!Array.isArray(items)) return null;
158
+ return items.find(it => it && it.is_preorder && String(it.pre_order_payment_type).toLowerCase() === 'deposit');
159
+ }, [items]);
160
+
161
+ const [completePreorder, { loading: completingPreorder }] = useMutation(COMPLETE_PREORDER);
162
+
163
+ const handleCompletePreorder = async () => {
164
+ try {
165
+ const targetItem = preorderItem || (Array.isArray(items) && items.length ? items[0] : null);
166
+ if (!targetItem) {
167
+ console.warn('No eligible preorder item found to complete preorder');
168
+ return;
169
+ }
170
+
171
+ const input = {
172
+ cartId: cartId || '',
173
+ item_id: String(targetItem.id || ''),
174
+ order_reference: String(orderNumber || ''),
175
+ product_name: String(targetItem.product_name || ''),
176
+ qty: Number(targetItem.quantity_ordered || 1)
177
+ };
178
+
179
+ const { data: result } = await completePreorder({ variables: { input } });
180
+ const payload = result?.completePreorder;
181
+ if (payload?.success) {
182
+ addToast({
183
+ type: 'success',
184
+ message: payload.message || formatMessage({ id: 'orderRow.completePreorder.success', defaultMessage: 'Preorder completed successfully.' }),
185
+ dismissable: true,
186
+ timeout: 5000
187
+ });
188
+ history.push('/cart');
189
+ } else {
190
+ addToast({
191
+ type: 'error',
192
+ message: payload?.message || formatMessage({ id: 'orderRow.completePreorder.failed', defaultMessage: 'Failed to complete preorder.' }),
193
+ dismissable: true,
194
+ timeout: 7000
195
+ });
196
+ }
197
+ } catch (e) {
198
+ addToast({
199
+ type: 'error',
200
+ message: e?.message || formatMessage({ id: 'orderRow.completePreorder.error', defaultMessage: 'Something went wrong completing preorder.' }),
201
+ dismissable: true,
202
+ timeout: 7000
203
+ });
204
+ }
205
+ };
206
+
141
207
  const handleNewReturn = () => {
142
208
  // Inject product_image per item with safe fallbacks (prefer product_image_url from query)
143
209
  let orderWithImages = { ...order };
@@ -180,7 +246,6 @@ const OrderRow = props => {
180
246
  };
181
247
 
182
248
  const handleWriteReview = useCallback(( order ) => {
183
- console.log('order',order)
184
249
  if (order) {
185
250
  setReviewOrder(order);
186
251
  }
@@ -277,6 +342,22 @@ const OrderRow = props => {
277
342
  </span>
278
343
  </>
279
344
  )}
345
+ {preorderItem && (
346
+ <button
347
+ type="button"
348
+ onClick={handleCompletePreorder}
349
+ disabled={completingPreorder}
350
+ aria-busy={completingPreorder}
351
+ aria-disabled={completingPreorder}
352
+ className={`bg-blue-700 rounded-full px-[30px] py-[8px] text-[13px] font-medium text-white transition-all duration-300 ease-in-out ${completingPreorder ? 'opacity-60 cursor-not-allowed pointer-events-none bg-gray-200 text-white' : ''}`}
353
+ >
354
+ {completingPreorder ? (
355
+ <FormattedMessage id={'orderRow.completingPreorder'} defaultMessage={'Complete Loading...'} />
356
+ ) : (
357
+ <FormattedMessage id={'orderRow.completePreorder'} defaultMessage={'Complete Preorder'} />
358
+ )}
359
+ </button>
360
+ )}
280
361
  <Link
281
362
  to={{
282
363
  pathname: `/order-history/view/${orderNumber}`,
@@ -33,6 +33,7 @@ export const GET_CATEGORY_CONTENT = gql`
33
33
  allowed_filters {
34
34
  code
35
35
  }
36
+ prefixes
36
37
  custom_subcategory {
37
38
  name
38
39
  path
@@ -34,6 +34,7 @@ export const GET_CATEGORY_CONTENT = gql`
34
34
  allowed_filters {
35
35
  code
36
36
  }
37
+ prefixes
37
38
  custom_subcategory {
38
39
  name
39
40
  path