@riosst100/pwa-marketplace 2.7.5 → 2.7.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.
@@ -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';
@@ -23,7 +22,7 @@ import cn from 'classnames';
23
22
  import Tabs from '@riosst100/pwa-marketplace/src/components/commons/Tabs';
24
23
  import ProductReviews from './components/productReview';
25
24
  import RichText from '@magento/venia-ui/lib/components/RichText';
26
- import { Star1, Verify, Sms, Message, Shop } from 'iconsax-react';
25
+ import { Star1, Verify, Sms, Message, Shop, ArrowUp2 } from 'iconsax-react';
27
26
  import { Link } from "react-router-dom";
28
27
  import Divider from '@riosst100/pwa-marketplace/src/components/Divider';
29
28
 
@@ -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,11 @@ 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, 'justify-between flex gap-x-[20px] px-[15px] py-0')}>
220
+ <RFQ
221
+ disabled={isAddToCartDisabled}
222
+ classes={{ rfqButton: cn(classes.rfqButton, "w-full") }}
223
+ />
238
224
  <Button
239
225
  data-cy="ProductFullDetail-addToCartButton"
240
226
  disabled={isAddToCartDisabled}
@@ -249,7 +235,8 @@ const ProductFullDetail = props => {
249
235
  : ''
250
236
  }
251
237
  classes={{
252
- content: 'normal-case font-medium text-[16px]'
238
+ rootClass: '!px-0 !py-3',
239
+ content: 'w-full normal-case font-medium text-[14px]'
253
240
  }}
254
241
  priority="high"
255
242
  type="submit"
@@ -295,17 +282,7 @@ const ProductFullDetail = props => {
295
282
 
296
283
  const contentContainerClass = 'content-container max-w-[1040px] p-2.5 m-auto relative mt-0 lg_mt-[34px] pb-6 lg_pb-0'
297
284
  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} /> */}
285
+ <div className={cn(contentContainerClass, classes.contentContainerTabOverride)}>
309
286
  <RichText
310
287
  rootClassName="px-0"
311
288
  content={productDetails.description}
