Merge branch 'release-stable' of github.com:KieIO/grocery-vercel-commerce into feature/m2-add-product-to-cart

This commit is contained in:
DatNguyen
2021-10-08 17:19:14 +07:00
85 changed files with 1710 additions and 710 deletions

View File

@@ -10,6 +10,7 @@ import type {
GetProductOperation,
} from '../types/product'
import type { APIProvider, CommerceAPI } from '.'
import { GetAllCollectionsOperation } from '@commerce/types/collection';
const noop = () => {
throw new Error('Not implemented')
@@ -25,6 +26,7 @@ export const OPERATIONS = [
'getAllProducts',
'getProduct',
'getAllFacets',
'getAllCollections',
] as const
@@ -174,6 +176,22 @@ export type Operations<P extends APIProvider> = {
): Promise<T['data']>
}
getAllCollections: {
<T extends GetAllCollectionsOperation>(opts: {
variables?: T['variables']
config?: P['config']
preview?: boolean
}): Promise<T['data']>
<T extends GetAllCollectionsOperation>(
opts: {
variables?: T['variables']
config?: P['config']
preview?: boolean
} & OperationOptions
): Promise<T['data']>
}
}

View File

@@ -16,6 +16,7 @@ Adding a commerce provider means adding a new folder in `framework` with a folde
- getProduct
- getAllProducts
- getAllFacets
- getAllCollections
- `wishlist`
- useWishlist
- useAddItem

View File

@@ -0,0 +1,54 @@
import { Asset } from '../../vendure/schema.d';
export type Collection = {
id: string
name: string
slug: string
description: string
featuredAsse: Asset
asset: Asset[]
}
export type SearchCollectionsBody = {
search?: string
sort?: string
locale?: string
}
export type CollectionTypes = {
collection: Collection
searchBody: SearchCollectionsBody
}
export type SearchCollectionsHook<T extends CollectionTypes = CollectionTypes> = {
data: {
collections: T['collection'][]
found: boolean
}
body: T['searchBody']
input: T['searchBody']
fetcherInput: T['searchBody']
}
export type CollectionsSchema<T extends CollectionTypes = CollectionTypes> = {
endpoint: {
options: {}
handlers: {
getCollections: SearchCollectionsHook<T>
}
}
}
export type GetAllCollectionsOperation<T extends CollectionTypes = CollectionTypes> = {
data: { collections: T['collection'][] }
variables: {
ids?: string[]
first?: number
}
}
export type GetCollectionOperation<T extends CollectionTypes = CollectionTypes> = {
data: { collection?: T['collection'] }
variables: { code: string; } | { code?: never; }
}

View File

