From 58385dc491da2621dab917551ecba89c8f69f1b6 Mon Sep 17 00:00:00 2001 From: Franco Arza Date: Mon, 26 Oct 2020 18:28:09 -0300 Subject: [PATCH 1/5] improve the grid on mobile a bit --- components/product/ProductSlider/ProductSlider.module.css | 3 ++- pages/index.tsx | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/components/product/ProductSlider/ProductSlider.module.css b/components/product/ProductSlider/ProductSlider.module.css index c07228d0b..5ad48cc3d 100644 --- a/components/product/ProductSlider/ProductSlider.module.css +++ b/components/product/ProductSlider/ProductSlider.module.css @@ -48,7 +48,8 @@ @apply hidden; @screen sm { - @apply block absolute bottom-6 left-1/2 -translate-x-1/2 transform; + @apply block absolute bottom-6 left-1/2; + transform: translateX(-50%); } } diff --git a/pages/index.tsx b/pages/index.tsx index 44a93c1d7..9f374253b 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -129,9 +129,9 @@ export default function Home({ /> ))} -
-
-
+
+
+
  • From 411c6b8d230ad2a0f09da0e2682011b79a5b601a Mon Sep 17 00:00:00 2001 From: Franco Arza Date: Mon, 26 Oct 2020 20:02:29 -0300 Subject: [PATCH 2/5] componentize the homepage grid --- .../HomeAllProductsGrid.module.css | 23 +++++++ .../HomeAllProductsGrid.tsx | 66 +++++++++++++++++++ components/core/HomeAllProductsGrid/index.ts | 1 + pages/index.tsx | 55 ++-------------- 4 files changed, 96 insertions(+), 49 deletions(-) create mode 100644 components/core/HomeAllProductsGrid/HomeAllProductsGrid.module.css create mode 100644 components/core/HomeAllProductsGrid/HomeAllProductsGrid.tsx create mode 100644 components/core/HomeAllProductsGrid/index.ts diff --git a/components/core/HomeAllProductsGrid/HomeAllProductsGrid.module.css b/components/core/HomeAllProductsGrid/HomeAllProductsGrid.module.css new file mode 100644 index 000000000..464087ebc --- /dev/null +++ b/components/core/HomeAllProductsGrid/HomeAllProductsGrid.module.css @@ -0,0 +1,23 @@ +.root { + @apply py-12 flex flex-col w-full px-6; + + @screen md { + @apply flex-row; + } +} + +.asideWrapper { + @apply pr-3 w-full relative; + + @screen md { + @apply w-48; + } +} + +.aside { + @apply flex flex-row w-full justify-around mb-12; + + @screen md { + @apply mb-0 block sticky top-32; + } +} diff --git a/components/core/HomeAllProductsGrid/HomeAllProductsGrid.tsx b/components/core/HomeAllProductsGrid/HomeAllProductsGrid.tsx new file mode 100644 index 000000000..fc58486cd --- /dev/null +++ b/components/core/HomeAllProductsGrid/HomeAllProductsGrid.tsx @@ -0,0 +1,66 @@ +import { FC } from 'react' +import Link from 'next/link' +import { getCategoryPath, getDesignerPath } from '@utils/search' +import { Grid } from '@components/ui' +import { ProductCard } from '@components/product' +import s from './HomeAllProductsGrid.module.css' + +interface Props { + categories?: any + brands?: any + newestProducts?: any +} + +const Head: FC = ({ categories, brands, newestProducts }) => { + return ( +
    +
    +
    + + +
    +
    +
    + + {newestProducts.map(({ node }: any) => ( + + ))} + +
    +
    + ) +} + +export default Head diff --git a/components/core/HomeAllProductsGrid/index.ts b/components/core/HomeAllProductsGrid/index.ts new file mode 100644 index 000000000..31d313d16 --- /dev/null +++ b/components/core/HomeAllProductsGrid/index.ts @@ -0,0 +1 @@ +export { default } from './HomeAllProductsGrid' diff --git a/pages/index.tsx b/pages/index.tsx index 64443f536..48777bea5 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -5,11 +5,10 @@ import getAllProducts from '@lib/bigcommerce/api/operations/get-all-products' import getSiteInfo from '@lib/bigcommerce/api/operations/get-site-info' import getAllPages from '@lib/bigcommerce/api/operations/get-all-pages' import rangeMap from '@lib/range-map' -import { getCategoryPath, getDesignerPath } from '@utils/search' import { Layout } from '@components/core' import { Grid, Marquee, Hero } from '@components/ui' import { ProductCard } from '@components/product' -import Link from 'next/link' +import HomeAllProductsGrid from '@components/core/HomeAllProductsGrid' export async function getStaticProps({ preview, @@ -129,53 +128,11 @@ export default function Home({ /> ))} -
    -
    -
    - - -
    -
    -
    - - {newestProducts.map(({ node }) => ( - - ))} - -
    -
    +
) } From 0f4f061cbde5dd54ad6a7f122e9eaeaa41f7ac67 Mon Sep 17 00:00:00 2001 From: Luis Alvarez Date: Mon, 26 Oct 2020 18:25:35 -0500 Subject: [PATCH 3/5] Added useRemoveItem and other fixes --- .../WishlistButton/WishlistButton.tsx | 27 ++++++++++++------ lib/bigcommerce/api/utils/fetch-store-api.ts | 2 +- .../api/wishlist/handlers/remove-item.ts | 22 ++++++++++++--- lib/bigcommerce/api/wishlist/index.ts | 11 +++----- lib/bigcommerce/cart/use-remove-item.tsx | 4 +-- lib/bigcommerce/wishlist/use-add-item.tsx | 2 +- lib/bigcommerce/wishlist/use-remove-item.tsx | 28 +++++++++++++------ lib/commerce/wishlist/use-remove-item.tsx | 5 ++++ 8 files changed, 68 insertions(+), 33 deletions(-) create mode 100644 lib/commerce/wishlist/use-remove-item.tsx diff --git a/components/wishlist/WishlistButton/WishlistButton.tsx b/components/wishlist/WishlistButton/WishlistButton.tsx index ef19c4dd4..5831df6d4 100644 --- a/components/wishlist/WishlistButton/WishlistButton.tsx +++ b/components/wishlist/WishlistButton/WishlistButton.tsx @@ -2,6 +2,7 @@ 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 useRemoveItem from '@lib/bigcommerce/wishlist/use-remove-item' import useWishlist from '@lib/bigcommerce/wishlist/use-wishlist' import useCustomer from '@lib/bigcommerce/use-customer' import { Heart } from '@components/icons' @@ -19,19 +20,21 @@ const WishlistButton: FC = ({ ...props }) => { const addItem = useAddItem() + const removeItem = useRemoveItem() const { data } = useWishlist() const { data: customer } = useCustomer() const [loading, setLoading] = useState(false) const { openModal, setModalView } = useUI() - const isInWishlist = data?.items?.some( + const itemInWishlist = data?.items?.find( (item) => item.product_id === productId && item.variant_id === variant?.node.entityId ) - const addToWishlist = async (e: any) => { + const handleWishlistChange = async (e: any) => { e.preventDefault() - setLoading(true) + + if (loading) return // A login is required before adding an item to the wishlist if (!customer) { @@ -39,11 +42,17 @@ const WishlistButton: FC = ({ return openModal() } + setLoading(true) + try { - await addItem({ - productId, - variantId: variant?.node.entityId!, - }) + if (itemInWishlist) { + await removeItem({ id: itemInWishlist.id! }) + } else { + await addItem({ + productId, + variantId: variant?.node.entityId!, + }) + } setLoading(false) } catch (err) { @@ -55,9 +64,9 @@ const WishlistButton: FC = ({ ) } diff --git a/lib/bigcommerce/api/utils/fetch-store-api.ts b/lib/bigcommerce/api/utils/fetch-store-api.ts index 22b3e5a99..7e59b9f06 100644 --- a/lib/bigcommerce/api/utils/fetch-store-api.ts +++ b/lib/bigcommerce/api/utils/fetch-store-api.ts @@ -41,7 +41,7 @@ export default async function fetchStoreApi( throw new BigcommerceApiError(msg, res, data) } - if (!isJSON) { + if (res.status !== 204 && !isJSON) { throw new BigcommerceApiError( `Fetch to Bigcommerce API failed, expected JSON content but found: ${contentType}`, res diff --git a/lib/bigcommerce/api/wishlist/handlers/remove-item.ts b/lib/bigcommerce/api/wishlist/handlers/remove-item.ts index 9be970f11..29b6eff60 100644 --- a/lib/bigcommerce/api/wishlist/handlers/remove-item.ts +++ b/lib/bigcommerce/api/wishlist/handlers/remove-item.ts @@ -1,20 +1,34 @@ +import getCustomerId from '../../operations/get-customer-id' +import getCustomerWishlist, { + Wishlist, +} from '../../operations/get-customer-wishlist' import type { WishlistHandlers } from '..' // Return current wishlist info const removeItem: WishlistHandlers['removeItem'] = async ({ res, - body: { wishlistId, itemId }, + body: { customerToken, itemId }, config, }) => { - if (!wishlistId || !itemId) { + const customerId = + customerToken && (await getCustomerId({ customerToken, config })) + const { wishlist } = + (customerId && + (await getCustomerWishlist({ + variables: { customerId }, + config, + }))) || + {} + + if (!wishlist || !itemId) { return res.status(400).json({ data: null, errors: [{ message: 'Invalid request' }], }) } - const result = await config.storeApiFetch<{ data: any } | null>( - `/v3/wishlists/${wishlistId}/items/${itemId}`, + const result = await config.storeApiFetch<{ data: Wishlist } | null>( + `/v3/wishlists/${wishlist.id}/items/${itemId}`, { method: 'DELETE' } ) const data = result?.data ?? null diff --git a/lib/bigcommerce/api/wishlist/index.ts b/lib/bigcommerce/api/wishlist/index.ts index 13cbf60f7..e9ae8c688 100644 --- a/lib/bigcommerce/api/wishlist/index.ts +++ b/lib/bigcommerce/api/wishlist/index.ts @@ -22,7 +22,7 @@ export type ItemBody = { export type AddItemBody = { item: ItemBody } -export type RemoveItemBody = { wishlistId: string; itemId: string } +export type RemoveItemBody = { itemId: string } export type WishlistBody = { customer_id: number @@ -52,7 +52,7 @@ export type WishlistHandlers = { > removeItem: BigcommerceHandler< Wishlist, - { wishlistId: string } & Body + { customerToken?: string } & Body > removeWishlist: BigcommerceHandler } @@ -93,11 +93,8 @@ const wishlistApi: BigcommerceApiHandler = async ( } // Remove an item from the wishlist - if (req.method === 'DELETE' && wishlistId && itemId) { - const body = { - wishlistId: wishlistId as string, - itemId: itemId as string, - } + if (req.method === 'DELETE') { + const body = { ...req.body, customerToken } return await handlers['removeItem']({ req, res, config, body }) } diff --git a/lib/bigcommerce/cart/use-remove-item.tsx b/lib/bigcommerce/cart/use-remove-item.tsx index c07aa718e..81897c42a 100644 --- a/lib/bigcommerce/cart/use-remove-item.tsx +++ b/lib/bigcommerce/cart/use-remove-item.tsx @@ -26,7 +26,7 @@ export const fetcher: HookFetcher = ( } export function extendHook(customFetcher: typeof fetcher) { - const useRemoveItem = (item?: any) => { + const useRemoveItem = () => { const { mutate } = useCart() const fn = useCartRemoveItem( defaultOpts, @@ -35,7 +35,7 @@ export function extendHook(customFetcher: typeof fetcher) { return useCallback( async function removeItem(input: RemoveItemInput) { - const data = await fn({ itemId: input.id ?? item?.id }) + const data = await fn({ itemId: input.id }) await mutate(data, false) return data }, diff --git a/lib/bigcommerce/wishlist/use-add-item.tsx b/lib/bigcommerce/wishlist/use-add-item.tsx index 60ea09c7f..0545a3607 100644 --- a/lib/bigcommerce/wishlist/use-add-item.tsx +++ b/lib/bigcommerce/wishlist/use-add-item.tsx @@ -45,7 +45,7 @@ export function extendHook(customFetcher: typeof fetcher) { await mutate(data, false) return data }, - [fn, mutate] + [fn, mutate, customer] ) } diff --git a/lib/bigcommerce/wishlist/use-remove-item.tsx b/lib/bigcommerce/wishlist/use-remove-item.tsx index cd4e7ddeb..c7d75f782 100644 --- a/lib/bigcommerce/wishlist/use-remove-item.tsx +++ b/lib/bigcommerce/wishlist/use-remove-item.tsx @@ -1,45 +1,55 @@ import { useCallback } from 'react' import { HookFetcher } from '@lib/commerce/utils/types' -import useAction from '@lib/commerce/utils/use-action' +import { CommerceError } from '@lib/commerce/utils/errors' +import useWishlistRemoveItem from '@lib/commerce/wishlist/use-remove-item' import type { RemoveItemBody } from '../api/wishlist' +import useCustomer from '../use-customer' import useWishlist, { Wishlist } from './use-wishlist' const defaultOpts = { - url: '/api/bigcommerce/wishlists', + url: '/api/bigcommerce/wishlist', method: 'DELETE', } export type RemoveItemInput = { - id: string + id: string | number } export const fetcher: HookFetcher = ( options, - { wishlistId, itemId }, + { itemId }, fetch ) => { return fetch({ ...defaultOpts, ...options, - body: { wishlistId, itemId }, + body: { itemId }, }) } export function extendHook(customFetcher: typeof fetcher) { - const useRemoveItem = (wishlistId: string, item?: any) => { + const useRemoveItem = () => { + const { data: customer } = useCustomer() const { mutate } = useWishlist() - const fn = useAction( + const fn = useWishlistRemoveItem( defaultOpts, customFetcher ) return useCallback( async function removeItem(input: RemoveItemInput) { - const data = await fn({ wishlistId, itemId: input.id ?? item?.id }) + if (!customer) { + // A signed customer is required in order to have a wishlist + throw new CommerceError({ + message: 'Signed customer not found', + }) + } + + const data = await fn({ itemId: String(input.id) }) await mutate(data, false) return data }, - [fn, mutate] + [fn, mutate, customer] ) } diff --git a/lib/commerce/wishlist/use-remove-item.tsx b/lib/commerce/wishlist/use-remove-item.tsx new file mode 100644 index 000000000..dfa60c363 --- /dev/null +++ b/lib/commerce/wishlist/use-remove-item.tsx @@ -0,0 +1,5 @@ +import useAction from '../utils/use-action' + +const useRemoveItem = useAction + +export default useRemoveItem From 0ec552c2b86faaa02675196db3877674fdd3cdf3 Mon Sep 17 00:00:00 2001 From: Luis Alvarez Date: Mon, 26 Oct 2020 18:26:40 -0500 Subject: [PATCH 4/5] Removed Body type --- lib/bigcommerce/api/cart/index.ts | 8 +++----- lib/bigcommerce/api/wishlist/index.ts | 10 ++++------ 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/bigcommerce/api/cart/index.ts b/lib/bigcommerce/api/cart/index.ts index 4f6062674..c8a4913d6 100644 --- a/lib/bigcommerce/api/cart/index.ts +++ b/lib/bigcommerce/api/cart/index.ts @@ -9,8 +9,6 @@ import addItem from './handlers/add-item' import updateItem from './handlers/update-item' import removeItem from './handlers/remove-item' -type Body = Partial | undefined - export type ItemBody = { productId: number variantId: number @@ -46,14 +44,14 @@ export type Cart = { export type CartHandlers = { getCart: BigcommerceHandler - addItem: BigcommerceHandler> + addItem: BigcommerceHandler> updateItem: BigcommerceHandler< Cart, - { cartId?: string } & Body + { cartId?: string } & Partial > removeItem: BigcommerceHandler< Cart, - { cartId?: string } & Body + { cartId?: string } & Partial > } diff --git a/lib/bigcommerce/api/wishlist/index.ts b/lib/bigcommerce/api/wishlist/index.ts index e9ae8c688..d4fe8472d 100644 --- a/lib/bigcommerce/api/wishlist/index.ts +++ b/lib/bigcommerce/api/wishlist/index.ts @@ -13,8 +13,6 @@ import removeWishlist from './handlers/remove-wishlist' import addWishlist from './handlers/add-wishlist' import { definitions } from '../definitions/wishlist' -type Body = Partial | undefined - export type ItemBody = { productId: number variantId: number @@ -40,19 +38,19 @@ export type WishlistHandlers = { getWishlist: BigcommerceHandler addWishlist: BigcommerceHandler< Wishlist, - { wishlistId: string } & Body + { wishlistId: string } & Partial > updateWishlist: BigcommerceHandler< Wishlist, - { wishlistId: string } & Body + { wishlistId: string } & Partial > addItem: BigcommerceHandler< Wishlist, - { customerToken?: string } & Body + { customerToken?: string } & Partial > removeItem: BigcommerceHandler< Wishlist, - { customerToken?: string } & Body + { customerToken?: string } & Partial > removeWishlist: BigcommerceHandler } From 364ef332c138f94a5004924185c8d25e4ae70909 Mon Sep 17 00:00:00 2001 From: Luis Alvarez Date: Mon, 26 Oct 2020 18:46:38 -0500 Subject: [PATCH 5/5] Bug fixes --- components/product/ProductCard/ProductCard.module.css | 2 +- components/product/ProductCard/ProductCard.tsx | 2 +- components/wishlist/WishlistButton/WishlistButton.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/product/ProductCard/ProductCard.module.css b/components/product/ProductCard/ProductCard.module.css index 171190df0..e46f6ba5c 100644 --- a/components/product/ProductCard/ProductCard.module.css +++ b/components/product/ProductCard/ProductCard.module.css @@ -119,7 +119,7 @@ } .wishlistButton { - @apply w-10 h-10 flex ml-auto flex items-center justify-center bg-primary text-primary font-semibold text-xs leading-6 cursor-pointer; + @apply w-10 h-10 flex ml-auto flex items-center justify-center bg-primary text-primary font-semibold text-xs leading-6 cursor-pointer z-10; } .imageContainer { diff --git a/components/product/ProductCard/ProductCard.tsx b/components/product/ProductCard/ProductCard.tsx index d48c5b4cf..4323977f3 100644 --- a/components/product/ProductCard/ProductCard.tsx +++ b/components/product/ProductCard/ProductCard.tsx @@ -52,7 +52,7 @@ const ProductCard: FC = ({ } return ( - + diff --git a/components/wishlist/WishlistButton/WishlistButton.tsx b/components/wishlist/WishlistButton/WishlistButton.tsx index 5831df6d4..e9d6236f0 100644 --- a/components/wishlist/WishlistButton/WishlistButton.tsx +++ b/components/wishlist/WishlistButton/WishlistButton.tsx @@ -66,7 +66,7 @@ const WishlistButton: FC = ({ className={cn({ 'opacity-50': loading }, className)} onClick={handleWishlistChange} > - + ) }