@@ -315,9 +292,10 @@ const ProductFullDetail = props => {
315
292
 
316
293
  const ProductMoreInfo = () => (
317
294
  <>
318
- <div className={cn(contentContainerClass)}>
295
+ <div className={cn(contentContainerClass, classes.contentContainerTabOverride)}>
319
296
  <CustomAttributes
320
297
  customAttributes={customAttributesDetails.list}
298
+ classes={{ list: classes.customAttributesList }}
321
299
  />
322
300
  </div>
323
301
  {pageBuilderAttributes}
@@ -342,7 +320,7 @@ const ProductFullDetail = props => {
342
320
  );
343
321
 
344
322
  const ProductTNC = () => (
345
- <div className={cn(contentContainerClass)}>
323
+ <div className={cn(contentContainerClass, classes.contentContainerTabOverride)}>
346
324
  <p>{customAttributesList.map((data, index) => {
347
325
  if (data.code == "term_and_conditions") {
348
326
  return data.value;
@@ -352,7 +330,7 @@ const ProductFullDetail = props => {
352
330
  )
353
331
 
354
332
  const ShippingPolicy = () => (
355
- <div className={cn(contentContainerClass)}>
333
+ <div className={cn(contentContainerClass, classes.contentContainerTabOverride)}>
356
334
  <p>{customAttributesList.map((data, index) => {
357
335
  if (data.code == "shipping_policy") {
358
336
  return data.value;
@@ -362,7 +340,7 @@ const ProductFullDetail = props => {
362
340
  )
363
341
 
364
342
  const ReturnPolicy = () => (
365
- <div className={cn(contentContainerClass)}>
343
+ <div className={cn(contentContainerClass, classes.contentContainerTabOverride)}>
366
344
  <p>{customAttributesList.map((data, index) => {
367
345
  if (data.code == "return_policy") {
368
346
  return data.value;
@@ -372,7 +350,7 @@ const ProductFullDetail = props => {
372
350
  )
373
351
 
374
352
  const ProductFAQ = () => (
375
- <div className={cn(contentContainerClass)}>
353
+ <div className={cn(contentContainerClass, classes.contentContainerTabOverride)}>
376
354
  {customAttributesList.map((data, index) => {
377
355
  if (data.code == "faq") {
378
356
  return (
@@ -387,19 +365,108 @@ const ProductFullDetail = props => {
387
365
  </div>
388
366
  )
389
367
 
368
+
369
+ const getAttributeValue = (customAttributesDetails, key, useSuffix = false) => {
370
+ if (!customAttributesDetails?.list?.length) return "";
371
+
372
+ const attr = customAttributesDetails.list.find(attr => {
373
+ const code = attr.attribute_metadata?.code || "";
374
+ return useSuffix ? code.endsWith(key) : code === key;
375
+ });
376
+
377
+ if (!attr) return "";
378
+
379
+ if (attr.selected_attribute_options?.attribute_option?.length) {
380
+ return attr.selected_attribute_options.attribute_option
381
+ .map(opt => opt.label)
382
+ .join(", ");
383
+ }
384
+ return attr.entered_attribute_value?.value || "";
385
+ };
386
+
387
+ const setNameValue = getAttributeValue(customAttributesDetails, "card_set", true);
388
+ const cardNameValue = getAttributeValue(customAttributesDetails, "card_name", true);
389
+ const cardNumberValue = getAttributeValue(customAttributesDetails, "card_number", true);
390
+ const rarityValue = getAttributeValue(customAttributesDetails, "card_rarity", true);
391
+ const featureValue = getAttributeValue(customAttributesDetails, "card_feature", true);
392
+ const conditionValue = getAttributeValue(customAttributesDetails, "card_condition", true);
393
+ const foilValue = getAttributeValue(customAttributesDetails, "card_foil", true);
394
+ const ExpandableSection = ({ children, maxHeight = 480 }) => {
395
+ const [expanded, setExpanded] = useState(false);
396
+ const [showButton, setShowButton] = useState(false);
397
+ const contentRef = useRef(null);
398
+
399
+ useEffect(() => {
400
+ if (!contentRef.current) return;
401
+
402
+ const checkContent = () => {
403
+ const { scrollHeight } = contentRef.current;
404
+ const isDesktop = window.innerWidth >= 769;
405
+
406
+ if (isDesktop && scrollHeight > maxHeight) {
407
+ setShowButton(true);
408
+ } else {
409
+ setShowButton(false);
410
+ setExpanded(false);
411
+ }
412
+ };
413
+
414
+ checkContent();
415
+ window.addEventListener("resize", checkContent);
416
+ return () => window.removeEventListener("resize", checkContent);
417
+ }, [children, maxHeight]);
418
+
419
+ const isDesktop = typeof window !== "undefined" && window.innerWidth >= 769;
420
+
421
+ return (
422
+ <>
423
+ <div className="relative">
424
+ <div
425
+ ref={contentRef}
426
+ style={{
427
+ maxHeight:
428
+ isDesktop && showButton && !expanded
429
+ ? `${maxHeight}px`
430
+ : "none",
431
+ overflow: "hidden",
432
+ transition: "max-height 0.3s ease"
433
+ }}
434
+ >
435
+ {children}
436
+ </div>
437
+
438
+ {isDesktop && !expanded && showButton && (
439
+ <div className={cn("absolute bottom-0 left-0 w-full h-16 bg-gradient-to-t to-transparent pointer-events-none", classes.productDetailsMaxContent)}/>
440
+ )}
441
+ </div>
442
+ {isDesktop && showButton && (
443
+ <button
444
+ type="button"
445
+ onClick={() => setExpanded(!expanded)}
446
+ className="mt-0 text-[14px] text-blue-600 font-medium underline focus:outline-none"
447
+ >
448
+ {expanded ? "Show Less" : "Read More"} <ArrowUp2 size="14" style={{
449
+ "display": "inline-block",
450
+ "marginLeft": "5px"
451
+ }} className={cn(expanded ? 'rotate-0 ' : 'rotate-180', 'transition-all stroke-current')} variant="Outline" />
452
+ </button>
453
+ )}
454
+ </>
455
+ );
456
+ };
390
457
 
391
458
  const dataTabs =
392
459
  [
393
- {
394
- id: 'product-detail',
395
- title: 'Description',
396
- content: <ProductDescription />
397
- },
398
460
  {
399
461
  id: 'product-more-info',
400
- title: 'Details',
462
+ title: 'Product Information',
401
463
  content: <ProductMoreInfo />
402
464
  },
465
+ {
466
+ id: 'product-detail',
467
+ title: 'Product Description',
468
+ content: <ProductDescription />
469
+ },
403
470
  {
404
471
  id: 'product-tnc',
405
472
  title: 'Term & Conditions',
@@ -423,7 +490,7 @@ const ProductFullDetail = props => {
423
490
  {
424
491
  id: 'product-reviews',
425
492
  title: 'Reviews',
426
- content: <ProductReviews className={cn(contentContainerClass)} />
493
+ content: <ProductReviews className={cn(contentContainerClass, classes.contentContainerTabOverride)} />
427
494
  }
428
495
  ];
429
496
 
@@ -478,22 +545,6 @@ const ProductFullDetail = props => {
478
545
  <section className={cn(classes.leftContainer, 'relative')}>
479
546
  <ProductLabel item={productDetails} />
480
547
  <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
548
  </section>
498
549
  <section className={classes.rightContainer}>
499
550
  <div
@@ -506,179 +557,140 @@ const ProductFullDetail = props => {
506
557
  aria-live="polite"
507
558
  className={cn(
508
559
  classes.productName,
509
- '!font-medium leading-[normal] mb-4 line-clamp-2'
560
+ '!font-medium leading-[1] mb-1.5 line-clamp-2 !text-[1.5rem]'
510
561
  )}
511
562
  data-cy="ProductFullDetail-productName"
512
563
  >
513
564
  {productDetails.name}
514
565
  </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',
534
- )}
535
- >
536
- {shortDescription}
537
566
  </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"
554
- className={cn(
555
- classes.productPrice,
556
- 'text-[32px] font-medium leading-[32px] mb-0',
567
+ <section className="bottom_right-container justify-center gap-x-6 block sm_flex md_flex lg_flex xl_flex 2xl_flex gap-[7px]">
568
+ <section className='right_left-container w-full'>
569
+ <ExpandableSection>
570
+ <div className="text-sm leading-6 leading-[2.5rem]">
571
+ {setNameValue && (
572
+ <p><strong>Set Name:</strong> {setNameValue}</p>
557
573
  )}
558
- >
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"
574
+ {cardNameValue && (
575
+ <p><strong>Card Name:</strong> {cardNameValue}</p>
576
+ )}
577
+ {cardNumberValue && (
578
+ <p><strong>Card Number:</strong> {cardNumberValue}</p>
579
+ )}
580
+ {rarityValue && (
581
+ <p><strong>Rarity:</strong> {rarityValue}</p>
582
+ )}
583
+ {featureValue && (
584
+ <p><strong>Feature:</strong> {featureValue}</p>
585
+ )}
586
+ {conditionValue && (
587
+ <p><strong>Condition:</strong> {conditionValue}</p>
588
+ )}
589
+ {foilValue && (
590
+ <p><strong>Foil/Non Foil:</strong> {foilValue}</p>
591
+ )}
592
+ </div>
593
+ </ExpandableSection>
594
+ </section>
595
+ <section className='right_right-container w-full'>
596
+ <div className={cn('product_purchase-section', 'border border-[lightgray] rounded-[10px] mb-[15px]')}>
597
+ <div
567
598
  className={cn(
568
- classes.productPrice,
569
- 'text-lg font-normal leading-none text-gray-400 mb-0 line-through',
599
+ 'product_price_container',
600
+ 'flex justify-between flex-wrap gap-y-5'
570
601
  )}
571
602
  >
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 : ''}
643
- </div>
644
- <div className="flex items-center relative">
645
- <Verify variant='Bold' color='#f76b1c' size={20} />
646
- </div>
647
- </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
- </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>
603
+ <div className='flex flex-col gap-y-2 pl-[1rem] pt-[1rem]'>
604
+ <div className='flex flex-col gap-y-1'>
605
+ <p
606
+ data-cy="ProductFullDetail-productPrice"
607
+ className={cn(
608
+ classes.productPrice,
609
+ 'text-[32px] font-medium leading-[32px] mb-0',
610
+ )}
611
+ >
612
+ <Price
613
+ currencyCode={productDetails.price.currency}
614
+ priceRange={productDetails.price_range}
615
+ value={productDetails.price.value}
616
+ />
617
+ </p>
667
618
  </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
619
+ <AuctionDetail className="auction_detail-container" />
620
+ <PreorderDetail className={'preorder_detail-container'} />
621
+ <small className='shipping-calculation-notes text-gray-200 text-xs'>
622
+ Shipping is calculated on checkout
623
+ </small>
624
+ <div className='flex flex-col xs_items-center md_items-start gap-[6px] relative'>
625
+ <div className="gap-x-[10px] gap-y-1 flex xs_flex-col md_flex-row xs_items-center md_items-start relative">
626
+ <Link to={"/seller/"+sellerDetails.url_key} class="flex items-center justify-center gap-[5px] py-1 relative bg-white">
627
+ <div class="flex items-center justify-center gap-[5px] relative">
628
+ <p>Sold by</p>
629
+ <div class="relative xs_hidden lg_flex w-fit font-medium text-[#f76b1c] text-[14px] tracking-[0] leading-[20px] whitespace-nowrap">
630
+ {sellerDetails ? sellerDetails.name : ''}
631
+ </div>
632
+ </div>
633
+ </Link>
674
634
  </div>
675
635
  </div>
676
- </Link>
636
+ </div>
677
637
  </div>
638
+ <FormError
639
+ classes={{
640
+ root: classes.formErrors
641
+ }}
642
+ errors={errors.get('form') || []}
643
+ />
644
+ { options &&
645
+ <section className={classes.options}>{options}</section>
646
+ }
647
+ <section className={cn(classes.quantity, 'pb-[20px] pt-[10px] !border-none')}>
648
+ <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'>
649
+ <QuantityStepper
650
+ min={1}
651
+ message={errors.get('quantity')}
652
+ />
653
+ <Suspense fallback={null}>
654
+ <WishlistButton
655
+ classes={{
656
+ root: cn(
657
+ 'button_share border border-solid border-gray-100 p-2.5',
658
+ 'rounded-full flex justify-center items-center h-fitContent min-w-min'
659
+ )
660
+ }}
661
+ {...wishlistButtonProps}
662
+ buttonText={''}
663
+ />
664
+ </Suspense>
665
+ </div>
666
+ <div className='product_actions-wrapper'>
667
+ {cartActionContent}
668
+ </div>
669
+ </section>
670
+ </div>
671
+ <div className={cn('product_otherlink-section', 'border border-[lightgray] rounded-[10px] mb-[15px]')}>
672
+ <LinkToOtherStores productDetails={productDetails} />
678
673
  </div>
679
- </div>
674
+ <section>
675
+ <div
676
+ className="text-center pt-3 pb-3 cursor-pointer border border-[lightgray] rounded-[10px]"
677
+ onClick={() => {
678
+ const section = document.getElementById("cross-seller-section");
679
+ if (section) {
680
+ section.scrollIntoView({ behavior: "smooth" });
681
+ }
682
+ }}
683
+ >
684
+ <span className="font-bold underline text-[14px]">
685
+ View {totalListings} Other Listings
686
+ </span>
687
+ <p className="text-sm text-gray-600">
688
+ As low as ${lowestPrice.toFixed(2)}
689
+ </p>
690
+ </div>
691
+ </section>
692
+ </section>
680
693
  </section>
681
- <Divider />
682
694
  </section>
683
695
  </Form>
684
696
  <section className='section_product-details-container mt-8 mb-10'>
@@ -687,21 +699,16 @@ const ProductFullDetail = props => {
687
699
  data={dataTabs}
688
700
  tabContentWrapperClassName='!p-0'
689
701
  hasContent
690
- tabWrapperClassName='xl_gap-x-[60px] justify-center'
702
+ tabWrapperClassName='xl_gap-x-[60px] justify-between'
691
703
  />
692
704
  </div>
693
705
  <div className='block lg_hidden'>
694
706
  <ProductDetailsCollapsible data={dataTabs} />
695
707
  </div>
696
708
  </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'>
709
+ <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
710
  <div className='lg_max-w-[1200px] px-2.5 mx-auto relative max-w-screen-md'>
704
- <CrossSeller />
711
+ <CrossSeller/>
705
712
  </div>
706
713
  </section>
707
714
  </Fragment>