Guest User

useproductfulldetail.js

a guest
Mar 23rd, 2024
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 31.84 KB | None | 0 0
  1. import { useCallback, useState, useMemo } from 'react';
  2. import { useIntl } from 'react-intl';
  3. import { useMutation, useQuery, gql } from '@apollo/client';
  4. import { useCartContext } from '@magento/peregrine/lib/context/cart';
  5. import { useUserContext } from '@magento/peregrine/lib/context/user';
  6.  
  7. import { appendOptionsToPayload } from '@magento/peregrine/lib/util/appendOptionsToPayload';
  8. import { findMatchingVariant } from '@magento/peregrine/lib/util/findMatchingProductVariant';
  9. import { isProductConfigurable } from '@magento/peregrine/lib/util/isProductConfigurable';
  10. import { isSupportedProductType as isSupported } from '@magento/peregrine/lib/util/isSupportedProductType';
  11. import { deriveErrorMessage } from '@magento/peregrine/lib/util/deriveErrorMessage';
  12. import mergeOperations from '@magento/peregrine/lib/util/shallowMerge';
  13. import defaultOperations from '@magento/peregrine/lib/talons/ProductFullDetail/productFullDetail.gql';
  14. import { useEventingContext } from '@magento/peregrine/lib/context/eventing';
  15. import apiClient from '../../api';
  16.  
  17. import { CartTriggerFragment } from '@magento/peregrine/lib/talons/Header/cartTriggerFragments.gql';
  18. import { MiniCartFragment } from '@magento/peregrine/lib/talons/MiniCart/miniCartFragments.gql';
  19. import { BrowserPersistence } from '@magento/peregrine/lib/util';
  20.  
  21. import { GTMEventTrigger } from '../../lib/util/GTMEventTrigger';
  22.  
  23. const INITIAL_OPTION_CODES = new Map();
  24. const INITIAL_OPTION_SELECTIONS = new Map();
  25. const OUT_OF_STOCK_CODE = 'OUT_OF_STOCK';
  26.  
  27. const deriveOptionCodesFromProduct = product => {
  28. // If this is a simple product it has no option codes.
  29. if (!isProductConfigurable(product)) {
  30. return INITIAL_OPTION_CODES;
  31. }
  32.  
  33. // Initialize optionCodes based on the options of the product.
  34. const initialOptionCodes = new Map();
  35. for (const {
  36. attribute_id,
  37. attribute_code
  38. } of product.configurable_options) {
  39. initialOptionCodes.set(attribute_id, attribute_code);
  40. }
  41.  
  42. return initialOptionCodes;
  43. };
  44.  
  45. // Similar to deriving the initial codes for each option.
  46. const deriveOptionSelectionsFromProduct = product => {
  47. if (!isProductConfigurable(product)) {
  48. return INITIAL_OPTION_SELECTIONS;
  49. }
  50.  
  51. const initialOptionSelections = new Map();
  52. for (const { attribute_id } of product.configurable_options) {
  53. initialOptionSelections.set(attribute_id, undefined);
  54. }
  55.  
  56. return initialOptionSelections;
  57. };
  58.  
  59. const getIsMissingOptions = (product, optionSelections) => {
  60. // Non-configurable products can't be missing options.
  61. if (!isProductConfigurable(product)) {
  62. return false;
  63. }
  64.  
  65. // Configurable products are missing options if we have fewer
  66. // option selections than the product has options.
  67. const { configurable_options } = product;
  68. const numProductOptions = configurable_options.length;
  69. const numProductSelections = Array.from(optionSelections.values()).filter(
  70. value => !!value
  71. ).length;
  72.  
  73. return numProductSelections < numProductOptions;
  74. };
  75.  
  76. const getIsOutOfStock = (product, optionCodes, optionSelections) => {
  77. const { stock_status, variants } = product;
  78. const isConfigurable = isProductConfigurable(product);
  79. const optionsSelected =
  80. Array.from(optionSelections.values()).filter(value => !!value).length >
  81. 0;
  82.  
  83. if (isConfigurable && optionsSelected) {
  84. const item = findMatchingVariant({
  85. optionCodes,
  86. optionSelections,
  87. variants
  88. });
  89. const stockStatus = item?.product?.stock_status;
  90.  
  91. return stockStatus === OUT_OF_STOCK_CODE || !stockStatus;
  92. }
  93. return stock_status === OUT_OF_STOCK_CODE;
  94. };
  95.  
  96. const getMediaGalleryEntries = (product, optionCodes, optionSelections) => {
  97. let value = [];
  98.  
  99. const { media_gallery_entries, variants } = product;
  100. const isConfigurable = isProductConfigurable(product);
  101.  
  102. // Selections are initialized to "code => undefined". Once we select a value, like color, the selections change. This filters out unselected options.
  103. const optionsSelected =
  104. Array.from(optionSelections.values()).filter(value => !!value).length >
  105. 0;
  106.  
  107. if (!isConfigurable || !optionsSelected) {
  108. value = media_gallery_entries;
  109. } else {
  110. // If any of the possible variants matches the selection add that
  111. // variant's image to the media gallery. NOTE: This _can_, and does,
  112. // include variants such as size. If Magento is configured to display
  113. // an image for a size attribute, it will render that image.
  114. const item = findMatchingVariant({
  115. optionCodes,
  116. optionSelections,
  117. variants
  118. });
  119.  
  120. value = item
  121. ? [...item.product.media_gallery_entries, ...media_gallery_entries]
  122. : media_gallery_entries;
  123. }
  124.  
  125. return value;
  126. };
  127.  
  128. // We only want to display breadcrumbs for one category on a PDP even if a
  129. // product has multiple related categories. This function filters and selects
  130. // one category id for that purpose.
  131. const getBreadcrumbCategoryId = categories => {
  132. // Exit if there are no categories for this product.
  133. if (!categories || !categories.length) {
  134. return;
  135. }
  136. const breadcrumbSet = new Set();
  137. categories.forEach(({ breadcrumbs }) => {
  138. // breadcrumbs can be `null`...
  139. (breadcrumbs || []).forEach(({ category_id }) =>
  140. breadcrumbSet.add(category_id)
  141. );
  142. });
  143.  
  144. // Until we can get the single canonical breadcrumb path to a product we
  145. // will just return the first category id of the potential leaf categories.
  146. const leafCategory = categories.find(
  147. category => !breadcrumbSet.has(category.uid)
  148. );
  149.  
  150. // If we couldn't find a leaf category then just use the first category
  151. // in the list for this product.
  152. return leafCategory.uid || categories[0].uid;
  153. };
  154.  
  155. const getConfigPrice = (product, optionCodes, optionSelections) => {
  156. let value;
  157.  
  158. const { variants } = product;
  159. const isConfigurable = isProductConfigurable(product);
  160.  
  161. const optionsSelected =
  162. Array.from(optionSelections.values()).filter(value => !!value).length >
  163. 0;
  164.  
  165. if (!isConfigurable || !optionsSelected) {
  166. value = product.price_range?.maximum_price;
  167. } else {
  168. const item = findMatchingVariant({
  169. optionCodes,
  170. optionSelections,
  171. variants
  172. });
  173.  
  174. value = item
  175. ? item.product.price_range?.maximum_price
  176. : product.price_range?.maximum_price;
  177. }
  178.  
  179. return value;
  180. };
  181.  
  182. const attributeLabelCompare = (attribute1, attribute2) => {
  183. const label1 = attribute1['attribute_metadata']['label'].toLowerCase();
  184. const label2 = attribute2['attribute_metadata']['label'].toLowerCase();
  185. if (label1 < label2) return -1;
  186. else if (label1 > label2) return 1;
  187. else return 0;
  188. };
  189.  
  190. const getCustomAttributes = (product, optionCodes, optionSelections) => {
  191. const { custom_attributes, variants } = product;
  192. const isConfigurable = isProductConfigurable(product);
  193. const optionsSelected =
  194. Array.from(optionSelections.values()).filter(value => !!value).length >
  195. 0;
  196.  
  197. if (isConfigurable && optionsSelected) {
  198. const item = findMatchingVariant({
  199. optionCodes,
  200. optionSelections,
  201. variants
  202. });
  203.  
  204. return item && item.product
  205. ? [...item.product.custom_attributes].sort(attributeLabelCompare)
  206. : [];
  207. }
  208.  
  209. return custom_attributes
  210. ? [...custom_attributes].sort(attributeLabelCompare)
  211. : [];
  212. };
  213.  
  214. /**
  215. * @param {GraphQLDocument} props.addConfigurableProductToCartMutation - configurable product mutation
  216. * @param {GraphQLDocument} props.addSimpleProductToCartMutation - configurable product mutation
  217. * @param {Object.<string, GraphQLDocument>} props.operations - collection of operation overrides merged into defaults
  218. * @param {Object} props.product - the product, see RootComponents/Product
  219. *
  220. * @returns {{
  221. * breadcrumbCategoryId: string|undefined,
  222. * errorMessage: string|undefined,
  223. * handleAddToCart: func,
  224. * handleSelectionChange: func,
  225. * handleSetQuantity: func,
  226. * isAddToCartDisabled: boolean,
  227. * isSupportedProductType: boolean,
  228. * mediaGalleryEntries: array,
  229. * productDetails: object,
  230. * quantity: number
  231. * }}
  232. */
  233. export const useProductFullDetail = props => {
  234. const {
  235. addConfigurableProductToCartMutation,
  236. addSimpleProductToCartMutation,
  237. product
  238. } = props;
  239.  
  240. const GET_CROSS_SELL_PRODUCTS = gql`
  241. query getProductDetailForProductPage($urlKey: String!) {
  242. products(filter: { url_key: { eq: $urlKey } }) {
  243. items {
  244. uid
  245. categories {
  246. uid
  247. }
  248. crosssell_products {
  249. small_image {
  250. url
  251. }
  252. uid
  253. stock_status
  254. rating_summary
  255. __typename
  256. url_key
  257. sku
  258. name
  259. price_range {
  260. maximum_price {
  261. final_price {
  262. currency
  263. value
  264. }
  265. regular_price {
  266. currency
  267. value
  268. }
  269. discount {
  270. amount_off
  271. }
  272. }
  273. }
  274. }
  275. }
  276. }
  277. }
  278. `;
  279. const ADD_CUSTOM_PRODUCT = gql`
  280. mutation addSimpleProductsToCart(
  281. $cartId: String!
  282. $sku: String!
  283. $custom_options: [CustomizableOptionInput]
  284. ) {
  285. addSimpleProductsToCart(
  286. input: {
  287. cart_id: $cartId
  288. cart_items: [
  289. {
  290. data: { quantity: 1, sku: $sku }
  291. customizable_options: $custom_options
  292. }
  293. ]
  294. }
  295. ) {
  296. cart {
  297. id
  298. ...CartTriggerFragment
  299. ...MiniCartFragment
  300. items {
  301. ... on SimpleCartItem {
  302. product {
  303. name
  304. sku
  305. }
  306. quantity
  307. customizable_options {
  308. label
  309. type
  310. values {
  311. label
  312. value
  313. price {
  314. value
  315. }
  316. }
  317. }
  318. }
  319. }
  320. }
  321. }
  322. }
  323. ${CartTriggerFragment}
  324. ${MiniCartFragment}
  325. `;
  326.  
  327. const GET_ADD_DATA = gql`
  328. mutation addSimpleProductsToCart(
  329. $cartId: String!
  330. $sku: String!
  331. $optId: Int!
  332. $value: String!
  333. ) {
  334. addSimpleProductsToCart(
  335. input: {
  336. cart_id: $cartId
  337. cart_items: [
  338. {
  339. data: { quantity: 1, sku: $sku }
  340. customizable_options: [
  341. { id: $optId, value_string: $value }
  342. ]
  343. }
  344. ]
  345. }
  346. ) {
  347. cart {
  348. items {
  349. ... on SimpleCartItem {
  350. product {
  351. name
  352. sku
  353. }
  354. quantity
  355. customizable_options {
  356. label
  357. type
  358. values {
  359. label
  360. value
  361. price {
  362. value
  363. }
  364. }
  365. }
  366. }
  367. }
  368. }
  369. }
  370. }
  371. `;
  372.  
  373. const [, { dispatch }] = useEventingContext();
  374.  
  375. const [isAddedItem, setIsAddedItem] = useState(false);
  376. const [pincode, setPincode] = useState('');
  377. const [deliveryDate, setDeliveryDate] = useState('');
  378. const [isInvalidPincode, setInvalidPincode] = useState(false);
  379.  
  380. const hasDeprecatedOperationProp = !!(
  381. addConfigurableProductToCartMutation || addSimpleProductToCartMutation
  382. );
  383.  
  384. const operations = mergeOperations(defaultOperations, props.operations);
  385.  
  386. const productType = product.__typename;
  387.  
  388. const isSupportedProductType = isSupported(productType);
  389.  
  390. const [{ cartId }] = useCartContext();
  391. const [{ isSignedIn }] = useUserContext();
  392. const { formatMessage } = useIntl();
  393.  
  394. const { data: storeConfigData } = useQuery(
  395. operations.getWishlistConfigQuery,
  396. {
  397. fetchPolicy: 'cache-and-network'
  398. }
  399. );
  400.  
  401. const { data: crossSellProductsData } = useQuery(GET_CROSS_SELL_PRODUCTS, {
  402. fetchPolicy: 'cache-and-network',
  403. variables: {
  404. urlKey: product.url_key
  405. }
  406. });
  407.  
  408. const [
  409. addConfigurableProductToCart,
  410. {
  411. error: errorAddingConfigurableProduct,
  412. loading: isAddConfigurableLoading
  413. }
  414. ] = useMutation(
  415. addConfigurableProductToCartMutation ||
  416. operations.addConfigurableProductToCartMutation
  417. );
  418.  
  419. const [
  420. addSimpleProductToCart,
  421. { error: errorAddingSimpleProduct, loading: isAddSimpleLoading }
  422. ] = useMutation(
  423. addSimpleProductToCartMutation ||
  424. operations.addSimpleProductToCartMutation
  425. );
  426.  
  427. const [
  428. addSolitaireProductToCart,
  429. { error: errorAddingSolitaireProduct, loading: isAddSolitaireLoading }
  430. ] = useMutation(GET_ADD_DATA);
  431.  
  432. const [
  433. addCustomizableProductToCart,
  434. {
  435. error: errorAddingCustomizableProduct,
  436. loading: isAddCustomizableLoading
  437. }
  438. ] = useMutation(ADD_CUSTOM_PRODUCT);
  439.  
  440. const [
  441. addProductToCart,
  442. { error: errorAddingProductToCart, loading: isAddProductLoading }
  443. ] = useMutation(operations.addProductToCartMutation);
  444.  
  445. const breadcrumbCategoryId = useMemo(
  446. () => getBreadcrumbCategoryId(product.categories),
  447. [product.categories]
  448. );
  449.  
  450. const derivedOptionSelections = useMemo(
  451. () => deriveOptionSelectionsFromProduct(product),
  452. [product]
  453. );
  454.  
  455. const [optionSelections, setOptionSelections] = useState(
  456. derivedOptionSelections
  457. );
  458.  
  459. const derivedOptionCodes = useMemo(
  460. () => deriveOptionCodesFromProduct(product),
  461. [product]
  462. );
  463. const [optionCodes] = useState(derivedOptionCodes);
  464.  
  465. const isMissingOptions = useMemo(
  466. () => getIsMissingOptions(product, optionSelections),
  467. [product, optionSelections]
  468. );
  469.  
  470. const isOutOfStock = useMemo(
  471. () => getIsOutOfStock(product, optionCodes, optionSelections),
  472. [product, optionCodes, optionSelections]
  473. );
  474.  
  475. const mediaGalleryEntries = useMemo(
  476. () => getMediaGalleryEntries(product, optionCodes, optionSelections),
  477. [product, optionCodes, optionSelections]
  478. );
  479.  
  480. const customAttributes = useMemo(
  481. () => getCustomAttributes(product, optionCodes, optionSelections),
  482. [product, optionCodes, optionSelections]
  483. );
  484.  
  485. const productPrice = useMemo(
  486. () => getConfigPrice(product, optionCodes, optionSelections),
  487. [product, optionCodes, optionSelections]
  488. );
  489.  
  490. // The map of ids to values (and their uids)
  491. // For example:
  492. // { "179" => [{ uid: "abc", value_index: 1 }, { uid: "def", value_index: 2 }]}
  493. const attributeIdToValuesMap = useMemo(() => {
  494. const map = new Map();
  495. // For simple items, this will be an empty map.
  496. const options = product.configurable_options || [];
  497. for (const { attribute_id, values } of options) {
  498. map.set(attribute_id, values);
  499. }
  500. return map;
  501. }, [product.configurable_options]);
  502.  
  503. // An array of selected option uids. Useful for passing to mutations.
  504. // For example:
  505. // ["abc", "def"]
  506. const selectedOptionsArray = useMemo(() => {
  507. const selectedOptions = [];
  508.  
  509. optionSelections.forEach((value, key) => {
  510. const values = attributeIdToValuesMap.get(key);
  511.  
  512. const selectedValue = values.find(
  513. item => item.value_index === value
  514. );
  515.  
  516. if (selectedValue) {
  517. selectedOptions.push(selectedValue.uid);
  518. }
  519. });
  520. return selectedOptions;
  521. }, [attributeIdToValuesMap, optionSelections]);
  522.  
  523. const handleAddToCart = useCallback(
  524. async formValues => {
  525. const { quantity } = formValues;
  526.  
  527. /*
  528. @deprecated in favor of general addProductsToCart mutation. Will support until the next MAJOR.
  529. */
  530. if (hasDeprecatedOperationProp) {
  531. const payload = {
  532. item: product,
  533. productType,
  534. quantity
  535. };
  536.  
  537. if (isProductConfigurable(product)) {
  538. appendOptionsToPayload(
  539. payload,
  540. optionSelections,
  541. optionCodes
  542. );
  543. }
  544.  
  545. if (isSupportedProductType) {
  546. const variables = {
  547. cartId,
  548. parentSku: payload.parentSku,
  549. product: payload.item,
  550. quantity: payload.quantity,
  551. sku: payload.item.sku
  552. };
  553. // Use the proper mutation for the type.
  554. if (productType === 'SimpleProduct') {
  555. try {
  556. await addSimpleProductToCart({
  557. variables
  558. });
  559. GTMEventTrigger({
  560. route: window.location.pathname,
  561. event: 'add_to_cart',
  562. title: document.title
  563. });
  564. } catch {
  565. return;
  566. }
  567. } else if (productType === 'ConfigurableProduct') {
  568. try {
  569. await addConfigurableProductToCart({
  570. variables
  571. });
  572. GTMEventTrigger({
  573. route: window.location.pathname,
  574. event: 'add_to_cart',
  575. title: document.title
  576. });
  577. } catch {
  578. return;
  579. }
  580. }
  581. } else {
  582. console.error(
  583. 'Unsupported product type. Cannot add to cart.'
  584. );
  585. }
  586. } else {
  587. const variables = {
  588. cartId,
  589. product: {
  590. sku: product.sku,
  591. quantity
  592. },
  593. entered_options: [
  594. {
  595. uid: product.uid,
  596. value: product.name
  597. }
  598. ]
  599. };
  600.  
  601. if (selectedOptionsArray.length) {
  602. variables.product.selected_options = selectedOptionsArray;
  603. }
  604.  
  605. try {
  606. await addProductToCart({ variables });
  607.  
  608. const selectedOptionsLabels =
  609. selectedOptionsArray?.map((uid, i) => ({
  610. attribute: product.configurable_options[i].label,
  611. value:
  612. product.configurable_options[i].values.findLast(
  613. x => x.uid === uid
  614. )?.label || null
  615. })) || null;
  616. GTMEventTrigger({
  617. route: window.location.pathname,
  618. event: 'add_to_cart',
  619. title: document.title
  620. });
  621. dispatch({
  622. type: 'CART_ADD_ITEM',
  623. payload: {
  624. cartId,
  625. sku: product.sku,
  626. name: product.name,
  627. priceTotal: productPrice.final_price.value,
  628. currencyCode: productPrice.final_price.currency,
  629. discountAmount: productPrice.discount.amount_off,
  630. selectedOptions: selectedOptionsLabels,
  631. quantity
  632. }
  633. });
  634. setIsAddedItem(true);
  635. } catch {
  636. setIsAddedItem(false);
  637. return;
  638. }
  639. }
  640. },
  641. [
  642. addConfigurableProductToCart,
  643. addProductToCart,
  644. addSimpleProductToCart,
  645. cartId,
  646. dispatch,
  647. hasDeprecatedOperationProp,
  648. isSupportedProductType,
  649. optionCodes,
  650. optionSelections,
  651. product,
  652. productPrice,
  653. productType,
  654. selectedOptionsArray
  655. ]
  656. );
  657.  
  658. const handleCustomizableProductToCart = useCallback(
  659. async params => {
  660. const { value, optId } = params;
  661.  
  662. const storage = new BrowserPersistence();
  663. const custom_options = [
  664. {
  665. id: storage.getItem('size_id'),
  666. value_string: storage.getItem('size'),
  667. },
  668. {
  669. id: storage.getItem('color_id'),
  670. value_string: storage.getItem('color'),
  671. }
  672. ].filter(a => a.id && a.value_string);
  673.  
  674. try {
  675. await addCustomizableProductToCart({
  676. variables: {
  677. cartId,
  678. sku: product.sku,
  679. custom_options,
  680. }
  681. });
  682.  
  683. const selectedOptionsLabels = value || null;
  684. GTMEventTrigger({
  685. route: window.location.pathname,
  686. event: 'add_to_cart',
  687. title: document.title
  688. });
  689. dispatch({
  690. type: 'CART_ADD_ITEM',
  691. payload: {
  692. cartId,
  693. sku: product.sku,
  694. name: product.name,
  695. priceTotal: productPrice.final_price.value,
  696. currencyCode: productPrice.final_price.currency,
  697. discountAmount: productPrice.discount.amount_off,
  698. selectedOptions: selectedOptionsLabels,
  699. quantity: 1
  700. }
  701. });
  702. setIsAddedItem(true);
  703. } catch {
  704. setIsAddedItem(false);
  705. return;
  706. }
  707. },
  708. [
  709. addConfigurableProductToCart,
  710. addProductToCart,
  711.  
  712. cartId,
  713. dispatch,
  714. hasDeprecatedOperationProp,
  715. isSupportedProductType,
  716. optionCodes,
  717. optionSelections,
  718. product,
  719. productPrice,
  720. productType,
  721. selectedOptionsArray
  722. ]
  723. );
  724.  
  725. const solitaireAddToCart = useCallback(
  726. async params => {
  727. console.log("params", params);
  728. const { value, optId } = params;
  729. const storage = new BrowserPersistence();
  730. const custom_options = [
  731. {
  732. id: storage.getItem('size_id'),
  733. value_string: storage.getItem('size'),
  734. },
  735. {
  736. id: storage.getItem('color_id'),
  737. value_string: storage.getItem('color'),
  738. },
  739. {
  740. id: optId,
  741. value_string:value
  742. }
  743. ].filter(a => a.id && a.value_string);
  744. console.log("custom options", custom_options);
  745. try {
  746. await addCustomizableProductToCart({
  747. variables: {
  748. cartId,
  749. sku: product.sku,
  750. custom_options,
  751. }
  752. });
  753.  
  754. const selectedOptionsLabels = value || null;
  755.  
  756. dispatch({
  757. type: 'CART_ADD_ITEM',
  758. payload: {
  759. cartId,
  760. sku: product.sku,
  761. name: product.name,
  762. priceTotal: productPrice.final_price.value,
  763. currencyCode: productPrice.final_price.currency,
  764. discountAmount: productPrice.discount.amount_off,
  765. selectedOptions: selectedOptionsLabels,
  766. quantity: 1
  767. }
  768. });
  769. setIsAddedItem(true);
  770. } catch {
  771. setIsAddedItem(false);
  772. return;
  773. }
  774. },
  775. [
  776. addConfigurableProductToCart,
  777. addProductToCart,
  778.  
  779. cartId,
  780. dispatch,
  781. hasDeprecatedOperationProp,
  782. isSupportedProductType,
  783. optionCodes,
  784. optionSelections,
  785. product,
  786. productPrice,
  787. productType,
  788. selectedOptionsArray
  789. ]
  790. );
  791.  
  792. const handleSelectionChange = useCallback(
  793. (optionId, selection) => {
  794. // We must create a new Map here so that React knows that the value
  795. // of optionSelections has changed.
  796. const nextOptionSelections = new Map([...optionSelections]);
  797. nextOptionSelections.set(optionId, selection);
  798. setOptionSelections(nextOptionSelections);
  799. },
  800. [optionSelections]
  801. );
  802.  
  803. const handlePincode = useCallback(
  804. value => {
  805. setPincode(value);
  806. },
  807. [setPincode]
  808. );
  809.  
  810. const checkDeliveryDate = useCallback(
  811. async (sku, ringSize = null, goldColor = null) => {
  812. try {
  813. if (pincode.length == 0) {
  814. setInvalidPincode(false);
  815. setDeliveryDate('Please Enter Pincode');
  816. return;
  817. } else if (pincode.length !== 6) {
  818. setInvalidPincode(true);
  819. setDeliveryDate('Invalid Pincode');
  820. return;
  821. }
  822. const response = await apiClient.get(
  823. apiClient.Urls.checkDeliveryDate,
  824. { sku, pin: pincode, ringSize, goldColor },
  825. {}
  826. );
  827. if (response.success) {
  828. if (response.data && response.data.success) {
  829. setInvalidPincode(false);
  830. setDeliveryDate(response.data && response.data.message);
  831. } else {
  832. setInvalidPincode(true);
  833. setDeliveryDate(response.data && response.data.message);
  834. }
  835. }
  836. } catch {
  837. return;
  838. }
  839. },
  840. [pincode]
  841. );
  842.  
  843. // Normalization object for product details we need for rendering.
  844. const productDetails = {
  845. description: product.description,
  846. shortDescription: product.short_description,
  847. name: product.name,
  848. regularPrice: product.price_range,
  849. price: productPrice?.final_price,
  850. sku: product.sku
  851. };
  852.  
  853. const derivedErrorMessage = useMemo(
  854. () =>
  855. deriveErrorMessage([
  856. errorAddingSimpleProduct,
  857. errorAddingConfigurableProduct,
  858. errorAddingProductToCart
  859. ]),
  860. [
  861. errorAddingConfigurableProduct,
  862. errorAddingProductToCart,
  863. errorAddingSimpleProduct
  864. ]
  865. );
  866.  
  867. const wishlistItemOptions = useMemo(() => {
  868. const options = {
  869. quantity: 1,
  870. sku: product.sku
  871. };
  872.  
  873. if (productType === 'ConfigurableProduct') {
  874. options.selected_options = selectedOptionsArray;
  875. }
  876.  
  877. return options;
  878. }, [product, productType, selectedOptionsArray]);
  879.  
  880. const wishlistButtonProps = {
  881. buttonText: isSelected =>
  882. isSelected
  883. ? formatMessage({
  884. id: 'wishlistButton.addedText',
  885. defaultMessage: 'Added to Favorites'
  886. })
  887. : formatMessage({
  888. id: 'wishlistButton.addText',
  889. defaultMessage: 'Add to Favorites'
  890. }),
  891. item: wishlistItemOptions,
  892. storeConfig: storeConfigData ? storeConfigData.storeConfig : {}
  893. };
  894.  
  895. return {
  896. breadcrumbCategoryId,
  897. errorMessage: derivedErrorMessage,
  898. handleAddToCart,
  899. handleCustomizableProductToCart,
  900. solitaireAddToCart,
  901. handleSelectionChange,
  902. isOutOfStock,
  903. isAddToCartDisabled:
  904. isOutOfStock ||
  905. isMissingOptions ||
  906. isAddConfigurableLoading ||
  907. isAddSimpleLoading ||
  908. isAddProductLoading,
  909. isSupportedProductType,
  910. mediaGalleryEntries,
  911. shouldShowWishlistButton:
  912. isSignedIn &&
  913. storeConfigData &&
  914. !!storeConfigData.storeConfig.magento_wishlist_general_is_enabled,
  915. productDetails,
  916. customAttributes,
  917. wishlistButtonProps,
  918. wishlistItemOptions,
  919. isAddedItem,
  920. setIsAddedItem,
  921. handlePincode,
  922. pincode,
  923. checkDeliveryDate,
  924. deliveryDate,
  925. isInvalidPincode,
  926. parentCategoryId:
  927. crossSellProductsData?.products?.items[0]?.categories[0]?.uid,
  928. designFamilyValue:
  929. crossSellProductsData?.products?.items[0]?.design_family,
  930. crossSellProducts:
  931. crossSellProductsData?.products?.items[0]?.crosssell_products
  932. };
  933. };
  934.  
Add Comment
Please, Sign In to add comment