@@ -43,8 +43,10 @@ export type Product = {
slug?: string
path?: string
images: ProductImage[]
price: ProductPrice
price: number
currencyCode: CurrencyCode
options: ProductOption[]
facetValueIds?: string[]
}
export type ProductCard = {
@@ -54,11 +56,12 @@ export type ProductCard = {
imageSrc: string
price: number
currencyCode: CurrencyCode
oldPrice?: number,
oldPrice?: number
discount?: number
weight?: number
// TODO: collection
category?: string,
facetValueIds?: string[],
collectionIds?: string[],
collection?: string,
isNotSell?: boolean
productVariantId?:string
}

View File

@@ -1,6 +1,7 @@
import type { CommerceAPIConfig } from '@commerce/api'
import { CommerceAPI, getCommerceApi as commerceApi } from '@commerce/api'
import getAllFacets from './operations/get-all-facets'
import getAllCollections from './operations/get-all-collection'
import getAllPages from './operations/get-all-pages'
import getAllProductPaths from './operations/get-all-product-paths'
import getAllProducts from './operations/get-all-products'
@@ -42,6 +43,7 @@ const operations = {
getAllProducts,
getProduct,
getAllFacets,
getAllCollections,
}
export const provider = { config, operations }

View File

@@ -0,0 +1,45 @@
import { OperationContext } from '@commerce/api/operations'
import { Collection } from '@commerce/types/collection'
import { Provider, VendureConfig } from '..'
import { GetAllCollectionsQuery } from '../../schema'
import { getAllCollectionsQuery } from '../../utils/queries/get-all-collections-query'
export type CollectionVariables = { first?: number }
export default function getAllCollectionsOperation({
commerce,
}: OperationContext<Provider>) {
async function getAllCollections(opts?: {
variables?: CollectionVariables
config?: Partial<VendureConfig>
preview?: boolean
}): Promise<{ collections: Collection[] }>
async function getAllCollections({
query = getAllCollectionsQuery,
variables: { ...vars } = {},
config: cfg,
}: {
query?: string
variables?: CollectionVariables
config?: Partial<VendureConfig>
preview?: boolean
} = {}): Promise<{ collections: Collection[] | any[] }> {
const config = commerce.getConfig(cfg)
const variables = {
input: {
take: vars.first,
groupByCollection: true,
},
}
const { data } = await config.fetch<GetAllCollectionsQuery>(query, {
variables,
})
return {
collections: data.collections.items,
}
}
return getAllCollections
}

View File

@@ -1,10 +1,10 @@
import { OperationContext } from '@commerce/api/operations'
import { Facet } from '@commerce/types/facet'
import { Provider, VendureConfig } from '../'
import { GetAllFacetsQuery } from '../../schema'
import { FacetFilterParameter, FacetSortParameter, GetAllFacetsQuery } from '../../schema'
import { getAllFacetsQuery } from '../../utils/queries/get-all-facets-query'
export type FacetVariables = { first?: number }
export type FacetVariables = { first?: number, filter?: FacetFilterParameter, sort?: FacetSortParameter }
export default function getAllFacetsOperation({
commerce,
@@ -27,9 +27,10 @@ export default function getAllFacetsOperation({
} = {}): Promise<{ facets: Facet[] | any[] }> {
const config = commerce.getConfig(cfg)
const variables = {
input: {
options: {
take: vars.first,
groupByFacet: true,
filter: vars.filter,
sort: vars.sort,
},
}
const { data } = await config.fetch<GetAllFacetsQuery>(query, {

View File

@@ -14,7 +14,7 @@ export default function getAllProductsOperation({
variables?: ProductVariables
config?: Partial<VendureConfig>
preview?: boolean
}): Promise<{ products: Product[] }>
}): Promise<{ products: Product[], totalItems: number }>
async function getAllProducts({
query = getAllProductsQuery,
@@ -25,7 +25,7 @@ export default function getAllProductsOperation({
variables?: ProductVariables
config?: Partial<VendureConfig>
preview?: boolean
} = {}): Promise<{ products: Product[] | any[] }> {
} = {}): Promise<{ products: Product[] | any[], totalItems: number }> {
const config = commerce.getConfig(cfg)
const variables = {
input: {
@@ -41,6 +41,7 @@ export default function getAllProductsOperation({
return {
products: data.search.items.map((item) => normalizeSearchResult(item)),
totalItems: data.search.totalItems as number,
}
}

View File

@@ -16,10 +16,8 @@ export default function getProductOperation({
variables: { slug: string }
config?: Partial<VendureConfig>
preview?: boolean
}): Promise<Product | {} | any> {
}): Promise<Product | null> {
const config = commerce.getConfig(cfg)
const locale = config.locale
const { data } = await config.fetch<GetProductQuery>(query, { variables })
const product = data.product
@@ -28,7 +26,6 @@ export default function getProductOperation({
return product.optionGroups.find((og) => og.id === id)!.name
}
return {
product: {
id: product.id,
name: product.name,
description: product.description,
@@ -49,20 +46,18 @@ export default function getProductOperation({
values: [{ label: o.name }],
})),
})),
price: {
value: product.variants[0].priceWithTax / 100,
currencyCode: product.variants[0].currencyCode,
},
price: product.variants[0].priceWithTax / 100,
currencyCode: product.variants[0].currencyCode,
options: product.optionGroups.map((og) => ({
id: og.id,
displayName: og.name,
values: og.options.map((o) => ({ label: o.name })),
})),
} as Product,
}
facetValueIds: product.facetValues.map(item=> item.id)
} as Product
}
return {}
return null
}
return getProduct

View File

@@ -1,3 +1,4 @@
import { FacetValue } from './schema.d';
export type Maybe<T> = T | null
export type Exact<T extends { [key: string]: unknown }> = {
[K in keyof T]: T[K]
@@ -3038,7 +3039,7 @@ export type SearchResultFragment = { __typename?: 'SearchResult' } & Pick<
SearchResult,
'productId' | 'sku' | 'productName' | 'description' | 'slug' | 'sku' | 'currencyCode'
| 'productAsset' | 'price' | 'priceWithTax' | 'currencyCode'
| 'collectionIds' | 'productVariantId'
| 'collectionIds' | 'productVariantId' | 'facetValueIds'
> & {
productAsset?: Maybe<
{ __typename?: 'SearchResultAsset' } & Pick<
@@ -3218,7 +3219,8 @@ export type GetAllProductsQueryVariables = Exact<{
export type GetAllProductsQuery = { __typename?: 'Query' } & {
search: { __typename?: 'SearchResponse' } & {
items: Array<{ __typename?: 'SearchResult' } & SearchResultFragment>
items: Array<{ __typename?: 'SearchResult' } & SearchResultFragment>,
'totalItems'
}
}
@@ -3227,8 +3229,9 @@ export type GetAllFacetsQuery = { __typename?: 'Query' } & {
items: Array<
{ __typename?: 'Facet' } & Pick<
Facet,
'id' | 'name' | 'code'
> & {
'id' | 'name' | 'code' | 'values'
>
& {
parent?: Maybe<{ __typename?: 'Facet' } & Pick<Facet, 'id'>>
children?: Maybe<
Array<{ __typename?: 'Facet' } & Pick<Facet, 'id'>>
@@ -3239,6 +3242,23 @@ export type GetAllFacetsQuery = { __typename?: 'Query' } & {
}
}
export type GetAllCollectionsQuery = { __typename?: 'Query' } & {
collections: { __typename?: 'CollectionList' } & {
items: Array<
{ __typename?: 'Collection' } & Pick<
Collection,
'id' | 'name' | 'slug'
> & {
parent?: Maybe<{ __typename?: 'Collection' } & Pick<Collection, 'id'>>
children?: Maybe<
Array<{ __typename?: 'Collection' } & Pick<Collection, 'id'>>
>
}
>,
'totalItems'
}
}
export type ActiveOrderQueryVariables = Exact<{ [key: string]: never }>
export type ActiveOrderQuery = { __typename?: 'Query' } & {
@@ -3318,6 +3338,18 @@ export type GetProductQuery = { __typename?: 'Query' } & {
>
}
>
facetValues: Array<
{ __typename?: 'FacetValue' } & Pick<
FacetValue,
'id'
>
>
collections: Array<
{ __typename?: 'Collection' } & Pick<
Collection,
'id'
>
>
}
>
}

View File

@@ -20,6 +20,8 @@ export const searchResultFragment = /* GraphQL */ `
min
max
}
}
},
facetValueIds,
collectionIds,
}
`

View File

@@ -1,24 +1,24 @@
import { Product, ProductCard } from '@commerce/types/product'
import { Cart } from '@commerce/types/cart'
import { ProductCard } from '@commerce/types/product'
import { CartFragment, SearchResultFragment } from '../schema'
export function normalizeSearchResult(item: SearchResultFragment): ProductCard {
return {
id: item.productId,
name: item.productName,
slug: item.slug,
imageSrc: item.productAsset?.preview ? item.productAsset?.preview + '?w=800&mode=crop' : '',
price: (item.priceWithTax as any).min / 100,
currencyCode: item.currencyCode,
productVariantId: item.productVariantId?item.productVariantId:"",
productVariantId: item.productVariantId,
facetValueIds: item.facetValueIds,
collectionIds: item.collectionIds,
// TODO:
// oldPrice: item.price
// discount
// isNotSell
// weight
// category
}
}

View File

@@ -0,0 +1,12 @@
export const getAllCollectionsQuery = /* GraphQL */ `
query collections ($options: CollectionListOptions) {
collections (options: $options){
totalItems,
items {
id
name
slug
}
}
}
`

View File

@@ -3,6 +3,7 @@ import { searchResultFragment } from '../fragments/search-result-fragment'
export const getAllProductsQuery = /* GraphQL */ `
query getAllProducts($input: SearchInput!) {
search(input: $input) {
totalItems
items {
...SearchResult
}

View File

@@ -24,7 +24,7 @@ export const getCollectionsNameQuery = /* GraphQL */ `
collections{
items{
name
link:slug
slug
}
}
}

View File

@@ -36,6 +36,9 @@ export const getProductQuery = /* GraphQL */ `
name
}
}
facetValues {
id
}
}
}
`