Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React, { useMemo, Fragment, Suspense, useState, useEffect } from 'react';
- import { Link, useHistory } from 'react-router-dom';
- import { FormattedMessage, useIntl } from 'react-intl';
- import { arrayOf, bool, number, shape, string } from 'prop-types';
- import { Form } from 'informed';
- import {
- Info,
- ChevronRight,
- ChevronDown as ArrowDown,
- ChevronUp as ArrowUp,
- Check
- } from 'react-feather';
- import LoadingIndicator from '../LoadingIndicator';
- // import Price from '@magento/venia-ui/lib/components/Price';
- import { useProductFullDetail } from '../../talons/ProductFullDetail/useProductFullDetail';
- import { isProductConfigurable } from '@magento/peregrine/lib/util/isProductConfigurable';
- import { useStyle } from '@magento/venia-ui/lib/classify';
- import Breadcrumbs from '../Breadcrumbs';
- import Carousel from '../ProductImageCarousel';
- import FormError from '@magento/venia-ui/lib/components/FormError';
- import QuantityStepper from '@magento/venia-ui/lib/components/QuantityStepper';
- import RichContent from '@magento/venia-ui/lib/components/RichContent/richContent';
- import { ProductOptionsShimmer } from '@magento/venia-ui/lib/components/ProductOptions';
- import CustomAttributes from '@magento/venia-ui/lib/components/ProductFullDetail/CustomAttributes';
- import defaultClasses from './productFullDetail.module.css';
- import shareIcon from './ShareIcon.svg';
- import reviewsIcon from './ReviewsIcon.svg';
- import Field from '../Field';
- import timeIcon from './TimeIcon.svg';
- import CompleteLook from './components/CompleteLook';
- import LinkButton from '@magento/venia-ui/lib/components/LinkButton';
- import Promise from './components/Promise';
- import DropdownBlock from './components/DropdownBlock';
- import TrustedPartners from './components/TrustedPartners';
- import apiClient from '../../api';
- import TrendingProducts from '../HomePage/components/TrendingProducts';
- import ShopPdpCategory from './components/PDPCategory/ShopByPdpCategory';
- import Price, { CurrencyCodeUI } from '../Price/price';
- import TryAtHomeSection from './components/TryAtHomeSection';
- import './index.css';
- import { BrowserPersistence } from '@magento/peregrine/lib/util';
- import ProductTags from '../Common/productTags';
- import { useWindowSize } from '@magento/peregrine';
- import whatsapp from './images/whatsapp.png';
- import RelatedProducts from './RelatedProducts';
- import CustomizableOptions from './components/CustomizableOptions';
- import ProductDetailsBlock from './components/ProductDetailsBlock';
- import { useSelector } from 'react-redux';
- const WishlistButton = React.lazy(() => import('../Wishlist/AddToListButton'));
- import { gql, useQuery } from '@apollo/client';
- import SimilarProduct from './SimilarProduct';
- import GlowPromise from '../HomePage/components/GlowPromise';
- import ForeverGlow from './components/ForeverGlow';
- import UserDetails from './components/UserDetails';
- import rating from './images/rating.png';
- import { netcoreEvent } from '../../initialize-netcore.js';
- import resourceUrl from '@magento/peregrine/lib/util/makeUrl';
- const Options = React.lazy(() =>
- import('@magento/venia-ui/lib/components/ProductOptions')
- );
- // Correlate a GQL error message to a field. GQL could return a longer error
- // string but it may contain contextual info such as product id. We can use
- // parts of the string to check for which field to apply the error.
- const ERROR_MESSAGE_TO_FIELD_MAPPING = {
- 'The requested qty is not available': 'quantity',
- 'Product that you are trying to add is not available.': 'quantity',
- "The product that was requested doesn't exist.": 'quantity'
- };
- // Field level error messages for rendering.
- const ERROR_FIELD_TO_MESSAGE_MAPPING = {
- quantity: 'The requested quantity is not available.'
- };
- const MINUS_SYMBOL = '-';
- const storage = new BrowserPersistence();
- const ProductFullDetail = props => {
- const { product, element } = props;
- const [showShare, setShowShare] = useState(false);
- const [showModal, setShowModal] = useState(false);
- const [popUpModal, setPopupModal] = useState(false);
- const handleCloseModal = () => {
- setShowModal(!showModal);
- };
- const talonProps = useProductFullDetail({ product });
- const {
- breadcrumbCategoryId,
- errorMessage,
- handleAddToCart,
- handleCustomizableProductToCart,
- handleSelectionChange,
- isOutOfStock,
- isAddToCartDisabled,
- isSupportedProductType,
- mediaGalleryEntries,
- productDetails,
- customAttributes,
- wishlistButtonProps,
- setFormApi,
- handleSubmit,
- isBusy,
- clearErrors,
- isAddedItem,
- setIsAddedItem,
- handlePincode,
- checkDeliveryDate,
- pincode,
- deliveryDate,
- isInvalidPincode,
- parentCategoryId,
- designFamilyValue,
- crossSellProducts
- } = talonProps;
- const { formatMessage } = useIntl();
- const regularPrice = product?.price?.regularPrice?.amount;
- const discountPercent =
- ((regularPrice.value - productDetails.price.value) /
- regularPrice.value) *
- 100;
- const windowSize = useWindowSize();
- const isMobile = windowSize.innerWidth <= 640;
- const pinCode = storage.getItem('pin_code');
- const userInfo = JSON.parse(localStorage.getItem('user_info')) || null;
- const customData = useSelector(state => state.custom);
- // Overall Rating of the product
- const GET_PRODUCT_REVIEWS = gql`
- query getProductReviews($sku: String!) {
- products(filter: {sku: {eq: $sku}}) {
- items {
- uid
- reviews {
- items {
- summary
- average_rating
- text
- created_at
- nickname
- }
- }
- }
- }
- }`;
- const { data:overallRating, loading:loadingReviews } = useQuery(GET_PRODUCT_REVIEWS, {
- fetchPolicy: 'cache-and-network',
- nextFetchPolicy: 'cache-first',
- // skip: !sku,
- variables: {
- sku: product.sku
- }
- });
- const productData = overallRating ? overallRating?.products?.items[0] : null;
- const ProductReviews = productData?.reviews?.items;
- let sum = 0;
- ProductReviews?.forEach(review => {
- let rating = (review?.average_rating / 20).toFixed(1);
- sum += parseFloat(rating);
- });
- const overall_Avg_Rating = ProductReviews?.length > 0 ? (sum / ProductReviews?.length).toFixed(1) : null;
- const GET_CART_DETAILS = gql`
- query GetCartDetails($cartId: String!) {
- cart(cart_id: $cartId) {
- id
- items {
- uid
- product {
- uid
- sku
- }
- }
- }
- }
- `;
- const cart = useSelector(state => state.cart);
- const { cartId } = cart;
- const { data, loading } = useQuery(GET_CART_DETAILS, {
- fetchPolicy: 'cache-and-network',
- nextFetchPolicy: 'cache-first',
- skip: !cartId,
- variables: {
- cartId: cartId
- }
- });
- const GET_CUSTOMER = gql`
- query getCustomer {
- customer {
- addresses {
- postcode
- default_shipping
- }
- }
- }
- `;
- const { data: getCustomerData, error: errorCustomer } = useQuery(
- GET_CUSTOMER
- );
- const customerDetails =
- getCustomerData &&
- getCustomerData.customer.addresses.find(i =>
- i.default_shipping == true ? i : null
- );
- const customerPostcode = customerDetails && customerDetails.postcode;
- const { storeUserInfo } = customData;
- const isStoreUser = storeUserInfo?.isStorefrontUser;
- useEffect(() => {
- handlePincode(customerPostcode || pinCode);
- }, []);
- useEffect(() => {
- if (pincode && pincode.length >= 6) {
- checkDeliveryDate(productDetails.sku);
- }
- }, [pincode]);
- const history = useHistory();
- useEffect(() => {
- if (isAddedItem) {
- netcoreEvent('dispatch','Add to Cart', {
- 'prid': product.id,
- 'name': product?.name,
- 'brand':'glow',
- 'sale_price':product?.price_range?.maximum_price?.final_price.value,
- 'price': product?.price_range?.maximum_price?.final_price.value,
- 'prqt':1,
- 'is_in_stock':product?.stock_status,
- 'product_image': product?.small_image,
- 'produrl': resourceUrl(`${location.host}/${product?.url_key}` || ''),
- 'product_type':product?.__typename,
- 'currency': product?.price_range?.maximum_price?.final_price.currency
- });
- history.push('cart');
- setIsAddedItem(false);
- }
- }, [isAddedItem]);
- const getMostViewedItems = async () => {
- try {
- const response = await apiClient.get(apiClient.Urls.getMostViewedProducts, {
- productId: product.id
- });
- if (response.success) {
- }
- }
- catch (error) {
- console.log('error', error);
- }
- }
- const productViews = () => {
- netcoreEvent('dispatch','Product view', {
- 'prid': product.id,
- 'name': product?.name,
- 'brand': 'glow',
- 'sale_price': product?.price_range?.maximum_price?.final_price.value,
- 'price':product?.price_range?.maximum_price?.final_price.value,
- 'prqt': 1,
- 'is_in_stock':product?.stock_status,
- 'product_image': product?.small_image,
- 'produrl': resourceUrl(`${location.host}/${product?.url_key}` || ''),
- 'currency': product?.price_range?.maximum_price?.final_price.currency
- });
- }
- useEffect(() => {
- getMostViewedItems()
- productViews()
- }, []);
- const [contactInfo, setContactInfo] = useState()
- const getContactDetails = async () => {
- try {
- const response = await apiClient.get(apiClient.Urls.getSlider, {
- identifier: 'contact_info'
- });
- if (response.success) {
- setContactInfo(response.data);
- }
- } catch (error) {
- console.log('error', error);
- }
- };
- useEffect(() => {
- getContactDetails()
- }, [])
- const whatsappNumber = contactInfo && contactInfo.find(i => i.slide_title === "whatsapp_number");
- const classes = useStyle(defaultClasses, props.classes);
- const options = isProductConfigurable(product) ? (
- <Suspense fallback={<ProductOptionsShimmer />}>
- <Options
- onSelectionChange={handleSelectionChange}
- options={product.configurable_options}
- />
- </Suspense>
- ) : null;
- const breadcrumbs = breadcrumbCategoryId ? (
- <Breadcrumbs
- categoryId={breadcrumbCategoryId}
- currentProduct={productDetails.name}
- />
- ) : null;
- // Fill a map with field/section -> error.
- const errors = new Map();
- if (errorMessage) {
- Object.keys(ERROR_MESSAGE_TO_FIELD_MAPPING).forEach(key => {
- if (errorMessage.includes(key)) {
- const target = ERROR_MESSAGE_TO_FIELD_MAPPING[key];
- const message = ERROR_FIELD_TO_MESSAGE_MAPPING[target];
- errors.set(target, message);
- }
- });
- // Handle cases where a user token is invalid or expired. Preferably
- // this would be handled elsewhere with an error code and not a string.
- if (errorMessage.includes('The current user cannot')) {
- errors.set('form', [
- new Error(
- formatMessage({
- id: 'productFullDetail.errorToken',
- defaultMessage:
- 'There was a problem with your cart. Please sign in again and try adding the item once more.'
- })
- )
- ]);
- }
- // Handle cases where a cart wasn't created properly.
- if (
- errorMessage.includes('Variable "$cartId" got invalid value null')
- ) {
- errors.set('form', [
- new Error(
- formatMessage({
- id: 'productFullDetail.errorCart',
- defaultMessage:
- 'There was a problem with your cart. Please refresh the page and try adding the item once more.'
- })
- )
- ]);
- }
- // An unknown error should still present a readable message.
- if (!errors.size) {
- errors.set('form', [
- new Error(
- formatMessage({
- id: 'productFullDetail.errorUnknown',
- defaultMessage:
- 'Could not add item to cart. Please check required options and try again.'
- })
- )
- ]);
- }
- }
- var readyToShip = false;
- if (Array.isArray(customAttributes)) {
- customAttributes.filter(customAttribute => {
- if (customAttribute.attribute_metadata.code === 'ready_to_ship') {
- if (
- customAttribute?.selected_attribute_options
- ?.attribute_option[0]?.label == 'Yes'
- ) {
- readyToShip = true;
- }
- }
- });
- }
- var isVirtualTryOn = false;
- var glowSku = '';
- if (Array.isArray(customAttributes)) {
- customAttributes.filter(customAttribute => {
- if (
- customAttribute.attribute_metadata.code === 'is_virtual_try_on'
- ) {
- if (
- customAttribute?.selected_attribute_options
- ?.attribute_option[0]?.label == 'Yes'
- ) {
- isVirtualTryOn = true;
- }
- }
- });
- const glowSkuAttribute = customAttributes.find(
- customAttribute =>
- customAttribute.attribute_metadata.code === 'glow_sku'
- );
- if (glowSkuAttribute) {
- glowSku = glowSkuAttribute.entered_attribute_value?.value;
- }
- }
- const customAttributesDetails = useMemo(() => {
- const list = [];
- const pagebuilder = [];
- const skuAttribute = {
- attribute_metadata: {
- uid: 'attribute_sku',
- used_in_components: ['PRODUCT_DETAILS_PAGE'],
- ui_input: {
- ui_input_type: 'TEXT'
- },
- label: formatMessage({
- id: 'global.sku',
- defaultMessage: 'SKU'
- })
- },
- entered_attribute_value: {
- value: productDetails.sku
- }
- };
- if (Array.isArray(customAttributes)) {
- customAttributes.forEach(customAttribute => {
- if (
- customAttribute.attribute_metadata.ui_input
- .ui_input_type === 'PAGEBUILDER'
- ) {
- pagebuilder.push(customAttribute);
- } else {
- list.push(customAttribute);
- }
- });
- }
- list.unshift(skuAttribute);
- return {
- list: list,
- pagebuilder: pagebuilder
- };
- }, [customAttributes, productDetails.sku, formatMessage]);
- const cartDetails = data ? data.cart?.items : null;
- const cartCallToActionText = !isOutOfStock ? (
- isStoreUser ? (
- <FormattedMessage
- id="productFullDetail.addItemToCart1"
- defaultMessage="ADD TO CART"
- />
- ) : (
- <FormattedMessage
- id="productFullDetail.addItemToCart1"
- defaultMessage="BUY NOW"
- />
- )
- ) : (
- <FormattedMessage
- id="productFullDetail.itemOutOfStock"
- defaultMessage="Out of Stock"
- />
- );
- const cartActionContent = isSupportedProductType ? (
- <button
- className={isInvalidPincode ? 'rounded' : 'rounded buy_now_button'}
- data-cy="ProductFullDetail-addToCartButton"
- disabled={isAddToCartDisabled || isInvalidPincode}
- priority="high"
- type="submit"
- style={
- isInvalidPincode
- ? {
- background: 'rgb(199, 164, 111, 0.5)',
- width: '100%',
- height: '40px',
- color: '#fff',
- letterSpacing: 4
- }
- : {
- background:
- 'linear-gradient(90deg, #C7A46F 0%, #886C44 100%)',
- width: '100%',
- height: '40px',
- color: '#fff',
- letterSpacing: 4
- }
- }
- >
- {cartCallToActionText}
- </button>
- ) : (
- <div className={classes.unavailableContainer}>
- <Info />
- <p>
- <FormattedMessage
- id={'productFullDetail.unavailableProduct'}
- defaultMessage={
- 'This product is currently unavailable for purchase.'
- }
- />
- </p>
- </div>
- );
- const shortDescription = productDetails.shortDescription ? (
- <div className="text-[#656565]"
- style={{display:'none'}}>
- <RichContent html={productDetails.shortDescription.html}/>
- </div>
- ) : null;
- const pageBuilderAttributes = customAttributesDetails.pagebuilder.length ? (
- <section className={classes.detailsPageBuilder}>
- <CustomAttributes
- classes={{ list: classes.detailsPageBuilderList }}
- customAttributes={customAttributesDetails.pagebuilder}
- showLabels={false}
- />
- </section>
- ) : null;
- // let selectedProductColorId = null;
- // const handleProductSelected = productColorId => {
- // setSelectedProductColorId(productColorId);
- // };
- const productDetailsAc = (
- <div dangerouslySetInnerHTML={{ __html: product.description || '' }} />
- );
- const [breakDown, setBreakDown] = useState([]);
- const [selectedSize, setSelectedSize] = useState(null);
- const [selectedColor, setSelectedColor] = useState(null);
- const [fireWishListEvent,setFireWishListEvent] = useState(false);
- const [isCustomizable, setIsCustomizable] = useState(false);
- const [extraPrice, setExtraPrice] = useState(null);
- useEffect(() => {
- getProductBreakDown();
- }, [selectedSize,selectedColor]);
- const getProductBreakDown = async () => {
- try {
- const customOptionId = storage.getItem('size_id');
- const optionValue = storage.getItem('size');
- const ringSize = selectedSize?.title;
- const goldColor = selectedColor?.title;
- const productVariant = '';
- const response = await apiClient.get(
- apiClient.Urls.productBreakDown, {
- productId: product.id,
- customOptionId,
- optionValue,
- ringSize,
- goldColor,
- productVariant
- }
- );
- if (response.success && response.data) {
- setBreakDown(response.data);
- }
- } catch (error) {
- console.log('error', error);
- }
- };
- const glow_sku = breakDown ? breakDown?.productDetails?.variant_sku : null;
- const productPriceBreakdownAc = (
- <div>
- {breakDown.content &&
- breakDown.content.map((i, index) => {
- return (
- i.variant_type && (
- <div
- className="flex justify-between p-1"
- key={index}
- >
- <span
- className={
- classes.nameColumn +
- ' font-bold !w-auto'
- }
- >
- {i.variant_type}
- </span>
- <span>
- <CurrencyCodeUI
- currencyCode={
- productDetails?.price?.currency
- }
- />
- {Math.round(i.variant_price)}
- </span>
- </div>
- )
- );
- })}
- <div className="flex justify-between p-1">
- <span className={classes.nameColumn + ' font-bold !w-auto'}>
- Value Addition
- </span>
- <span>
- <CurrencyCodeUI
- currencyCode={productDetails?.price?.currency}
- />{' '}
- {Math.round(breakDown.valueAddition)}
- </span>
- </div>
- {
- // breakDown && breakDown?.subTotal ? <div className="flex justify-between p-1">
- // <span className={classes.nameColumn + ' font-bold !w-auto'}>
- // Sub Total
- // </span>
- // <span>
- // <CurrencyCodeUI
- // currencyCode={productDetails?.price?.currency}
- // />{' '}
- // {Math.round(breakDown.subTotal)}
- // </span>
- // </div> : null
- }
- {
- breakDown && breakDown?.discountAmount ? <div className="flex justify-between p-1">
- <span className={classes.nameColumn + ' font-bold !w-auto'}>
- Discount Amount
- </span>
- <span>
- {MINUS_SYMBOL}
- <CurrencyCodeUI
- currencyCode={productDetails?.price?.currency}
- />{' '}
- {Math.round(breakDown.discountAmount)}
- </span>
- </div> : null
- }
- {
- // breakDown && breakDown?.netAmount ? <div className="flex justify-between p-1">
- // <span className={classes.nameColumn + ' font-bold !w-auto'}>
- // Net Amount
- // </span>
- // <span>
- // <CurrencyCodeUI
- // currencyCode={productDetails?.price?.currency}
- // />{' '}
- // {Math.round(breakDown.netAmount)}
- // </span>
- // </div> : null
- }
- <div className="flex justify-between p-1">
- <span className={classes.nameColumn + ' font-bold !w-auto'}>
- Tax
- </span>
- <span>
- <CurrencyCodeUI
- currencyCode={productDetails?.price?.currency}
- />{' '}
- {Math.round(breakDown.tax)}
- </span>
- </div>
- </div>
- );
- const hiddenTags = [
- 'setting_type',
- 'is_on_sale',
- 'ready_to_ship',
- 'best_seller',
- 'new_launch',
- 'make_on_order',
- 'design_family',
- 'is_outlet_available',
- 'is_virtual_try_on'
- ];
- const productCustomAttributeData = (
- <div>
- <table>
- <tbody>
- {customAttributes &&
- customAttributes.map((i, index) => {
- return (
- !hiddenTags.includes(
- i?.attribute_metadata?.code
- ) && (
- <tr key={index}>
- <td
- className={
- classes.nameColumn +
- ' font-semibold'
- }
- >
- {i?.attribute_metadata?.label}
- </td>
- <td>
- {i?.selected_attribute_options
- ?.attribute_option?.length
- ? i?.selected_attribute_options?.attribute_option.map(
- (j, index) => {
- return index ==
- i
- ?.selected_attribute_options
- ?.attribute_option
- ?.length -
- 1
- ? j.label
- : j.label + ', ';
- }
- )
- : i?.entered_attribute_value
- ?.value
- ? i?.entered_attribute_value
- ?.value
- : ''}
- </td>
- </tr>
- )
- );
- })}
- </tbody>
- </table>
- </div>
- );
- const disclaimerAc = (
- <div>
- <p>
- Actual product dimensions may vary, please refer to the
- dimensions of the product for exact size. Color of the product
- may slightly vary from the image. We here by convey that final
- prices might vary depending on weight and size. A credit note or
- refund will be issued for any Difference value of less amount
- and If any access value incurred to be paid by customers. Our
- customer care team will inform you on prior before dispatching
- the product with complete details.
- </p>
- </div>
- );
- const facebookShareLink = () => {
- const currentUri = encodeURIComponent(window.location.href);
- const shareUrl1 = currentUri;
- return `https://www.facebook.com/dialog/share?display=popup&href=${shareUrl1}&redirect_uri=${currentUri}`;
- };
- const whatsappShareLink = () => {
- const text = encodeURIComponent(window.location.href);
- return `https://api.whatsapp.com/send?text=${text}`;
- };
- const twitterShareLink = () => {
- const text = encodeURIComponent(window.location.href);
- return `https://twitter.com/intent/tweet?text=${text}`;
- };
- const emailShareLink = () => {
- const text = encodeURIComponent(shareContent);
- const subject = encodeURIComponent(shareTitle);
- return `mailto:?body=${text}&subject=${subject}`;
- };
- const [earnedPoints, setEarnedPoints] = useState(null);
- useEffect(() => {
- getEarnedPoints();
- }, []);
- const [isDefaultProduct, setDefaultProduct] = useState(true);
- const getEarnedPoints = async () => {
- const customOptionId = storage.getItem('size_id');
- const optionValue = storage.getItem('size');
- try {
- const response = await apiClient.post(apiClient.Urls.getPoints, {
- params: {
- sku: product.sku,
- customOptionId: customOptionId,
- optionValue: optionValue
- }
- });
- if (response.success) {
- setEarnedPoints(response.points);
- }
- } catch (error) {
- console.log('error', error);
- }
- };
- var isMatched = cartDetails && cartDetails.find(item => item.product.sku == product.sku);
- return (
- <Fragment>
- {!isMobile && breadcrumbs}
- <Form
- className={classes.root}
- style={{ paddingTop: 0 }}
- data-cy="ProductFullDetail-root"
- onSubmit={(...args) => {
- // if (userInfo == null || userInfo?.userName == '') {
- // setPopupModal(true);
- // }
- // else {
- const handler = isCustomizable
- ? handleCustomizableProductToCart
- : handleAddToCart;
- return popUpModal ? null : handler(...args);
- // }
- }
- }
- >
- {
- popUpModal || userInfo?.userName == '' ? <UserDetails
- popUpModal={popUpModal}
- setPopupModal={setPopupModal}
- history={history}
- onSubmit={(...args) => {
- const handler = isCustomizable
- ? handleCustomizableProductToCart
- : handleAddToCart;
- return handler(...args)
- }}
- /> : null
- }
- <SimilarProduct
- showModal={showModal}
- handleAddToCart={
- isCustomizable
- ? handleCustomizableProductToCart
- : handleAddToCart
- }
- setShowModal={setShowModal}
- handleCloseModal={handleCloseModal}
- />
- <section className={classes.imageCarousel + ' max-w-[640px]'}>
- <ProductTags product={product} page={'PDP'} />
- <Carousel
- images={mediaGalleryEntries}
- item={product}
- isVirtualTryOn={isVirtualTryOn}
- selectedColor={selectedColor}
- />
- </section>
- <div
- className={
- classes.productDesc +
- ' overflow-y-scroll overflow-x-auto'
- }
- >
- <section
- className={classes.title}
- style={{ paddingTop: 0 }}
- >
- <div className="relative">
- <p className="flex justify-between text-[12px] text-[#939BA5] uppercase">
- SKU {glow_sku}
- <input type="hidden" name="productid" value={product.id} />
- </p>
- {earnedPoints ? (
- <h3 className="bg-[#363636] product_points">
- <span className="selected_product">
- Buy this & earn upto
- </span>
- <span className="points_section">
- {earnedPoints}
- </span>
- points
- </h3>
- ) : (
- <div className="min-h-[50px]" />
- )}
- <div className="flex">
- <h1
- aria-live="polite"
- className={
- classes.productName +
- ' text-[22px] font-ivyModeRegular'
- }
- data-cy="ProductFullDetail-productName"
- >
- {productDetails.name}
- </h1>
- <div className="flex absolute top-[30px] right-0">
- <Suspense fallback={null}>
- <div
- className="flex items-center relative">
- <div
- onClick={() =>
- setShowShare(!showShare)
- }
- className="cursor-pointer"
- >
- <img
- src={shareIcon}
- class="mr-[20px]"
- alt="Share Icon"
- />
- </div>
- {showShare && (
- <div onMouseLeave={()=>setShowShare(false)} className="rounded-[6px] absolute bg-[#fff] border-[#C1A87E] border-[1px] flex flex-col right-[10px] top-[25px]">
- <a
- href={facebookShareLink()}
- target="blank"
- title="Share on Facebook"
- class="flex px-4 py-2 text-sm text-gray-800 border-b hover:bg-blue-100"
- >
- <svg
- aria-hidden="true"
- focusable="false"
- data-prefix="fab"
- data-icon="facebook-messenger"
- class="w-5 h-5 mr-4 text-[#227aff]"
- role="img"
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 512 512"
- >
- <path
- fill="currentColor"
- 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"
- />
- </svg>
- <span class="text-gray-600">
- Facebook
- </span>
- </a>
- <a
- href={twitterShareLink()}
- target="blank"
- title="Share on Twitter"
- class="flex px-4 py-2 text-sm text-gray-800 border-b hover:bg-blue-100"
- >
- <svg
- aria-hidden="true"
- focusable="false"
- data-prefix="fab"
- data-icon="twitter-square"
- class="w-5 h-5 mr-4 text-[#329bff]"
- role="img"
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 448 512"
- >
- <path
- fill="currentColor"
- 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"
- />
- </svg>
- <span class="text-gray-600">
- Twitter
- </span>
- </a>
- <a
- href={whatsappShareLink()}
- target="blank"
- title="Share on Whatsapp"
- class="flex px-4 py-2 text-sm text-gray-800 border-b hover:bg-blue-100"
- >
- <svg
- xmlns="http://www.w3.org/2000/svg"
- width="16"
- height="16"
- class="w-5 h-5 mr-4 text-[#25D366] bi bi-whatsapp"
- fill="currentColor"
- viewBox="0 0 16 16"
- >
- <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" />{' '}
- </svg>
- <span class="text-gray-600">
- Whatsapp
- </span>
- </a>
- </div>
- )}
- </div>
- </Suspense>
- </div>
- </div>
- {
- ProductReviews && ProductReviews?.length > 0 ? <div className='flex items-center gap-x-[10px]'>
- <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}
- <img src={rating} alt="Average rating" className='object-cover w-[15px] h-[15px]' />
- </div>
- <span
- className='font-lato font-medium text-[12px] text-[#181A1D] cursor-pointer underline'
- onClick={() => {
- const reviewElement = document.getElementById(element);
- if (reviewElement) {
- reviewElement.scrollIntoView({
- behavior: 'smooth'
- });
- }
- }
- }
- >
- {ProductReviews?.length} Reviews
- </span>
- </div> : null
- }
- </div>
- {/* <div>
- <img
- src={reviewsIcon}
- className="mr-3"
- alt="Reviews icon"
- />
- <p className="text-xs">102 Reviews</p>
- </div> */}
- <div className="flex items-end mt-[15px]">
- <p
- data-cy="ProductFullDetail-productPrice"
- className={
- classes.productPrice +
- ' text-[22px] font-bold'
- }
- >
- <Price
- currencyCode={productDetails.price.currency}
- value={
- productDetails.price.value +
- extraPrice -
- (discountPercent
- ? extraPrice / discountPercent
- : 0)
- }
- />
- </p>
- {regularPrice.value !==
- productDetails.price.value ? (
- <s
- data-cy="ProductFullDetail-productPrice"
- className={
- classes.productPrice +
- ' text-xs py-1 ml-1 text-[#35383A] font-bold'
- }
- >
- <Price
- currencyCode={regularPrice.currency}
- value={regularPrice.value + extraPrice}
- />
- </s>
- ) : null}
- </div>
- {shortDescription}
- <CustomizableOptions
- setExtraPrice={setExtraPrice}
- sku={product.sku}
- setIsCustomizable={setIsCustomizable}
- customAttributes={customAttributes}
- setDefaultProduct={setDefaultProduct}
- checkDeliveryDate={checkDeliveryDate}
- setSelectedSize={setSelectedSize}
- setSelectedColor={setSelectedColor}
- getEarnedPoints={getEarnedPoints}
- />
- <div className="max-w-[392px] mt-[10px] ">
- <div
- getApi={setFormApi}
- className={
- 'border-[#e1e6eb] border-[1px] flex justify-between px-2 items-center'
- }
- >
- <input
- autoComplete="pincode"
- field="pincode"
- id="pincode"
- className="h-[40px] px-[10px] text-[14px] focus:border-none"
- value={pincode}
- placeholder="Enter Pin Code"
- onChange={e => {
- storage.setItem(
- 'pin_code',
- e.target.value,
- null
- );
- handlePincode(e.target.value);
- }}
- />
- <LinkButton
- data-cy="Newsletter-submitButton"
- className={
- ' max-h-[35px] py-2 focus:outline-none'
- }
- // type="submit"
- disabled={isBusy}
- // onClick={clearErrors}
- onClick={() =>
- checkDeliveryDate(productDetails.sku)
- }
- >
- <ChevronRight
- size={20}
- className="rounded-full border border-[#C77F44] text-[#C77F44]"
- />
- </LinkButton>
- </div>
- <p>{deliveryDate}</p>
- </div>
- <p className="text-sm flex items-center my-[20px]">
- <span className="mr-[5px]">Need help ?</span>
- <a
- href="https://wa.me/+91994321251"
- target={'_blank'}
- data-cy="ScheduleAppointment-link"
- className="flex items-center"
- >
- <span className="flex text-[#C77F44] text-xs cursor-pointer tracking-[1.2px] mr-[5px]">
- CHAT WITH US ON WHATSAPP
- </span>
- <img
- src={whatsapp}
- alt="whatsapp_icon"
- className="w-[20px] h-[20px]"
- />
- {/* <svg
- aria-hidden="true"
- focusable="false"
- data-prefix="fab"
- data-icon="linkedin"
- class="w-5 h-5 mr-4 text-[#C77F44]"
- role="img"
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 32 32"
- >
- <path
- 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"
- fill-rule="evenodd"
- />
- </svg> */}
- </a>
- </p>
- {readyToShip && isDefaultProduct && (
- <div className="flex text-sm mt-[15px]">
- <div className="flex w-1/2 gap-2">
- <img src={timeIcon} alt="Time Icon" />
- <span className="text-xs uppercase tracking-[1.2px]">
- {' '}
- Ready to ship
- </span>
- </div>
- <div className="flex gap-2 w-1/2">
- <div
- data-cy="ScheduleAppointment-link"
- onClick={() => {
- const element = document.getElementById(
- 'try-at-store'
- );
- if (element) {
- element.scrollIntoView({
- behavior: 'smooth'
- });
- }
- }}
- >
- <span className="text-[#C77F44] text-xs uppercase cursor-pointer tracking-[1.2px]">
- Find in store
- </span>
- </div>
- </div>
- </div>
- )}
- </section>
- <FormError
- classes={{
- root: classes.formErrors
- }}
- errors={errors.get('form') || []}
- />
- <section className={classes.options}>{options}</section>
- <section className={classes.quantity + ' hidden'}>
- <span
- data-cy="ProductFullDetail-quantityTitle"
- className={classes.quantityTitle}
- >
- <FormattedMessage
- id={'global.quantity'}
- defaultMessage={'Quantity'}
- />
- </span>
- <QuantityStepper
- classes={{ root: classes.quantityRoot }}
- min={1}
- message={errors.get('quantity')}
- />
- </section>
- <section
- className={classes.actions}
- style={{ paddingTop: 0 }}
- >
- {!isMobile && (
- <div
- className="lg_pr-[74px]"
- // onClick={(e) => {
- // if (userInfo?.userName != '') {
- // if (isMatched) {
- // e.preventDefault();
- // setShowModal(!showModal);
- // }
- // }
- // }}
- >
- {cartActionContent}
- <Suspense fallback={null}>
- <WishlistButton {...wishlistButtonProps} />
- </Suspense>
- </div>
- )}
- {/* <p className="text-sm mt-2.5">
- Want a get Notification on a{' '}
- <span className="font-bold text-sm">
- Price drop
- </span>{' '}
- <span className="text-[#C77F44] text-xs">
- NOTIFY ME
- </span>
- </p> */}
- <div className={classes.dropdownBlock}>
- <DropdownBlock
- name="Product Details"
- content={
- <ProductDetailsBlock
- selectedSize={selectedSize}
- selectedColor={selectedColor}
- classes={classes}
- customAttributes={customAttributes}
- breakDown={breakDown}
- productDetails={breakDown?.productDetails}
- />
- }
- />
- <DropdownBlock
- name="Product Story"
- content={productDetailsAc}
- />
- {breakDown.content ? (
- <DropdownBlock
- name="Product Price / Breakdown"
- content={productPriceBreakdownAc}
- />
- ) : null}
- <DropdownBlock
- name="Disclaimers"
- content={disclaimerAc}
- />
- </div>
- </section>
- </div>
- {isMobile && (
- <div className={classes.cartActionButton}
- // onClick={(e) => {
- // if (userInfo?.userName != '') {
- // if (isMatched) {
- // e.preventDefault();
- // setShowModal(!showModal);
- // }
- // }
- // }}
- >
- <div className="px-3 h-[46px] m-auto w-full">
- {cartActionContent}
- <Suspense fallback={null}>
- <WishlistButton {...wishlistButtonProps} />
- </Suspense>
- </div>
- </div>
- )}
- {pageBuilderAttributes}
- </Form>
- <div className="flex pb-[2rem] justify-center mt-10">
- {crossSellProducts && crossSellProducts.length > 0 && (
- <div className="w-[100%] bg-[#F7F2EC] rounded-lg">
- <CompleteLook
- wishlistButtonProps={wishlistButtonProps}
- productDetails={productDetails}
- products={crossSellProducts}
- />
- </div>
- )}
- </div>
- <ForeverGlow />
- <div className="flex justify-center">
- {/* <Promise /> */}
- <GlowPromise />
- </div>
- {designFamilyValue && parentCategoryId ? (
- <RelatedProducts
- df_id={designFamilyValue}
- category_id={parentCategoryId}
- current={product.sku}
- />
- ) : null}
- <div id="try-at-store">
- <TryAtHomeSection
- sku={product.sku}
- pincode={pincode}
- handlePincode={handlePincode}
- />
- </div>
- {/* <div className="flex p-[1rem] justify-center mt-10">
- <div className="w-[100%]">
- <TrustedPartners />
- </div>
- </div> */}
- {/* <div className="flex justify-center mt-10">
- <div className="text-center">
- <h1 className="text-[42px] text-[#774E4F] font-medium font-ivyModeRegular">
- Watch How It is Designed
- </h1>
- <p className="text-sm text-[#181A1D]">
- Lorem ipsum dolor sit amet, consetetur sadipscing
- </p>
- </div>
- </div> */}
- {/* <div className="flex justify-center p-[1rem]">
- <div className="w-[100%] h-[600px] border-2 border-solid bg-[#F7F2EC]">
- <iframe
- width="100%"
- height="100%"
- src="https://www.youtube.com/embed/J-N4qrH6Lgk"
- title="Making of a Masterpiece"
- frameborder="0"
- allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
- allowfullscreen
- />
- </div>
- </div> */}
- <TrendingProducts />
- <ShopPdpCategory />
- </Fragment>
- );
- };
- ProductFullDetail.propTypes = {
- classes: shape({
- cartActions: string,
- description: string,
- descriptionTitle: string,
- details: string,
- detailsPageBuilder: string,
- detailsPageBuilderList: string,
- detailsTitle: string,
- imageCarousel: string,
- options: string,
- productName: string,
- productPrice: string,
- quantity: string,
- quantityTitle: string,
- quantityRoot: string,
- root: string,
- title: string,
- unavailableContainer: string
- }),
- product: shape({
- __typename: string,
- id: number,
- stock_status: string,
- sku: string.isRequired,
- price: shape({
- regularPrice: shape({
- amount: shape({
- currency: string.isRequired,
- value: number.isRequired
- })
- }).isRequired
- }).isRequired,
- media_gallery_entries: arrayOf(
- shape({
- uid: string,
- label: string,
- position: number,
- disabled: bool,
- file: string.isRequired
- })
- ),
- description: string,
- short_description: shape({
- html: string,
- __typename: string
- })
- }).isRequired
- };
- export default ProductFullDetail;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement