UNPKG

@shopgate/engage

Version:
139 lines (135 loc) 4.79 kB
import React, { useState, useEffect, useCallback, useMemo } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { showModal } from '@shopgate/engage/core/actions'; import { Accordion, Card, ConditionalWrapper } from '@shopgate/engage/components'; import { makeGetFavorites, getUseGetFavoriteIdsPipeline } from '@shopgate/pwa-common-commerce/favorites/selectors'; import { FAVORITES_SHOW_LIMIT } from '@shopgate/engage/favorites/constants'; import ListAccordionLabel from "./ListAccordionLabel"; import ListContent from "./ListContent"; import styles from "./styles"; import ListAccordionHeader from "./ListAccordionHeader"; /** * @param {Object} _ State * @param {Object} props Props * @returns {Object} */ import { jsx as _jsx } from "react/jsx-runtime"; const makeMapStateToProps = (_, { id }) => { const getFavorites = makeGetFavorites(() => id); return state => ({ items: getFavorites(state), useGetFavoriteIdsPipeline: getUseGetFavoriteIdsPipeline(state) }); }; /** * @param {Object} dispatch Dispatch * @param {Object} props The component props * @returns {Object} */ const mapDispatchToProps = (dispatch, props) => ({ remove: async id => { // Protect list deletion with a confirmation modal const confirmed = await dispatch(showModal({ message: 'favorites.delete_list_modal.message', title: 'favorites.delete_list_modal.title', params: { name: props.name } })); if (confirmed) { props.remove(id); } } }); /** * Favorite List component * @return {JSX.Element} */ const FavoriteList = ({ id, name, items, rename, remove, removeItem, addToCart, hasMultipleFavoritesListsSupport, useGetFavoriteIdsPipeline }) => { const [offset, setOffset] = useState(FAVORITES_SHOW_LIMIT); const filteredItems = useMemo(() => { /** * The getFavoriteIds pipeline doesn't return full products, but only product ids. Product data * is selected inside the ListContent component via the ProductProvider. To avoid requests with * huge response data, the favlist items are splitted into chunks, so that the ProductProvider * only has to request fresh data for each chunk. * * As long as not all products from the list are shown, a "Load More" button is presented to the * user, which will add an additional chunk of product ids to the ListContent component. */ if (useGetFavoriteIdsPipeline) { return items.slice(0, offset); } // When the getFavorites pipeline is used, no special handling is necessary. "items" can passed // the the ListContent component as they are. return items; }, [items, offset, useGetFavoriteIdsPipeline]); const allFavoritesLoaded = useMemo(() => { if (useGetFavoriteIdsPipeline) { return items.length - filteredItems.length > 0; } /** * In case of getFavorites pipeline is used, and all favorites are always loaded, "false" as * return value might seem a bit weird, but the value is actually used to determine if the * load more button is supposed to be shown (not needed if all favorites are already present). */ return false; }, [filteredItems.length, items.length, useGetFavoriteIdsPipeline]); const [showLoadMoreButton, setShowLoadMoreButton] = useState(allFavoritesLoaded); const handleLoadMore = useCallback(() => { setOffset(offset + FAVORITES_SHOW_LIMIT); }, [offset]); useEffect(() => { setShowLoadMoreButton(allFavoritesLoaded); }, [offset, allFavoritesLoaded]); return /*#__PURE__*/_jsx(ConditionalWrapper, { condition: hasMultipleFavoritesListsSupport, wrapperFalsy: children => /*#__PURE__*/_jsx("div", { className: styles.rootNoFavoritesLists, children: children }), wrapper: children => /*#__PURE__*/_jsx(Card, { className: styles.root, children: /*#__PURE__*/_jsx(Accordion, { className: "", renderAdditionalHeaderContent: () => /*#__PURE__*/_jsx(ListAccordionHeader, { rename: newName => rename(id, newName), remove: remove, id: id }), renderLabel: () => /*#__PURE__*/_jsx(ListAccordionLabel, { title: name }), chevronPosition: "left", startOpened: true, children: children }) }), children: /*#__PURE__*/_jsx(ListContent, { listId: id, items: filteredItems, removeItem: removeItem, addToCart: addToCart, onLoadMore: handleLoadMore, showLoadMoreButton: showLoadMoreButton }) }); }; FavoriteList.defaultProps = { hasMultipleFavoritesListsSupport: false, useGetFavoriteIdsPipeline: false }; export default connect(makeMapStateToProps, mapDispatchToProps)(FavoriteList);