Add translations, update operations & fixes

This commit is contained in:
cond0r 2021-05-26 14:02:23 +03:00
parent 61db441df4
commit 9a126164b4
53 changed files with 306 additions and 177 deletions

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -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">

View File

@ -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'

View File

@ -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'

View File

@ -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'

View File

@ -47,7 +47,7 @@ const Swatch: FC<Omit<ButtonProps, 'variant'> & Props> = ({
<Check />
</span>
)}
{variant === 'size' ? label : null}
{variant !== 'color' ? label : null}
</Button>
)
}

View File

@ -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) {

View File

@ -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']

View File

@ -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 } })

View File

@ -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 '.'

View File

@ -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

View File

@ -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 '.'

View File

@ -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 '.'

View File

@ -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

View File

@ -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'

View File

@ -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) {

View File

@ -9,6 +9,7 @@ export type SearchProductsInput = {
categoryId?: number
brandId?: number
sort?: string
locale?: string
}
export const handler: SWRHook<SearchProductsHook> = {

View File

@ -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

View File

@ -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>
}
}

View File

@ -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 = {

View File

@ -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)
}

View File

@ -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)),
[]
),
}
}

View File

@ -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 }) =>

View File

@ -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 } : {}
}

View File

@ -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 && {

View File

@ -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,

View File

@ -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,
},

View File

@ -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,
},

View File

@ -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 } = {}

View File

@ -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

View File

@ -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() },
})

View File

@ -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,
}),
},
})
)

View File

@ -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,

View File

@ -24,4 +24,4 @@ export const shopifyProvider = {
auth: { useLogin, useLogout, useSignup },
}
export type ShopifyProvider = typeof shopifyProvider
export type ShopifyProvider = any

View File

@ -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>

View File

@ -0,0 +1 @@
export * from '@commerce/types/checkout'

View File

@ -0,0 +1 @@
export * from '@commerce/types/common'

View File

@ -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,
}

View File

@ -0,0 +1 @@
export * from '@commerce/types/wishlist'

View File

@ -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(

View File

@ -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,
}),
}
}

View File

@ -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))

View File

@ -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)

View File

@ -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 },

View File

@ -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 },

View File

@ -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,

View File

@ -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 },

View File

@ -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 },

View File

@ -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 },

View File

@ -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) => {

View File

@ -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: {