mirror of
https://github.com/vercel/commerce.git
synced 2025-06-19 05:31:22 +00:00
Add translations, update operations & fixes
This commit is contained in:
parent
61db441df4
commit
9a126164b4
@ -5,7 +5,7 @@ import Link from 'next/link'
|
||||
import s from './CartItem.module.css'
|
||||
import { Trash, Plus, Minus } from '@components/icons'
|
||||
import { useUI } from '@components/ui/context'
|
||||
import type { LineItem } from '@framework/types'
|
||||
import type { LineItem } from '@framework/types/cart'
|
||||
import usePrice from '@framework/product/use-price'
|
||||
import useUpdateItem from '@framework/cart/use-update-item'
|
||||
import useRemoveItem from '@framework/cart/use-remove-item'
|
||||
|
@ -2,7 +2,7 @@ import { FC } from 'react'
|
||||
import cn from 'classnames'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import type { Page } from '@framework/common/get-all-pages'
|
||||
import type { Page } from '@framework/types/page'
|
||||
import getSlug from '@lib/get-slug'
|
||||
import { Github, Vercel } from '@components/icons'
|
||||
import { Logo, Container } from '@components/ui'
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { FC } from 'react'
|
||||
import Link from 'next/link'
|
||||
import type { Product } from '@commerce/types'
|
||||
import type { Product } from '@framework/types/product'
|
||||
import { Grid } from '@components/ui'
|
||||
import { ProductCard } from '@components/product'
|
||||
import s from './HomeAllProductsGrid.module.css'
|
||||
|
@ -11,7 +11,7 @@ import CartSidebarView from '@components/cart/CartSidebarView'
|
||||
|
||||
import LoginView from '@components/auth/LoginView'
|
||||
import { CommerceProvider } from '@framework'
|
||||
import type { Page } from '@framework/common/get-all-pages'
|
||||
import type { Page } from '@framework/types/page'
|
||||
|
||||
const Loading = () => (
|
||||
<div className="w-80 h-80 flex items-center text-center justify-center p-3">
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { FC } from 'react'
|
||||
import Link from 'next/link'
|
||||
import cn from 'classnames'
|
||||
import type { LineItem } from '@framework/types'
|
||||
import type { LineItem } from '@framework/types/cart'
|
||||
import useCart from '@framework/cart/use-cart'
|
||||
import useCustomer from '@framework/customer/use-customer'
|
||||
import { Avatar } from '@components/common'
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { FC } from 'react'
|
||||
import cn from 'classnames'
|
||||
import Link from 'next/link'
|
||||
import type { Product } from '@commerce/types'
|
||||
import type { Product } from '@framework/types/product'
|
||||
import s from './ProductCard.module.css'
|
||||
import Image, { ImageProps } from 'next/image'
|
||||
import WishlistButton from '@components/wishlist/WishlistButton'
|
||||
|
@ -5,7 +5,7 @@ import { FC, useEffect, useState } from 'react'
|
||||
import s from './ProductView.module.css'
|
||||
import { Swatch, ProductSlider } from '@components/product'
|
||||
import { Button, Container, Text, useUI } from '@components/ui'
|
||||
import type { Product } from '@commerce/types'
|
||||
import type { Product } from '@framework/types/product'
|
||||
import usePrice from '@framework/product/use-price'
|
||||
import { useAddItem } from '@framework/cart'
|
||||
import { getVariant, SelectedOptions } from '../helpers'
|
||||
|
@ -47,7 +47,7 @@ const Swatch: FC<Omit<ButtonProps, 'variant'> & Props> = ({
|
||||
<Check />
|
||||
</span>
|
||||
)}
|
||||
{variant === 'size' ? label : null}
|
||||
{variant !== 'color' ? label : null}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { Product } from '@commerce/types'
|
||||
import type { Product } from '@framework/types/product'
|
||||
export type SelectedOptions = Record<string, string | null>
|
||||
|
||||
export function getVariant(product: Product, opts: SelectedOptions) {
|
||||
|
@ -6,7 +6,7 @@ import useAddItem from '@framework/wishlist/use-add-item'
|
||||
import useCustomer from '@framework/customer/use-customer'
|
||||
import useWishlist from '@framework/wishlist/use-wishlist'
|
||||
import useRemoveItem from '@framework/wishlist/use-remove-item'
|
||||
import type { Product, ProductVariant } from '@commerce/types'
|
||||
import type { Product, ProductVariant } from '@framework/types/product'
|
||||
|
||||
type Props = {
|
||||
productId: Product['id']
|
||||
|
@ -7,7 +7,7 @@ import { Trash } from '@components/icons'
|
||||
import { Button, Text } from '@components/ui'
|
||||
|
||||
import { useUI } from '@components/ui/context'
|
||||
import type { Product } from '@commerce/types'
|
||||
import type { Product } from '@framework/types/product'
|
||||
import usePrice from '@framework/product/use-price'
|
||||
import useAddItem from '@framework/cart/use-add-item'
|
||||
import useRemoveItem from '@framework/wishlist/use-remove-item'
|
||||
@ -18,9 +18,9 @@ interface Props {
|
||||
|
||||
const WishlistCard: FC<Props> = ({ product }) => {
|
||||
const { price } = usePrice({
|
||||
amount: product.prices?.price?.value,
|
||||
baseAmount: product.prices?.retailPrice?.value,
|
||||
currencyCode: product.prices?.price?.currencyCode!,
|
||||
amount: product.price?.value,
|
||||
baseAmount: product.price?.retailPrice,
|
||||
currencyCode: product.price?.currencyCode!,
|
||||
})
|
||||
// @ts-ignore Wishlist is not always enabled
|
||||
const removeItem = useRemoveItem({ wishlist: { includeProducts: true } })
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { normalizeCart } from '@framework/lib/normalize'
|
||||
import { normalizeCart } from '../../../lib/normalize'
|
||||
import { parseCartItem } from '../../utils/parse-item'
|
||||
import getCartCookie from '../../utils/get-cart-cookie'
|
||||
import type { CartEndpoint } from '.'
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { normalizeCart } from '@framework/lib/normalize'
|
||||
import { normalizeCart } from '../../../lib/normalize'
|
||||
import { BigcommerceApiError } from '../../utils/errors'
|
||||
import getCartCookie from '../../utils/get-cart-cookie'
|
||||
import type { BigcommerceCart } from '../../../types'
|
||||
import type { BigcommerceCart } from '../../../types/cart'
|
||||
import type { CartEndpoint } from '.'
|
||||
|
||||
// Return current cart info
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { normalizeCart } from '@framework/lib/normalize'
|
||||
import { normalizeCart } from '../../../lib/normalize'
|
||||
import getCartCookie from '../../utils/get-cart-cookie'
|
||||
import type { CartEndpoint } from '.'
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { normalizeCart } from '@framework/lib/normalize'
|
||||
import { normalizeCart } from '../../../lib/normalize'
|
||||
import { parseCartItem } from '../../utils/parse-item'
|
||||
import getCartCookie from '../../utils/get-cart-cookie'
|
||||
import type { CartEndpoint } from '.'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { ItemBody as WishlistItemBody } from '../wishlist'
|
||||
import type { CartItemBody, OptionSelections } from '../../types'
|
||||
import type { WishlistItemBody } from '../../types/wishlist'
|
||||
import type { CartItemBody, OptionSelections } from '../../types/cart'
|
||||
|
||||
type BCWishlistItemBody = {
|
||||
product_id: number
|
||||
|
@ -6,7 +6,7 @@ import type {
|
||||
} from '@commerce/utils/types'
|
||||
import { ValidationError } from '@commerce/utils/errors'
|
||||
import useUpdateItem, { UseUpdateItem } from '@commerce/cart/use-update-item'
|
||||
import type { LineItem, UpdateItemHook } from '../types'
|
||||
import type { LineItem, UpdateItemHook } from '../types/cart'
|
||||
import { handler as removeItemHandler } from './use-remove-item'
|
||||
import useCart from './use-cart'
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { Product } from '@commerce/types'
|
||||
import type { Cart, BigcommerceCart, LineItem } from '../types'
|
||||
import type { Product } from '../types/product'
|
||||
import type { Cart, BigcommerceCart, LineItem } from '../types/cart'
|
||||
import update from './immutability'
|
||||
|
||||
function normalizeProductOption(productOption: any) {
|
||||
|
@ -9,6 +9,7 @@ export type SearchProductsInput = {
|
||||
categoryId?: number
|
||||
brandId?: number
|
||||
sort?: string
|
||||
locale?: string
|
||||
}
|
||||
|
||||
export const handler: SWRHook<SearchProductsHook> = {
|
||||
|
@ -148,6 +148,7 @@ export const createEndpoint = <API extends GetAPISchema<any, any>>(
|
||||
|
||||
export interface CommerceAPIConfig {
|
||||
locale?: string
|
||||
locales?: string[]
|
||||
commerceUrl: string
|
||||
apiToken: string
|
||||
cartCookie: string
|
||||
|
@ -6,35 +6,53 @@ import {
|
||||
useMemo,
|
||||
useRef,
|
||||
} from 'react'
|
||||
|
||||
import type {
|
||||
AddItemHook,
|
||||
GetCartHook,
|
||||
RemoveItemHook,
|
||||
UpdateItemHook,
|
||||
} from '@framework/types/cart'
|
||||
|
||||
import {
|
||||
AddItemHook as WishlistAddItemHook,
|
||||
GetWishlistHook,
|
||||
RemoveItemHook as WishlistRemoveItemHook,
|
||||
} from '@framework/types/wishlist'
|
||||
|
||||
import { CustomerHook } from '@framework/types/customer'
|
||||
import { LoginHook } from '@framework/types/login'
|
||||
import { LogoutHook } from '@framework/types/logout'
|
||||
import { SearchProductsHook } from '@framework/types/product'
|
||||
import { SignupHook } from '@framework/types/signup'
|
||||
|
||||
import { Fetcher, SWRHook, MutationHook } from './utils/types'
|
||||
import type { FetchCartInput } from './cart/use-cart'
|
||||
import type { Cart, Wishlist, Customer, SearchProductsData } from './types'
|
||||
|
||||
const Commerce = createContext<CommerceContextValue<any> | {}>({})
|
||||
|
||||
export type Provider = CommerceConfig & {
|
||||
fetcher: Fetcher
|
||||
cart?: {
|
||||
useCart?: SWRHook<Cart | null, any, FetchCartInput>
|
||||
useAddItem?: MutationHook<any, any, any>
|
||||
useUpdateItem?: MutationHook<any, any, any>
|
||||
useRemoveItem?: MutationHook<any, any, any>
|
||||
useCart?: SWRHook<GetCartHook>
|
||||
useAddItem?: MutationHook<AddItemHook>
|
||||
useUpdateItem?: MutationHook<UpdateItemHook>
|
||||
useRemoveItem?: MutationHook<RemoveItemHook>
|
||||
}
|
||||
wishlist?: {
|
||||
useWishlist?: SWRHook<Wishlist | null, any, any>
|
||||
useAddItem?: MutationHook<any, any, any>
|
||||
useRemoveItem?: MutationHook<any, any, any>
|
||||
useWishlist?: SWRHook<GetWishlistHook>
|
||||
useAddItem?: MutationHook<WishlistAddItemHook>
|
||||
useRemoveItem?: MutationHook<WishlistRemoveItemHook>
|
||||
}
|
||||
customer?: {
|
||||
useCustomer?: SWRHook<Customer | null, any, any>
|
||||
useCustomer?: SWRHook<CustomerHook>
|
||||
}
|
||||
products?: {
|
||||
useSearch?: SWRHook<SearchProductsData, any, any>
|
||||
useSearch?: SWRHook<SearchProductsHook>
|
||||
}
|
||||
auth?: {
|
||||
useSignup?: MutationHook<any, any, any>
|
||||
useLogin?: MutationHook<any, any, any>
|
||||
useLogout?: MutationHook<any, any, any>
|
||||
useSignup?: MutationHook<SignupHook>
|
||||
useLogin?: MutationHook<LoginHook>
|
||||
useLogout?: MutationHook<LogoutHook>
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,8 @@ export type ProductPrice = {
|
||||
}
|
||||
|
||||
export type ProductOption = {
|
||||
__typename: 'MultipleChoiceOption'
|
||||
id: string
|
||||
displayName: string
|
||||
values: ProductOptionValues[]
|
||||
}
|
||||
@ -47,6 +49,7 @@ export type SearchProductsBody = {
|
||||
categoryId?: string
|
||||
brandId?: string
|
||||
sort?: string
|
||||
locale?: string
|
||||
}
|
||||
|
||||
export type ProductTypes = {
|
||||
|
@ -4,7 +4,12 @@ import {
|
||||
getCommerceApi as commerceApi,
|
||||
} from '@commerce/api'
|
||||
|
||||
import { API_URL, API_TOKEN, SHOPIFY_CUSTOMER_TOKEN_COOKIE } from '../const'
|
||||
import {
|
||||
API_URL,
|
||||
API_TOKEN,
|
||||
SHOPIFY_CUSTOMER_TOKEN_COOKIE,
|
||||
SHOPIFY_CHECKOUT_ID_COOKIE,
|
||||
} from '../const'
|
||||
|
||||
import fetchGraphqlApi from './utils/fetch-graphql-api'
|
||||
|
||||
@ -29,7 +34,7 @@ const config: ShopifyConfig = {
|
||||
commerceUrl: API_URL,
|
||||
apiToken: API_TOKEN,
|
||||
customerCookie: SHOPIFY_CUSTOMER_TOKEN_COOKIE,
|
||||
cartCookie: process.env.SHOPIFY_CART_COOKIE ?? 'shopify_checkoutId',
|
||||
cartCookie: SHOPIFY_CHECKOUT_ID_COOKIE,
|
||||
cartCookieMaxAge: ONE_DAY * 30,
|
||||
fetch: fetchGraphqlApi,
|
||||
}
|
||||
@ -46,6 +51,5 @@ export type ShopifyAPI<P extends Provider = Provider> = CommerceAPI<P>
|
||||
export function getCommerceApi<P extends Provider>(
|
||||
customProvider: P = provider as any
|
||||
): ShopifyAPI<P> {
|
||||
console.log(customProvider)
|
||||
return commerceApi(customProvider)
|
||||
}
|
||||
|
@ -2,9 +2,14 @@ import type {
|
||||
OperationContext,
|
||||
OperationOptions,
|
||||
} from '@commerce/api/operations'
|
||||
import { GetAllPagesQuery, GetAllPagesQueryVariables } from '@framework/schema'
|
||||
import {
|
||||
GetAllPagesQuery,
|
||||
GetAllPagesQueryVariables,
|
||||
PageEdge,
|
||||
} from '@framework/schema'
|
||||
import { normalizePages } from '@framework/utils'
|
||||
import type { ShopifyConfig, Provider } from '..'
|
||||
import { GetAllPagesOperation } from '../../types/page'
|
||||
import type { GetAllPagesOperation, Page } from '../../types/page'
|
||||
import getAllPagesQuery from '../../utils/queries/get-all-pages-query'
|
||||
|
||||
export default function getAllPagesOperation({
|
||||
@ -25,21 +30,36 @@ export default function getAllPagesOperation({
|
||||
async function getAllPages<T extends GetAllPagesOperation>({
|
||||
query = getAllPagesQuery,
|
||||
config,
|
||||
variables,
|
||||
}: {
|
||||
url?: string
|
||||
config?: Partial<ShopifyConfig>
|
||||
variables?: GetAllPagesQueryVariables
|
||||
preview?: boolean
|
||||
query?: string
|
||||
} = {}): Promise<T['data']> {
|
||||
const cfg = commerce.getConfig(config)
|
||||
const { fetch, locale, locales = ['en-US'] } = commerce.getConfig(config)
|
||||
|
||||
const { data } = await cfg.fetch<
|
||||
GetAllPagesQuery,
|
||||
GetAllPagesQueryVariables
|
||||
>(query)
|
||||
const { data } = await fetch<GetAllPagesQuery, GetAllPagesQueryVariables>(
|
||||
query,
|
||||
{
|
||||
variables,
|
||||
},
|
||||
{
|
||||
...(locale && {
|
||||
headers: {
|
||||
'Accept-Language': locale,
|
||||
},
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
pages: data.pages.edges,
|
||||
pages: locales.reduce<Page[]>(
|
||||
(arr, locale) =>
|
||||
arr.concat(normalizePages(data.pages.edges as PageEdge[], locale)),
|
||||
[]
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,12 +39,22 @@ export default function getAllProductsOperation({
|
||||
config?: Partial<ShopifyConfig>
|
||||
preview?: boolean
|
||||
} = {}): Promise<T['data']> {
|
||||
const cfg = commerce.getConfig(config)
|
||||
const { fetch, locale } = commerce.getConfig(config)
|
||||
|
||||
const { data } = await cfg.fetch<
|
||||
const { data } = await fetch<
|
||||
GetAllProductsQuery,
|
||||
GetAllProductsQueryVariables
|
||||
>(query, { variables })
|
||||
>(
|
||||
query,
|
||||
{ variables },
|
||||
{
|
||||
...(locale && {
|
||||
headers: {
|
||||
'Accept-Language': locale,
|
||||
},
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
products: data.products.edges.map(({ node }) =>
|
||||
|
@ -35,11 +35,23 @@ export default function getPageOperation({
|
||||
config?: Partial<ShopifyConfig>
|
||||
preview?: boolean
|
||||
}): Promise<T['data']> {
|
||||
const cfg = commerce.getConfig(config)
|
||||
const { fetch, locale } = commerce.getConfig(config)
|
||||
|
||||
const {
|
||||
data: { node: page },
|
||||
} = await cfg.fetch<GetPageQuery, GetPageQueryVariables>(query)
|
||||
} = await fetch<GetPageQuery, GetPageQueryVariables>(
|
||||
query,
|
||||
{
|
||||
variables,
|
||||
},
|
||||
{
|
||||
...(locale && {
|
||||
headers: {
|
||||
'Accept-Language': locale,
|
||||
},
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
return page ? { page } : {}
|
||||
}
|
||||
|
@ -20,13 +20,23 @@ export default function getProductOperation({
|
||||
config?: ShopifyConfig
|
||||
variables?: GetProductBySlugQueryVariables
|
||||
} = {}): Promise<T['data']> {
|
||||
config = commerce.getConfig(config)
|
||||
const { fetch, locale } = commerce.getConfig(config)
|
||||
|
||||
const {
|
||||
data: { productByHandle },
|
||||
} = await config.fetch<GetProductBySlugQuery>(query, {
|
||||
variables,
|
||||
})
|
||||
} = await fetch<GetProductBySlugQuery>(
|
||||
query,
|
||||
{
|
||||
variables,
|
||||
},
|
||||
{
|
||||
...(locale && {
|
||||
headers: {
|
||||
'Accept-Language': locale,
|
||||
},
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
...(productByHandle && {
|
||||
|
@ -26,20 +26,31 @@ export default function getSiteInfoOperation({
|
||||
async function getSiteInfo<T extends GetSiteInfoOperation>({
|
||||
query = getSiteInfoQuery,
|
||||
config,
|
||||
variables,
|
||||
}: {
|
||||
query?: string
|
||||
config?: Partial<ShopifyConfig>
|
||||
preview?: boolean
|
||||
variables?: GetSiteInfoQueryVariables
|
||||
} = {}): Promise<T['data']> {
|
||||
const cfg = commerce.getConfig(config)
|
||||
|
||||
const categories = await getCategories(cfg)
|
||||
const brands = await getBrands(cfg)
|
||||
|
||||
const { data } = await cfg.fetch<
|
||||
GetSiteInfoQuery,
|
||||
GetSiteInfoQueryVariables
|
||||
>(query)
|
||||
/*
|
||||
const { fetch, locale } = cfg
|
||||
const { data } = await fetch<GetSiteInfoQuery, GetSiteInfoQueryVariables>(
|
||||
query,
|
||||
{ variables },
|
||||
{
|
||||
...(locale && {
|
||||
headers: {
|
||||
'Accept-Language': locale,
|
||||
},
|
||||
}),
|
||||
}
|
||||
)
|
||||
*/
|
||||
|
||||
return {
|
||||
categories,
|
||||
|
@ -2,18 +2,19 @@ import { useCallback } from 'react'
|
||||
import type { MutationHook } from '@commerce/utils/types'
|
||||
import { CommerceError } from '@commerce/utils/errors'
|
||||
import useAddItem, { UseAddItem } from '@commerce/cart/use-add-item'
|
||||
import type { AddItemHook } from '../types/cart'
|
||||
import useCart from './use-cart'
|
||||
|
||||
import {
|
||||
checkoutLineItemAddMutation,
|
||||
getCheckoutId,
|
||||
checkoutToCart,
|
||||
} from '../utils'
|
||||
import { Cart, CartItemBody } from '../types'
|
||||
import { Mutation, MutationCheckoutLineItemsAddArgs } from '../schema'
|
||||
|
||||
export default useAddItem as UseAddItem<typeof handler>
|
||||
|
||||
export const handler: MutationHook<Cart, {}, CartItemBody> = {
|
||||
export const handler: MutationHook<AddItemHook> = {
|
||||
fetchOptions: {
|
||||
query: checkoutLineItemAddMutation,
|
||||
},
|
||||
|
@ -1,22 +1,14 @@
|
||||
import { useMemo } from 'react'
|
||||
import useCommerceCart, {
|
||||
FetchCartInput,
|
||||
UseCart,
|
||||
} from '@commerce/cart/use-cart'
|
||||
import useCommerceCart, { UseCart } from '@commerce/cart/use-cart'
|
||||
|
||||
import { Cart } from '../types'
|
||||
import { SWRHook } from '@commerce/utils/types'
|
||||
import { checkoutCreate, checkoutToCart } from '../utils'
|
||||
import getCheckoutQuery from '../utils/queries/get-checkout-query'
|
||||
import { GetCartHook } from '../types/cart'
|
||||
|
||||
export default useCommerceCart as UseCart<typeof handler>
|
||||
|
||||
export const handler: SWRHook<
|
||||
Cart | null,
|
||||
{},
|
||||
FetchCartInput,
|
||||
{ isEmpty?: boolean }
|
||||
> = {
|
||||
export const handler: SWRHook<GetCartHook> = {
|
||||
fetchOptions: {
|
||||
query: getCheckoutQuery,
|
||||
},
|
||||
|
@ -3,31 +3,29 @@ import type {
|
||||
MutationHookContext,
|
||||
HookFetcherContext,
|
||||
} from '@commerce/utils/types'
|
||||
import { RemoveCartItemBody } from '@commerce/types'
|
||||
import { ValidationError } from '@commerce/utils/errors'
|
||||
import useRemoveItem, {
|
||||
RemoveItemInput as RemoveItemInputBase,
|
||||
UseRemoveItem,
|
||||
} from '@commerce/cart/use-remove-item'
|
||||
import useRemoveItem, { UseRemoveItem } from '@commerce/cart/use-remove-item'
|
||||
import type { Cart, LineItem, RemoveItemHook } from '../types/cart'
|
||||
import useCart from './use-cart'
|
||||
|
||||
export type RemoveItemFn<T = any> = T extends LineItem
|
||||
? (input?: RemoveItemActionInput<T>) => Promise<Cart | null>
|
||||
: (input: RemoveItemActionInput<T>) => Promise<Cart | null>
|
||||
|
||||
export type RemoveItemActionInput<T = any> = T extends LineItem
|
||||
? Partial<RemoveItemHook['actionInput']>
|
||||
: RemoveItemHook['actionInput']
|
||||
|
||||
export default useRemoveItem as UseRemoveItem<typeof handler>
|
||||
|
||||
import {
|
||||
checkoutLineItemRemoveMutation,
|
||||
getCheckoutId,
|
||||
checkoutToCart,
|
||||
} from '../utils'
|
||||
import { Cart, LineItem } from '../types'
|
||||
|
||||
import { Mutation, MutationCheckoutLineItemsRemoveArgs } from '../schema'
|
||||
|
||||
export type RemoveItemFn<T = any> = T extends LineItem
|
||||
? (input?: RemoveItemInput<T>) => Promise<Cart | null>
|
||||
: (input: RemoveItemInput<T>) => Promise<Cart | null>
|
||||
|
||||
export type RemoveItemInput<T = any> = T extends LineItem
|
||||
? Partial<RemoveItemInputBase>
|
||||
: RemoveItemInputBase
|
||||
|
||||
export default useRemoveItem as UseRemoveItem<typeof handler>
|
||||
|
||||
export const handler = {
|
||||
fetchOptions: {
|
||||
query: checkoutLineItemRemoveMutation,
|
||||
@ -36,16 +34,14 @@ export const handler = {
|
||||
input: { itemId },
|
||||
options,
|
||||
fetch,
|
||||
}: HookFetcherContext<RemoveCartItemBody>) {
|
||||
}: HookFetcherContext<RemoveItemHook>) {
|
||||
const data = await fetch<Mutation, MutationCheckoutLineItemsRemoveArgs>({
|
||||
...options,
|
||||
variables: { checkoutId: getCheckoutId(), lineItemIds: [itemId] },
|
||||
})
|
||||
return checkoutToCart(data.checkoutLineItemsRemove)
|
||||
},
|
||||
useHook: ({
|
||||
fetch,
|
||||
}: MutationHookContext<Cart | null, RemoveCartItemBody>) => <
|
||||
useHook: ({ fetch }: MutationHookContext<RemoveItemHook>) => <
|
||||
T extends LineItem | undefined = undefined
|
||||
>(
|
||||
ctx: { item?: T } = {}
|
||||
|
@ -5,21 +5,21 @@ import type {
|
||||
MutationHookContext,
|
||||
} from '@commerce/utils/types'
|
||||
import { ValidationError } from '@commerce/utils/errors'
|
||||
import useUpdateItem, {
|
||||
UpdateItemInput as UpdateItemInputBase,
|
||||
UseUpdateItem,
|
||||
} from '@commerce/cart/use-update-item'
|
||||
import useUpdateItem, { UseUpdateItem } from '@commerce/cart/use-update-item'
|
||||
|
||||
import useCart from './use-cart'
|
||||
import { handler as removeItemHandler } from './use-remove-item'
|
||||
import type { Cart, LineItem, UpdateCartItemBody } from '../types'
|
||||
import { checkoutToCart } from '../utils'
|
||||
import { getCheckoutId, checkoutLineItemUpdateMutation } from '../utils'
|
||||
import type { UpdateItemHook, LineItem } from '../types/cart'
|
||||
import {
|
||||
getCheckoutId,
|
||||
checkoutLineItemUpdateMutation,
|
||||
checkoutToCart,
|
||||
} from '../utils'
|
||||
import { Mutation, MutationCheckoutLineItemsUpdateArgs } from '../schema'
|
||||
|
||||
export type UpdateItemInput<T = any> = T extends LineItem
|
||||
? Partial<UpdateItemInputBase<LineItem>>
|
||||
: UpdateItemInputBase<LineItem>
|
||||
export type UpdateItemActionInput<T = any> = T extends LineItem
|
||||
? Partial<UpdateItemHook['actionInput']>
|
||||
: UpdateItemHook['actionInput']
|
||||
|
||||
export default useUpdateItem as UseUpdateItem<typeof handler>
|
||||
|
||||
@ -31,7 +31,7 @@ export const handler = {
|
||||
input: { itemId, item },
|
||||
options,
|
||||
fetch,
|
||||
}: HookFetcherContext<UpdateCartItemBody>) {
|
||||
}: HookFetcherContext<UpdateItemHook>) {
|
||||
if (Number.isInteger(item.quantity)) {
|
||||
// Also allow the update hook to remove an item if the quantity is lower than 1
|
||||
if (item.quantity! < 1) {
|
||||
@ -64,9 +64,7 @@ export const handler = {
|
||||
|
||||
return checkoutToCart(checkoutLineItemsUpdate)
|
||||
},
|
||||
useHook: ({
|
||||
fetch,
|
||||
}: MutationHookContext<Cart | null, UpdateCartItemBody>) => <
|
||||
useHook: ({ fetch }: MutationHookContext<UpdateItemHook>) => <
|
||||
T extends LineItem | undefined = undefined
|
||||
>(
|
||||
ctx: {
|
||||
@ -78,7 +76,7 @@ export const handler = {
|
||||
const { mutate } = useCart() as any
|
||||
|
||||
return useCallback(
|
||||
debounce(async (input: UpdateItemInput<T>) => {
|
||||
debounce(async (input: UpdateItemActionInput<T>) => {
|
||||
const itemId = input.id ?? item?.id
|
||||
const productId = input.productId ?? item?.productId
|
||||
const variantId = input.productId ?? item?.variantId
|
||||
|
@ -1,18 +1,19 @@
|
||||
import useCustomer, { UseCustomer } from '@commerce/customer/use-customer'
|
||||
import { Customer } from '@commerce/types'
|
||||
import type { CustomerHook } from '../types/customer'
|
||||
import { SWRHook } from '@commerce/utils/types'
|
||||
import { getCustomerQuery, getCustomerToken } from '../utils'
|
||||
import { GetCustomerQuery, GetCustomerQueryVariables } from '../schema'
|
||||
|
||||
export default useCustomer as UseCustomer<typeof handler>
|
||||
|
||||
export const handler: SWRHook<Customer | null> = {
|
||||
export const handler: SWRHook<CustomerHook> = {
|
||||
fetchOptions: {
|
||||
query: getCustomerQuery,
|
||||
},
|
||||
async fetcher({ options, fetch }) {
|
||||
const customerAccessToken = getCustomerToken()
|
||||
if (customerAccessToken) {
|
||||
const data = await fetch({
|
||||
const data = await fetch<GetCustomerQuery, GetCustomerQueryVariables>({
|
||||
...options,
|
||||
variables: { customerAccessToken: getCustomerToken() },
|
||||
})
|
||||
|
@ -8,13 +8,17 @@ const fetcher: Fetcher = async ({
|
||||
variables,
|
||||
query,
|
||||
}) => {
|
||||
const { locale, ...vars } = variables
|
||||
return handleFetchResponse(
|
||||
await fetch(url, {
|
||||
method,
|
||||
body: JSON.stringify({ query, variables }),
|
||||
body: JSON.stringify({ query, variables: vars }),
|
||||
headers: {
|
||||
'X-Shopify-Storefront-Access-Token': API_TOKEN!,
|
||||
'Content-Type': 'application/json',
|
||||
...(locale && {
|
||||
'Accept-Language': locale,
|
||||
}),
|
||||
},
|
||||
})
|
||||
)
|
||||
|
@ -4,9 +4,11 @@ import useSearch, { UseSearch } from '@commerce/product/use-search'
|
||||
import {
|
||||
CollectionEdge,
|
||||
GetAllProductsQuery,
|
||||
GetProductsFromCollectionQueryVariables,
|
||||
Product as ShopifyProduct,
|
||||
ProductEdge,
|
||||
} from '../schema'
|
||||
|
||||
import {
|
||||
getAllProductsQuery,
|
||||
getCollectionProductsQuery,
|
||||
@ -14,27 +16,19 @@ import {
|
||||
normalizeProduct,
|
||||
} from '../utils'
|
||||
|
||||
import { Product } from '@commerce/types'
|
||||
|
||||
export default useSearch as UseSearch<typeof handler>
|
||||
import type { SearchProductsHook } from '../types/product'
|
||||
|
||||
export type SearchProductsInput = {
|
||||
search?: string
|
||||
categoryId?: string
|
||||
brandId?: string
|
||||
categoryId?: number
|
||||
brandId?: number
|
||||
sort?: string
|
||||
locale?: string
|
||||
}
|
||||
|
||||
export type SearchProductsData = {
|
||||
products: Product[]
|
||||
found: boolean
|
||||
}
|
||||
export default useSearch as UseSearch<typeof handler>
|
||||
|
||||
export const handler: SWRHook<
|
||||
SearchProductsData,
|
||||
SearchProductsInput,
|
||||
SearchProductsInput
|
||||
> = {
|
||||
export const handler: SWRHook<SearchProductsHook> = {
|
||||
fetchOptions: {
|
||||
query: getAllProductsQuery,
|
||||
},
|
||||
@ -46,7 +40,10 @@ export const handler: SWRHook<
|
||||
|
||||
// change the query to getCollectionProductsQuery when categoryId is set
|
||||
if (categoryId) {
|
||||
const data = await fetch<CollectionEdge>({
|
||||
const data = await fetch<
|
||||
CollectionEdge,
|
||||
GetProductsFromCollectionQueryVariables
|
||||
>({
|
||||
query: getCollectionProductsQuery,
|
||||
method,
|
||||
variables,
|
||||
@ -81,6 +78,7 @@ export const handler: SWRHook<
|
||||
['categoryId', input.categoryId],
|
||||
['brandId', input.brandId],
|
||||
['sort', input.sort],
|
||||
['locale', input.locale],
|
||||
],
|
||||
swrOptions: {
|
||||
revalidateOnFocus: false,
|
||||
|
@ -24,4 +24,4 @@ export const shopifyProvider = {
|
||||
auth: { useLogin, useLogout, useSignup },
|
||||
}
|
||||
|
||||
export type ShopifyProvider = typeof shopifyProvider
|
||||
export type ShopifyProvider = any
|
||||
|
@ -10,23 +10,10 @@ export type ShopifyCart = {}
|
||||
|
||||
export type Cart = Core.Cart & {
|
||||
lineItems: Core.LineItem[]
|
||||
url?: string
|
||||
}
|
||||
|
||||
export type OptionSelections = {
|
||||
option_id: number
|
||||
option_value: number | string
|
||||
}
|
||||
|
||||
export type CartItemBody = Core.CartItemBody & {
|
||||
productId: string // The product id is always required for BC
|
||||
optionSelections?: OptionSelections
|
||||
}
|
||||
|
||||
export type CartTypes = {
|
||||
cart: Cart
|
||||
item: Core.LineItem
|
||||
itemBody: CartItemBody
|
||||
}
|
||||
export type CartTypes = Core.CartTypes
|
||||
|
||||
export type CartHooks = Core.CartHooks<CartTypes>
|
||||
|
||||
|
1
framework/shopify/types/checkout.ts
Normal file
1
framework/shopify/types/checkout.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from '@commerce/types/checkout'
|
1
framework/shopify/types/common.ts
Normal file
1
framework/shopify/types/common.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from '@commerce/types/common'
|
@ -1,2 +1,25 @@
|
||||
export * from '@commerce/types'
|
||||
export * from './cart'
|
||||
import * as Cart from './cart'
|
||||
import * as Checkout from './checkout'
|
||||
import * as Common from './common'
|
||||
import * as Customer from './customer'
|
||||
import * as Login from './login'
|
||||
import * as Logout from './logout'
|
||||
import * as Page from './page'
|
||||
import * as Product from './product'
|
||||
import * as Signup from './signup'
|
||||
import * as Site from './site'
|
||||
import * as Wishlist from './wishlist'
|
||||
|
||||
export type {
|
||||
Cart,
|
||||
Checkout,
|
||||
Common,
|
||||
Customer,
|
||||
Login,
|
||||
Logout,
|
||||
Page,
|
||||
Product,
|
||||
Signup,
|
||||
Site,
|
||||
Wishlist,
|
||||
}
|
||||
|
1
framework/shopify/types/wishlist.ts
Normal file
1
framework/shopify/types/wishlist.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from '@commerce/types/wishlist'
|
@ -8,12 +8,25 @@ export type Category = {
|
||||
path: string
|
||||
}
|
||||
|
||||
const getCategories = async (config: ShopifyConfig): Promise<Category[]> => {
|
||||
const { data } = await config.fetch(getSiteCollectionsQuery, {
|
||||
variables: {
|
||||
first: 250,
|
||||
const getCategories = async ({
|
||||
fetch,
|
||||
locale,
|
||||
}: ShopifyConfig): Promise<Category[]> => {
|
||||
const { data } = await fetch(
|
||||
getSiteCollectionsQuery,
|
||||
{
|
||||
variables: {
|
||||
first: 250,
|
||||
},
|
||||
},
|
||||
})
|
||||
{
|
||||
...(locale && {
|
||||
headers: {
|
||||
'Accept-Language': locale,
|
||||
},
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
return (
|
||||
data.collections?.edges?.map(
|
||||
|
@ -1,12 +1,13 @@
|
||||
import getSortVariables from './get-sort-variables'
|
||||
import type { SearchProductsInput } from '../product/use-search'
|
||||
import { SearchProductsBody } from '../types/product'
|
||||
|
||||
export const getSearchVariables = ({
|
||||
brandId,
|
||||
search,
|
||||
categoryId,
|
||||
sort,
|
||||
}: SearchProductsInput) => {
|
||||
locale,
|
||||
}: SearchProductsBody) => {
|
||||
let query = ''
|
||||
|
||||
if (search) {
|
||||
@ -21,6 +22,9 @@ export const getSearchVariables = ({
|
||||
categoryId,
|
||||
query,
|
||||
...getSortVariables(sort, !!categoryId),
|
||||
...(locale && {
|
||||
locale,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { Product } from '@commerce/types'
|
||||
import type { Page } from '../types/page'
|
||||
import type { Product } from '../types/product'
|
||||
import type { Cart, LineItem } from '../types/cart'
|
||||
|
||||
import {
|
||||
Product as ShopifyProduct,
|
||||
@ -9,10 +11,10 @@ import {
|
||||
ProductVariantConnection,
|
||||
MoneyV2,
|
||||
ProductOption,
|
||||
Page as ShopifyPage,
|
||||
PageEdge,
|
||||
} from '../schema'
|
||||
|
||||
import type { Cart, LineItem } from '../types'
|
||||
|
||||
const money = ({ amount, currencyCode }: MoneyV2) => {
|
||||
return {
|
||||
value: +amount,
|
||||
@ -152,12 +154,18 @@ function normalizeLineItem({
|
||||
discounts: [],
|
||||
options:
|
||||
// By default Shopify adds a default variant with default names, we're removing it. https://community.shopify.com/c/Shopify-APIs-SDKs/Adding-new-product-variant-is-automatically-adding-quot-Default/td-p/358095
|
||||
variant?.title == 'Default Title'
|
||||
? []
|
||||
: [
|
||||
{
|
||||
value: variant?.title,
|
||||
},
|
||||
],
|
||||
variant?.title == 'Default Title' ? [] : variant?.selectedOptions,
|
||||
}
|
||||
}
|
||||
|
||||
export const normalizePage = (
|
||||
{ title: name, handle, ...page }: ShopifyPage,
|
||||
locale: string
|
||||
): Page => ({
|
||||
...page,
|
||||
url: `/${locale}/${handle}`,
|
||||
name,
|
||||
})
|
||||
|
||||
export const normalizePages = (edges: PageEdge[], locale: string): Page[] =>
|
||||
edges?.map((edge) => normalizePage(edge.node, locale))
|
||||
|
@ -14,8 +14,9 @@ export async function getStaticProps({
|
||||
preview,
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
}: GetStaticPropsContext<{ pages: string[] }>) {
|
||||
const config = { locale }
|
||||
const config = { locale, locales }
|
||||
const { pages } = await commerce.getAllPages({ preview, config })
|
||||
const path = params?.pages.join('/')
|
||||
const slug = locale ? `${locale}/${path}` : path
|
||||
@ -42,7 +43,8 @@ export async function getStaticProps({
|
||||
}
|
||||
|
||||
export async function getStaticPaths({ locales }: GetStaticPathsContext) {
|
||||
const { pages } = await commerce.getAllPages()
|
||||
const config = { locales }
|
||||
const { pages } = await commerce.getAllPages({ config })
|
||||
const [invalidPaths, log] = missingLocaleInPages()
|
||||
const paths = pages
|
||||
.map((page) => page.url)
|
||||
|
@ -6,8 +6,9 @@ import { Container } from '@components/ui'
|
||||
export async function getStaticProps({
|
||||
preview,
|
||||
locale,
|
||||
locales,
|
||||
}: GetStaticPropsContext) {
|
||||
const config = { locale }
|
||||
const config = { locale, locales }
|
||||
const { pages } = await commerce.getAllPages({ config, preview })
|
||||
return {
|
||||
props: { pages },
|
||||
|
@ -10,8 +10,9 @@ import { CartItem } from '@components/cart'
|
||||
export async function getStaticProps({
|
||||
preview,
|
||||
locale,
|
||||
locales,
|
||||
}: GetStaticPropsContext) {
|
||||
const config = { locale }
|
||||
const config = { locale, locales }
|
||||
const { pages } = await commerce.getAllPages({ config, preview })
|
||||
return {
|
||||
props: { pages },
|
||||
|
@ -8,8 +8,9 @@ import type { GetStaticPropsContext, InferGetStaticPropsType } from 'next'
|
||||
export async function getStaticProps({
|
||||
preview,
|
||||
locale,
|
||||
locales,
|
||||
}: GetStaticPropsContext) {
|
||||
const config = { locale }
|
||||
const config = { locale, locales }
|
||||
const { products } = await commerce.getAllProducts({
|
||||
variables: { first: 12 },
|
||||
config,
|
||||
|
@ -7,8 +7,9 @@ import { Container, Text } from '@components/ui'
|
||||
export async function getStaticProps({
|
||||
preview,
|
||||
locale,
|
||||
locales,
|
||||
}: GetStaticPropsContext) {
|
||||
const config = { locale }
|
||||
const config = { locale, locales }
|
||||
const { pages } = await commerce.getAllPages({ config, preview })
|
||||
return {
|
||||
props: { pages },
|
||||
|
@ -11,9 +11,10 @@ import { ProductView } from '@components/product'
|
||||
export async function getStaticProps({
|
||||
params,
|
||||
locale,
|
||||
locales,
|
||||
preview,
|
||||
}: GetStaticPropsContext<{ slug: string }>) {
|
||||
const config = { locale }
|
||||
const config = { locale, locales }
|
||||
const { pages } = await commerce.getAllPages({ config, preview })
|
||||
const { product } = await commerce.getProduct({
|
||||
variables: { slug: params!.slug },
|
||||
|
@ -7,8 +7,9 @@ import { Container, Text } from '@components/ui'
|
||||
export async function getStaticProps({
|
||||
preview,
|
||||
locale,
|
||||
locales,
|
||||
}: GetStaticPropsContext) {
|
||||
const config = { locale }
|
||||
const config = { locale, locales }
|
||||
const { pages } = await commerce.getAllPages({ config, preview })
|
||||
return {
|
||||
props: { pages },
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
getDesignerPath,
|
||||
useSearchMeta,
|
||||
} from '@lib/search'
|
||||
import { Product } from '@commerce/types'
|
||||
import type { Product } from '@framework/types/product'
|
||||
|
||||
// TODO(bc) Remove this. This should come from the API
|
||||
import getSlug from '@lib/get-slug'
|
||||
@ -34,8 +34,9 @@ const SORT = Object.entries({
|
||||
export async function getStaticProps({
|
||||
preview,
|
||||
locale,
|
||||
locales,
|
||||
}: GetStaticPropsContext) {
|
||||
const config = { locale }
|
||||
const config = { locale, locales }
|
||||
const { pages } = await commerce.getAllPages({ config, preview })
|
||||
const { categories, brands } = await commerce.getSiteInfo({ config, preview })
|
||||
return {
|
||||
@ -55,7 +56,7 @@ export default function Search({
|
||||
const [toggleFilter, setToggleFilter] = useState(false)
|
||||
|
||||
const router = useRouter()
|
||||
const { asPath } = router
|
||||
const { asPath, locale } = router
|
||||
const { q, sort } = router.query
|
||||
// `q` can be included but because categories and designers can't be searched
|
||||
// in the same way of products, it's better to ignore the search input if one
|
||||
@ -75,6 +76,7 @@ export default function Search({
|
||||
categoryId: activeCategory?.entityId,
|
||||
brandId: activeBrand?.entityId,
|
||||
sort: typeof sort === 'string' ? sort : '',
|
||||
locale,
|
||||
})
|
||||
|
||||
const handleClick = (event: any, filter: string) => {
|
||||
|
@ -11,6 +11,7 @@ import useWishlist from '@framework/wishlist/use-wishlist'
|
||||
export async function getStaticProps({
|
||||
preview,
|
||||
locale,
|
||||
locales,
|
||||
}: GetStaticPropsContext) {
|
||||
// Disabling page if Feature is not available
|
||||
if (!process.env.COMMERCE_WISHLIST_ENABLED) {
|
||||
@ -19,7 +20,7 @@ export async function getStaticProps({
|
||||
}
|
||||
}
|
||||
|
||||
const config = { locale }
|
||||
const config = { locale, locales }
|
||||
const { pages } = await commerce.getAllPages({ config, preview })
|
||||
return {
|
||||
props: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user