Fix Shopify translations issue

This commit is contained in:
cond0r 2021-05-22 09:28:00 +03:00
parent a4f56d1549
commit b4fb64a292
27 changed files with 211 additions and 133 deletions

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,16 +1,9 @@
import { SWRHook } from '@commerce/utils/types'
import useSearch, { UseSearch } from '@commerce/product/use-search'
import type { SearchProductsData } from '../api/catalog/products'
import { SearchProductsData, SearchProductsInput } from '@commerce/types'
export default useSearch as UseSearch<typeof handler>
export type SearchProductsInput = {
search?: string
categoryId?: number
brandId?: number
sort?: string
}
export const handler: SWRHook<
SearchProductsData,
SearchProductsInput,

View File

@ -2,6 +2,7 @@ import type { RequestInit, Response } from '@vercel/fetch'
export interface CommerceAPIConfig {
locale?: string
locales?: string[]
commerceUrl: string
apiToken: string
cartCookie: string

View File

@ -1,6 +1,5 @@
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
@ -97,8 +96,18 @@ export interface Wishlist extends BCWishlist {}
// TODO: Properly define this type
export interface Customer extends BCCustomer {}
// TODO: Properly define this type
export interface SearchProductsData extends BCSearchProductsData {}
export type SearchProductsData = {
products: Product[]
found: boolean
}
export type SearchProductsInput = {
search?: string
categoryId?: string
brandId?: string
sort?: string
locale?: string
}
/**
* Cart mutations

View File

@ -43,7 +43,6 @@ export class Config {
}
const config = new Config({
locale: 'en-US',
commerceUrl: API_URL,
apiToken: API_TOKEN!,
cartCookie: SHOPIFY_CHECKOUT_ID_COOKIE,

View File

@ -1,10 +1,12 @@
import { ProductEdge } from '../../schema'
import { ProductEdge, QueryRoot, QueryRootProductsArgs } from '../../schema'
import { ShopifyConfig } from '..'
const fetchAllProducts = async ({
config,
query,
variables,
variables = {
first: 250,
},
acc = [],
cursor,
}: {
@ -14,9 +16,20 @@ const fetchAllProducts = async ({
variables?: any
cursor?: string
}): Promise<ProductEdge[]> => {
const { data } = await config.fetch(query, {
const { fetch, locale } = config
const { data } = await fetch<QueryRoot, QueryRootProductsArgs>(
query,
{
variables: { ...variables, cursor },
})
},
{
...(locale && {
headers: {
'Accept-Locale': locale,
},
}),
}
)
const edges: ProductEdge[] = data.products?.edges ?? []
const hasNextPage = data.products?.pageInfo?.hasNextPage

View File

@ -1,14 +1,6 @@
import { getConfig, ShopifyConfig } from '../api'
import { PageEdge } from '../schema'
import { getAllPagesQuery } from '../utils/queries'
type Variables = {
first?: number
}
type ReturnType = {
pages: Page[]
}
import { QueryRoot, QueryRootPagesArgs } from '../schema'
import { normalizePages, getAllPagesQuery } from '../utils'
export type Page = {
id: string
@ -18,25 +10,40 @@ export type Page = {
body: string
}
const getAllPages = async (options?: {
variables?: Variables
config: ShopifyConfig
preview?: boolean
}): Promise<ReturnType> => {
let { config, variables = { first: 250 } } = options ?? {}
config = getConfig(config)
const { locale } = config
const { data } = await config.fetch(getAllPagesQuery, { variables })
export type GetAllPagesResult = Promise<{
pages: Page[]
}>
const pages = data.pages?.edges?.map(
({ node: { title: name, handle, ...node } }: PageEdge) => ({
...node,
url: `/${locale}/${handle}`,
name,
})
const getAllPages = async (options?: {
variables?: QueryRootPagesArgs
config?: ShopifyConfig
preview?: boolean
}): GetAllPagesResult => {
let { config, variables } = options ?? {}
const { fetch, locale = 'en-US', locales = ['en-US'] } = getConfig(config)
const {
data: {
pages: { edges },
},
} = await fetch<QueryRoot, QueryRootPagesArgs>(
getAllPagesQuery,
{
variables,
},
{
headers: {
'Accept-Language': locale,
},
}
)
return { pages }
return {
pages: locales.reduce<Page[]>(
(arr, locale) => arr.concat(normalizePages(edges, locale)),
[]
),
}
}
export default getAllPages

View File

@ -1,37 +1,41 @@
import { Page as ShopifyPage, QueryRoot, QueryRootPagesArgs } from '../schema'
import { normalizePage, getPageQuery } from '../utils'
import { getConfig, ShopifyConfig } from '../api'
import getPageQuery from '../utils/queries/get-page-query'
import { Page } from './get-all-pages'
import type { Page } from './get-all-pages'
type Variables = {
type GetPageInput = {
id: string
}
export type GetPageResult<T extends { page?: any } = { page?: Page }> = T
type GetPageResult = {
page?: Page
}
const getPage = async (options: {
variables: Variables
config: ShopifyConfig
const getPage = async ({
variables,
config,
}: {
variables: GetPageInput
config?: ShopifyConfig
preview?: boolean
}): Promise<GetPageResult> => {
let { config, variables } = options ?? {}
const { locale = 'en-US', fetch } = getConfig(config)
config = getConfig(config)
const { locale } = config
const { data } = await config.fetch(getPageQuery, {
const {
data: { node: page },
} = await fetch<QueryRoot, GetPageInput>(
getPageQuery,
{
variables,
})
const page = data.node
},
{
headers: {
'Accept-Language': locale,
},
}
)
return {
page: page
? {
...page,
name: page.title,
url: `/${locale}/${page.handle}`,
}
: null,
}
return page ? { page: normalizePage(page as ShopifyPage, locale) } : {}
}
export default getPage

View File

@ -8,13 +8,15 @@ 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

@ -22,7 +22,6 @@ export type ShopifyConfig = Partial<CommerceConfig>
export type ShopifyProps = {
children?: ReactNode
locale: string
} & ShopifyConfig
export function CommerceProvider({ children, ...config }: ShopifyProps) {

View File

@ -1,4 +1,3 @@
import { Product } from '@commerce/types'
import { getConfig, ShopifyConfig } from '../api'
import fetchAllProducts from '../api/utils/fetch-all-products'
import { ProductEdge } from '../schema'

View File

@ -1,9 +1,8 @@
import { GraphQLFetcherResult } from '@commerce/api'
import { Product } from '@commerce/types'
import { getConfig, ShopifyConfig } from '../api'
import { ProductEdge } from '../schema'
import { QueryRoot, QueryRootProductsArgs } from '../schema'
import { getAllProductsQuery } from '../utils/queries'
import { normalizeProduct } from '../utils/normalize'
import { Product } from '@commerce/types'
type Variables = {
first?: number
@ -21,16 +20,25 @@ const getAllProducts = async (options: {
}): Promise<ReturnType> => {
let { config, variables = { first: 250 } } = options ?? {}
config = getConfig(config)
let products: Product[] = []
const { data }: GraphQLFetcherResult = await config.fetch(
const { data } = await config!.fetch<QueryRoot, QueryRootProductsArgs>(
getAllProductsQuery,
{ variables }
{
variables,
},
{
...(config.locale && {
headers: {
'Accept-Language': config.locale!,
},
}),
}
)
const products =
data.products?.edges?.map(({ node: p }: ProductEdge) =>
normalizeProduct(p)
) ?? []
products = [
...products,
...data.products.edges.map(({ node: p }) => normalizeProduct(p)),
]
return {
products,

View File

@ -1,31 +1,43 @@
import { GraphQLFetcherResult } from '@commerce/api'
import { Product } from '@commerce/types'
import { QueryRoot } from '../schema'
import { getConfig, ShopifyConfig } from '../api'
import { normalizeProduct, getProductQuery } from '../utils'
type Variables = {
export type GetProductInput = {
slug: string
}
type ReturnType = {
product: any
export type GetProductResult = {
product?: Product
}
const getProduct = async (options: {
variables: Variables
config: ShopifyConfig
preview?: boolean
}): Promise<ReturnType> => {
let { config, variables } = options ?? {}
config = getConfig(config)
const { data }: GraphQLFetcherResult = await config.fetch(getProductQuery, {
const getProduct = async ({
variables,
})
const { productByHandle } = data
config,
}: {
variables: GetProductInput
config?: ShopifyConfig
preview?: boolean
}): Promise<GetProductResult> => {
const { fetch, locale } = getConfig(config)
return {
product: productByHandle ? normalizeProduct(productByHandle) : null,
const {
data: { productByHandle },
} = await fetch<QueryRoot>(
getProductQuery,
{
variables,
},
{
...(locale && {
headers: {
'Accept-Language': locale,
},
}),
}
)
return productByHandle ? { product: normalizeProduct(productByHandle) } : {}
}
export default getProduct

View File

@ -1,7 +1,9 @@
import { SWRHook } from '@commerce/utils/types'
import useSearch, { UseSearch } from '@commerce/product/use-search'
import { SearchProductsInput, SearchProductsData } from '@commerce/types'
import { ProductEdge } from '../schema'
import {
getAllProductsQuery,
getCollectionProductsQuery,
@ -9,22 +11,8 @@ import {
normalizeProduct,
} from '../utils'
import { Product } from '@commerce/types'
export default useSearch as UseSearch<typeof handler>
export type SearchProductsInput = {
search?: string
categoryId?: string
brandId?: string
sort?: string
}
export type SearchProductsData = {
products: Product[]
found: boolean
}
export const handler: SWRHook<
SearchProductsData,
SearchProductsInput,
@ -68,6 +56,7 @@ export const handler: SWRHook<
['categoryId', input.categoryId],
['brandId', input.brandId],
['sort', input.sort],
['locale', input.locale],
],
swrOptions: {
revalidateOnFocus: false,

View File

@ -1,5 +1,5 @@
import { ShopifyConfig } from '../api'
import { CollectionEdge } from '../schema'
import { CollectionEdge, QueryRoot, QueryRootCollectionsArgs } from '../schema'
import getSiteCollectionsQuery from './queries/get-all-collections-query'
export type Category = {
@ -9,11 +9,22 @@ export type Category = {
}
const getCategories = async (config: ShopifyConfig): Promise<Category[]> => {
const { data } = await config.fetch(getSiteCollectionsQuery, {
const { fetch, locale } = config
const { data } = await fetch<QueryRoot, QueryRootCollectionsArgs>(
getSiteCollectionsQuery,
{
variables: {
first: 250,
},
})
},
{
...(locale && {
headers: {
'Accept-Language': locale,
},
}),
}
)
return (
data.collections?.edges?.map(

View File

@ -1,11 +1,12 @@
import getSortVariables from './get-sort-variables'
import type { SearchProductsInput } from '../product/use-search'
import type { SearchProductsInput } from '@commerce/types'
export const getSearchVariables = ({
brandId,
search,
categoryId,
sort,
locale,
}: SearchProductsInput) => {
let query = ''
@ -20,6 +21,7 @@ export const getSearchVariables = ({
return {
categoryId,
query,
locale,
...getSortVariables(sort, !!categoryId),
}
}

View File

@ -18,9 +18,6 @@ const getVendors = async (config: ShopifyConfig): Promise<BrandEdge[]> => {
const vendors = await fetchAllProducts({
config,
query: getAllProductVendors,
variables: {
first: 250,
},
})
let vendorsStrings = vendors.map(({ node: { vendor } }) => vendor)

View File

@ -9,10 +9,14 @@ import {
ProductVariantConnection,
MoneyV2,
ProductOption,
PageEdge,
Page as ShopifyPage,
} from '../schema'
import type { Cart, LineItem } from '../types'
import type { Page } from '../common/get-all-pages'
const money = ({ amount, currencyCode }: MoneyV2) => {
return {
value: +amount,
@ -39,6 +43,7 @@ const normalizeProductOption = ({
hexColors: [value],
}
}
return output
}),
}
@ -163,3 +168,15 @@ function normalizeLineItem({
],
}
}
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

@ -9,16 +9,18 @@ import getSlug from '@lib/get-slug'
import { missingLocaleInPages } from '@lib/usage-warns'
import { getConfig } from '@framework/api'
import getPage from '@framework/common/get-page'
import getAllPages from '@framework/common/get-all-pages'
import getAllPages, { Page } from '@framework/common/get-all-pages'
import { defaultPageProps } from '@lib/defaults'
export async function getStaticProps({
preview,
params,
locale,
locales,
}: GetStaticPropsContext<{ pages: string[] }>) {
const config = getConfig({ locale })
const { pages } = await getAllPages({ preview, config })
const config = getConfig({ locale, locales })
let { pages } = await getAllPages({ preview, config })
const path = params?.pages.join('/')
const slug = locale ? `${locale}/${path}` : path
@ -40,8 +42,10 @@ export async function getStaticProps({
}
export async function getStaticPaths({ locales }: GetStaticPathsContext) {
const { pages } = await getAllPages()
const config = getConfig({ locales })
let { pages } = await getAllPages({ config })
const [invalidPaths, log] = missingLocaleInPages()
const paths = pages
.map((page) => page.url)
.filter((url) => {

View File

@ -7,8 +7,9 @@ import { Container } from '@components/ui'
export async function getStaticProps({
preview,
locale,
locales,
}: GetStaticPropsContext) {
const config = getConfig({ locale })
const config = getConfig({ locale, locales })
const { pages } = await getAllPages({ config, preview })
return {
props: { pages },

View File

@ -11,8 +11,9 @@ import { CartItem } from '@components/cart'
export async function getStaticProps({
preview,
locale,
locales,
}: GetStaticPropsContext) {
const config = getConfig({ locale })
const config = getConfig({ locale, locales })
const { pages } = await getAllPages({ config, preview })
return {
props: { pages },

View File

@ -12,8 +12,9 @@ import getAllPages from '@framework/common/get-all-pages'
export async function getStaticProps({
preview,
locale,
locales,
}: GetStaticPropsContext) {
const config = getConfig({ locale })
const config = getConfig({ locale, locales })
const { products } = await getAllProducts({
variables: { first: 12 },

View File

@ -8,8 +8,9 @@ import getAllPages from '@framework/common/get-all-pages'
export async function getStaticProps({
preview,
locale,
locales,
}: GetStaticPropsContext) {
const config = getConfig({ locale })
const config = getConfig({ locale, locales })
const { pages } = await getAllPages({ config, preview })
return {
props: { pages },

View File

@ -16,9 +16,11 @@ export async function getStaticProps({
params,
locale,
preview,
locales,
}: GetStaticPropsContext<{ slug: string }>) {
const config = getConfig({ locale })
const config = getConfig({ locale, locales })
const { pages } = await getAllPages({ config, preview })
const { product } = await getProduct({
variables: { slug: params!.slug },
config,

View File

@ -8,8 +8,9 @@ import { Container, Text } from '@components/ui'
export async function getStaticProps({
preview,
locale,
locales,
}: GetStaticPropsContext) {
const config = getConfig({ locale })
const config = getConfig({ locale, locales })
const { pages } = await getAllPages({ config, preview })
return {
props: { pages },

View File

@ -37,8 +37,9 @@ import { Product } from '@commerce/types'
export async function getStaticProps({
preview,
locale,
locales,
}: GetStaticPropsContext) {
const config = getConfig({ locale })
const config = getConfig({ locale, locales })
const { pages } = await getAllPages({ config, preview })
const { categories, brands } = await getSiteInfo({ config, preview })
return {
@ -46,6 +47,7 @@ export async function getStaticProps({
pages,
categories,
brands,
locale,
},
}
}
@ -53,6 +55,7 @@ export async function getStaticProps({
export default function Search({
categories,
brands,
locale,
}: InferGetStaticPropsType<typeof getStaticProps>) {
const [activeFilter, setActiveFilter] = useState('')
const [toggleFilter, setToggleFilter] = useState(false)
@ -78,6 +81,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

@ -12,6 +12,7 @@ import getAllPages from '@framework/common/get-all-pages'
export async function getStaticProps({
preview,
locale,
locales,
}: GetStaticPropsContext) {
// Disabling page if Feature is not available
if (!process.env.COMMERCE_WISHLIST_ENABLED) {
@ -20,7 +21,7 @@ export async function getStaticProps({
}
}
const config = getConfig({ locale })
const config = getConfig({ locale, locales })
const { pages } = await getAllPages({ config, preview })
return {
props: {