@riosst100/pwa-marketplace 2.7.4 → 2.7.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.7.4",
4
+ "version": "2.7.7",
5
5
  "main": "src/index.js",
6
6
  "pwa-studio": {
7
7
  "targets": {
@@ -1,19 +1,29 @@
1
+ // crossSellerBuy.js
1
2
  import React from 'react';
2
3
  import Item from './item';
3
4
 
4
- const crossSellerBuy = () => {
5
+ export const listings = [
6
+ { id: 1, sellerName: 'SuperGamesInc', sales: 3329, condition: 'Near Mint 1st Edition', price: 34.19 },
7
+ { id: 2, sellerName: 'GameWorld', sales: 1520, condition: 'Near Mint 1st Edition', price: 28.49 },
8
+ { id: 3, sellerName: 'MegaPlay', sales: 980, condition: 'Near Mint 1st Edition', price: 31.00 }
9
+ ];
10
+
11
+ export const totalListings = listings.length;
12
+ export const lowestPrice = Math.min(...listings.map(item => item.price));
13
+
14
+ const CrossSellerBuy = () => {
5
15
  return (
6
16
  <>
7
- <h3 className='capitalize font-medium text-xl mb-[30px]'>
8
- Also Available
9
- </h3>
10
- <div className='flex flex-col gap-y-5'>
11
- {[...Array(6)].map(() => (
12
- <Item />
17
+ <h3 className="font-semibold text-sm sm_text-base md_text-lg lg_text-xl xl_text-2xl mb-1">{totalListings} Listings</h3>
18
+ <p className="text-[16px] mb-6">As low as ${lowestPrice.toFixed(2)}</p>
19
+
20
+ <div className="flex flex-col gap-y-4">
21
+ {listings.map(item => (
22
+ <Item key={item.id} {...item} />
13
23
  ))}
14
24
  </div>
15
25
  </>
16
- )
17
- }
26
+ );
27
+ };
18
28
 
19
- export default crossSellerBuy
29
+ export default CrossSellerBuy;
@@ -7,73 +7,55 @@ import Verify from './verifyIcon';
7
7
  import Star from './starIcon';
8
8
  import logoImage from './logo_seller.png';
9
9
 
10
- const item = () => {
10
+ const Item = ({ sellerName, sales, price, condition }) => {
11
11
  return (
12
- <>
13
- <div className='flex flex-col gap-y-4 lg_flex-row justify-between bg-white rounded-lg border border-gray-100 p-[15px]'>
14
- <div className='seller_info-container flex flex-row gap-x-[15px]'>
15
- <div className='logo_wrapper w-[100px] h-[100px]'>
16
- <Image
17
- alt='seller name'
18
- className="relative mt-[-5px]"
19
- src={logoImage}
20
- />
21
- </div>
22
- <div className='flex flex-col gap-y-[15px]'>
23
- <div className='seller_summary-wrapper flex flex-row gap-x-2.5 items-center'>
24
- <div className='seller_name text-lg font-medium leading-6'>
25
- Zen Market
26
- </div>
27
- <div className='seller_badge flex flex-row gap-x-[5px] items-center leading-6'>
28
- <Verify />
29
- <span className='text-xs font-medium text-gray-600-transparent capitalize'>
30
- Verified
31
- </span>
32
- </div>
33
- </div>
34
- <div className='rating_sales flex flex-row gap-x-[5px] items-center'>
35
- <Star />
36
- <span className='font-normal text-[14px] text-gray-200'>
37
- 4.7 (Sales 120)
38
- </span>
12
+ <div className='flex flex-col items-center text-center lg_text-left md_text-left lg_flex-row md_flex-row bg-white rounded-lg border border-gray-100 p-[15px] gap-y-4'>
13
+ <div className='seller_info-container flex flex-row gap-x-[15px] lg_w-1/3 md_w-1/3'>
14
+ <div className='flex flex-col gap-y-[15px]'>
15
+ <div className='seller_summary-wrapper flex flex-row gap-x-2.5 items-center'>
16
+ <div className='seller_name text-lg font-semibold leading-6'>
17
+ {sellerName}
39
18
  </div>
40
19
  </div>
20
+ <div className='rating_sales flex flex-row gap-x-[5px] items-center'>
21
+ <span className='font-normal text-[14px] text-gray-200'>
22
+ {sales}+ Sales
23
+ </span>
24
+ </div>
41
25
  </div>
26
+ </div>
42
27
 
43
- <div className='price_container'>
44
- <div className='price text-lg font-medium'>
45
- $34.19
46
- </div>
47
- <span className='shipping_note text-xs text-gray-200'>
48
- Shipping method is calculated on checkout
49
- </span>
28
+ <div className='price_container lg_w-1/3 md_w-1/3'>
29
+ <div className="text-sm font-medium text-gray-800">{condition}</div>
30
+ <div className='price text-lg font-medium text-[#f76b1c]'>
31
+ ${price}
50
32
  </div>
33
+ <span className='shipping_note text-xs text-gray-200'>
34
+ Shipping method is calculated on checkout
35
+ </span>
36
+ </div>
51
37
 
52
- <div className='form_wrapper'>
53
- <Form
54
- data-cy="FormAddToCartCrossSeller"
55
- onSubmit={() => { }}
56
- className="flex flex-row gap-x-7"
38
+ <div className='form_wrapper'>
39
+ <Form
40
+ data-cy="FormAddToCartCrossSeller"
41
+ onSubmit={() => { }}
42
+ className="flex flex-col gap-x-7 gap-y-7 items-center lg_flex-row md_flex-row"
43
+ >
44
+ <QuantityStepper min={1} />
45
+ <Button
46
+ data-cy="addToCartButton"
47
+ classes={{
48
+ content: 'normal-case font-medium text-[16px]'
49
+ }}
50
+ priority="high"
51
+ type="button"
57
52
  >
58
- <QuantityStepper
59
- min={1}
60
- // message={'error quantity'}
61
- />
62
- <Button
63
- data-cy="addToCartButton"
64
- classes={{
65
- content: 'normal-case font-medium text-[16px]'
66
- }}
67
- priority="high"
68
- type="button"
69
- >
70
- Add To Cart
71
- </Button>
72
- </Form>
73
- </div>
53
+ Add To Cart
54
+ </Button>
55
+ </Form>
74
56
  </div>
75
- </>
76
- )
77
- }
57
+ </div>
58
+ );
59
+ };
78
60
 
79
- export default item
61
+ export default Item;
@@ -61,14 +61,13 @@ const LinkToOtherStores = (props) => {
61
61
 
62
62
  return finalLinkToOtherStores && finalLinkToOtherStores.length ? <>
63
63
  <section className='product_from-other-platform py-xs'>
64
- <div className='text-sm flex mb-3'>
64
+ <div className='title-section text-gray-400 text-sm flex mb-3 pl-[1rem]'>
65
65
  Also available in
66
66
  </div>
67
- <div className='platform-container flex gap-x-2.5'>
67
+ <div className='content-section platform-container flex gap-x-2.5 pl-[1rem]'>
68
68
  {finalLinkToOtherStores}
69
69
  </div>
70
70
  </section>
71
- <Divider />
72
71
  </> : '';
73
72
  }
74
73
 
@@ -2,41 +2,33 @@ import React, { useState } from 'react';
2
2
  import Button from '@magento/venia-ui/lib/components/Button';
3
3
  import { useIntl } from 'react-intl';
4
4
  import ModalRFQ from './modalRfq';
5
+ import cn from 'classnames';
5
6
 
6
- const RFQ = (props) => {
7
+ const RFQ = ({ disabled, classes: customClasses = {} }) => {
8
+ const [open, setOpen] = useState(false);
9
+ const { formatMessage } = useIntl();
7
10
 
8
- const { disabled } = props;
11
+ return (
12
+ <>
13
+ <ModalRFQ open={open} setOpen={setOpen} />
9
14
 
10
- const [open, setOpen] = useState(false);
11
- const { formatMessage } = useIntl();
15
+ <Button
16
+ data-cy="ProductFullDetail-RFQ"
17
+ disabled={disabled}
18
+ classes={{
19
+ rootClass: cn(customClasses.rfqButton),
20
+ content: cn('normal-case font-medium text-[16px]', customClasses.content)
21
+ }}
22
+ priority="low"
23
+ onClick={() => setOpen(true)}
24
+ >
25
+ {formatMessage({
26
+ id: 'productFullDetail.RequestQuote',
27
+ defaultMessage: 'Make An Offer'
28
+ })}
29
+ </Button>
30
+ </>
31
+ );
32
+ };
12
33
 
13
- return (
14
- <>
15
- <ModalRFQ
16
- open={open}
17
- setOpen={setOpen}
18
- />
19
-
20
- <Button
21
- data-cy="ProductFullDetail-RFQ"
22
- disabled={disabled}
23
- classes={{
24
- content: 'normal-case font-medium text-[16px]'
25
- }}
26
- priority="low"
27
- type="submit"
28
- onClick={() => { setOpen(true) }}
29
- >
30
- {
31
- formatMessage({
32
- id: 'productFullDetail.RequestQuote',
33
- defaultMessage:
34
- 'Make An Offer'
35
- })
36
- }
37
- </Button>
38
- </>
39
- )
40
- }
41
-
42
- export default RFQ;
34
+ export default RFQ;
@@ -248,6 +248,33 @@ const getConfigName = (product, optionCodes, optionSelections) => {
248
248
  return value;
249
249
  };
250
250
 
251
+ const getConfigSku = (product, optionCodes, optionSelections) => {
252
+ let value;
253
+
254
+ const { variants } = product;
255
+ const isConfigurable = isProductConfigurable(product);
256
+
257
+ const optionsSelected =
258
+ Array.from(optionSelections.values()).filter(value => !!value).length >
259
+ 0;
260
+
261
+ if (!isConfigurable) {
262
+ value = product.name;
263
+ } else {
264
+ const item = findMatchingVariant({
265
+ optionCodes,
266
+ optionSelections,
267
+ variants
268
+ });
269
+
270
+ value = optionsSelected && item
271
+ ? item.product.sku
272
+ : product.sku;
273
+ }
274
+
275
+ return value;
276
+ };
277
+
251
278
  const attributeLabelCompare = (attribute1, attribute2) => {
252
279
  const label1 = attribute1['attribute_metadata']['label'].toLowerCase();
253
280
  const label2 = attribute2['attribute_metadata']['label'].toLowerCase();
@@ -450,6 +477,11 @@ export const useProductFullDetail = props => {
450
477
  [product, optionCodes, optionSelections]
451
478
  );
452
479
 
480
+ const productSku = useMemo(
481
+ () => getConfigSku(product, optionCodes, optionSelections),
482
+ [product, optionCodes, optionSelections]
483
+ );
484
+
453
485
  // The map of ids to values (and their uids)
454
486
  // For example:
455
487
  // { "179" => [{ uid: "abc", value_index: 1 }, { uid: "def", value_index: 2 }]}
@@ -625,7 +657,7 @@ export const useProductFullDetail = props => {
625
657
  name: productName,
626
658
  price: productPrice?.final_price,
627
659
  price_range: product?.price_range,
628
- sku: product.sku,
660
+ sku: productSku,
629
661
  publish_status: product.publish_status,
630
662
  term_and_conditions: product.term_and_conditions,
631
663
  link_to_other_stores: product.link_to_other_stores,
@@ -1,4 +1,4 @@
1
- import React, { useState, useMemo, Fragment, Suspense } from 'react';
1
+ import React, { useState, useMemo, Fragment, Suspense, useRef, useEffect } from 'react';
2
2
  import { FormattedMessage, useIntl } from 'react-intl';
3
3
  import { arrayOf, bool, number, shape, string } from 'prop-types';
4
4
  import { Form } from 'informed';
@@ -15,7 +15,6 @@ import Carousel from '@magento/venia-ui/lib/components/ProductImageCarousel';
15
15
  import FormError from '@magento/venia-ui/lib/components/FormError';
16
16
  import RichContent from '@magento/venia-ui/lib/components/RichContent/richContent';
17
17
  import QuantityStepper from '../QuantityStepper';
18
- // import RichContent from '../RichContent/richContent';
19
18
  import { ProductOptionsShimmer } from '@magento/venia-ui/lib/components/ProductOptions';
20
19
  import CustomAttributes from './CustomAttributes';
21
20
  import defaultClasses from './productFullDetail.module.css';
@@ -33,13 +32,14 @@ import Share from '@riosst100/pwa-marketplace/src/components/SocialMediaShare';
33
32
  import PreorderDetail from './components/preOrderDetail';
34
33
  import AuctionDetail from './components/auctionDetail';
35
34
  import CrossSeller from '@riosst100/pwa-marketplace/src/components/CrossSeller';
36
- import RelatedProduct from '@riosst100/pwa-marketplace/src/components/RelatedProduct';
37
35
  import ProductLabel from '@riosst100/pwa-marketplace/src/components/ProductLabel';
38
36
  import RFQ from '@riosst100/pwa-marketplace/src/components/RFQ';
39
37
  import LinkToOtherStores from '@riosst100/pwa-marketplace/src/components/LinkToOtherStores';
40
38
  import Collapsible from '@riosst100/pwa-marketplace/src/components/commons/Collapsible';
41
39
  import { useLocation } from 'react-router-dom';
42
40
 
41
+ import { totalListings, lowestPrice } from '@riosst100/pwa-marketplace/src/components/CrossSeller/crossSellerBuy';
42
+
43
43
  // Correlate a GQL error message to a field. GQL could return a longer error
44
44
  // string but it may contain contextual info such as product id. We can use
45
45
  // parts of the string to check for which field to apply the error.
@@ -100,7 +100,7 @@ const ProductFullDetail = props => {
100
100
  wishlistButtonProps,
101
101
  sellerDetails
102
102
  } = talonProps;
103
-
103
+
104
104
  const { formatMessage } = useIntl();
105
105
 
106
106
  const classes = useStyle(defaultClasses, props.classes);
@@ -126,7 +126,6 @@ const ProductFullDetail = props => {
126
126
  currentProduct={productDetails.name}
127
127
  />
128
128
  ) : null;
129
-
130
129
  // Fill a map with field/section -> error.
131
130
  const errors = new Map();
132
131
  if (errorMessage) {
@@ -184,22 +183,6 @@ const ProductFullDetail = props => {
184
183
  const customAttributesDetails = useMemo(() => {
185
184
  const list = [];
186
185
  const pagebuilder = [];
187
- // const skuAttribute = {
188
- // attribute_metadata: {
189
- // uid: 'attribute_sku',
190
- // used_in_components: ['PRODUCT_DETAILS_PAGE'],
191
- // ui_input: {
192
- // ui_input_type: 'TEXT'
193
- // },
194
- // label: formatMessage({
195
- // id: 'global.sku',
196
- // defaultMessage: 'SKU'
197
- // })
198
- // },
199
- // entered_attribute_value: {
200
- // value: productDetails.sku
201
- // }
202
- // };
203
186
  if (Array.isArray(customAttributes)) {
204
187
  customAttributes.forEach(customAttribute => {
205
188
  if (
@@ -233,8 +216,12 @@ const ProductFullDetail = props => {
233
216
  );
234
217
  // Error message for screen reader
235
218
  const cartActionContent = isSupportedProductType ? (
236
- <section className={cn(classes.actButton, 'flex gap-x-[30px]')}>
237
- <RFQ disabled={isAddToCartDisabled} />
219
+ <section className={cn(classes.actButton, 'flex gap-x-[20px] px-[12px] py-0')}>
220
+ <RFQ
221
+ disabled={isAddToCartDisabled}
222
+ classes={{ rfqButton: classes.rfqButton }}
223
+ />
224
+
238
225
  <Button
239
226
  data-cy="ProductFullDetail-addToCartButton"
240
227
  disabled={isAddToCartDisabled}
@@ -249,7 +236,8 @@ const ProductFullDetail = props => {
249
236
  : ''
250
237
  }
251
238
  classes={{
252
- content: 'normal-case font-medium text-[16px]'
239
+ rootClass: '!px-0 !py-3',
240
+ content: 'normal-case font-medium text-[14px]'
253
241
  }}
254
242
  priority="high"
255
243
  type="submit"
@@ -295,17 +283,7 @@ const ProductFullDetail = props => {
295
283
 
296
284
  const contentContainerClass = 'content-container max-w-[1040px] p-2.5 m-auto relative mt-0 lg_mt-[34px] pb-6 lg_pb-0'
297
285
  const ProductDescription = () => (
298
- <div className={cn(contentContainerClass)}>
299
- {/* <span
300
- data-cy="ProductFullDetail-descriptionTitle"
301
- className={classes.descriptionTitle}
302
- >
303
- <FormattedMessage
304
- id={'productFullDetail.description'}
305
- defaultMessage={'Description'}
306
- />
307
- </span> */}
308
- {/* <RichContent html={productDetails.description} /> */}
286
+ <div className={cn(contentContainerClass, classes.contentContainerTabOverride)}>
309
287
  <RichText
310
288
  rootClassName="px-0"
311
289
  content={productDetails.description}
@@ -313,11 +291,12 @@ const ProductFullDetail = props => {
313
291
  </div>
314
292
  );
315
293
 
316
- const ProductMoreInfo = () => (
294
+ const ProductMoreInfo = ({ className }) => (
317
295
  <>
318
- <div className={cn(contentContainerClass)}>
296
+ <div className={cn(contentContainerClass, className)}>
319
297
  <CustomAttributes
320
298
  customAttributes={customAttributesDetails.list}
299
+ classes={{ list: classes.customAttributesList }}
321
300
  />
322
301
  </div>
323
302
  {pageBuilderAttributes}
@@ -342,7 +321,7 @@ const ProductFullDetail = props => {
342
321
  );
343
322
 
344
323
  const ProductTNC = () => (
345
- <div className={cn(contentContainerClass)}>
324
+ <div className={cn(contentContainerClass, classes.contentContainerTabOverride)}>
346
325
  <p>{customAttributesList.map((data, index) => {
347
326
  if (data.code == "term_and_conditions") {
348
327
  return data.value;
@@ -352,7 +331,7 @@ const ProductFullDetail = props => {
352
331
  )
353
332
 
354
333
  const ShippingPolicy = () => (
355
- <div className={cn(contentContainerClass)}>
334
+ <div className={cn(contentContainerClass, classes.contentContainerTabOverride)}>
356
335
  <p>{customAttributesList.map((data, index) => {
357
336
  if (data.code == "shipping_policy") {
358
337
  return data.value;
@@ -362,7 +341,7 @@ const ProductFullDetail = props => {
362
341
  )
363
342
 
364
343
  const ReturnPolicy = () => (
365
- <div className={cn(contentContainerClass)}>
344
+ <div className={cn(contentContainerClass, classes.contentContainerTabOverride)}>
366
345
  <p>{customAttributesList.map((data, index) => {
367
346
  if (data.code == "return_policy") {
368
347
  return data.value;
@@ -372,7 +351,7 @@ const ProductFullDetail = props => {
372
351
  )
373
352
 
374
353
  const ProductFAQ = () => (
375
- <div className={cn(contentContainerClass)}>
354
+ <div className={cn(contentContainerClass, classes.contentContainerTabOverride)}>
376
355
  {customAttributesList.map((data, index) => {
377
356
  if (data.code == "faq") {
378
357
  return (
@@ -387,6 +366,88 @@ const ProductFullDetail = props => {
387
366
  </div>
388
367
  )
389
368
 
369
+
370
+ const getAttributeValue = (customAttributesDetails, key, useSuffix = false) => {
371
+ if (!customAttributesDetails?.list?.length) return "";
372
+
373
+ const attr = customAttributesDetails.list.find(attr => {
374
+ const code = attr.attribute_metadata?.code || "";
375
+ return useSuffix ? code.endsWith(key) : code === key;
376
+ });
377
+
378
+ if (!attr) return "";
379
+
380
+ if (attr.selected_attribute_options?.attribute_option?.length) {
381
+ return attr.selected_attribute_options.attribute_option
382
+ .map(opt => opt.label)
383
+ .join(", ");
384
+ }
385
+ return attr.entered_attribute_value?.value || "";
386
+ };
387
+
388
+
389
+ const setNameValue = getAttributeValue(customAttributesDetails, "card_set", true);
390
+ const conditionValue = getAttributeValue(customAttributesDetails, "card_condition");
391
+
392
+ const ExpandableSection = ({ children, maxHeight = 280 }) => {
393
+ const [expanded, setExpanded] = useState(false);
394
+ const [showButton, setShowButton] = useState(false);
395
+ const contentRef = useRef(null);
396
+
397
+ useEffect(() => {
398
+ if (!contentRef.current) return;
399
+
400
+ const checkContent = () => {
401
+ const { scrollHeight } = contentRef.current;
402
+ const isDesktop = window.innerWidth >= 769;
403
+
404
+ if (isDesktop && scrollHeight > maxHeight) {
405
+ setShowButton(true);
406
+ } else {
407
+ setShowButton(false);
408
+ setExpanded(false);
409
+ }
410
+ };
411
+
412
+ checkContent();
413
+ window.addEventListener("resize", checkContent);
414
+ return () => window.removeEventListener("resize", checkContent);
415
+ }, [children, maxHeight]);
416
+
417
+ const isDesktop = typeof window !== "undefined" && window.innerWidth >= 769;
418
+
419
+ return (
420
+ <div className="relative">
421
+ <div
422
+ ref={contentRef}
423
+ style={{
424
+ maxHeight:
425
+ isDesktop && showButton && !expanded
426
+ ? `${maxHeight}px`
427
+ : "none",
428
+ overflow: "hidden",
429
+ transition: "max-height 0.3s ease"
430
+ }}
431
+ >
432
+ {children}
433
+ </div>
434
+
435
+ {isDesktop && !expanded && showButton && (
436
+ <div className="absolute bottom-0 left-0 w-full h-16 bg-gradient-to-t to-transparent pointer-events-none" />
437
+ )}
438
+
439
+ {isDesktop && showButton && (
440
+ <button
441
+ type="button"
442
+ onClick={() => setExpanded(!expanded)}
443
+ className="mt-2 text-blue-600 font-medium underline focus:outline-none"
444
+ >
445
+ {expanded ? "Show Less" : "Read More"}
446
+ </button>
447
+ )}
448
+ </div>
449
+ );
450
+ };
390
451
 
391
452
  const dataTabs =
392
453
  [
@@ -395,11 +456,11 @@ const ProductFullDetail = props => {
395
456
  title: 'Description',
396
457
  content: <ProductDescription />
397
458
  },
398
- {
399
- id: 'product-more-info',
400
- title: 'Details',
401
- content: <ProductMoreInfo />
402
- },
459
+ // {
460
+ // id: 'product-more-info',
461
+ // title: 'Details',
462
+ // content: <ProductMoreInfo />
463
+ // },
403
464
  {
404
465
  id: 'product-tnc',
405
466
  title: 'Term & Conditions',
@@ -423,7 +484,7 @@ const ProductFullDetail = props => {
423
484
  {
424
485
  id: 'product-reviews',
425
486
  title: 'Reviews',
426
- content: <ProductReviews className={cn(contentContainerClass)} />
487
+ content: <ProductReviews className={cn(contentContainerClass, classes.contentContainerTabOverride)} />
427
488
  }
428
489
  ];
429
490
 
@@ -478,22 +539,6 @@ const ProductFullDetail = props => {
478
539
  <section className={cn(classes.leftContainer, 'relative')}>
479
540
  <ProductLabel item={productDetails} />
480
541
  <Carousel images={mediaGalleryEntries} hoveredMedia={hoveredMedia} selectedMedia={selectedMedia}/>
481
- <div className='product_group-actions flex gap-x-[18px] gap-y-4 justify-center items-center mt-2 lg_mt-5 mb-6 lg_mb-0'>
482
- <Suspense fallback={null}>
483
- <WishlistButton
484
- classes={{
485
- root: cn(
486
- 'button_share border border-solid border-gray-100 p-2.5',
487
- 'rounded-full flex justify-center items-center h-fitContent min-w-min'
488
- )
489
- }}
490
- {...wishlistButtonProps}
491
- buttonText={''}
492
- />
493
- </Suspense>
494
- <Divider className="w-[1px] !h-[40px]" />
495
- <Share />
496
- </div>
497
542
  </section>
498
543
  <section className={classes.rightContainer}>
499
544
  <div
@@ -506,179 +551,135 @@ const ProductFullDetail = props => {
506
551
  aria-live="polite"
507
552
  className={cn(
508
553
  classes.productName,
509
- '!font-medium leading-[normal] mb-4 line-clamp-2'
554
+ '!font-medium leading-[normal] mb-4 line-clamp-2 !text-[1.5rem]'
510
555
  )}
511
556
  data-cy="ProductFullDetail-productName"
512
557
  >
513
558
  {productDetails.name}
514
559
  </h1>
515
- <div className='product_review-container flex items-center gap-x-2'>
516
- <div className='product_rating leading-[14px] flex items-center gap-x-[5px]'>
517
- <span className="w-3.5 h-3.5 relative">
518
- <Star1 color='#F7C317' size={14} className='fill-[#F7C317]' />
519
- </span>
520
- <span className='text-gray-200 text-sm'>
521
- {rating_value}
522
- </span>
523
- </div>
524
- <div className='before_block before_w-[1px] before_bg-gray-200 before_h-full before_relative w-[1px] h-[14px]'></div>
525
- <span className='review_count text-gray-200 text-base leading-[14px]'>
526
- {review_count} Reviews
527
- </span>
528
- </div>
529
- </div>
530
- <div
531
- className={cn(
532
- 'product_short_description',
533
- 'mb-xs',
560
+ {setNameValue && (
561
+ <div className="text-gray-400 text-sm mb-2">{setNameValue}</div>
534
562
  )}
535
- >
536
- {shortDescription}
537
563
  </div>
538
- {/* <div className='product_brand-container mb-[30px] leading-[18px]'>
539
- <div className='text-sm'>
540
- Brand : <span className='text-blue-700'><Link to="">Bandai Namco</Link></span>
541
- </div>
542
- </div> */}
543
- <Divider />
544
- <div
545
- className={cn(
546
- 'product_price_container',
547
- 'py-xs flex justify-between flex-wrap gap-y-5'
548
- )}
549
- >
550
- <div className='flex flex-col gap-y-3'>
551
- <div className='flex flex-col gap-y-3'>
552
- <p
553
- data-cy="ProductFullDetail-productPrice"
564
+ <section className="bottom_right-container block sm_flex md_flex lg_flex xl_flex 2xl_flex gap-[7px]">
565
+ <section className='right_left-container'>
566
+ <ExpandableSection maxHeight={280}>
567
+ <div
554
568
  className={cn(
555
- classes.productPrice,
556
- 'text-[32px] font-medium leading-[32px] mb-0',
569
+ 'product_short_description',
570
+ 'mb-xs',
557
571
  )}
558
572
  >
559
- <Price
560
- currencyCode={productDetails.price.currency}
561
- priceRange={productDetails.price_range}
562
- value={productDetails.price.value}
563
- />
564
- </p>
565
- {/* <p
566
- data-cy="ProductFullDetail-productOldPrice"
573
+ <p className="font-bold text-[15px] mb-3">Product Details</p>
574
+ {shortDescription}
575
+ <ProductMoreInfo className="!mt-0 lg:!mt-0 !p-0" />
576
+ </div>
577
+ </ExpandableSection>
578
+ </section>
579
+ <section className='right_right-container'>
580
+ <div className={cn('product_purchase-section', 'border border-[lightgray] rounded-[10px] mb-[15px]')}>
581
+ <div
567
582
  className={cn(
568
- classes.productPrice,
569
- 'text-lg font-normal leading-none text-gray-400 mb-0 line-through',
583
+ 'product_price_container',
584
+ 'flex justify-between flex-wrap gap-y-5'
570
585
  )}
571
586
  >
572
- <Price
573
- currencyCode={productDetails.price.currency}
574
- value={productDetails.price.value}
575
- />
576
- </p> */}
577
- </div>
578
- <AuctionDetail className="auction_detail-container" />
579
- <PreorderDetail className={'preorder_detail-container'} />
580
- <small className='shipping-calculation-notes text-gray-200 text-xs'>
581
- Shipping method is calculated on checkout
582
- </small>
583
- </div>
584
- <div>
585
- <p className='text-gray-200 text-[14px]'>
586
- SKU : {productDetails.sku}
587
- </p>
588
- </div>
589
- </div>
590
- <Divider />
591
- <FormError
592
- classes={{
593
- root: classes.formErrors
594
- }}
595
- errors={errors.get('form') || []}
596
- />
597
- <section className={classes.options}>{options}</section>
598
- <section className={cn(classes.quantity, 'py-xs !border-none')}>
599
- {/* <span
600
- data-cy="ProductFullDetail-quantityTitle"
601
- className={classes.quantityTitle}
602
- >
603
- <FormattedMessage
604
- id={'global.quantity'}
605
- defaultMessage={'Quantity'}
606
- />
607
- </span> */}
608
- <QuantityStepper
609
- min={1}
610
- message={errors.get('quantity')}
611
- />
612
-
613
- {/* <div className='product_shipping-information mb-[30px] leading-[18px] mt-[25px]'>
614
- {sellerDetails &&
615
- <div className='text-xs'>
616
- Ship From <span className='font-medium'>{sellerDetails.country}</span>
617
- </div>}
618
- <div className='text-xs'>
619
- Ship To <span className='font-medium'>Yishun</span>
620
- </div>
621
- <div className='text-xs'>
622
- Shiping Method <span className='font-medium'>Store Pick Up | Meet Up</span>
623
- </div>
624
- </div> */}
625
-
626
- <div className='product_actions-wrapper'>
627
- {cartActionContent}
628
- </div>
629
- </section>
630
- {/* <Divider />
631
- <section className={cn(classes.quantity, 'py-[30px] !border-none')}>
632
- <RFQ />
633
- </section> */}
634
- <Divider />
635
- <LinkToOtherStores productDetails={productDetails} />
636
- <section className='seller-information py-xs'>
637
- <div className='flex xs_flex-col md_flex-row xs_items-center md_items-start items-start gap-[15px] relative'>
638
- <div className='flex flex-row justify-between relative w-full'>
639
- <div className='flex flex-col xs_items-center md_items-start gap-[6px] relative'>
640
- <div className="gap-x-[10px] gap-y-1 flex xs_flex-col md_flex-row xs_items-center md_items-start relative">
641
- <div className="text-sm">
642
- {sellerDetails ? sellerDetails.name : ''}
587
+ <div className='flex flex-col gap-y-3 pl-[1rem] pt-[1.5rem]'>
588
+ <div className='flex flex-col gap-y-3'>
589
+ {conditionValue && (
590
+ <div className="text-gray-600 text-sm mb-1">
591
+ {conditionValue}
592
+ </div>
593
+ )}
594
+ <p
595
+ data-cy="ProductFullDetail-productPrice"
596
+ className={cn(
597
+ classes.productPrice,
598
+ 'text-[32px] font-medium leading-[32px] mb-0',
599
+ )}
600
+ >
601
+ <Price
602
+ currencyCode={productDetails.price.currency}
603
+ priceRange={productDetails.price_range}
604
+ value={productDetails.price.value}
605
+ />
606
+ </p>
643
607
  </div>
644
- <div className="flex items-center relative">
645
- <Verify variant='Bold' color='#f76b1c' size={20} />
608
+ <AuctionDetail className="auction_detail-container" />
609
+ <PreorderDetail className={'preorder_detail-container'} />
610
+ <small className='shipping-calculation-notes text-gray-200 text-xs'>
611
+ Shipping is calculated on checkout
612
+ </small>
613
+ <div className='flex flex-col xs_items-center md_items-start gap-[6px] relative'>
614
+ <div className="gap-x-[10px] gap-y-1 flex xs_flex-col md_flex-row xs_items-center md_items-start relative">
615
+ <Link to={"/seller/"+sellerDetails.url_key} class="flex items-center justify-center gap-[5px] py-1 relative bg-white">
616
+ <div class="flex items-center justify-center gap-[10px] relative">
617
+ <p>Sold by</p>
618
+ <div class="relative xs_hidden lg_flex w-fit font-medium text-[#f76b1c] text-[14px] tracking-[0] leading-[20px] whitespace-nowrap">
619
+ {sellerDetails ? sellerDetails.name : ''}
620
+ </div>
621
+ </div>
622
+ </Link>
623
+ </div>
646
624
  </div>
647
625
  </div>
648
- <div class="relative w-fit font-normal text-[#999999] text-[12px] tracking-[0] leading-[14px] whitespace-nowrap">
649
- {sellerDetails ? getSellerAddressDisplay(sellerDetails) : ''}
650
- </div>
651
626
  </div>
652
- <div className='flex flex-wrap items-start gap-4 relative'>
653
- <Link to='/' class="flex items-center justify-center gap-[5px] py-1 px-5 relative bg-white rounded-[30px] border border-solid border-[#f76b1c]">
654
- <div class="flex items-center justify-center gap-[10px] relative">
655
- <Sms color="#f76b1c" size={14} variant="Outline" className='stroke-[#f76b1c]' />
656
- <div class="relative xs_hidden lg_flex w-fit font-medium text-[#f76b1c] text-[14px] tracking-[0] leading-[20px] whitespace-nowrap">
657
- Message
658
- </div>
659
- </div>
660
- </Link>
661
- <Link to='/' class="flex items-center justify-center gap-[5px] py-1 px-5 relative bg-[#280135] rounded-[30px] border border-solid border-[#280135]">
662
- <div class="flex items-center justify-center gap-[10px] relative">
663
- <Message color='#FFFFFF' size={14} variant="Outline" className='stroke-[#FFFFFF]' />
664
- <div class="relative xs_hidden lg_flex w-fit font-medium text-[#fff] text-[14px] tracking-[0] leading-[20px] whitespace-nowrap">
665
- Chat With Seller
666
- </div>
667
- </div>
668
- </Link>
669
- <Link to={"/seller/"+sellerDetails.url_key} class="flex items-center justify-center gap-[5px] py-1 px-5 relative bg-white rounded-[30px] border border-solid border-[#f76b1c]">
670
- <div class="flex items-center justify-center gap-[10px] relative">
671
- <Shop color="#f76b1c" size={14} variant="Outline" className='stroke-[#f76b1c]' />
672
- <div class="relative xs_hidden lg_flex w-fit font-medium text-[#f76b1c] text-[14px] tracking-[0] leading-[20px] whitespace-nowrap">
673
- Visit Store
674
- </div>
675
- </div>
676
- </Link>
627
+ <FormError
628
+ classes={{
629
+ root: classes.formErrors
630
+ }}
631
+ errors={errors.get('form') || []}
632
+ />
633
+ { options &&
634
+ <section className={classes.options}>{options}</section>
635
+ }
636
+ <section className={cn(classes.quantity, 'py-xs !border-none')}>
637
+ <div className='product_group-actions flex gap-x-[18px] gap-y-4 pl-[1rem] items-center mt-2 lg_mt-0 mb-6 lg_mb-0'>
638
+ <QuantityStepper
639
+ min={1}
640
+ message={errors.get('quantity')}
641
+ />
642
+ <Suspense fallback={null}>
643
+ <WishlistButton
644
+ classes={{
645
+ root: cn(
646
+ 'button_share border border-solid border-gray-100 p-2.5',
647
+ 'rounded-full flex justify-center items-center h-fitContent min-w-min'
648
+ )
649
+ }}
650
+ {...wishlistButtonProps}
651
+ buttonText={''}
652
+ />
653
+ </Suspense>
654
+ </div>
655
+ <div className='product_actions-wrapper'>
656
+ {cartActionContent}
657
+ </div>
658
+ </section>
659
+ </div>
660
+ <section>
661
+ <div
662
+ className="text-center pt-3 pb-3 cursor-pointer border border-[lightgray] rounded-[10px] mb-[15px]"
663
+ onClick={() => {
664
+ const section = document.getElementById("cross-seller-section");
665
+ if (section) {
666
+ section.scrollIntoView({ behavior: "smooth" });
667
+ }
668
+ }}
669
+ >
670
+ <span className="font-bold underline">
671
+ View {totalListings} Other Listings
672
+ </span>
673
+ <p className="text-sm text-gray-600">
674
+ As low as ${lowestPrice.toFixed(2)}
675
+ </p>
677
676
  </div>
677
+ </section>
678
+ <div className={cn('product_otherlink-section', 'border border-[lightgray] rounded-[10px]')}>
679
+ <LinkToOtherStores productDetails={productDetails} />
678
680
  </div>
679
- </div>
681
+ </section>
680
682
  </section>
681
- <Divider />
682
683
  </section>
683
684
  </Form>
684
685
  <section className='section_product-details-container mt-8 mb-10'>
@@ -687,21 +688,16 @@ const ProductFullDetail = props => {
687
688
  data={dataTabs}
688
689
  tabContentWrapperClassName='!p-0'
689
690
  hasContent
690
- tabWrapperClassName='xl_gap-x-[60px] justify-center'
691
+ tabWrapperClassName='xl_gap-x-[60px] justify-between'
691
692
  />
692
693
  </div>
693
694
  <div className='block lg_hidden'>
694
695
  <ProductDetailsCollapsible data={dataTabs} />
695
696
  </div>
696
697
  </section>
697
-
698
- <section className='pt-8 lg_pt-10'>
699
- <RelatedProduct />
700
- </section>
701
-
702
- <section className='w-[calc(100vw-9px)] relative left-1/2 right-1/2 ml-[-50vw] mr-[-50vw] bg-gray-50 py-[30px] px-0 mb-10'>
698
+ <section id="cross-seller-section" className='w-[calc(100vw-9px)] relative left-1/2 right-1/2 ml-[-50vw] mr-[-50vw] bg-gray-50 py-[30px] px-0 mb-10'>
703
699
  <div className='lg_max-w-[1200px] px-2.5 mx-auto relative max-w-screen-md'>
704
- <CrossSeller />
700
+ <CrossSeller/>
705
701
  </div>
706
702
  </section>
707
703
  </Fragment>
@@ -4,26 +4,24 @@
4
4
  composes: lg_items-start from global;
5
5
  composes: gap-x-10 from global;
6
6
  }
7
-
8
- @media (min-width: 1024px) {
9
- .root {
10
- grid-template-areas:
11
- 'left-container right-container';
12
- grid-template-columns: minmax(0, 495px) minmax(0, 1fr);
13
- grid-template-rows: repeat(5, min-content) 1fr [fold];
14
- }
15
-
16
- .title {
17
- grid-template-columns: 1fr max-content;
18
- }
7
+ .rfqButton {
8
+ padding: 10px 0px;
9
+ }
10
+ .rfqButton span {
11
+ font-size: 14px;
12
+ }
13
+ .customAttributesList {
14
+ padding-left: 0 !important;
15
+ }
16
+ .contentContainerTabOverride {
17
+ max-width: none !important;
19
18
  }
20
-
21
19
  .section {
22
20
  composes: border-solid from global;
23
21
  composes: border-subtle from global;
24
22
  composes: border-t-0 from global;
25
23
  composes: border-r-0 from global;
26
- composes: border-b from global;
24
+ composes: border-b-0 from global;
27
25
  composes: border-l-0 from global;
28
26
  }
29
27
 
@@ -35,7 +33,10 @@
35
33
  composes: mb-sm from global;
36
34
  composes: text-colorDefault from global;
37
35
  }
38
-
36
+ :global(.root).makeOfferButton {
37
+ padding-left: 0 !important;
38
+ padding-right: 0 !important;
39
+ }
39
40
  .title {
40
41
  /* composes: section;
41
42
  composes: gap-2 from global;
@@ -74,6 +75,13 @@
74
75
 
75
76
  .options {
76
77
  grid-area: options;
78
+ border: none;
79
+ }
80
+ .options :global([class*="option"]) {
81
+ border-bottom: none !important;
82
+ }
83
+ .options {
84
+ border: none !important;
77
85
  }
78
86
 
79
87
  .formErrors {
@@ -145,16 +153,6 @@
145
153
  list-style: none;
146
154
  }
147
155
 
148
- @media (min-width: 1024px) {
149
- .details {
150
- align-self: stretch;
151
- border-top-width: 1px;
152
- margin: 0;
153
- padding-left: 1.5rem;
154
- padding-right: 1.5rem;
155
- }
156
- }
157
-
158
156
  .detailsTitle {
159
157
  composes: sectionTitle;
160
158
  }
@@ -206,4 +204,36 @@
206
204
  flex-direction: column;
207
205
  row-gap: 16px;
208
206
  }
207
+ }
208
+
209
+ @media only screen and (min-width: 1025px) {
210
+ .root {
211
+ grid-template-areas:
212
+ 'left-container right-container';
213
+ grid-template-columns: minmax(0, 500px) minmax(0, 1fr);
214
+ grid-template-rows: repeat(5, min-content) 1fr [fold];
215
+ }
216
+ .details {
217
+ align-self: stretch;
218
+ border-top-width: 1px;
219
+ margin: 0;
220
+ padding-left: 1.5rem;
221
+ padding-right: 1.5rem;
222
+ }
223
+ .title {
224
+ grid-template-columns: 1fr max-content;
225
+ }
226
+ }
227
+ @media only screen and (max-width: 1024px) {
228
+ .root {
229
+ grid-template-areas:
230
+ 'left-container right-container';
231
+ grid-template-columns: minmax(0, 400px) minmax(0, 1fr);
232
+ grid-template-rows: repeat(5, min-content) 1fr [fold];
233
+ }
234
+ }
235
+ @media (max-width: 769px) {
236
+ .leftContainer {
237
+ composes: max-w-[100%] from global;
238
+ }
209
239
  }
@@ -67,7 +67,7 @@ const Option = props => {
67
67
 
68
68
  return (
69
69
  <div className={classes.root} data-cy="ProductOptions-Option-root">
70
- <span className={classes.title}>{label}</span>
70
+ {/* <span className={classes.title}>{label}</span> */}
71
71
  <ValueList
72
72
  getItemKey={getItemKey}
73
73
  selectedValue={initialSelection}
@@ -76,7 +76,7 @@ const Tile = props => {
76
76
  root: classes.variantImageSwatch
77
77
  }}
78
78
  resource={variantImg}
79
- width={24}
79
+ width={20}
80
80
  />
81
81
  );
82
82
 
@@ -19,6 +19,9 @@
19
19
  .variantImageSwatch {
20
20
  width: 24px;
21
21
  height: 24px;
22
+ display: table;
23
+ margin-bottom: 2px;
24
+ margin-right: 5px;
22
25
  }
23
26
 
24
27
  .root:hover {
@@ -27,7 +30,7 @@
27
30
  }
28
31
 
29
32
  .label {
30
- padding-left: 0.4rem;
33
+ padding-left: 5px;
31
34
  padding-right: 5px;
32
35
  }
33
36