From fc023de8445fc5fd23553e1dd895598c44f6f774 Mon Sep 17 00:00:00 2001 From: Luis Alvarez Date: Thu, 25 Feb 2021 18:10:59 -0500 Subject: [PATCH 1/5] Ignore some types --- components/wishlist/WishlistButton/WishlistButton.tsx | 2 ++ components/wishlist/WishlistCard/WishlistCard.tsx | 1 + framework/commerce/types.ts | 6 +++--- framework/shopify/cart/use-cart.tsx | 2 +- framework/shopify/cart/utils/checkout-to-cart.ts | 2 +- framework/shopify/index.tsx | 3 ++- framework/shopify/utils/get-categories.ts | 2 +- package.json | 1 + pages/[...pages].tsx | 3 ++- pages/search.tsx | 7 +++++-- pages/wishlist.tsx | 2 ++ scripts/commerce.js | 1 + 12 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 scripts/commerce.js diff --git a/components/wishlist/WishlistButton/WishlistButton.tsx b/components/wishlist/WishlistButton/WishlistButton.tsx index 57f769e3d..290f7f9ec 100644 --- a/components/wishlist/WishlistButton/WishlistButton.tsx +++ b/components/wishlist/WishlistButton/WishlistButton.tsx @@ -26,7 +26,9 @@ const WishlistButton: FC = ({ const { openModal, setModalView } = useUI() const [loading, setLoading] = useState(false) + // @ts-ignore Wishlist is not always enabled const itemInWishlist = data?.items?.find( + // @ts-ignore Wishlist is not always enabled (item) => item.product_id === productId && (item.variant_id as any) === variant.id ) diff --git a/components/wishlist/WishlistCard/WishlistCard.tsx b/components/wishlist/WishlistCard/WishlistCard.tsx index 5e4cce72a..1568d9e7e 100644 --- a/components/wishlist/WishlistCard/WishlistCard.tsx +++ b/components/wishlist/WishlistCard/WishlistCard.tsx @@ -22,6 +22,7 @@ const WishlistCard: FC = ({ product }) => { baseAmount: product.prices?.retailPrice?.value, currencyCode: product.prices?.price?.currencyCode!, }) + // @ts-ignore Wishlist is not always enabled const removeItem = useRemoveItem({ wishlist: { includeProducts: true } }) const [loading, setLoading] = useState(false) const [removing, setRemoving] = useState(false) diff --git a/framework/commerce/types.ts b/framework/commerce/types.ts index bf635c9dc..a398070ac 100644 --- a/framework/commerce/types.ts +++ b/framework/commerce/types.ts @@ -1,6 +1,6 @@ -import type { Wishlist as BCWishlist } from '@framework/api/wishlist' -import type { Customer as BCCustomer } from '@framework/api/customers' -import type { SearchProductsData as BCSearchProductsData } from '@framework/api/catalog/products' +import type { Wishlist as BCWishlist } from '../bigcommerce/api/wishlist' +import type { Customer as BCCustomer } from '../bigcommerce/api/customers' +import type { SearchProductsData as BCSearchProductsData } from '../bigcommerce/api/catalog/products' export type Discount = { // The value of the discount, can be an amount or percentage diff --git a/framework/shopify/cart/use-cart.tsx b/framework/shopify/cart/use-cart.tsx index 5f1f87299..d154bb837 100644 --- a/framework/shopify/cart/use-cart.tsx +++ b/framework/shopify/cart/use-cart.tsx @@ -4,7 +4,7 @@ import useCommerceCart, { UseCart, } from '@commerce/cart/use-cart' -import { Cart } from '@commerce/types' +import { Cart } from '../types' import { SWRHook } from '@commerce/utils/types' import { checkoutCreate, checkoutToCart } from './utils' import getCheckoutQuery from '../utils/queries/get-checkout-query' diff --git a/framework/shopify/cart/utils/checkout-to-cart.ts b/framework/shopify/cart/utils/checkout-to-cart.ts index fa8b988f9..03005f342 100644 --- a/framework/shopify/cart/utils/checkout-to-cart.ts +++ b/framework/shopify/cart/utils/checkout-to-cart.ts @@ -1,4 +1,4 @@ -import { Cart } from '@commerce/types' +import { Cart } from '../../types' import { CommerceError, ValidationError } from '@commerce/utils/errors' import { diff --git a/framework/shopify/index.tsx b/framework/shopify/index.tsx index 5b25d6b21..c26704771 100644 --- a/framework/shopify/index.tsx +++ b/framework/shopify/index.tsx @@ -28,7 +28,8 @@ export type ShopifyProps = { export function CommerceProvider({ children, ...config }: ShopifyProps) { return ( {children} diff --git a/framework/shopify/utils/get-categories.ts b/framework/shopify/utils/get-categories.ts index e1176b068..54048b896 100644 --- a/framework/shopify/utils/get-categories.ts +++ b/framework/shopify/utils/get-categories.ts @@ -3,7 +3,7 @@ import { CollectionEdge } from '../schema' import getSiteCollectionsQuery from './queries/get-all-collections-query' export type Category = { - endityId: string + entityId: string name: string path: string } diff --git a/package.json b/package.json index 906d950dc..491071e55 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "analyze": "BUNDLE_ANALYZE=both yarn build", "prettier-fix": "prettier --write .", "find:unused": "next-unused", + "commerce": "node scripts/commerce.js", "generate": "graphql-codegen", "generate:definitions": "node framework/bigcommerce/scripts/generate-definitions.js" }, diff --git a/pages/[...pages].tsx b/pages/[...pages].tsx index 3f39845b5..67adb6287 100644 --- a/pages/[...pages].tsx +++ b/pages/[...pages].tsx @@ -25,7 +25,8 @@ export async function getStaticProps({ const pageItem = pages.find((p) => (p.url ? getSlug(p.url) === slug : false)) const data = pageItem && - (await getPage({ variables: { id: pageItem.id! }, config, preview })) + // TODO: Shopify - Fix this type + (await getPage({ variables: { id: pageItem.id! } as any, config, preview })) const page = data?.page if (!page) { diff --git a/pages/search.tsx b/pages/search.tsx index a05203892..da2edccd8 100644 --- a/pages/search.tsx +++ b/pages/search.tsx @@ -75,8 +75,10 @@ export default function Search({ const { data } = useSearch({ search: typeof q === 'string' ? q : '', - categoryId: activeCategory?.entityId, - brandId: activeBrand?.entityId, + // TODO: Shopify - Fix this type + categoryId: activeCategory?.entityId as any, + // TODO: Shopify - Fix this type + brandId: (activeBrand as any)?.entityId, sort: typeof sort === 'string' ? sort : '', }) @@ -266,6 +268,7 @@ export default function Search({ className={cn( 'block text-sm leading-5 text-gray-700 hover:bg-gray-100 lg:hover:bg-transparent hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900', { + // @ts-ignore Shopify - Fix this types underline: activeBrand?.entityId === node.entityId, } )} diff --git a/pages/wishlist.tsx b/pages/wishlist.tsx index ce97532b0..9938698d4 100644 --- a/pages/wishlist.tsx +++ b/pages/wishlist.tsx @@ -35,6 +35,7 @@ export async function getStaticProps({ export default function Wishlist() { const { data: customer } = useCustomer() + // @ts-ignore Shopify - Fix this types const { data, isLoading, isEmpty } = useWishlist() const router = useRouter() @@ -57,6 +58,7 @@ export default function Wishlist() { ) : ( data && + // @ts-ignore Shopify - Fix this types data.items?.map((item) => ( )) diff --git a/scripts/commerce.js b/scripts/commerce.js new file mode 100644 index 000000000..e6eefa224 --- /dev/null +++ b/scripts/commerce.js @@ -0,0 +1 @@ +console.log('Hello') From 42be44c7ee62b3139e6eba8518c5dd03c85e8908 Mon Sep 17 00:00:00 2001 From: okbel Date: Fri, 26 Feb 2021 14:25:02 -0300 Subject: [PATCH 2/5] Adding link for Cart --- commerce.config.json | 3 ++- .../cart/CartSidebarView/CartSidebarView.tsx | 25 +++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/commerce.config.json b/commerce.config.json index 1c14a53f5..05dd2a043 100644 --- a/commerce.config.json +++ b/commerce.config.json @@ -1,6 +1,7 @@ { "provider": "bigcommerce", "features": { - "wishlist": false + "wishlist": true, + "customCheckout": true } } diff --git a/components/cart/CartSidebarView/CartSidebarView.tsx b/components/cart/CartSidebarView/CartSidebarView.tsx index cb932247f..326390327 100644 --- a/components/cart/CartSidebarView/CartSidebarView.tsx +++ b/components/cart/CartSidebarView/CartSidebarView.tsx @@ -1,14 +1,14 @@ import { FC } from 'react' import cn from 'classnames' -import { UserNav } from '@components/common' -import { Button } from '@components/ui' -import { Bag, Cross, Check } from '@components/icons' -import { useUI } from '@components/ui/context' -import useCart from '@framework/cart/use-cart' -import usePrice from '@framework/product/use-price' +import Link from 'next/link' import CartItem from '../CartItem' import s from './CartSidebarView.module.css' -import { LineItem } from '@commerce/types' +import { Button } from '@components/ui' +import { UserNav } from '@components/common' +import { useUI } from '@components/ui/context' +import { Bag, Cross, Check } from '@components/icons' +import useCart from '@framework/cart/use-cart' +import usePrice from '@framework/product/use-price' const CartSidebarView: FC = () => { const { closeSidebar } = useUI() @@ -88,9 +88,14 @@ const CartSidebarView: FC = () => { ) : ( <>
-

- My Cart -

+ +

+ My Cart +

+
    {data!.lineItems.map((item: any) => ( Date: Fri, 26 Feb 2021 15:52:09 -0300 Subject: [PATCH 3/5] Adding customCheckout --- commerce.config.json | 2 +- components/icons/CreditCard.tsx | 20 ++++++++++++++++++++ components/icons/MapPin.tsx | 20 ++++++++++++++++++++ components/icons/index.ts | 2 ++ components/ui/context.tsx | 7 ++++++- pages/cart.tsx | 33 +++++++++++++++++++++++++++++++-- 6 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 components/icons/CreditCard.tsx create mode 100644 components/icons/MapPin.tsx diff --git a/commerce.config.json b/commerce.config.json index 05dd2a043..bef7db222 100644 --- a/commerce.config.json +++ b/commerce.config.json @@ -2,6 +2,6 @@ "provider": "bigcommerce", "features": { "wishlist": true, - "customCheckout": true + "customCheckout": false } } diff --git a/components/icons/CreditCard.tsx b/components/icons/CreditCard.tsx new file mode 100644 index 000000000..85504d8ba --- /dev/null +++ b/components/icons/CreditCard.tsx @@ -0,0 +1,20 @@ +const CreditCard = ({ ...props }) => { + return ( + + + + + ) +} + +export default CreditCard diff --git a/components/icons/MapPin.tsx b/components/icons/MapPin.tsx new file mode 100644 index 000000000..6323b9c1c --- /dev/null +++ b/components/icons/MapPin.tsx @@ -0,0 +1,20 @@ +const MapPin = ({ ...props }) => { + return ( + + + + + ) +} + +export default MapPin diff --git a/components/icons/index.ts b/components/icons/index.ts index 6e57ab0e8..1f2089085 100644 --- a/components/icons/index.ts +++ b/components/icons/index.ts @@ -14,3 +14,5 @@ export { default as RightArrow } from './RightArrow' export { default as Info } from './Info' export { default as ChevronUp } from './ChevronUp' export { default as Vercel } from './Vercel' +export { default as MapPin } from './MapPin' +export { default as CreditCard } from './CreditCard' diff --git a/components/ui/context.tsx b/components/ui/context.tsx index 13992a736..f66adb9d7 100644 --- a/components/ui/context.tsx +++ b/components/ui/context.tsx @@ -59,7 +59,12 @@ type Action = value: string } -type MODAL_VIEWS = 'SIGNUP_VIEW' | 'LOGIN_VIEW' | 'FORGOT_VIEW' +type MODAL_VIEWS = + | 'SIGNUP_VIEW' + | 'LOGIN_VIEW' + | 'FORGOT_VIEW' + | 'NEW_SHIPPING_ADDRESS' + | 'NEW_PAYMENT_METHOD' type ToastText = string export const UIContext = React.createContext(initialState) diff --git a/pages/cart.tsx b/pages/cart.tsx index 8b2dbb57b..cd5bedacc 100644 --- a/pages/cart.tsx +++ b/pages/cart.tsx @@ -5,7 +5,7 @@ import useCart from '@framework/cart/use-cart' import usePrice from '@framework/product/use-price' import { Layout } from '@components/common' import { Button, Text } from '@components/ui' -import { Bag, Cross, Check } from '@components/icons' +import { Bag, Cross, Check, MapPin, CreditCard } from '@components/icons' import { CartItem } from '@components/cart' export async function getStaticProps({ @@ -38,7 +38,7 @@ export default function Cart() { ) return ( -
    +
    {isLoading || isEmpty ? (
    @@ -103,6 +103,35 @@ export default function Cart() {
    + {process.env.COMMERCE_CUSTOMCHECKOUT_ENABLED && ( + <> + {/* Shipping Address */} + {/* Only available with customCheckout set to true - Meaning that the provider does offer checkout functionality. */} +
    +
    + +
    +
    + + Add Shipping Address + {/* + 1046 Kearny Street.
    + San Franssisco, California +
    */} +
    +
    + {/* Payment Method */} + {/* Only available with customCheckout set to true - Meaning that the provider does offer checkout functionality. */} +
    +
    + +
    +
    + + Add Payment Method + {/* VISA #### #### #### 2345 */} +
    +
    + + )}
    • From 751011767a93e670755f24cec490cfd86b5faaf1 Mon Sep 17 00:00:00 2001 From: Luis Alvarez Date: Fri, 26 Feb 2021 21:35:09 -0500 Subject: [PATCH 4/5] multiple changes to fix the wishlist --- .../wishlist/WishlistButton/WishlistButton.tsx | 3 ++- framework/bigcommerce/api/utils/parse-item.ts | 13 ++++++++++--- .../bigcommerce/customer/get-customer-wishlist.ts | 5 +++-- framework/bigcommerce/wishlist/use-wishlist.tsx | 4 ++-- framework/shopify/api/index.ts | 1 - package.json | 1 - pages/wishlist.tsx | 8 ++------ scripts/commerce.js | 1 - 8 files changed, 19 insertions(+), 17 deletions(-) delete mode 100644 scripts/commerce.js diff --git a/components/wishlist/WishlistButton/WishlistButton.tsx b/components/wishlist/WishlistButton/WishlistButton.tsx index 290f7f9ec..6dc59b900 100644 --- a/components/wishlist/WishlistButton/WishlistButton.tsx +++ b/components/wishlist/WishlistButton/WishlistButton.tsx @@ -30,7 +30,8 @@ const WishlistButton: FC = ({ const itemInWishlist = data?.items?.find( // @ts-ignore Wishlist is not always enabled (item) => - item.product_id === productId && (item.variant_id as any) === variant.id + item.product_id === Number(productId) && + (item.variant_id as any) === Number(variant.id) ) const handleWishlistChange = async (e: any) => { diff --git a/framework/bigcommerce/api/utils/parse-item.ts b/framework/bigcommerce/api/utils/parse-item.ts index dcc716c23..7c8cd4728 100644 --- a/framework/bigcommerce/api/utils/parse-item.ts +++ b/framework/bigcommerce/api/utils/parse-item.ts @@ -1,6 +1,11 @@ import type { ItemBody as WishlistItemBody } from '../wishlist' import type { CartItemBody, OptionSelections } from '../../types' +type BCWishlistItemBody = { + product_id: number + variant_id: number +} + type BCCartItemBody = { product_id: number variant_id: number @@ -8,9 +13,11 @@ type BCCartItemBody = { option_selections?: OptionSelections } -export const parseWishlistItem = (item: WishlistItemBody) => ({ - product_id: item.productId, - variant_id: item.variantId, +export const parseWishlistItem = ( + item: WishlistItemBody +): BCWishlistItemBody => ({ + product_id: Number(item.productId), + variant_id: Number(item.variantId), }) export const parseCartItem = (item: CartItemBody): BCCartItemBody => ({ diff --git a/framework/bigcommerce/customer/get-customer-wishlist.ts b/framework/bigcommerce/customer/get-customer-wishlist.ts index e854ff933..97e5654a9 100644 --- a/framework/bigcommerce/customer/get-customer-wishlist.ts +++ b/framework/bigcommerce/customer/get-customer-wishlist.ts @@ -68,14 +68,15 @@ async function getCustomerWishlist({ const productsById = graphqlData.products.reduce<{ [k: number]: ProductEdge }>((prods, p) => { - prods[Number(p.node.entityId)] = p as any + prods[Number(p.id)] = p as any return prods }, {}) // Populate the wishlist items with the graphql products wishlist.items.forEach((item) => { const product = item && productsById[item.product_id!] if (item && product) { - item.product = product.node + // @ts-ignore Fix this type when the wishlist type is properly defined + item.product = product } }) } diff --git a/framework/bigcommerce/wishlist/use-wishlist.tsx b/framework/bigcommerce/wishlist/use-wishlist.tsx index 3efba7ffd..4850d1cd9 100644 --- a/framework/bigcommerce/wishlist/use-wishlist.tsx +++ b/framework/bigcommerce/wishlist/use-wishlist.tsx @@ -18,7 +18,7 @@ export const handler: SWRHook< url: '/api/bigcommerce/wishlist', method: 'GET', }, - fetcher({ input: { customerId, includeProducts }, options, fetch }) { + async fetcher({ input: { customerId, includeProducts }, options, fetch }) { if (!customerId) return null // Use a dummy base as we only care about the relative path @@ -35,7 +35,7 @@ export const handler: SWRHook< const { data: customer } = useCustomer() const response = useData({ input: [ - ['customerId', (customer as any)?.id], + ['customerId', customer?.entityId], ['includeProducts', input?.includeProducts], ], swrOptions: { diff --git a/framework/shopify/api/index.ts b/framework/shopify/api/index.ts index 0fe58f2df..4e23ce99c 100644 --- a/framework/shopify/api/index.ts +++ b/framework/shopify/api/index.ts @@ -8,7 +8,6 @@ import { } from '../const' if (!API_URL) { - console.log(process.env) throw new Error( `The environment variable NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN is missing and it's required to access your store` ) diff --git a/package.json b/package.json index 491071e55..906d950dc 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,6 @@ "analyze": "BUNDLE_ANALYZE=both yarn build", "prettier-fix": "prettier --write .", "find:unused": "next-unused", - "commerce": "node scripts/commerce.js", "generate": "graphql-codegen", "generate:definitions": "node framework/bigcommerce/scripts/generate-definitions.js" }, diff --git a/pages/wishlist.tsx b/pages/wishlist.tsx index 9938698d4..0dddaf23d 100644 --- a/pages/wishlist.tsx +++ b/pages/wishlist.tsx @@ -1,7 +1,4 @@ -import { useEffect } from 'react' -import { useRouter } from 'next/router' import type { GetStaticPropsContext } from 'next' - import { Heart } from '@components/icons' import { Layout } from '@components/common' import { Text, Container } from '@components/ui' @@ -36,8 +33,7 @@ export async function getStaticProps({ export default function Wishlist() { const { data: customer } = useCustomer() // @ts-ignore Shopify - Fix this types - const { data, isLoading, isEmpty } = useWishlist() - const router = useRouter() + const { data, isLoading, isEmpty } = useWishlist({ includeProducts: true }) return ( @@ -60,7 +56,7 @@ export default function Wishlist() { data && // @ts-ignore Shopify - Fix this types data.items?.map((item) => ( - + )) )}
    diff --git a/scripts/commerce.js b/scripts/commerce.js deleted file mode 100644 index e6eefa224..000000000 --- a/scripts/commerce.js +++ /dev/null @@ -1 +0,0 @@ -console.log('Hello') From 641ce0aa64cc46fbdc492dc55df7942d1d2be3fa Mon Sep 17 00:00:00 2001 From: cond0r Date: Mon, 1 Mar 2021 16:47:30 +0200 Subject: [PATCH 5/5] Shopify Provier Updates (#212) * changes * Adding shopify commit * Changed to query page by id * Fixed page query, Changed use-search GraphQl query * Update use-search.tsx * remove unused util * Changed cookie expiration * Update tsconfig.json Co-authored-by: okbel --- framework/bigcommerce/.env.template | 2 +- framework/shopify/api/index.ts | 4 +- .../shopify/cart/utils/checkout-create.ts | 8 ++- framework/shopify/common/get-all-pages.ts | 3 +- framework/shopify/common/get-page.ts | 15 ++-- framework/shopify/const.ts | 2 + framework/shopify/product/use-search.tsx | 34 ++++++--- framework/shopify/utils/customer-token.ts | 17 +++-- framework/shopify/utils/get-categories.ts | 4 +- .../shopify/utils/get-search-variables.ts | 11 ++- framework/shopify/utils/get-sort-variables.ts | 4 +- framework/shopify/utils/normalize.ts | 59 ++++++++++------ .../utils/queries/get-all-products-query.ts | 69 ++++++++++--------- .../queries/get-collection-products-query.ts | 21 ++++-- .../shopify/utils/queries/get-page-query.ts | 15 ++-- .../utils/queries/get-product-query.ts | 1 + .../shopify/utils/to-commerce-products.ts | 68 ------------------ framework/shopify/wishlist/use-wishlist.tsx | 2 - 18 files changed, 164 insertions(+), 175 deletions(-) delete mode 100644 framework/shopify/utils/to-commerce-products.ts diff --git a/framework/bigcommerce/.env.template b/framework/bigcommerce/.env.template index 83e7dd403..43e85c046 100644 --- a/framework/bigcommerce/.env.template +++ b/framework/bigcommerce/.env.template @@ -3,4 +3,4 @@ BIGCOMMERCE_STOREFRONT_API_TOKEN= BIGCOMMERCE_STORE_API_URL= BIGCOMMERCE_STORE_API_TOKEN= BIGCOMMERCE_STORE_API_CLIENT_ID= -BIGCOMMERCE_CHANNEL_ID= \ No newline at end of file +BIGCOMMERCE_CHANNEL_ID= diff --git a/framework/shopify/api/index.ts b/framework/shopify/api/index.ts index 4e23ce99c..4f15cae15 100644 --- a/framework/shopify/api/index.ts +++ b/framework/shopify/api/index.ts @@ -5,6 +5,7 @@ import { API_TOKEN, SHOPIFY_CHECKOUT_ID_COOKIE, SHOPIFY_CUSTOMER_TOKEN_COOKIE, + SHOPIFY_COOKIE_EXPIRE, } from '../const' if (!API_URL) { @@ -43,10 +44,11 @@ export class Config { } const config = new Config({ + locale: 'en-US', commerceUrl: API_URL, apiToken: API_TOKEN!, cartCookie: SHOPIFY_CHECKOUT_ID_COOKIE, - cartCookieMaxAge: 60 * 60 * 24 * 30, + cartCookieMaxAge: SHOPIFY_COOKIE_EXPIRE, fetch: fetchGraphqlApi, customerCookie: SHOPIFY_CUSTOMER_TOKEN_COOKIE, }) diff --git a/framework/shopify/cart/utils/checkout-create.ts b/framework/shopify/cart/utils/checkout-create.ts index 6c4f81c21..e950cc7e4 100644 --- a/framework/shopify/cart/utils/checkout-create.ts +++ b/framework/shopify/cart/utils/checkout-create.ts @@ -1,6 +1,7 @@ import { SHOPIFY_CHECKOUT_ID_COOKIE, SHOPIFY_CHECKOUT_URL_COOKIE, + SHOPIFY_COOKIE_EXPIRE, } from '../../const' import checkoutCreateMutation from '../../utils/mutations/checkout-create' @@ -15,8 +16,11 @@ export const checkoutCreate = async (fetch: any) => { const checkoutId = checkout?.id if (checkoutId) { - Cookies.set(SHOPIFY_CHECKOUT_ID_COOKIE, checkoutId) - Cookies.set(SHOPIFY_CHECKOUT_URL_COOKIE, checkout?.webUrl) + const options = { + expires: SHOPIFY_COOKIE_EXPIRE, + } + Cookies.set(SHOPIFY_CHECKOUT_ID_COOKIE, checkoutId, options) + Cookies.set(SHOPIFY_CHECKOUT_URL_COOKIE, checkout?.webUrl, options) } return checkout diff --git a/framework/shopify/common/get-all-pages.ts b/framework/shopify/common/get-all-pages.ts index 6f06185e2..54231ed03 100644 --- a/framework/shopify/common/get-all-pages.ts +++ b/framework/shopify/common/get-all-pages.ts @@ -25,12 +25,13 @@ const getAllPages = async (options?: { }): Promise => { let { config, variables = { first: 250 } } = options ?? {} config = getConfig(config) + const { locale } = config const { data } = await config.fetch(getAllPagesQuery, { variables }) const pages = data.pages?.edges?.map( ({ node: { title: name, handle, ...node } }: PageEdge) => ({ ...node, - url: `/${handle}`, + url: `/${locale}/${handle}`, name, }) ) diff --git a/framework/shopify/common/get-page.ts b/framework/shopify/common/get-page.ts index 6016c8c9a..be934aa42 100644 --- a/framework/shopify/common/get-page.ts +++ b/framework/shopify/common/get-page.ts @@ -3,33 +3,32 @@ import getPageQuery from '../utils/queries/get-page-query' import { Page } from './get-all-pages' type Variables = { - slug: string + id: string } -type ReturnType = { - page: Page -} +export type GetPageResult = T const getPage = async (options: { variables: Variables config: ShopifyConfig preview?: boolean -}): Promise => { +}): Promise => { let { config, variables } = options ?? {} + config = getConfig(config) + const { locale } = config const { data } = await config.fetch(getPageQuery, { variables, }) - - const { pageByHandle: page } = data + const page = data.node return { page: page ? { ...page, name: page.title, - url: page?.handle, + url: `/${locale}/${page.handle}`, } : null, } diff --git a/framework/shopify/const.ts b/framework/shopify/const.ts index a6e9e8d90..06fbe5054 100644 --- a/framework/shopify/const.ts +++ b/framework/shopify/const.ts @@ -6,6 +6,8 @@ export const SHOPIFY_CUSTOMER_TOKEN_COOKIE = 'shopify_customerToken' export const STORE_DOMAIN = process.env.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN +export const SHOPIFY_COOKIE_EXPIRE = 30 + export const API_URL = `https://${STORE_DOMAIN}/api/2021-01/graphql.json` export const API_TOKEN = process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN diff --git a/framework/shopify/product/use-search.tsx b/framework/shopify/product/use-search.tsx index 4b14249ca..425df9e83 100644 --- a/framework/shopify/product/use-search.tsx +++ b/framework/shopify/product/use-search.tsx @@ -4,6 +4,7 @@ import useSearch, { UseSearch } from '@commerce/product/use-search' import { ProductEdge } from '../schema' import { getAllProductsQuery, + getCollectionProductsQuery, getSearchVariables, normalizeProduct, } from '../utils' @@ -14,8 +15,8 @@ export default useSearch as UseSearch export type SearchProductsInput = { search?: string - categoryId?: number - brandId?: number + categoryId?: string + brandId?: string sort?: string } @@ -23,6 +24,7 @@ export type SearchProductsData = { products: Product[] found: boolean } + export const handler: SWRHook< SearchProductsData, SearchProductsInput, @@ -32,18 +34,30 @@ export const handler: SWRHook< query: getAllProductsQuery, }, async fetcher({ input, options, fetch }) { - const resp = await fetch({ - query: options?.query, + const { categoryId, brandId } = input + + const data = await fetch({ + query: categoryId ? getCollectionProductsQuery : options.query, method: options?.method, variables: getSearchVariables(input), }) - const edges = resp.products?.edges + + let edges + + if (categoryId) { + edges = data.node?.products?.edges ?? [] + if (brandId) { + edges = edges.filter( + ({ node: { vendor } }: ProductEdge) => vendor === brandId + ) + } + } else { + edges = data.products?.edges ?? [] + } + return { - products: edges?.map(({ node: p }: ProductEdge) => - // TODO: Fix this product type - normalizeProduct(p as any) - ), - found: !!edges?.length, + products: edges.map(({ node }: ProductEdge) => normalizeProduct(node)), + found: !!edges.length, } }, useHook: ({ useData }) => (input = {}) => { diff --git a/framework/shopify/utils/customer-token.ts b/framework/shopify/utils/customer-token.ts index beae54765..85454cb83 100644 --- a/framework/shopify/utils/customer-token.ts +++ b/framework/shopify/utils/customer-token.ts @@ -1,12 +1,21 @@ -import Cookies from 'js-cookie' -import { SHOPIFY_CUSTOMER_TOKEN_COOKIE } from '../const' +import Cookies, { CookieAttributes } from 'js-cookie' +import { SHOPIFY_COOKIE_EXPIRE, SHOPIFY_CUSTOMER_TOKEN_COOKIE } from '../const' export const getCustomerToken = () => Cookies.get(SHOPIFY_CUSTOMER_TOKEN_COOKIE) -export const setCustomerToken = (token: string | null, options?: any) => { +export const setCustomerToken = ( + token: string | null, + options?: CookieAttributes +) => { if (!token) { Cookies.remove(SHOPIFY_CUSTOMER_TOKEN_COOKIE) } else { - Cookies.set(SHOPIFY_CUSTOMER_TOKEN_COOKIE, token, options) + Cookies.set( + SHOPIFY_CUSTOMER_TOKEN_COOKIE, + token, + options ?? { + expires: SHOPIFY_COOKIE_EXPIRE, + } + ) } } diff --git a/framework/shopify/utils/get-categories.ts b/framework/shopify/utils/get-categories.ts index 54048b896..cce4b2ad7 100644 --- a/framework/shopify/utils/get-categories.ts +++ b/framework/shopify/utils/get-categories.ts @@ -17,8 +17,8 @@ const getCategories = async (config: ShopifyConfig): Promise => { return ( data.collections?.edges?.map( - ({ node: { title: name, handle } }: CollectionEdge) => ({ - entityId: handle, + ({ node: { id: entityId, title: name, handle } }: CollectionEdge) => ({ + entityId, name, path: `/${handle}`, }) diff --git a/framework/shopify/utils/get-search-variables.ts b/framework/shopify/utils/get-search-variables.ts index 6f5d08b1a..c1b40ae5d 100644 --- a/framework/shopify/utils/get-search-variables.ts +++ b/framework/shopify/utils/get-search-variables.ts @@ -2,9 +2,9 @@ import getSortVariables from './get-sort-variables' import type { SearchProductsInput } from '../product/use-search' export const getSearchVariables = ({ - categoryId, brandId, search, + categoryId, sort, }: SearchProductsInput) => { let query = '' @@ -13,17 +13,14 @@ export const getSearchVariables = ({ query += `product_type:${search} OR title:${search} OR tag:${search}` } - if (categoryId) { - query += `tag:${categoryId}` - } - if (brandId) { - query += `${categoryId ? ' AND ' : ''}vendor:${brandId}` + query += `${search ? ' AND ' : ''}vendor:${brandId}` } return { + categoryId, query, - ...getSortVariables(sort), + ...getSortVariables(sort, !!categoryId), } } diff --git a/framework/shopify/utils/get-sort-variables.ts b/framework/shopify/utils/get-sort-variables.ts index 47650c0d7..b8cdeec51 100644 --- a/framework/shopify/utils/get-sort-variables.ts +++ b/framework/shopify/utils/get-sort-variables.ts @@ -1,4 +1,4 @@ -const getSortVariables = (sort?: string) => { +const getSortVariables = (sort?: string, isCategory = false) => { let output = {} switch (sort) { case 'price-asc': @@ -21,7 +21,7 @@ const getSortVariables = (sort?: string) => { break case 'latest-desc': output = { - sortKey: 'CREATED_AT', + sortKey: isCategory ? 'CREATED' : 'CREATED_AT', reverse: true, } break diff --git a/framework/shopify/utils/normalize.ts b/framework/shopify/utils/normalize.ts index 67ab3a8a2..c9b428b37 100644 --- a/framework/shopify/utils/normalize.ts +++ b/framework/shopify/utils/normalize.ts @@ -1,3 +1,5 @@ +import { Product } from '@commerce/types' + import { Product as ShopifyProduct, Checkout, @@ -5,8 +7,8 @@ import { SelectedOption, ImageConnection, ProductVariantConnection, - ProductOption, MoneyV2, + ProductOption, } from '../schema' import type { Cart, LineItem } from '../types' @@ -19,18 +21,26 @@ const money = ({ amount, currencyCode }: MoneyV2) => { } const normalizeProductOption = ({ + id, name: displayName, values, - ...rest }: ProductOption) => { return { __typename: 'MultipleChoiceOption', + id, displayName, - values: values.map((value) => ({ - label: value, - hexColors: displayName === 'Color' ? [value] : null, - })), - ...rest, + values: values.map((value) => { + let output: any = { + label: value, + } + if (displayName === 'Color') { + output = { + ...output, + hexColors: [value], + } + } + return output + }), } } @@ -41,19 +51,28 @@ const normalizeProductImages = ({ edges }: ImageConnection) => })) const normalizeProductVariants = ({ edges }: ProductVariantConnection) => { - return edges?.map(({ node: { id, selectedOptions } }) => ({ - id, - options: selectedOptions.map(({ name, value }: SelectedOption) => - normalizeProductOption({ - id, - name, - values: [value], - }) - ), - })) + return edges?.map( + ({ + node: { id, selectedOptions, sku, title, priceV2, compareAtPriceV2 }, + }) => ({ + id, + name: title, + sku: sku ?? id, + price: +priceV2.amount, + listPrice: +compareAtPriceV2?.amount, + requiresShipping: true, + options: selectedOptions.map(({ name, value }: SelectedOption) => + normalizeProductOption({ + id, + name, + values: [value], + }) + ), + }) + ) } -export function normalizeProduct(productNode: ShopifyProduct): any { +export function normalizeProduct(productNode: ShopifyProduct): Product { const { id, title: name, @@ -95,8 +114,8 @@ export function normalizeCart(checkout: Checkout): Cart { }, taxesIncluded: checkout.taxesIncluded, lineItems: checkout.lineItems?.edges.map(normalizeLineItem), - lineItemsSubtotalPrice: checkout.subtotalPriceV2?.amount, - subtotalPrice: checkout.subtotalPriceV2?.amount, + lineItemsSubtotalPrice: +checkout.subtotalPriceV2?.amount, + subtotalPrice: +checkout.subtotalPriceV2?.amount, totalPrice: checkout.totalPriceV2?.amount, discounts: [], } diff --git a/framework/shopify/utils/queries/get-all-products-query.ts b/framework/shopify/utils/queries/get-all-products-query.ts index 4a6c20b6e..5eb44c7a7 100644 --- a/framework/shopify/utils/queries/get-all-products-query.ts +++ b/framework/shopify/utils/queries/get-all-products-query.ts @@ -1,3 +1,38 @@ +export const productConnection = ` +pageInfo { + hasNextPage + hasPreviousPage +} +edges { + node { + id + title + vendor + handle + description + priceRange { + minVariantPrice { + amount + currencyCode + } + } + images(first: 1) { + pageInfo { + hasNextPage + hasPreviousPage + } + edges { + node { + originalSrc + altText + width + height + } + } + } + } +}` + export const productsFragment = ` products( first: $first @@ -5,39 +40,7 @@ products( reverse: $reverse query: $query ) { - pageInfo { - hasNextPage - hasPreviousPage - } - edges { - node { - id - title - vendor - handle - description - priceRange { - minVariantPrice { - amount - currencyCode - } - } - images(first: 1) { - pageInfo { - hasNextPage - hasPreviousPage - } - edges { - node { - originalSrc - altText - width - height - } - } - } - } - } + ${productConnection} } ` diff --git a/framework/shopify/utils/queries/get-collection-products-query.ts b/framework/shopify/utils/queries/get-collection-products-query.ts index dd504b575..04766caa4 100644 --- a/framework/shopify/utils/queries/get-collection-products-query.ts +++ b/framework/shopify/utils/queries/get-collection-products-query.ts @@ -1,16 +1,23 @@ -import { productsFragment } from './get-all-products-query' +import { productConnection } from './get-all-products-query' const getCollectionProductsQuery = /* GraphQL */ ` query getProductsFromCollection( - $categoryHandle: String! + $categoryId: ID! $first: Int = 250 - $query: String = "" - $sortKey: ProductSortKeys = RELEVANCE + $sortKey: ProductCollectionSortKeys = RELEVANCE $reverse: Boolean = false ) { - collectionByHandle(handle: $categoryHandle) - { - ${productsFragment} + node(id: $categoryId) { + id + ... on Collection { + products( + first: $first + sortKey: $sortKey + reverse: $reverse + ) { + ${productConnection} + } + } } } ` diff --git a/framework/shopify/utils/queries/get-page-query.ts b/framework/shopify/utils/queries/get-page-query.ts index dcafdc30d..2ca79abd4 100644 --- a/framework/shopify/utils/queries/get-page-query.ts +++ b/framework/shopify/utils/queries/get-page-query.ts @@ -1,12 +1,13 @@ export const getPageQuery = /* GraphQL */ ` - query getPageBySlug($slug: String!) { - pageByHandle(handle: $slug) { + query($id: ID!) { + node(id: $id) { id - title - handle - body - bodySummary - url + ... on Page { + title + handle + body + bodySummary + } } } ` diff --git a/framework/shopify/utils/queries/get-product-query.ts b/framework/shopify/utils/queries/get-product-query.ts index d054c023d..5c109901b 100644 --- a/framework/shopify/utils/queries/get-product-query.ts +++ b/framework/shopify/utils/queries/get-product-query.ts @@ -32,6 +32,7 @@ const getProductQuery = /* GraphQL */ ` node { id title + sku selectedOptions { name value diff --git a/framework/shopify/utils/to-commerce-products.ts b/framework/shopify/utils/to-commerce-products.ts deleted file mode 100644 index 84925e001..000000000 --- a/framework/shopify/utils/to-commerce-products.ts +++ /dev/null @@ -1,68 +0,0 @@ -// TODO: Fix the types in this file -// import { Product, Image } from '../types' - -type Product = any -type Image = any - -export default function toCommerceProducts(products: Product[]) { - return products.map((product: Product) => { - return { - id: product.id, - entityId: product.id, - name: product.title, - slug: product.handle, - title: product.title, - vendor: product.vendor, - description: product.descriptionHtml, - path: `/${product.handle}`, - price: { - value: +product.variants[0].price, - currencyCode: 'USD', // TODO - }, - images: product.images.map((image: Image) => { - return { - url: image.src, - } - }), - // TODO: Fix the variant type - variants: product.variants.map((variant: any) => { - return { - id: variant.id, - // TODO: Fix the selectedOption type - options: variant.selectedOptions.map((selectedOption: any) => { - return { - __typename: 'MultipleChoiceOption', - displayName: selectedOption.name, - values: [ - { - node: { - id: variant.id, - label: selectedOption.value, - }, - }, - ], - } - }), - } - }), - // TODO: Fix the option type - productOptions: product.options.map((option: any) => { - return { - __typename: 'MultipleChoiceOption', - displayName: option.name, - // TODO: Fix the value type - values: option.values.map((value: any) => { - return { - node: { - entityId: 1, - label: value.value, - hexColors: [value.value], - }, - } - }), - } - }), - options: [], - } - }) -} diff --git a/framework/shopify/wishlist/use-wishlist.tsx b/framework/shopify/wishlist/use-wishlist.tsx index 13632bb95..d2ce9db5b 100644 --- a/framework/shopify/wishlist/use-wishlist.tsx +++ b/framework/shopify/wishlist/use-wishlist.tsx @@ -2,9 +2,7 @@ // Shopify doesn't have a wishlist import { HookFetcher } from '@commerce/utils/types' -import useCommerceWishlist from '@commerce/wishlist/use-wishlist' import { Product } from '../schema' -import useCustomer from '../customer/use-customer' const defaultOpts = {}