diff --git a/framework/commerce/api/operations.ts b/framework/commerce/api/operations.ts index 8e5137c40..342d6bbc9 100644 --- a/framework/commerce/api/operations.ts +++ b/framework/commerce/api/operations.ts @@ -1,3 +1,4 @@ +import { GetAllFacetsOperation } from './../types/facet'; import type { ServerResponse } from 'http' import type { LoginOperation } from '../types/login' import type { GetAllPagesOperation, GetPageOperation } from '../types/page' @@ -156,23 +157,26 @@ export type Operations

= { } & OperationOptions ): Promise } + + getAllFacets: { + (opts: { + variables?: T['variables'] + config?: P['config'] + preview?: boolean + }): Promise + + ( + opts: { + variables?: T['variables'] + config?: P['config'] + preview?: boolean + } & OperationOptions + ): Promise + } + + } -// getAllFacets: { -// (opts: { -// variables?: T['variables'] -// config?: P['config'] -// preview?: boolean -// }): Promise - -// ( -// opts: { -// variables?: T['variables'] -// config?: P['config'] -// preview?: boolean -// } & OperationOptions -// ): Promise -// } export type APIOperations

= { [K in keyof Operations

]?: (ctx: OperationContext

) => Operations

[K] diff --git a/framework/commerce/new-provider.md b/framework/commerce/new-provider.md index 8c2feeab2..a48e6961b 100644 --- a/framework/commerce/new-provider.md +++ b/framework/commerce/new-provider.md @@ -15,6 +15,7 @@ Adding a commerce provider means adding a new folder in `framework` with a folde - useSearch - getProduct - getAllProducts + - getAllFacets - `wishlist` - useWishlist - useAddItem diff --git a/framework/commerce/types/facet.ts b/framework/commerce/types/facet.ts index d1ae5b382..adfe1e061 100644 --- a/framework/commerce/types/facet.ts +++ b/framework/commerce/types/facet.ts @@ -1,40 +1,14 @@ - -export type FacetOption = { - __typename?: 'MultipleChoiceOption' - id: string - displayName: string - values: FacetOptionValues[] -} - -export type FacetOptionValues = { - label: string - hexColors?: string[] -} - -export type FacetVariant = { - id: string | number - options: FacetOption[] - availableForSale?: boolean -} +import { FacetValue } from './../../vendure/schema.d'; export type Facet = { id: string name: string - description: string - descriptionHtml?: string - sku?: string - slug?: string - path?: string - images: FacetImage[] - variants: FacetVariant[] - price: FacetPrice - options: FacetOption[] + code: string + values: FacetValue[] } export type SearchFacetsBody = { search?: string - categoryId?: string | number - brandId?: string | number sort?: string locale?: string } @@ -63,17 +37,10 @@ export type FacetsSchema = { } } -export type GetAllFacetPathsOperation< - T extends FacetTypes = FacetTypes -> = { - data: { facets: Pick[] } - variables: { first?: number } -} export type GetAllFacetsOperation = { data: { facets: T['facet'][] } variables: { - relevance?: 'featured' | 'best_selling' | 'newest' ids?: string[] first?: number } @@ -81,5 +48,5 @@ export type GetAllFacetsOperation = { export type GetFacetOperation = { data: { facet?: T['facet'] } - variables: { path: string; slug?: never } | { path?: never; slug: string } + variables: { code: string; } | { code?: never; } } diff --git a/framework/commerce/types/product.ts b/framework/commerce/types/product.ts index 6a68d8ad1..fec48a63d 100644 --- a/framework/commerce/types/product.ts +++ b/framework/commerce/types/product.ts @@ -1,3 +1,5 @@ +import { FacetValueFilterInput, LogicalOperator, SearchResultSortParameter } from "@framework/schema" + export type ProductImage = { url: string alt?: string @@ -40,7 +42,6 @@ export type Product = { slug?: string path?: string images: ProductImage[] - variants: ProductVariant[] price: ProductPrice options: ProductOption[] } @@ -79,17 +80,24 @@ export type ProductsSchema = { export type GetAllProductPathsOperation< T extends ProductTypes = ProductTypes -> = { - data: { products: Pick[] } - variables: { first?: number } -} + > = { + data: { products: Pick[] } + variables: { first?: number } + } export type GetAllProductsOperation = { data: { products: T['product'][] } variables: { - relevance?: 'featured' | 'best_selling' | 'newest' - ids?: string[] - first?: number + term?: String + facetValueIds?: string[] + facetValueOperator?: LogicalOperator + facetValueFilters?: FacetValueFilterInput[] + collectionId?: string + collectionSlug?: string + groupByProduct?: Boolean + take?: number + skip?: number + sort?: SearchResultSortParameter } } diff --git a/framework/vendure/api/operations/get-all-facets.ts b/framework/vendure/api/operations/get-all-facets.ts index 9187525d3..c4b002744 100644 --- a/framework/vendure/api/operations/get-all-facets.ts +++ b/framework/vendure/api/operations/get-all-facets.ts @@ -1,9 +1,8 @@ +import { OperationContext } from '@commerce/api/operations' import { Facet } from '@commerce/types/facet' import { Provider, VendureConfig } from '../' import { GetAllFacetsQuery } from '../../schema' -import { normalizeSearchResult } from '../../utils/normalize' import { getAllFacetsQuery } from '../../utils/queries/get-all-facets-query' -import { OperationContext } from '@commerce/api/operations' export type FacetVariables = { first?: number } @@ -38,7 +37,7 @@ export default function getAllFacetsOperation({ }) return { - facets: data.search.items.map((item) => normalizeSearchResult(item)), + facets: data.facets.items, } } diff --git a/framework/vendure/api/operations/get-all-products.ts b/framework/vendure/api/operations/get-all-products.ts index 68d4ce9b7..1f558a7cb 100644 --- a/framework/vendure/api/operations/get-all-products.ts +++ b/framework/vendure/api/operations/get-all-products.ts @@ -5,7 +5,7 @@ import { normalizeSearchResult } from '../../utils/normalize' import { getAllProductsQuery } from '../../utils/queries/get-all-products-query' import { OperationContext } from '@commerce/api/operations' -export type ProductVariables = { first?: number } +export type ProductVariables = { first?: number, facetValueIds?: string[] } export default function getAllProductsOperation({ commerce, @@ -30,6 +30,7 @@ export default function getAllProductsOperation({ const variables = { input: { take: vars.first, + facetValueIds: vars.facetValueIds, groupByProduct: true, }, } diff --git a/framework/vendure/schema.d.ts b/framework/vendure/schema.d.ts index 3922f679b..a817d6799 100644 --- a/framework/vendure/schema.d.ts +++ b/framework/vendure/schema.d.ts @@ -3036,7 +3036,9 @@ export type CartFragment = { __typename?: 'Order' } & Pick< export type SearchResultFragment = { __typename?: 'SearchResult' } & Pick< SearchResult, - 'productId' | 'productName' | 'description' | 'slug' | 'sku' | 'currencyCode' + 'productId' | 'sku' | 'productName' | 'description' | 'slug' | 'sku' | 'currencyCode' + | 'productAsset' | 'price' | 'priceWithTax' | 'currencyCode' + | 'collectionIds' > & { productAsset?: Maybe< { __typename?: 'SearchResultAsset' } & Pick< diff --git a/framework/vendure/utils/normalize.ts b/framework/vendure/utils/normalize.ts index 09c1c6e42..b99aa5096 100644 --- a/framework/vendure/utils/normalize.ts +++ b/framework/vendure/utils/normalize.ts @@ -3,18 +3,20 @@ import { Cart } from '@commerce/types/cart' import { CartFragment, SearchResultFragment } from '../schema' export function normalizeSearchResult(item: SearchResultFragment): Product { + const imageUrl = item.productAsset?.preview ? item.productAsset?.preview + '?w=800&mode=crop' : '' return { id: item.productId, name: item.productName, description: item.description, slug: item.slug, path: item.slug, - images: [{ url: item.productAsset?.preview + '?w=800&mode=crop' || '' }], - variants: [], + images: imageUrl ? [{ url: imageUrl }] : [], price: { + // TODO: check price value: (item.priceWithTax as any).min / 100, currencyCode: item.currencyCode, }, + // TODO: check product option options: [], sku: item.sku, } diff --git a/pages/index.tsx b/pages/index.tsx index 371922e59..3082d1790 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,20 +1,22 @@ +import { ProductVariables } from '@framework/api/operations/get-all-products'; +import { Product } from '@framework/schema'; import commerce from '@lib/api/commerce'; import { GetStaticPropsContext } from 'next'; import { Layout } from 'src/components/common'; import { FeaturedProductsCarousel, HomeBanner, HomeCategories, HomeCollection, HomeCTA, HomeFeature, HomeRecipe, HomeSubscribe, HomeVideo } from 'src/components/modules/home'; import HomeSpice from 'src/components/modules/home/HomeSpice/HomeSpice'; +import { getAllFeaturedFacetId, getFreshProductFacetId } from 'src/utils/funtion.utils'; interface Props { - products: any + freshProducts: Product[], + featuredProducts: Product[], + } -export default function Home({ products }: Props) { +export default function Home({ freshProducts, featuredProducts }: Props) { + console.log("total: ", freshProducts.length, featuredProducts.length) + console.log("rs: ", freshProducts, featuredProducts) return ( <> -

- TOTAL: {products?.length} -

- - {JSON.stringify(products[0])} @@ -39,29 +41,51 @@ export async function getStaticProps({ locales, }: GetStaticPropsContext) { const config = { locale, locales } - const productsPromise = commerce.getAllProducts({ - // const productsPromise = commerce.getAllFacets({ + const { facets } = await commerce.getAllFacets({ + variables: {}, + config, + preview, + }) + + + const freshProductvariables: ProductVariables = {} + const freshFacetId = getFreshProductFacetId(facets) + + if (freshFacetId) { + freshProductvariables.facetValueIds = [freshFacetId] + } + const freshProductsPromise = commerce.getAllProducts({ + variables: freshProductvariables, + config, + preview, + }) + + const allFeaturedFacetId = getAllFeaturedFacetId(facets) + const featuredProductsPromise = commerce.getAllProducts({ variables: { - first: 70, - // filter: { - // name: { - // contains: 'ca' - // } - // } + facetValueIds: allFeaturedFacetId }, config, preview, - // Saleor provider only - ...({ featured: true } as any), }) - const { products } = await productsPromise + try { + const rs = await Promise.all([freshProductsPromise, featuredProductsPromise]) + + return { + props: { + freshProducts: rs[0].products, + featuredProducts: rs[1].products + }, + revalidate: 60, + } + } catch (err) { - return { - props: { products }, - revalidate: 60, } + + + } diff --git a/src/components/modules/home/FreshProducts/FreshProducts.tsx b/src/components/modules/home/FreshProducts/FreshProducts.tsx new file mode 100644 index 000000000..b06138079 --- /dev/null +++ b/src/components/modules/home/FreshProducts/FreshProducts.tsx @@ -0,0 +1,148 @@ +import { Product } from '@framework/schema' +import React from 'react' +import { CollectionCarcousel } from '..' +import image5 from '../../../../../public/assets/images/image5.png' +import image6 from '../../../../../public/assets/images/image6.png' +import image7 from '../../../../../public/assets/images/image7.png' +import image8 from '../../../../../public/assets/images/image8.png' +interface FreshProductsProps { + data: Product[] +} +const dataTest = [ + { + name: 'Tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: image5.src, + }, + { + name: 'Cucumber', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: image6.src, + }, + { + name: 'Carrot', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: image7.src, + }, + { + name: 'Salad', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: image8.src, + }, + { + name: 'Tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: image5.src, + }, + { + name: 'Cucumber', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: image6.src, + }, + { + name: 'Tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: image5.src, + }, + { + name: 'Cucumber', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: image6.src, + }, + { + name: 'Carrot', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: image7.src, + }, + { + name: 'Salad', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: image8.src, + }, + { + name: 'Tomato', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: image5.src, + }, + { + name: 'Cucumber', + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: image6.src, + }, +] + +const FreshProducts = ({data}: FreshProductsProps) => { + return ( +
+ + + + + + +
+ ) +} + +export default FreshProducts diff --git a/src/components/modules/home/index.ts b/src/components/modules/home/index.ts index 82a0e3d8a..0618812c5 100644 --- a/src/components/modules/home/index.ts +++ b/src/components/modules/home/index.ts @@ -4,6 +4,7 @@ export { default as HomeCategories } from './HomeCategories/HomeCategories' export { default as HomeCTA } from './HomeCTA/HomeCTA' export { default as HomeSubscribe } from './HomeSubscribe/HomeSubscribe' export { default as HomeVideo } from './HomeVideo/HomeVideo' +export { default as FreshProducts } from './FreshProducts/FreshProducts' export { default as HomeCollection } from './HomeCollection/HomeCollection' export { default as HomeRecipe } from './HomeRecipe/HomeRecipe' export { default as FeaturedProductsCarousel } from './FeaturedProductsCarousel/FeaturedProductsCarousel' diff --git a/src/utils/constanst.utils.ts b/src/utils/constanst.utils.ts index f77991604..f66d6a7ea 100644 --- a/src/utils/constanst.utils.ts +++ b/src/utils/constanst.utils.ts @@ -107,7 +107,15 @@ export const CATEGORY = [ link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=chinsu`, }, ] - + +export const FACET = { + FEATURE: { + PARENT_NAME: 'Featured', + FRESH: 'Fresh', + BEST_SELLERS: 'Best seller' + } +} + export const FEATURED = [ { name: 'Best Sellers', @@ -141,3 +149,4 @@ export const STATE_OPTIONS = [ value: 'Hà Nội', }, ] + diff --git a/src/utils/funtion.utils.ts b/src/utils/funtion.utils.ts index 43d517589..d2ad83be1 100644 --- a/src/utils/funtion.utils.ts +++ b/src/utils/funtion.utils.ts @@ -1,11 +1,29 @@ +import { FacetValue } from './../../framework/vendure/schema.d'; +import { Facet } from "@commerce/types/facet"; +import { FACET } from "./constanst.utils"; + export function isMobile() { - return window.innerWidth < 768 + return window.innerWidth < 768 } -export function removeItem(arr: Array, value: T): Array { - const index = arr.indexOf(value); - if (index > -1) { - arr.splice(index, 1); - } - return [...arr]; +export function removeItem(arr: Array, value: T): Array { + const index = arr.indexOf(value); + if (index > -1) { + arr.splice(index, 1); + } + return [...arr]; +} + +export function getFreshProductFacetId(facets: Facet[]) { + const featuredFacet = facets.find((item: Facet) => item.name === FACET.FEATURE.PARENT_NAME) + const freshFacetValue = featuredFacet?.values.find((item: FacetValue) => item.name === FACET.FEATURE.FRESH) + + return freshFacetValue?.id +} + +export function getAllFeaturedFacetId(facets: Facet[]) { + const featuredFacet = facets.find((item: Facet) => item.name === FACET.FEATURE.PARENT_NAME) + const rs = featuredFacet?.values.map((item: FacetValue) => item.id) + + return rs } \ No newline at end of file