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

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

/**
 * 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 {ClayButtonWithIcon} from '@clayui/button';
import ClayDropDown from '@clayui/drop-down';
import ClayForm, {ClayInput} from '@clayui/form';
import ClayMultiSelect from '@clayui/multi-select';
import classNames from 'classnames';
import {fetch} from 'frontend-js-web';
import React, {useContext, useRef, useState} from 'react';

import {CHANNEL_RESOURCE_ENDPOINT} from '../../utilities/constants';
import {addToCart} from '../add_to_cart/data';
import InfiniteScroller from '../infinite_scroller/InfiniteScroller';
import MiniCartContext from './MiniCartContext';
import {getCorrectedQuantity} from './util/index';

const CART_QUICK_ADD_NAMESPACE = 'cartQuickAdd_';

const getSearchSKUsURL = (page, search, accountId, channelId) => {
	const url = new URL(
		`${themeDisplay.getPathContext()}${CHANNEL_RESOURCE_ENDPOINT}/${channelId}/products`,
		themeDisplay.getPortalURL()
	);

	url.searchParams.append('accountId', accountId);
	url.searchParams.append('nestedFields', 'skus');
	url.searchParams.append('page', page);
	url.searchParams.append('pageSize', '100');
	url.searchParams.append('search', search);
	url.searchParams.append('skus.accountId', accountId);

	return url.toString();
};

export default function CartQuickAdd() {
	const {cartState} = useContext(MiniCartContext);

	const keypressTimoutRef = useRef(null);
	const paginatorCurrentPageRef = useRef(1);
	const paginatorIsLoadingRef = useRef(false);
	const paginatorItemLengthRef = useRef(0);
	const paginatorLastPageRef = useRef(1);
	const paginatorTotalCountRef = useRef(0);
	const requestAbortControllerRef = useRef(new AbortController());

	const [formattedSKUs, setFormattedSKUs] = useState([]);
	const [quantityError, setQuantityError] = useState(false);
	const [quickAddToCartError, setQuickAddToCartError] = useState(false);
	const [searchInputValue, setSearchInputValue] = useState('');
	const [selectedSKUs, setSelectedSKUs] = useState([]);

	const {
		accountId,
		cartItems = [],
		channel: {channel},
		id: cartId,
	} = cartState;
	const channelId = channel.id;

	const ProductAutocompleteList = ({onItemClick, sourceItems}) => {
		return (
			 {
					if (!paginatorIsLoadingRef.current) {
						paginatorIsLoadingRef.current = true;
						paginatorCurrentPageRef.current =
							paginatorCurrentPageRef.current <
							paginatorLastPageRef.current
								? paginatorCurrentPageRef.current + 1
								: paginatorCurrentPageRef.current;

						searchSKUs(
							searchInputValue,
							paginatorCurrentPageRef.current,
							true
						);
					}
				}}
				scrollCompleted={
					paginatorItemLengthRef.current >=
					paginatorTotalCountRef.current
				}
			>
				
					{sourceItems
						.filter(
							(sku) =>
								!selectedSKUs.includes(sku) && sku.purchasable
						)
						.map((sku) => {
							const {id, label, value} = sku;

							return (
								 onItemClick(sku)}
								>
									
{value}
{label}
); })}
); }; const handleAddToCartClick = () => { const readySKUs = selectedSKUs.map((selectedSKUData) => { const { id: selectedId, productConfiguration: selectedConfiguration, replacementSku: replacementSKUData, sku: selectedSKU, skuUnitOfMeasures, urls, } = selectedSKUData; if (skuUnitOfMeasures && skuUnitOfMeasures.length) { selectedSKUData.skuUnitOfMeasure = skuUnitOfMeasures[0]; } if ( selectedSKUData.availability?.label !== 'available' && !selectedConfiguration.allowBackOrder && replacementSKUData ) { const { price, productConfiguration: replacementConfiguration, sku: replacementSKU, skuUnitOfMeasures: replacementUnitOfMeasures, urls: productURLs, } = replacementSKUData; if ( replacementUnitOfMeasures && replacementUnitOfMeasures.length ) { replacementSKUData.skuUnitOfMeasure = replacementUnitOfMeasures[0]; } return { ...replacementSKUData, price, productURLs, quantity: getCorrectedQuantity( { ...replacementConfiguration, multipleOrderQuantity: replacementSKUData.skuUnitOfMeasure ?.incrementalOrderQuantity || replacementConfiguration.multipleOrderQuantity, }, replacementSKU, cartItems, replacementSKUData.skuUnitOfMeasure?.precision || 0 ), replacedSkuId: selectedId, settings: replacementConfiguration, }; } return { ...selectedSKUData, productURLs: urls, quantity: getCorrectedQuantity( { ...selectedConfiguration, multipleOrderQuantity: selectedSKUData.skuUnitOfMeasure ?.incrementalOrderQuantity || selectedConfiguration.multipleOrderQuantity, }, selectedSKU, cartItems, selectedSKUData.skuUnitOfMeasure?.precision || 0 ), settings: selectedConfiguration, skuId: selectedId, }; }); const unavailableSKU = readySKUs.find( (readySKU) => readySKU.quantity === 0 ); if (!unavailableSKU) { addToCart( readySKUs, cartId, channel, accountId, null, CART_QUICK_ADD_NAMESPACE ) .then(() => {}) .catch((error) => { Liferay.Util.openToast({ message: error.detail || Liferay.Language.get( 'an-unexpected-system-error-occurred' ), type: 'danger', }); }); setSelectedSKUs([]); } else { setQuickAddToCartError(true); setQuantityError(true); } }; const handleProductQueryInput = (productQueryString) => { clearTimeout(keypressTimoutRef.current); requestAbortControllerRef.current.abort(); paginatorCurrentPageRef.current = 1; setSearchInputValue(productQueryString); keypressTimoutRef.current = setTimeout(() => { searchSKUs(productQueryString, 1, false); }, 500); }; const searchSKUs = (queryString, page, appendData) => { requestAbortControllerRef.current = new AbortController(); const {signal} = requestAbortControllerRef.current; if (!queryString.length) { paginatorIsLoadingRef.current = false; setFormattedSKUs([]); return; } paginatorIsLoadingRef.current = true; const searchSKUsURL = getSearchSKUsURL( page, queryString, accountId, channelId ); fetch(searchSKUsURL, { signal, }) .then((response) => response.json()) .then((availableSKUs) => { paginatorItemLengthRef.current = availableSKUs.page * availableSKUs.pageSize; paginatorLastPageRef.current = availableSKUs.lastPage; paginatorTotalCountRef.current = availableSKUs.totalCount; const responseSKUs = []; availableSKUs.items.forEach((availableSKU) => { availableSKU.skus.forEach((sku) => { responseSKUs.push({ ...sku, chipLabel: sku.sku, label: availableSKU.name, productConfiguration: availableSKU.productConfiguration, urls: availableSKU.urls, value: sku.sku, }); }); }); setFormattedSKUs(responseSKUs); if (appendData) { setFormattedSKUs(formattedSKUs.concat(responseSKUs)); } paginatorIsLoadingRef.current = false; }); }; return ( { setQuickAddToCartError(false); setQuantityError(false); newSKUs = newSKUs.filter((item) => { if (item.id) { return item; } else { setQuickAddToCartError(true); } }); setSelectedSKUs(newSKUs); }} onPaste={(event) => { const pastedText = event.clipboardData.getData('Text'); event.preventDefault(); handleProductQueryInput( searchInputValue.concat(pastedText) ); }} placeholder={Liferay.Language.get('search-products')} size="sm" sourceItems={formattedSKUs} value={searchInputValue} /> {quickAddToCartError && ( {`${Liferay.Language.get('error-colon')} `} {quantityError ? Liferay.Language.get( 'please-enter-a-valid-quantity' ) : Liferay.Language.get('select-from-list')} )} ); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy