forked from crowetic/commerce
Added wishlist button component
This commit is contained in:
parent
c2954d8e88
commit
e91a6791d5
@ -1,15 +1,14 @@
|
|||||||
import React, { FC, ReactNode, Component } from 'react'
|
import type { FC } from 'react'
|
||||||
import cn from 'classnames'
|
import cn from 'classnames'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import type { ProductNode } from '@lib/bigcommerce/api/operations/get-all-products'
|
import type { ProductNode } from '@lib/bigcommerce/api/operations/get-all-products'
|
||||||
import usePrice from '@lib/bigcommerce/use-price'
|
import usePrice from '@lib/bigcommerce/use-price'
|
||||||
import { Heart } from '@components/icons'
|
|
||||||
import { EnhancedImage } from '@components/core'
|
import { EnhancedImage } from '@components/core'
|
||||||
import s from './ProductCard.module.css'
|
import s from './ProductCard.module.css'
|
||||||
|
import WishlistButton from '@components/wishlist/WishlistButton'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string
|
className?: string
|
||||||
children?: ReactNode[] | Component[] | any[]
|
|
||||||
product: ProductNode
|
product: ProductNode
|
||||||
variant?: 'slim' | 'simple'
|
variant?: 'slim' | 'simple'
|
||||||
imgWidth: number
|
imgWidth: number
|
||||||
@ -25,7 +24,7 @@ const ProductCard: FC<Props> = ({
|
|||||||
imgHeight,
|
imgHeight,
|
||||||
priority,
|
priority,
|
||||||
}) => {
|
}) => {
|
||||||
const src = p.images.edges?.[0]?.node.urlOriginal!
|
const src = p.images.edges?.[0]?.node?.urlOriginal!
|
||||||
const { price } = usePrice({
|
const { price } = usePrice({
|
||||||
amount: p.prices?.price?.value,
|
amount: p.prices?.price?.value,
|
||||||
baseAmount: p.prices?.retailPrice?.value,
|
baseAmount: p.prices?.retailPrice?.value,
|
||||||
@ -65,9 +64,11 @@ const ProductCard: FC<Props> = ({
|
|||||||
</h3>
|
</h3>
|
||||||
<span className={s.productPrice}>{price}</span>
|
<span className={s.productPrice}>{price}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className={s.wishlistButton}>
|
<WishlistButton
|
||||||
<Heart />
|
className={s.wishlistButton}
|
||||||
</div>
|
productId={p.entityId}
|
||||||
|
variant={p.variants.edges?.[0]!}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={cn(s.imageContainer)}>
|
<div className={cn(s.imageContainer)}>
|
||||||
<EnhancedImage
|
<EnhancedImage
|
||||||
|
65
components/wishlist/WishlistButton/WishlistButton.tsx
Normal file
65
components/wishlist/WishlistButton/WishlistButton.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import React, { FC, useState } from 'react'
|
||||||
|
import cn from 'classnames'
|
||||||
|
import type { ProductNode } from '@lib/bigcommerce/api/operations/get-all-products'
|
||||||
|
import useAddItem from '@lib/bigcommerce/wishlist/use-add-item'
|
||||||
|
import useWishlist from '@lib/bigcommerce/wishlist/use-wishlist'
|
||||||
|
import useCustomer from '@lib/bigcommerce/use-customer'
|
||||||
|
import { Heart } from '@components/icons'
|
||||||
|
import { useUI } from '@components/ui/context'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
productId: number
|
||||||
|
variant: NonNullable<ProductNode['variants']['edges']>[0]
|
||||||
|
} & React.ButtonHTMLAttributes<HTMLButtonElement>
|
||||||
|
|
||||||
|
const WishlistButton: FC<Props> = ({
|
||||||
|
productId,
|
||||||
|
variant,
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
|
const addItem = useAddItem()
|
||||||
|
const { data } = useWishlist()
|
||||||
|
const { data: customer } = useCustomer()
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const { openModal, setModalView } = useUI()
|
||||||
|
const isInWishlist = data?.items?.some(
|
||||||
|
(item) =>
|
||||||
|
item.product_id === productId &&
|
||||||
|
item.variant_id === variant?.node.entityId
|
||||||
|
)
|
||||||
|
|
||||||
|
const addToWishlist = async (e: any) => {
|
||||||
|
e.preventDefault()
|
||||||
|
setLoading(true)
|
||||||
|
|
||||||
|
// A login is required before adding an item to the wishlist
|
||||||
|
if (!customer) {
|
||||||
|
setModalView('LOGIN_VIEW')
|
||||||
|
return openModal()
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await addItem({
|
||||||
|
productId,
|
||||||
|
variantId: variant?.node.entityId!,
|
||||||
|
})
|
||||||
|
|
||||||
|
setLoading(false)
|
||||||
|
} catch (err) {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
{...props}
|
||||||
|
className={cn({ 'opacity-50': loading }, className)}
|
||||||
|
onClick={addToWishlist}
|
||||||
|
>
|
||||||
|
<Heart fill={isInWishlist ? 'white' : 'none'} />
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WishlistButton
|
1
components/wishlist/WishlistButton/index.ts
Normal file
1
components/wishlist/WishlistButton/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './WishlistButton'
|
@ -41,7 +41,7 @@ async function getCustomerWishlist({
|
|||||||
|
|
||||||
const { data } = await config.storeApiFetch<
|
const { data } = await config.storeApiFetch<
|
||||||
RecursivePartial<{ data: Wishlist[] }>
|
RecursivePartial<{ data: Wishlist[] }>
|
||||||
>(`/v3/wishlists/customer_id=${variables.customerId}`)
|
>(`/v3/wishlists?customer_id=${variables.customerId}`)
|
||||||
const wishlists = (data as RecursiveRequired<typeof data>) ?? []
|
const wishlists = (data as RecursiveRequired<typeof data>) ?? []
|
||||||
const wishlist = wishlists[0]
|
const wishlist = wishlists[0]
|
||||||
|
|
||||||
|
@ -38,11 +38,14 @@ const addItem: WishlistHandlers['addItem'] = async ({
|
|||||||
items: [parseWishlistItem(item)],
|
items: [parseWishlistItem(item)],
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
|
name: 'Wishlist',
|
||||||
customer_id: customerId,
|
customer_id: customerId,
|
||||||
items: [parseWishlistItem(item)],
|
items: [parseWishlistItem(item)],
|
||||||
|
is_public: false,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data } = wishlist
|
const { data } = wishlist
|
||||||
? await config.storeApiFetch(`/v3/wishlists/${wishlist.id}/items`, options)
|
? await config.storeApiFetch(`/v3/wishlists/${wishlist.id}/items`, options)
|
||||||
: await config.storeApiFetch('/v3/wishlists', options)
|
: await config.storeApiFetch('/v3/wishlists', options)
|
||||||
|
@ -75,7 +75,7 @@ const wishlistApi: BigcommerceApiHandler<Wishlist, WishlistHandlers> = async (
|
|||||||
const { wishlistId, itemId, customerId } = req.body
|
const { wishlistId, itemId, customerId } = req.body
|
||||||
|
|
||||||
// Return current wishlist info
|
// Return current wishlist info
|
||||||
if (req.method === 'GET' && wishlistId) {
|
if (req.method === 'GET') {
|
||||||
const body = { customerToken }
|
const body = { customerToken }
|
||||||
return await handlers['getWishlist']({ req, res, config, body })
|
return await handlers['getWishlist']({ req, res, config, body })
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user