Advertisement
Guest User

productfulldetail.js

a guest
Jan 22nd, 2024
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 62.24 KB | None | 0 0
  1. import React, { useMemo, Fragment, Suspense, useState, useEffect } from 'react';
  2. import { Link, useHistory } from 'react-router-dom';
  3. import { FormattedMessage, useIntl } from 'react-intl';
  4. import { arrayOf, bool, number, shape, string } from 'prop-types';
  5. import { Form } from 'informed';
  6. import {
  7. Info,
  8. ChevronRight,
  9. ChevronDown as ArrowDown,
  10. ChevronUp as ArrowUp,
  11. Check
  12. } from 'react-feather';
  13. import LoadingIndicator from '../LoadingIndicator';
  14. // import Price from '@magento/venia-ui/lib/components/Price';
  15.  
  16. import { useProductFullDetail } from '../../talons/ProductFullDetail/useProductFullDetail';
  17. import { isProductConfigurable } from '@magento/peregrine/lib/util/isProductConfigurable';
  18.  
  19. import { useStyle } from '@magento/venia-ui/lib/classify';
  20. import Breadcrumbs from '../Breadcrumbs';
  21. import Carousel from '../ProductImageCarousel';
  22. import FormError from '@magento/venia-ui/lib/components/FormError';
  23. import QuantityStepper from '@magento/venia-ui/lib/components/QuantityStepper';
  24. import RichContent from '@magento/venia-ui/lib/components/RichContent/richContent';
  25. import { ProductOptionsShimmer } from '@magento/venia-ui/lib/components/ProductOptions';
  26. import CustomAttributes from '@magento/venia-ui/lib/components/ProductFullDetail/CustomAttributes';
  27. import defaultClasses from './productFullDetail.module.css';
  28. import shareIcon from './ShareIcon.svg';
  29. import reviewsIcon from './ReviewsIcon.svg';
  30. import Field from '../Field';
  31. import timeIcon from './TimeIcon.svg';
  32.  
  33. import CompleteLook from './components/CompleteLook';
  34. import LinkButton from '@magento/venia-ui/lib/components/LinkButton';
  35. import Promise from './components/Promise';
  36.  
  37. import DropdownBlock from './components/DropdownBlock';
  38. import TrustedPartners from './components/TrustedPartners';
  39. import apiClient from '../../api';
  40.  
  41. import TrendingProducts from '../HomePage/components/TrendingProducts';
  42. import ShopPdpCategory from './components/PDPCategory/ShopByPdpCategory';
  43. import Price, { CurrencyCodeUI } from '../Price/price';
  44. import TryAtHomeSection from './components/TryAtHomeSection';
  45. import './index.css';
  46. import { BrowserPersistence } from '@magento/peregrine/lib/util';
  47. import ProductTags from '../Common/productTags';
  48. import { useWindowSize } from '@magento/peregrine';
  49. import whatsapp from './images/whatsapp.png';
  50. import RelatedProducts from './RelatedProducts';
  51. import CustomizableOptions from './components/CustomizableOptions';
  52. import ProductDetailsBlock from './components/ProductDetailsBlock';
  53. import { useSelector } from 'react-redux';
  54. const WishlistButton = React.lazy(() => import('../Wishlist/AddToListButton'));
  55. import { gql, useQuery } from '@apollo/client';
  56. import SimilarProduct from './SimilarProduct';
  57. import GlowPromise from '../HomePage/components/GlowPromise';
  58. import ForeverGlow from './components/ForeverGlow';
  59. import UserDetails from './components/UserDetails';
  60. import rating from './images/rating.png';
  61. import { netcoreEvent } from '../../initialize-netcore.js';
  62. import resourceUrl from '@magento/peregrine/lib/util/makeUrl';
  63. const Options = React.lazy(() =>
  64. import('@magento/venia-ui/lib/components/ProductOptions')
  65. );
  66. // Correlate a GQL error message to a field. GQL could return a longer error
  67. // string but it may contain contextual info such as product id. We can use
  68. // parts of the string to check for which field to apply the error.
  69. const ERROR_MESSAGE_TO_FIELD_MAPPING = {
  70. 'The requested qty is not available': 'quantity',
  71. 'Product that you are trying to add is not available.': 'quantity',
  72. "The product that was requested doesn't exist.": 'quantity'
  73. };
  74.  
  75. // Field level error messages for rendering.
  76. const ERROR_FIELD_TO_MESSAGE_MAPPING = {
  77. quantity: 'The requested quantity is not available.'
  78. };
  79.  
  80. const MINUS_SYMBOL = '-';
  81.  
  82. const storage = new BrowserPersistence();
  83.  
  84. const ProductFullDetail = props => {
  85. const { product, element } = props;
  86. const [showShare, setShowShare] = useState(false);
  87. const [showModal, setShowModal] = useState(false);
  88. const [popUpModal, setPopupModal] = useState(false);
  89.  
  90. const handleCloseModal = () => {
  91. setShowModal(!showModal);
  92. };
  93.  
  94. const talonProps = useProductFullDetail({ product });
  95.  
  96. const {
  97. breadcrumbCategoryId,
  98. errorMessage,
  99. handleAddToCart,
  100. handleCustomizableProductToCart,
  101. handleSelectionChange,
  102. isOutOfStock,
  103. isAddToCartDisabled,
  104. isSupportedProductType,
  105. mediaGalleryEntries,
  106. productDetails,
  107. customAttributes,
  108. wishlistButtonProps,
  109. setFormApi,
  110. handleSubmit,
  111. isBusy,
  112. clearErrors,
  113. isAddedItem,
  114. setIsAddedItem,
  115. handlePincode,
  116. checkDeliveryDate,
  117. pincode,
  118. deliveryDate,
  119. isInvalidPincode,
  120. parentCategoryId,
  121. designFamilyValue,
  122. crossSellProducts
  123. } = talonProps;
  124.  
  125. const { formatMessage } = useIntl();
  126.  
  127. const regularPrice = product?.price?.regularPrice?.amount;
  128.  
  129. const discountPercent =
  130. ((regularPrice.value - productDetails.price.value) /
  131. regularPrice.value) *
  132. 100;
  133.  
  134. const windowSize = useWindowSize();
  135. const isMobile = windowSize.innerWidth <= 640;
  136.  
  137. const pinCode = storage.getItem('pin_code');
  138.  
  139. const userInfo = JSON.parse(localStorage.getItem('user_info')) || null;
  140.  
  141. const customData = useSelector(state => state.custom);
  142.  
  143.  
  144. // Overall Rating of the product
  145.  
  146. const GET_PRODUCT_REVIEWS = gql`
  147. query getProductReviews($sku: String!) {
  148. products(filter: {sku: {eq: $sku}}) {
  149. items {
  150. uid
  151. reviews {
  152. items {
  153. summary
  154. average_rating
  155. text
  156. created_at
  157. nickname
  158. }
  159. }
  160. }
  161. }
  162. }`;
  163.  
  164.  
  165. const { data:overallRating, loading:loadingReviews } = useQuery(GET_PRODUCT_REVIEWS, {
  166. fetchPolicy: 'cache-and-network',
  167. nextFetchPolicy: 'cache-first',
  168. // skip: !sku,
  169. variables: {
  170. sku: product.sku
  171. }
  172. });
  173.  
  174.  
  175.  
  176. const productData = overallRating ? overallRating?.products?.items[0] : null;
  177. const ProductReviews = productData?.reviews?.items;
  178.  
  179. let sum = 0;
  180. ProductReviews?.forEach(review => {
  181. let rating = (review?.average_rating / 20).toFixed(1);
  182. sum += parseFloat(rating);
  183. });
  184.  
  185. const overall_Avg_Rating = ProductReviews?.length > 0 ? (sum / ProductReviews?.length).toFixed(1) : null;
  186.  
  187. const GET_CART_DETAILS = gql`
  188. query GetCartDetails($cartId: String!) {
  189. cart(cart_id: $cartId) {
  190. id
  191. items {
  192. uid
  193. product {
  194. uid
  195. sku
  196. }
  197. }
  198. }
  199. }
  200. `;
  201.  
  202. const cart = useSelector(state => state.cart);
  203. const { cartId } = cart;
  204.  
  205. const { data, loading } = useQuery(GET_CART_DETAILS, {
  206. fetchPolicy: 'cache-and-network',
  207. nextFetchPolicy: 'cache-first',
  208. skip: !cartId,
  209. variables: {
  210. cartId: cartId
  211. }
  212. });
  213.  
  214. const GET_CUSTOMER = gql`
  215. query getCustomer {
  216. customer {
  217. addresses {
  218. postcode
  219. default_shipping
  220. }
  221. }
  222. }
  223. `;
  224.  
  225. const { data: getCustomerData, error: errorCustomer } = useQuery(
  226. GET_CUSTOMER
  227. );
  228.  
  229. const customerDetails =
  230. getCustomerData &&
  231. getCustomerData.customer.addresses.find(i =>
  232. i.default_shipping == true ? i : null
  233. );
  234. const customerPostcode = customerDetails && customerDetails.postcode;
  235.  
  236. const { storeUserInfo } = customData;
  237.  
  238. const isStoreUser = storeUserInfo?.isStorefrontUser;
  239.  
  240. useEffect(() => {
  241. handlePincode(customerPostcode || pinCode);
  242. }, []);
  243.  
  244. useEffect(() => {
  245. if (pincode && pincode.length >= 6) {
  246. checkDeliveryDate(productDetails.sku);
  247. }
  248. }, [pincode]);
  249.  
  250. const history = useHistory();
  251.  
  252. useEffect(() => {
  253. if (isAddedItem) {
  254. netcoreEvent('dispatch','Add to Cart', {
  255. 'prid': product.id,
  256. 'name': product?.name,
  257. 'brand':'glow',
  258. 'sale_price':product?.price_range?.maximum_price?.final_price.value,
  259. 'price': product?.price_range?.maximum_price?.final_price.value,
  260. 'prqt':1,
  261. 'is_in_stock':product?.stock_status,
  262. 'product_image': product?.small_image,
  263. 'produrl': resourceUrl(`${location.host}/${product?.url_key}` || ''),
  264. 'product_type':product?.__typename,
  265. 'currency': product?.price_range?.maximum_price?.final_price.currency
  266. });
  267. history.push('cart');
  268. setIsAddedItem(false);
  269. }
  270. }, [isAddedItem]);
  271.  
  272.  
  273. const getMostViewedItems = async () => {
  274. try {
  275. const response = await apiClient.get(apiClient.Urls.getMostViewedProducts, {
  276. productId: product.id
  277. });
  278. if (response.success) {
  279. }
  280. }
  281. catch (error) {
  282. console.log('error', error);
  283. }
  284. }
  285. const productViews = () => {
  286. netcoreEvent('dispatch','Product view', {
  287. 'prid': product.id,
  288. 'name': product?.name,
  289. 'brand': 'glow',
  290. 'sale_price': product?.price_range?.maximum_price?.final_price.value,
  291. 'price':product?.price_range?.maximum_price?.final_price.value,
  292. 'prqt': 1,
  293. 'is_in_stock':product?.stock_status,
  294. 'product_image': product?.small_image,
  295. 'produrl': resourceUrl(`${location.host}/${product?.url_key}` || ''),
  296. 'currency': product?.price_range?.maximum_price?.final_price.currency
  297. });
  298. }
  299.  
  300. useEffect(() => {
  301. getMostViewedItems()
  302. productViews()
  303. }, []);
  304.  
  305. const [contactInfo, setContactInfo] = useState()
  306. const getContactDetails = async () => {
  307. try {
  308. const response = await apiClient.get(apiClient.Urls.getSlider, {
  309. identifier: 'contact_info'
  310. });
  311. if (response.success) {
  312. setContactInfo(response.data);
  313. }
  314. } catch (error) {
  315. console.log('error', error);
  316. }
  317. };
  318.  
  319.  
  320. useEffect(() => {
  321. getContactDetails()
  322. }, [])
  323.  
  324. const whatsappNumber = contactInfo && contactInfo.find(i => i.slide_title === "whatsapp_number");
  325.  
  326. const classes = useStyle(defaultClasses, props.classes);
  327. const options = isProductConfigurable(product) ? (
  328. <Suspense fallback={<ProductOptionsShimmer />}>
  329. <Options
  330. onSelectionChange={handleSelectionChange}
  331. options={product.configurable_options}
  332. />
  333. </Suspense>
  334. ) : null;
  335.  
  336. const breadcrumbs = breadcrumbCategoryId ? (
  337. <Breadcrumbs
  338. categoryId={breadcrumbCategoryId}
  339. currentProduct={productDetails.name}
  340. />
  341. ) : null;
  342.  
  343. // Fill a map with field/section -> error.
  344. const errors = new Map();
  345.  
  346. if (errorMessage) {
  347. Object.keys(ERROR_MESSAGE_TO_FIELD_MAPPING).forEach(key => {
  348. if (errorMessage.includes(key)) {
  349. const target = ERROR_MESSAGE_TO_FIELD_MAPPING[key];
  350. const message = ERROR_FIELD_TO_MESSAGE_MAPPING[target];
  351. errors.set(target, message);
  352. }
  353. });
  354.  
  355. // Handle cases where a user token is invalid or expired. Preferably
  356. // this would be handled elsewhere with an error code and not a string.
  357. if (errorMessage.includes('The current user cannot')) {
  358. errors.set('form', [
  359. new Error(
  360. formatMessage({
  361. id: 'productFullDetail.errorToken',
  362. defaultMessage:
  363. 'There was a problem with your cart. Please sign in again and try adding the item once more.'
  364. })
  365. )
  366. ]);
  367. }
  368.  
  369. // Handle cases where a cart wasn't created properly.
  370. if (
  371. errorMessage.includes('Variable "$cartId" got invalid value null')
  372. ) {
  373. errors.set('form', [
  374. new Error(
  375. formatMessage({
  376. id: 'productFullDetail.errorCart',
  377. defaultMessage:
  378. 'There was a problem with your cart. Please refresh the page and try adding the item once more.'
  379. })
  380. )
  381. ]);
  382. }
  383.  
  384. // An unknown error should still present a readable message.
  385. if (!errors.size) {
  386. errors.set('form', [
  387. new Error(
  388. formatMessage({
  389. id: 'productFullDetail.errorUnknown',
  390. defaultMessage:
  391. 'Could not add item to cart. Please check required options and try again.'
  392. })
  393. )
  394. ]);
  395. }
  396. }
  397.  
  398. var readyToShip = false;
  399.  
  400. if (Array.isArray(customAttributes)) {
  401. customAttributes.filter(customAttribute => {
  402. if (customAttribute.attribute_metadata.code === 'ready_to_ship') {
  403. if (
  404. customAttribute?.selected_attribute_options
  405. ?.attribute_option[0]?.label == 'Yes'
  406. ) {
  407. readyToShip = true;
  408. }
  409. }
  410. });
  411. }
  412.  
  413. var isVirtualTryOn = false;
  414. var glowSku = '';
  415.  
  416. if (Array.isArray(customAttributes)) {
  417. customAttributes.filter(customAttribute => {
  418. if (
  419. customAttribute.attribute_metadata.code === 'is_virtual_try_on'
  420. ) {
  421. if (
  422. customAttribute?.selected_attribute_options
  423. ?.attribute_option[0]?.label == 'Yes'
  424. ) {
  425. isVirtualTryOn = true;
  426. }
  427. }
  428. });
  429. const glowSkuAttribute = customAttributes.find(
  430. customAttribute =>
  431. customAttribute.attribute_metadata.code === 'glow_sku'
  432. );
  433. if (glowSkuAttribute) {
  434. glowSku = glowSkuAttribute.entered_attribute_value?.value;
  435. }
  436. }
  437.  
  438. const customAttributesDetails = useMemo(() => {
  439. const list = [];
  440. const pagebuilder = [];
  441. const skuAttribute = {
  442. attribute_metadata: {
  443. uid: 'attribute_sku',
  444. used_in_components: ['PRODUCT_DETAILS_PAGE'],
  445. ui_input: {
  446. ui_input_type: 'TEXT'
  447. },
  448. label: formatMessage({
  449. id: 'global.sku',
  450. defaultMessage: 'SKU'
  451. })
  452. },
  453. entered_attribute_value: {
  454. value: productDetails.sku
  455. }
  456. };
  457. if (Array.isArray(customAttributes)) {
  458. customAttributes.forEach(customAttribute => {
  459. if (
  460. customAttribute.attribute_metadata.ui_input
  461. .ui_input_type === 'PAGEBUILDER'
  462. ) {
  463. pagebuilder.push(customAttribute);
  464. } else {
  465. list.push(customAttribute);
  466. }
  467. });
  468. }
  469. list.unshift(skuAttribute);
  470. return {
  471. list: list,
  472. pagebuilder: pagebuilder
  473. };
  474. }, [customAttributes, productDetails.sku, formatMessage]);
  475.  
  476. const cartDetails = data ? data.cart?.items : null;
  477.  
  478. const cartCallToActionText = !isOutOfStock ? (
  479. isStoreUser ? (
  480. <FormattedMessage
  481. id="productFullDetail.addItemToCart1"
  482. defaultMessage="ADD TO CART"
  483. />
  484. ) : (
  485. <FormattedMessage
  486. id="productFullDetail.addItemToCart1"
  487. defaultMessage="BUY NOW"
  488. />
  489. )
  490. ) : (
  491. <FormattedMessage
  492. id="productFullDetail.itemOutOfStock"
  493. defaultMessage="Out of Stock"
  494. />
  495. );
  496.  
  497. const cartActionContent = isSupportedProductType ? (
  498. <button
  499. className={isInvalidPincode ? 'rounded' : 'rounded buy_now_button'}
  500. data-cy="ProductFullDetail-addToCartButton"
  501. disabled={isAddToCartDisabled || isInvalidPincode}
  502. priority="high"
  503. type="submit"
  504. style={
  505. isInvalidPincode
  506. ? {
  507. background: 'rgb(199, 164, 111, 0.5)',
  508. width: '100%',
  509. height: '40px',
  510. color: '#fff',
  511. letterSpacing: 4
  512. }
  513. : {
  514. background:
  515. 'linear-gradient(90deg, #C7A46F 0%, #886C44 100%)',
  516. width: '100%',
  517. height: '40px',
  518. color: '#fff',
  519. letterSpacing: 4
  520. }
  521. }
  522. >
  523. {cartCallToActionText}
  524. </button>
  525. ) : (
  526. <div className={classes.unavailableContainer}>
  527. <Info />
  528. <p>
  529. <FormattedMessage
  530. id={'productFullDetail.unavailableProduct'}
  531. defaultMessage={
  532. 'This product is currently unavailable for purchase.'
  533. }
  534. />
  535. </p>
  536. </div>
  537. );
  538.  
  539. const shortDescription = productDetails.shortDescription ? (
  540. <div className="text-[#656565]"
  541. style={{display:'none'}}>
  542. <RichContent html={productDetails.shortDescription.html}/>
  543. </div>
  544. ) : null;
  545.  
  546. const pageBuilderAttributes = customAttributesDetails.pagebuilder.length ? (
  547. <section className={classes.detailsPageBuilder}>
  548. <CustomAttributes
  549. classes={{ list: classes.detailsPageBuilderList }}
  550. customAttributes={customAttributesDetails.pagebuilder}
  551. showLabels={false}
  552. />
  553. </section>
  554. ) : null;
  555.  
  556. // let selectedProductColorId = null;
  557. // const handleProductSelected = productColorId => {
  558. // setSelectedProductColorId(productColorId);
  559. // };
  560.  
  561. const productDetailsAc = (
  562. <div dangerouslySetInnerHTML={{ __html: product.description || '' }} />
  563. );
  564.  
  565. const [breakDown, setBreakDown] = useState([]);
  566. const [selectedSize, setSelectedSize] = useState(null);
  567. const [selectedColor, setSelectedColor] = useState(null);
  568. const [fireWishListEvent,setFireWishListEvent] = useState(false);
  569.  
  570. const [isCustomizable, setIsCustomizable] = useState(false);
  571.  
  572. const [extraPrice, setExtraPrice] = useState(null);
  573.  
  574. useEffect(() => {
  575. getProductBreakDown();
  576. }, [selectedSize,selectedColor]);
  577.  
  578. const getProductBreakDown = async () => {
  579. try {
  580. const customOptionId = storage.getItem('size_id');
  581. const optionValue = storage.getItem('size');
  582. const ringSize = selectedSize?.title;
  583. const goldColor = selectedColor?.title;
  584. const productVariant = '';
  585. const response = await apiClient.get(
  586. apiClient.Urls.productBreakDown, {
  587. productId: product.id,
  588. customOptionId,
  589. optionValue,
  590. ringSize,
  591. goldColor,
  592. productVariant
  593. }
  594. );
  595.  
  596. if (response.success && response.data) {
  597. setBreakDown(response.data);
  598. }
  599. } catch (error) {
  600. console.log('error', error);
  601. }
  602. };
  603.  
  604. const glow_sku = breakDown ? breakDown?.productDetails?.variant_sku : null;
  605.  
  606. const productPriceBreakdownAc = (
  607. <div>
  608. {breakDown.content &&
  609. breakDown.content.map((i, index) => {
  610. return (
  611. i.variant_type && (
  612. <div
  613. className="flex justify-between p-1"
  614. key={index}
  615. >
  616. <span
  617. className={
  618. classes.nameColumn +
  619. ' font-bold !w-auto'
  620. }
  621. >
  622. {i.variant_type}
  623. </span>
  624. <span>
  625. <CurrencyCodeUI
  626. currencyCode={
  627. productDetails?.price?.currency
  628. }
  629. />
  630. {Math.round(i.variant_price)}
  631. </span>
  632. </div>
  633. )
  634. );
  635. })}
  636. <div className="flex justify-between p-1">
  637. <span className={classes.nameColumn + ' font-bold !w-auto'}>
  638. Value Addition
  639. </span>
  640. <span>
  641. <CurrencyCodeUI
  642. currencyCode={productDetails?.price?.currency}
  643. />{' '}
  644. {Math.round(breakDown.valueAddition)}
  645. </span>
  646. </div>
  647. {
  648. // breakDown && breakDown?.subTotal ? <div className="flex justify-between p-1">
  649. // <span className={classes.nameColumn + ' font-bold !w-auto'}>
  650. // Sub Total
  651. // </span>
  652. // <span>
  653. // <CurrencyCodeUI
  654. // currencyCode={productDetails?.price?.currency}
  655. // />{' '}
  656. // {Math.round(breakDown.subTotal)}
  657. // </span>
  658. // </div> : null
  659. }
  660. {
  661. breakDown && breakDown?.discountAmount ? <div className="flex justify-between p-1">
  662. <span className={classes.nameColumn + ' font-bold !w-auto'}>
  663. Discount Amount
  664. </span>
  665. <span>
  666. {MINUS_SYMBOL}
  667. <CurrencyCodeUI
  668. currencyCode={productDetails?.price?.currency}
  669. />{' '}
  670. {Math.round(breakDown.discountAmount)}
  671. </span>
  672. </div> : null
  673. }
  674. {
  675. // breakDown && breakDown?.netAmount ? <div className="flex justify-between p-1">
  676. // <span className={classes.nameColumn + ' font-bold !w-auto'}>
  677. // Net Amount
  678. // </span>
  679. // <span>
  680. // <CurrencyCodeUI
  681. // currencyCode={productDetails?.price?.currency}
  682. // />{' '}
  683. // {Math.round(breakDown.netAmount)}
  684. // </span>
  685. // </div> : null
  686. }
  687. <div className="flex justify-between p-1">
  688. <span className={classes.nameColumn + ' font-bold !w-auto'}>
  689. Tax
  690. </span>
  691. <span>
  692. <CurrencyCodeUI
  693. currencyCode={productDetails?.price?.currency}
  694. />{' '}
  695. {Math.round(breakDown.tax)}
  696. </span>
  697. </div>
  698. </div>
  699. );
  700.  
  701. const hiddenTags = [
  702. 'setting_type',
  703. 'is_on_sale',
  704. 'ready_to_ship',
  705. 'best_seller',
  706. 'new_launch',
  707. 'make_on_order',
  708. 'design_family',
  709. 'is_outlet_available',
  710. 'is_virtual_try_on'
  711. ];
  712.  
  713. const productCustomAttributeData = (
  714. <div>
  715. <table>
  716. <tbody>
  717. {customAttributes &&
  718. customAttributes.map((i, index) => {
  719. return (
  720. !hiddenTags.includes(
  721. i?.attribute_metadata?.code
  722. ) && (
  723. <tr key={index}>
  724. <td
  725. className={
  726. classes.nameColumn +
  727. ' font-semibold'
  728. }
  729. >
  730. {i?.attribute_metadata?.label}
  731. </td>
  732. <td>
  733. {i?.selected_attribute_options
  734. ?.attribute_option?.length
  735. ? i?.selected_attribute_options?.attribute_option.map(
  736. (j, index) => {
  737. return index ==
  738. i
  739. ?.selected_attribute_options
  740. ?.attribute_option
  741. ?.length -
  742. 1
  743. ? j.label
  744. : j.label + ', ';
  745. }
  746. )
  747. : i?.entered_attribute_value
  748. ?.value
  749. ? i?.entered_attribute_value
  750. ?.value
  751. : ''}
  752. </td>
  753. </tr>
  754. )
  755. );
  756. })}
  757. </tbody>
  758. </table>
  759. </div>
  760. );
  761.  
  762. const disclaimerAc = (
  763. <div>
  764. <p>
  765. Actual product dimensions may vary, please refer to the
  766. dimensions of the product for exact size. Color of the product
  767. may slightly vary from the image. We here by convey that final
  768. prices might vary depending on weight and size. A credit note or
  769. refund will be issued for any Difference value of less amount
  770. and If any access value incurred to be paid by customers. Our
  771. customer care team will inform you on prior before dispatching
  772. the product with complete details.
  773. </p>
  774. </div>
  775. );
  776.  
  777. const facebookShareLink = () => {
  778. const currentUri = encodeURIComponent(window.location.href);
  779. const shareUrl1 = currentUri;
  780. return `https://www.facebook.com/dialog/share?display=popup&href=${shareUrl1}&redirect_uri=${currentUri}`;
  781. };
  782. const whatsappShareLink = () => {
  783. const text = encodeURIComponent(window.location.href);
  784. return `https://api.whatsapp.com/send?text=${text}`;
  785. };
  786.  
  787. const twitterShareLink = () => {
  788. const text = encodeURIComponent(window.location.href);
  789. return `https://twitter.com/intent/tweet?text=${text}`;
  790. };
  791.  
  792. const emailShareLink = () => {
  793. const text = encodeURIComponent(shareContent);
  794. const subject = encodeURIComponent(shareTitle);
  795. return `mailto:?body=${text}&subject=${subject}`;
  796. };
  797.  
  798. const [earnedPoints, setEarnedPoints] = useState(null);
  799.  
  800. useEffect(() => {
  801. getEarnedPoints();
  802. }, []);
  803.  
  804. const [isDefaultProduct, setDefaultProduct] = useState(true);
  805.  
  806. const getEarnedPoints = async () => {
  807. const customOptionId = storage.getItem('size_id');
  808. const optionValue = storage.getItem('size');
  809. try {
  810. const response = await apiClient.post(apiClient.Urls.getPoints, {
  811. params: {
  812. sku: product.sku,
  813. customOptionId: customOptionId,
  814. optionValue: optionValue
  815. }
  816. });
  817.  
  818. if (response.success) {
  819. setEarnedPoints(response.points);
  820. }
  821. } catch (error) {
  822. console.log('error', error);
  823. }
  824. };
  825.  
  826. var isMatched = cartDetails && cartDetails.find(item => item.product.sku == product.sku);
  827.  
  828. return (
  829. <Fragment>
  830. {!isMobile && breadcrumbs}
  831. <Form
  832. className={classes.root}
  833. style={{ paddingTop: 0 }}
  834. data-cy="ProductFullDetail-root"
  835. onSubmit={(...args) => {
  836. // if (userInfo == null || userInfo?.userName == '') {
  837. // setPopupModal(true);
  838. // }
  839. // else {
  840. const handler = isCustomizable
  841. ? handleCustomizableProductToCart
  842. : handleAddToCart;
  843. return popUpModal ? null : handler(...args);
  844. // }
  845. }
  846. }
  847. >
  848. {
  849. popUpModal || userInfo?.userName == '' ? <UserDetails
  850. popUpModal={popUpModal}
  851. setPopupModal={setPopupModal}
  852. history={history}
  853. onSubmit={(...args) => {
  854. const handler = isCustomizable
  855. ? handleCustomizableProductToCart
  856. : handleAddToCart;
  857. return handler(...args)
  858. }}
  859. /> : null
  860. }
  861.  
  862. <SimilarProduct
  863. showModal={showModal}
  864. handleAddToCart={
  865. isCustomizable
  866. ? handleCustomizableProductToCart
  867. : handleAddToCart
  868. }
  869. setShowModal={setShowModal}
  870. handleCloseModal={handleCloseModal}
  871. />
  872.  
  873. <section className={classes.imageCarousel + ' max-w-[640px]'}>
  874. <ProductTags product={product} page={'PDP'} />
  875. <Carousel
  876. images={mediaGalleryEntries}
  877. item={product}
  878. isVirtualTryOn={isVirtualTryOn}
  879. selectedColor={selectedColor}
  880. />
  881. </section>
  882. <div
  883. className={
  884. classes.productDesc +
  885. ' overflow-y-scroll overflow-x-auto'
  886. }
  887. >
  888. <section
  889. className={classes.title}
  890. style={{ paddingTop: 0 }}
  891. >
  892. <div className="relative">
  893. <p className="flex justify-between text-[12px] text-[#939BA5] uppercase">
  894. SKU {glow_sku}
  895. <input type="hidden" name="productid" value={product.id} />
  896. </p>
  897. {earnedPoints ? (
  898. <h3 className="bg-[#363636] product_points">
  899. <span className="selected_product">
  900. Buy this & earn upto
  901. </span>
  902. <span className="points_section">
  903. {earnedPoints}
  904. </span>
  905. points
  906. </h3>
  907. ) : (
  908. <div className="min-h-[50px]" />
  909. )}
  910. <div className="flex">
  911. <h1
  912. aria-live="polite"
  913. className={
  914. classes.productName +
  915. ' text-[22px] font-ivyModeRegular'
  916. }
  917. data-cy="ProductFullDetail-productName"
  918. >
  919. {productDetails.name}
  920. </h1>
  921.  
  922. <div className="flex absolute top-[30px] right-0">
  923. <Suspense fallback={null}>
  924. <div
  925. className="flex items-center relative">
  926. <div
  927. onClick={() =>
  928. setShowShare(!showShare)
  929. }
  930. className="cursor-pointer"
  931. >
  932. <img
  933. src={shareIcon}
  934. class="mr-[20px]"
  935. alt="Share Icon"
  936. />
  937. </div>
  938. {showShare && (
  939. <div onMouseLeave={()=>setShowShare(false)} className="rounded-[6px] absolute bg-[#fff] border-[#C1A87E] border-[1px] flex flex-col right-[10px] top-[25px]">
  940. <a
  941. href={facebookShareLink()}
  942. target="blank"
  943. title="Share on Facebook"
  944. class="flex px-4 py-2 text-sm text-gray-800 border-b hover:bg-blue-100"
  945. >
  946. <svg
  947. aria-hidden="true"
  948. focusable="false"
  949. data-prefix="fab"
  950. data-icon="facebook-messenger"
  951. class="w-5 h-5 mr-4 text-[#227aff]"
  952. role="img"
  953. xmlns="http://www.w3.org/2000/svg"
  954. viewBox="0 0 512 512"
  955. >
  956. <path
  957. fill="currentColor"
  958. d="M256.55 8C116.52 8 8 110.34 8 248.57c0 72.3 29.71 134.78 78.07 177.94 8.35 7.51 6.63 11.86 8.05 58.23A19.92 19.92 0 0 0 122 502.31c52.91-23.3 53.59-25.14 62.56-22.7C337.85 521.8 504 423.7 504 248.57 504 110.34 396.59 8 256.55 8zm149.24 185.13l-73 115.57a37.37 37.37 0 0 1-53.91 9.93l-58.08-43.47a15 15 0 0 0-18 0l-78.37 59.44c-10.46 7.93-24.16-4.6-17.11-15.67l73-115.57a37.36 37.36 0 0 1 53.91-9.93l58.06 43.46a15 15 0 0 0 18 0l78.41-59.38c10.44-7.98 24.14 4.54 17.09 15.62z"
  959. />
  960. </svg>
  961. <span class="text-gray-600">
  962. Facebook
  963. </span>
  964. </a>
  965. <a
  966. href={twitterShareLink()}
  967. target="blank"
  968. title="Share on Twitter"
  969. class="flex px-4 py-2 text-sm text-gray-800 border-b hover:bg-blue-100"
  970. >
  971. <svg
  972. aria-hidden="true"
  973. focusable="false"
  974. data-prefix="fab"
  975. data-icon="twitter-square"
  976. class="w-5 h-5 mr-4 text-[#329bff]"
  977. role="img"
  978. xmlns="http://www.w3.org/2000/svg"
  979. viewBox="0 0 448 512"
  980. >
  981. <path
  982. fill="currentColor"
  983. d="M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-48.9 158.8c.2 2.8.2 5.7.2 8.5 0 86.7-66 186.6-186.6 186.6-37.2 0-71.7-10.8-100.7-29.4 5.3.6 10.4.8 15.8.8 30.7 0 58.9-10.4 81.4-28-28.8-.6-53-19.5-61.3-45.5 10.1 1.5 19.2 1.5 29.6-1.2-30-6.1-52.5-32.5-52.5-64.4v-.8c8.7 4.9 18.9 7.9 29.6 8.3a65.447 65.447 0 0 1-29.2-54.6c0-12.2 3.2-23.4 8.9-33.1 32.3 39.8 80.8 65.8 135.2 68.6-9.3-44.5 24-80.6 64-80.6 18.9 0 35.9 7.9 47.9 20.7 14.8-2.8 29-8.3 41.6-15.8-4.9 15.2-15.2 28-28.8 36.1 13.2-1.4 26-5.1 37.8-10.2-8.9 13.1-20.1 24.7-32.9 34z"
  984. />
  985. </svg>
  986. <span class="text-gray-600">
  987. Twitter
  988. </span>
  989. </a>
  990. <a
  991. href={whatsappShareLink()}
  992. target="blank"
  993. title="Share on Whatsapp"
  994. class="flex px-4 py-2 text-sm text-gray-800 border-b hover:bg-blue-100"
  995. >
  996. <svg
  997. xmlns="http://www.w3.org/2000/svg"
  998. width="16"
  999. height="16"
  1000. class="w-5 h-5 mr-4 text-[#25D366] bi bi-whatsapp"
  1001. fill="currentColor"
  1002. viewBox="0 0 16 16"
  1003. >
  1004. <path d="M13.601 2.326A7.854 7.854 0 0 0 7.994 0C3.627 0 .068 3.558.064 7.926c0 1.399.366 2.76 1.057 3.965L0 16l4.204-1.102a7.933 7.933 0 0 0 3.79.965h.004c4.368 0 7.926-3.558 7.93-7.93A7.898 7.898 0 0 0 13.6 2.326zM7.994 14.521a6.573 6.573 0 0 1-3.356-.92l-.24-.144-2.494.654.666-2.433-.156-.251a6.56 6.56 0 0 1-1.007-3.505c0-3.626 2.957-6.584 6.591-6.584a6.56 6.56 0 0 1 4.66 1.931 6.557 6.557 0 0 1 1.928 4.66c-.004 3.639-2.961 6.592-6.592 6.592zm3.615-4.934c-.197-.099-1.17-.578-1.353-.646-.182-.065-.315-.099-.445.099-.133.197-.513.646-.627.775-.114.133-.232.148-.43.05-.197-.1-.836-.308-1.592-.985-.59-.525-.985-1.175-1.103-1.372-.114-.198-.011-.304.088-.403.087-.088.197-.232.296-.346.1-.114.133-.198.198-.33.065-.134.034-.248-.015-.347-.05-.099-.445-1.076-.612-1.47-.16-.389-.323-.335-.445-.34-.114-.007-.247-.007-.38-.007a.729.729 0 0 0-.529.247c-.182.198-.691.677-.691 1.654 0 .977.71 1.916.81 2.049.098.133 1.394 2.132 3.383 2.992.47.205.84.326 1.129.418.475.152.904.129 1.246.08.38-.058 1.171-.48 1.338-.943.164-.464.164-.86.114-.943-.049-.084-.182-.133-.38-.232z" />{' '}
  1005. </svg>
  1006. <span class="text-gray-600">
  1007. Whatsapp
  1008. </span>
  1009. </a>
  1010. </div>
  1011. )}
  1012. </div>
  1013.  
  1014.  
  1015. </Suspense>
  1016. </div>
  1017. </div>
  1018. {
  1019. ProductReviews && ProductReviews?.length > 0 ? <div className='flex items-center gap-x-[10px]'>
  1020. <div className='bg-[#181A1D] text-[#fff] font-lato font-bold text-[12px] w-[50px] justify-center px-0 py-[5px] rounded-md flex gap-x-[5px]'>{overall_Avg_Rating}
  1021. <img src={rating} alt="Average rating" className='object-cover w-[15px] h-[15px]' />
  1022. </div>
  1023. <span
  1024. className='font-lato font-medium text-[12px] text-[#181A1D] cursor-pointer underline'
  1025. onClick={() => {
  1026. const reviewElement = document.getElementById(element);
  1027. if (reviewElement) {
  1028. reviewElement.scrollIntoView({
  1029. behavior: 'smooth'
  1030. });
  1031. }
  1032. }
  1033. }
  1034. >
  1035. {ProductReviews?.length} Reviews
  1036. </span>
  1037. </div> : null
  1038. }
  1039.  
  1040. </div>
  1041. {/* <div>
  1042. <img
  1043. src={reviewsIcon}
  1044. className="mr-3"
  1045. alt="Reviews icon"
  1046. />
  1047. <p className="text-xs">102 Reviews</p>
  1048. </div> */}
  1049. <div className="flex items-end mt-[15px]">
  1050. <p
  1051. data-cy="ProductFullDetail-productPrice"
  1052. className={
  1053. classes.productPrice +
  1054. ' text-[22px] font-bold'
  1055. }
  1056. >
  1057. <Price
  1058. currencyCode={productDetails.price.currency}
  1059. value={
  1060. productDetails.price.value +
  1061. extraPrice -
  1062. (discountPercent
  1063. ? extraPrice / discountPercent
  1064. : 0)
  1065. }
  1066. />
  1067. </p>
  1068. {regularPrice.value !==
  1069. productDetails.price.value ? (
  1070. <s
  1071. data-cy="ProductFullDetail-productPrice"
  1072. className={
  1073. classes.productPrice +
  1074. ' text-xs py-1 ml-1 text-[#35383A] font-bold'
  1075. }
  1076. >
  1077. <Price
  1078. currencyCode={regularPrice.currency}
  1079. value={regularPrice.value + extraPrice}
  1080. />
  1081. </s>
  1082. ) : null}
  1083. </div>
  1084. {shortDescription}
  1085. <CustomizableOptions
  1086. setExtraPrice={setExtraPrice}
  1087. sku={product.sku}
  1088. setIsCustomizable={setIsCustomizable}
  1089. customAttributes={customAttributes}
  1090. setDefaultProduct={setDefaultProduct}
  1091. checkDeliveryDate={checkDeliveryDate}
  1092. setSelectedSize={setSelectedSize}
  1093. setSelectedColor={setSelectedColor}
  1094. getEarnedPoints={getEarnedPoints}
  1095. />
  1096. <div className="max-w-[392px] mt-[10px] ">
  1097. <div
  1098. getApi={setFormApi}
  1099. className={
  1100. 'border-[#e1e6eb] border-[1px] flex justify-between px-2 items-center'
  1101. }
  1102. >
  1103. <input
  1104. autoComplete="pincode"
  1105. field="pincode"
  1106. id="pincode"
  1107. className="h-[40px] px-[10px] text-[14px] focus:border-none"
  1108. value={pincode}
  1109. placeholder="Enter Pin Code"
  1110. onChange={e => {
  1111. storage.setItem(
  1112. 'pin_code',
  1113. e.target.value,
  1114. null
  1115. );
  1116. handlePincode(e.target.value);
  1117. }}
  1118. />
  1119. <LinkButton
  1120. data-cy="Newsletter-submitButton"
  1121. className={
  1122. ' max-h-[35px] py-2 focus:outline-none'
  1123. }
  1124. // type="submit"
  1125. disabled={isBusy}
  1126. // onClick={clearErrors}
  1127. onClick={() =>
  1128. checkDeliveryDate(productDetails.sku)
  1129. }
  1130. >
  1131. <ChevronRight
  1132. size={20}
  1133. className="rounded-full border border-[#C77F44] text-[#C77F44]"
  1134. />
  1135. </LinkButton>
  1136. </div>
  1137. <p>{deliveryDate}</p>
  1138. </div>
  1139. <p className="text-sm flex items-center my-[20px]">
  1140. <span className="mr-[5px]">Need help ?</span>
  1141. <a
  1142. href="https://wa.me/+91994321251"
  1143. target={'_blank'}
  1144. data-cy="ScheduleAppointment-link"
  1145. className="flex items-center"
  1146. >
  1147. <span className="flex text-[#C77F44] text-xs cursor-pointer tracking-[1.2px] mr-[5px]">
  1148. CHAT WITH US ON WHATSAPP
  1149. </span>
  1150. <img
  1151. src={whatsapp}
  1152. alt="whatsapp_icon"
  1153. className="w-[20px] h-[20px]"
  1154. />
  1155. {/* <svg
  1156. aria-hidden="true"
  1157. focusable="false"
  1158. data-prefix="fab"
  1159. data-icon="linkedin"
  1160. class="w-5 h-5 mr-4 text-[#C77F44]"
  1161. role="img"
  1162. xmlns="http://www.w3.org/2000/svg"
  1163. viewBox="0 0 32 32"
  1164. >
  1165. <path
  1166. d=" M19.11 17.205c-.372 0-1.088 1.39-1.518 1.39a.63.63 0 0 1-.315-.1c-.802-.402-1.504-.817-2.163-1.447-.545-.516-1.146-1.29-1.46-1.963a.426.426 0 0 1-.073-.215c0-.33.99-.945.99-1.49 0-.143-.73-2.09-.832-2.335-.143-.372-.214-.487-.6-.487-.187 0-.36-.043-.53-.043-.302 0-.53.115-.746.315-.688.645-1.032 1.318-1.06 2.264v.114c-.015.99.472 1.977 1.017 2.78 1.23 1.82 2.506 3.41 4.554 4.34.616.287 2.035.888 2.722.888.817 0 2.15-.515 2.478-1.318.13-.33.244-.73.244-1.088 0-.058 0-.144-.03-.215-.1-.172-2.434-1.39-2.678-1.39zm-2.908 7.593c-1.747 0-3.48-.53-4.942-1.49L7.793 24.41l1.132-3.337a8.955 8.955 0 0 1-1.72-5.272c0-4.955 4.04-8.995 8.997-8.995S25.2 10.845 25.2 15.8c0 4.958-4.04 8.998-8.998 8.998zm0-19.798c-5.96 0-10.8 4.842-10.8 10.8 0 1.964.53 3.898 1.546 5.574L5 27.176l5.974-1.92a10.807 10.807 0 0 0 16.03-9.455c0-5.958-4.842-10.8-10.802-10.8z"
  1167. fill-rule="evenodd"
  1168. />
  1169. </svg> */}
  1170. </a>
  1171. </p>
  1172. {readyToShip && isDefaultProduct && (
  1173. <div className="flex text-sm mt-[15px]">
  1174. <div className="flex w-1/2 gap-2">
  1175. <img src={timeIcon} alt="Time Icon" />
  1176. <span className="text-xs uppercase tracking-[1.2px]">
  1177. {' '}
  1178. Ready to ship
  1179. </span>
  1180. </div>
  1181. <div className="flex gap-2 w-1/2">
  1182. <div
  1183. data-cy="ScheduleAppointment-link"
  1184. onClick={() => {
  1185. const element = document.getElementById(
  1186. 'try-at-store'
  1187. );
  1188. if (element) {
  1189. element.scrollIntoView({
  1190. behavior: 'smooth'
  1191. });
  1192. }
  1193. }}
  1194. >
  1195. <span className="text-[#C77F44] text-xs uppercase cursor-pointer tracking-[1.2px]">
  1196. Find in store
  1197. </span>
  1198. </div>
  1199. </div>
  1200. </div>
  1201. )}
  1202. </section>
  1203. <FormError
  1204. classes={{
  1205. root: classes.formErrors
  1206. }}
  1207. errors={errors.get('form') || []}
  1208. />
  1209. <section className={classes.options}>{options}</section>
  1210. <section className={classes.quantity + ' hidden'}>
  1211. <span
  1212. data-cy="ProductFullDetail-quantityTitle"
  1213. className={classes.quantityTitle}
  1214. >
  1215. <FormattedMessage
  1216. id={'global.quantity'}
  1217. defaultMessage={'Quantity'}
  1218. />
  1219. </span>
  1220. <QuantityStepper
  1221. classes={{ root: classes.quantityRoot }}
  1222. min={1}
  1223. message={errors.get('quantity')}
  1224. />
  1225. </section>
  1226. <section
  1227. className={classes.actions}
  1228. style={{ paddingTop: 0 }}
  1229. >
  1230. {!isMobile && (
  1231. <div
  1232. className="lg_pr-[74px]"
  1233. // onClick={(e) => {
  1234. // if (userInfo?.userName != '') {
  1235. // if (isMatched) {
  1236. // e.preventDefault();
  1237. // setShowModal(!showModal);
  1238. // }
  1239. // }
  1240. // }}
  1241. >
  1242. {cartActionContent}
  1243. <Suspense fallback={null}>
  1244. <WishlistButton {...wishlistButtonProps} />
  1245. </Suspense>
  1246. </div>
  1247. )}
  1248. {/* <p className="text-sm mt-2.5">
  1249. Want a get Notification on a{' '}
  1250. <span className="font-bold text-sm">
  1251. Price drop
  1252. </span>{' '}
  1253. <span className="text-[#C77F44] text-xs">
  1254. NOTIFY ME
  1255. </span>
  1256. </p> */}
  1257. <div className={classes.dropdownBlock}>
  1258. <DropdownBlock
  1259. name="Product Details"
  1260. content={
  1261. <ProductDetailsBlock
  1262. selectedSize={selectedSize}
  1263. selectedColor={selectedColor}
  1264. classes={classes}
  1265. customAttributes={customAttributes}
  1266. breakDown={breakDown}
  1267. productDetails={breakDown?.productDetails}
  1268. />
  1269. }
  1270. />
  1271. <DropdownBlock
  1272. name="Product Story"
  1273. content={productDetailsAc}
  1274. />
  1275. {breakDown.content ? (
  1276. <DropdownBlock
  1277. name="Product Price / Breakdown"
  1278. content={productPriceBreakdownAc}
  1279. />
  1280. ) : null}
  1281. <DropdownBlock
  1282. name="Disclaimers"
  1283. content={disclaimerAc}
  1284. />
  1285. </div>
  1286. </section>
  1287. </div>
  1288. {isMobile && (
  1289. <div className={classes.cartActionButton}
  1290. // onClick={(e) => {
  1291. // if (userInfo?.userName != '') {
  1292. // if (isMatched) {
  1293. // e.preventDefault();
  1294. // setShowModal(!showModal);
  1295. // }
  1296. // }
  1297. // }}
  1298. >
  1299. <div className="px-3 h-[46px] m-auto w-full">
  1300. {cartActionContent}
  1301. <Suspense fallback={null}>
  1302. <WishlistButton {...wishlistButtonProps} />
  1303. </Suspense>
  1304. </div>
  1305. </div>
  1306. )}
  1307. {pageBuilderAttributes}
  1308. </Form>
  1309. <div className="flex pb-[2rem] justify-center mt-10">
  1310. {crossSellProducts && crossSellProducts.length > 0 && (
  1311. <div className="w-[100%] bg-[#F7F2EC] rounded-lg">
  1312. <CompleteLook
  1313. wishlistButtonProps={wishlistButtonProps}
  1314. productDetails={productDetails}
  1315. products={crossSellProducts}
  1316. />
  1317. </div>
  1318. )}
  1319. </div>
  1320. <ForeverGlow />
  1321. <div className="flex justify-center">
  1322. {/* <Promise /> */}
  1323.  
  1324. <GlowPromise />
  1325. </div>
  1326.  
  1327. {designFamilyValue && parentCategoryId ? (
  1328. <RelatedProducts
  1329. df_id={designFamilyValue}
  1330. category_id={parentCategoryId}
  1331. current={product.sku}
  1332. />
  1333. ) : null}
  1334. <div id="try-at-store">
  1335. <TryAtHomeSection
  1336. sku={product.sku}
  1337. pincode={pincode}
  1338. handlePincode={handlePincode}
  1339. />
  1340. </div>
  1341.  
  1342. {/* <div className="flex p-[1rem] justify-center mt-10">
  1343. <div className="w-[100%]">
  1344. <TrustedPartners />
  1345. </div>
  1346. </div> */}
  1347. {/* <div className="flex justify-center mt-10">
  1348. <div className="text-center">
  1349. <h1 className="text-[42px] text-[#774E4F] font-medium font-ivyModeRegular">
  1350. Watch How It is Designed
  1351. </h1>
  1352. <p className="text-sm text-[#181A1D]">
  1353. Lorem ipsum dolor sit amet, consetetur sadipscing
  1354. </p>
  1355. </div>
  1356. </div> */}
  1357. {/* <div className="flex justify-center p-[1rem]">
  1358. <div className="w-[100%] h-[600px] border-2 border-solid bg-[#F7F2EC]">
  1359. <iframe
  1360. width="100%"
  1361. height="100%"
  1362. src="https://www.youtube.com/embed/J-N4qrH6Lgk"
  1363. title="Making of a Masterpiece"
  1364. frameborder="0"
  1365. allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  1366. allowfullscreen
  1367. />
  1368. </div>
  1369. </div> */}
  1370. <TrendingProducts />
  1371.  
  1372. <ShopPdpCategory />
  1373. </Fragment>
  1374. );
  1375. };
  1376.  
  1377. ProductFullDetail.propTypes = {
  1378. classes: shape({
  1379. cartActions: string,
  1380. description: string,
  1381. descriptionTitle: string,
  1382. details: string,
  1383. detailsPageBuilder: string,
  1384. detailsPageBuilderList: string,
  1385. detailsTitle: string,
  1386. imageCarousel: string,
  1387. options: string,
  1388. productName: string,
  1389. productPrice: string,
  1390. quantity: string,
  1391. quantityTitle: string,
  1392. quantityRoot: string,
  1393. root: string,
  1394. title: string,
  1395. unavailableContainer: string
  1396. }),
  1397. product: shape({
  1398. __typename: string,
  1399. id: number,
  1400. stock_status: string,
  1401. sku: string.isRequired,
  1402. price: shape({
  1403. regularPrice: shape({
  1404. amount: shape({
  1405. currency: string.isRequired,
  1406. value: number.isRequired
  1407. })
  1408. }).isRequired
  1409. }).isRequired,
  1410. media_gallery_entries: arrayOf(
  1411. shape({
  1412. uid: string,
  1413. label: string,
  1414. position: number,
  1415. disabled: bool,
  1416. file: string.isRequired
  1417. })
  1418. ),
  1419. description: string,
  1420. short_description: shape({
  1421. html: string,
  1422. __typename: string
  1423. })
  1424. }).isRequired
  1425. };
  1426.  
  1427. export default ProductFullDetail;
  1428.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement