-
Notifications
You must be signed in to change notification settings - Fork 202
Add wishlist item to the cart #158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 11 commits
48cbf0f
79a1887
40b5a2b
4be3326
6d7b23c
11ef581
3be3314
6600db4
5b3d125
e78d65a
1b92a6d
93f5f0c
af4bffa
dcb8a11
029ad14
fe1a805
e848ec1
7c9ee57
128b859
a22b603
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,9 +4,10 @@ | |
| * SPDX-License-Identifier: BSD-3-Clause | ||
| * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
| */ | ||
| import React from 'react' | ||
| import React, {useContext, useState, useEffect} from 'react' | ||
| import {useLocation} from 'react-router-dom' | ||
| import PropTypes from 'prop-types' | ||
| import {useIntl} from 'react-intl' | ||
| import {useIntl, FormattedMessage} from 'react-intl' | ||
| import { | ||
| AspectRatio, | ||
| Box, | ||
|
|
@@ -22,33 +23,40 @@ import { | |
| Stack, | ||
| useBreakpointValue | ||
| } from '@chakra-ui/react' | ||
| import Link from '../link' | ||
| import useBasket from '../../commerce-api/hooks/useBasket' | ||
| import {LockIcon} from '../icons' | ||
| import {useCurrency} from '../../hooks' | ||
| import {useVariationAttributes} from '../../hooks' | ||
| import {findImageGroupBy} from '../../utils/image-groups-utils' | ||
| import useBasket from '../commerce-api/hooks/useBasket' | ||
| import Link from '../components/link' | ||
| import RecommendedProducts from '../components/recommended-products' | ||
| import {LockIcon} from '../components/icons' | ||
| import {DEFAULT_CURRENCY} from '../constants' | ||
| import {useVariationAttributes} from './' | ||
| import {findImageGroupBy} from '../utils/image-groups-utils' | ||
|
|
||
| export const AddToCartModalContext = React.createContext() | ||
| export const useAddToCartModalContext = () => useContext(AddToCartModalContext) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we declare this context inside the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'd say no, because i think the
So i think this question comes down to recognizing the separation of concerns. A mental model for myself is like OO programming's principle Encapsulation, I view the module (e.g. this
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed TL;DR i'm moving this to context.js
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I couldn't do this because there is a circular dependency between the context, hook and the component... I really don't want to separate the component from the hook and contexts because the component itself doesn't work, it is meant to work only with the hook.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would you mind adding a comment to explain that so it won't confuse other developers? |
||
|
|
||
| /** | ||
| * Visual feedback for adding item to the cart. | ||
| * Visual feedback (a modal) for adding item to the cart. | ||
| */ | ||
| const AddToCartModal = ({product, variant, quantity, isOpen, onClose, ...props}) => { | ||
| export const AddToCartModal = () => { | ||
| const {isOpen, onClose, data} = useAddToCartModalContext() | ||
| const {product, quantity} = data || {} | ||
| const intl = useIntl() | ||
| const basket = useBasket() | ||
| const size = useBreakpointValue({base: 'full', lg: '2xl', xl: '4xl'}) | ||
| const {currency, productItems, productSubTotal, itemAccumulatedCount} = basket | ||
| const variationAttributes = useVariationAttributes(product) | ||
| const {productId, variationValues} = variant | ||
| const lineItemPrice = | ||
| productItems?.find((item) => item.productId === productId)?.basePrice * quantity | ||
| if (!isOpen) { | ||
| return null | ||
| } | ||
| const {currency, productItems, productSubTotal, itemAccumulatedCount} = basket | ||
| const {id, variationValues} = product | ||
| const lineItemPrice = productItems?.find((item) => item.productId === id)?.basePrice * quantity | ||
| const image = findImageGroupBy(product.imageGroups, { | ||
| viewType: 'small', | ||
| selectedVariationAttributes: variationValues | ||
| })?.images?.[0] | ||
| const {currency: activeCurrency} = useCurrency() | ||
|
|
||
| return ( | ||
| <Modal size={size} isOpen={isOpen} onClose={onClose} {...props}> | ||
| <Modal size={size} isOpen={isOpen} onClose={onClose}> | ||
| <ModalOverlay /> | ||
| <ModalContent | ||
| margin="0" | ||
|
|
@@ -113,7 +121,7 @@ const AddToCartModal = ({product, variant, quantity, isOpen, onClose, ...props}) | |
| {!!lineItemPrice && | ||
| intl.formatNumber(lineItemPrice, { | ||
| style: 'currency', | ||
| currency: currency || activeCurrency | ||
| currency: currency || DEFAULT_CURRENCY | ||
| })} | ||
| </Text> | ||
| </Box> | ||
|
|
@@ -138,7 +146,7 @@ const AddToCartModal = ({product, variant, quantity, isOpen, onClose, ...props}) | |
| {productSubTotal && | ||
| intl.formatNumber(productSubTotal, { | ||
| style: 'currency', | ||
| currency: currency || activeCurrency | ||
| currency: currency || DEFAULT_CURRENCY | ||
| })} | ||
| </Text> | ||
| </Flex> | ||
|
|
@@ -164,7 +172,15 @@ const AddToCartModal = ({product, variant, quantity, isOpen, onClose, ...props}) | |
| </Box> | ||
| </Flex> | ||
| </ModalBody> | ||
| <Box padding="8">{props.children}</Box> | ||
| <Box padding="8"> | ||
| <RecommendedProducts | ||
| title={<FormattedMessage defaultMessage="You Might Also Like" />} | ||
| recommender={'pdp-similar-items'} | ||
| products={product && [product.id]} | ||
| mx={{base: -4, md: -8, lg: 0}} | ||
| shouldFetch={() => product?.id} | ||
| /> | ||
| </Box> | ||
| </ModalContent> | ||
| </Modal> | ||
| ) | ||
|
|
@@ -185,4 +201,34 @@ AddToCartModal.propTypes = { | |
| children: PropTypes.any | ||
| } | ||
|
|
||
| export default AddToCartModal | ||
| export const useAddToCartModal = () => { | ||
| const [state, setState] = useState({ | ||
| isOpen: false, | ||
| data: null | ||
| }) | ||
|
|
||
| const {pathname} = useLocation() | ||
| useEffect(() => { | ||
| setState({ | ||
| ...state, | ||
| isOpen: false | ||
| }) | ||
| }, [pathname]) | ||
|
|
||
| return { | ||
| isOpen: state.isOpen, | ||
| data: state.data, | ||
| onOpen: (data) => { | ||
| setState({ | ||
| isOpen: true, | ||
| data | ||
| }) | ||
| }, | ||
| onClose: () => { | ||
| setState({ | ||
| isOpen: false, | ||
| data: null | ||
| }) | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need this for the swatch images.