All Downloads are FREE. Search and download functionalities are using the official Maven repository.

META-INF.resources.components.mini_cart.CartItem.js Maven / Gradle / Ivy

The newest version!
/**
 * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
 * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
 */

import ClayButton, {ClayButtonWithIcon} from '@clayui/button';
import ClayDropDown from '@clayui/drop-down';
import ClayIcon from '@clayui/icon';
import {useIsMounted} from '@liferay/frontend-js-react-web';
import classnames from 'classnames';
import {sub} from 'frontend-js-web';
import React, {useContext, useEffect, useState} from 'react';

import ServiceProvider from '../../ServiceProvider/index';
import {debouncePromise} from '../../utilities/debounce';
import {CART_PRODUCT_QUANTITY_CHANGED} from '../../utilities/eventsDefinitions';
import {getMultipleQuantity} from '../../utilities/quantities';
import Price from '../price/Price';
import QuantitySelector from '../quantity_selector/QuantitySelector';
import ItemInfoView from './CartItemViews/ItemInfoView';
import MiniCartContext from './MiniCartContext';
import {
	INITIAL_ITEM_STATE,
	PRODUCT_QUANTITY_NOT_VALID_ERROR,
	REMOVAL_CANCELING_TIMEOUT,
	REMOVAL_TIMEOUT,
	UNEXPECTED_ERROR,
} from './util/constants';
import {filterOptions, generateProductPageURL, hasOptions} from './util/index';

const CartResource = ServiceProvider.DeliveryCartAPI('v1');

const deboncedUpdateItemQuantity = debouncePromise(
	(cartItemId, quantity, invalid) => {
		if (invalid) {
			return Promise.reject(PRODUCT_QUANTITY_NOT_VALID_ERROR);
		}

		return CartResource.updateItemById(cartItemId, {
			quantity,
		}).catch((error) => {
			let errorMessage;

			if (error.message) {
				errorMessage = error.message;
			}
			else if (error.detail) {
				errorMessage = error.detail;
			}
			else {
				errorMessage = UNEXPECTED_ERROR;
			}

			throw errorMessage;
		});
	},
	1000
);

const isValidMedia = (adaptiveMediaImageHTMLTag) => {
	if (adaptiveMediaImageHTMLTag) {
		const testElement = window.document.createElement('div');

		testElement.innerHTML = adaptiveMediaImageHTMLTag;

		const imgElement = testElement.querySelector('img');
		const srcAttribute = imgElement.getAttribute('src');

		return !!srcAttribute;
	}

	return false;
};

function CartItem({
	adaptiveMediaImageHTMLTag,
	cartItems: childItems,
	errorMessages = [],
	id: cartItemId,
	index,
	name,
	options: rawOptions,
	price,
	productURLs,
	quantity: cartItemQuantity,
	settings,
	sku,
	skuId,
	updateCartItem,
	replacedSku,
	skuUnitOfMeasure,
	productId,
}) {
	const [itemState, setItemState] = useState(INITIAL_ITEM_STATE);
	const [selectorQuantity, setSelectorQuantity] = useState(cartItemQuantity);
	const hasChildItems = !!childItems?.length;
	const hasSkuUnitOfMeasure = !!skuUnitOfMeasure?.key;
	const isMounted = useIsMounted();
	const options = filterOptions(rawOptions);

	useEffect(() => {
		setSelectorQuantity(cartItemQuantity);
	}, [cartItemQuantity]);

	const {
		actionURLs,
		cartState,
		displayDiscountLevels,
		setEditedItem,
		setIsUpdating,
		updateCartModel,
	} = useContext(MiniCartContext);

	const productPageUrl = generateProductPageURL(
		actionURLs.siteDefaultURL,
		productURLs,
		actionURLs.productURLSeparator
	);

	const cancelRemoveItem = (event) => {
		event.stopPropagation();

		clearTimeout(itemState.removalTimeoutRef);

		setItemState({
			...INITIAL_ITEM_STATE,
			isRemovalCanceled: true,
			removalTimeoutRef: setTimeout(() => {
				if (isMounted()) {
					setIsUpdating(false);

					setItemState(INITIAL_ITEM_STATE);
				}
			}, REMOVAL_CANCELING_TIMEOUT),
		});
	};

	const removeItem = (event) => {
		event.stopPropagation();

		setItemState({
			...INITIAL_ITEM_STATE,
			isGettingRemoved: true,
			removalTimeoutRef: setTimeout(() => {
				if (!isMounted()) {
					return;
				}

				setIsUpdating(true);

				setItemState({
					...INITIAL_ITEM_STATE,
					isGettingRemoved: true,
					isRemoved: true,
					removalTimeoutRef: setTimeout(() => {
						CartResource.deleteItemById(cartItemId)
							.then(() => {
								if (!isMounted()) {
									return;
								}

								updateCartModel({order: {id: cartState.id}});

								Liferay.fire(CART_PRODUCT_QUANTITY_CHANGED, {
									quantity: 0,
									skuId,
								});
							})
							.catch(() => {
								updateCartItem((cartItem) => ({
									...cartItem,
									errorMessages: [UNEXPECTED_ERROR],
								}));
							})
							.finally(() => {
								if (isMounted()) {
									setIsUpdating(false);
								}
							});
					}, REMOVAL_CANCELING_TIMEOUT),
				});
			}, REMOVAL_TIMEOUT),
		});
	};

	const {isGettingRemoved, isRemovalCanceled, isRemoved} = itemState;

	const getClassName = (className) => {
		return classnames(className, {
			'mini-cart-item-alignment': true,
		});
	};

	return (
		
{sub(Liferay.Language.get('go-to-x'), name)} {isValidMedia(adaptiveMediaImageHTMLTag) && (
)}
0 ? 'top' : 'bottom'} allowedQuantities={settings.allowedQuantities} max={settings.maxQuantity} min={settings.minQuantity} onUpdate={({errors, value: newQuantity}) => { setSelectorQuantity(newQuantity); if (!errors.length) { setIsUpdating(true); } deboncedUpdateItemQuantity( cartItemId, newQuantity, !!errors.length ) .then(() => { if (isMounted()) { setIsUpdating(false); updateCartModel({ order: {id: cartState.id}, }); } }) .catch((error) => { if (isMounted()) { setIsUpdating(false); if (error) { updateCartItem((cartItem) => ({ ...cartItem, errorMessages: [error], })); } } }); }} quantity={selectorQuantity} step={ skuUnitOfMeasure ? getMultipleQuantity( skuUnitOfMeasure.incrementalOrderQuantity, settings.multipleQuantity, skuUnitOfMeasure.precision ) : settings.multipleQuantity } {...settings} unitOfMeasure={skuUnitOfMeasure} />
{skuUnitOfMeasure?.key}
{hasOptions(rawOptions) || hasSkuUnitOfMeasure ? ( } > setEditedItem({ cartItemId, name, productId, }) } > {Liferay.Language.get('edit')} {Liferay.Language.get('delete')} ) : ( )}
{!!errorMessages.length && (
{errorMessages.map((errorMessage) => (
{errorMessage}
))}
)}
{Liferay.Language.get('the-item-has-been-removed')} {Liferay.Language.get('undo')}
); } export default CartItem;




© 2015 - 2025 Weber Informatics LLC | Privacy Policy