feat: feat fresh and featured products

:%s
This commit is contained in:
lytrankieio123
2021-10-04 14:16:32 +07:00
parent 6b7b8e4ad1
commit 77a0432d07
13 changed files with 280 additions and 96 deletions

View File

@@ -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<P extends APIProvider> = {
} & OperationOptions
): Promise<T['data']>
}
getAllFacets: {
<T extends GetAllFacetsOperation>(opts: {
variables?: T['variables']
config?: P['config']
preview?: boolean
}): Promise<T['data']>
<T extends GetAllFacetsOperation>(
opts: {
variables?: T['variables']
config?: P['config']
preview?: boolean
} & OperationOptions
): Promise<T['data']>
}
// getAllFacets: {
// <T extends GetAllFacetsOperation>(opts: {
// variables?: T['variables']
// config?: P['config']
// preview?: boolean
// }): Promise<T['data']>
// <T extends GetAllFacetsOperation>(
// opts: {
// variables?: T['variables']
// config?: P['config']
// preview?: boolean
// } & OperationOptions
// ): Promise<T['data']>
// }
}
export type APIOperations<P extends APIProvider> = {
[K in keyof Operations<P>]?: (ctx: OperationContext<P>) => Operations<P>[K]

View File

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

View File

@@ -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<T extends FacetTypes = FacetTypes> = {
}
}
export type GetAllFacetPathsOperation<
T extends FacetTypes = FacetTypes
> = {
data: { facets: Pick<T['facet'], 'path'>[] }
variables: { first?: number }
}
export type GetAllFacetsOperation<T extends FacetTypes = FacetTypes> = {
data: { facets: T['facet'][] }
variables: {
relevance?: 'featured' | 'best_selling' | 'newest'
ids?: string[]
first?: number
}
@@ -81,5 +48,5 @@ export type GetAllFacetsOperation<T extends FacetTypes = FacetTypes> = {
export type GetFacetOperation<T extends FacetTypes = FacetTypes> = {
data: { facet?: T['facet'] }
variables: { path: string; slug?: never } | { path?: never; slug: string }
variables: { code: string; } | { code?: never; }
}

View File

@@ -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[]
}
@@ -87,9 +88,16 @@ export type GetAllProductPathsOperation<
export type GetAllProductsOperation<T extends ProductTypes = ProductTypes> = {
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
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 (
<>
<p>
TOTAL: {products?.length}
</p>
{JSON.stringify(products[0])}
<HomeBanner />
<HomeFeature />
<HomeCategories />
@@ -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: { products },
props: {
freshProducts: rs[0].products,
featuredProducts: rs[1].products
},
revalidate: 60,
}
} catch (err) {
}
}

View File

@@ -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 (
<div className="w-full">
<CollectionCarcousel
type="highlight"
data={data}
itemKey="product-1"
title="Fresh Products Today"
subtitle="Last call! Shop deep deals on 100+ bulk picks while you can."
category={"veggie"}
/>
<CollectionCarcousel
data={dataTest}
itemKey="product-2"
title="VEGGIE"
subtitle="Last call! Shop deep deals on 100+ bulk picks while you can."
category={"veggie"}
/>
<CollectionCarcousel
data={dataTest}
itemKey="product-3"
title="VEGGIE"
subtitle="Last call! Shop deep deals on 100+ bulk picks while you can."
category={"veggie"}
/>
<CollectionCarcousel
data={dataTest}
itemKey="product-4"
title="VEGGIE"
subtitle="Last call! Shop deep deals on 100+ bulk picks while you can."
category={"veggie"}
/>
<CollectionCarcousel
data={dataTest}
itemKey="product-5"
title="VEGGIE"
subtitle="Last call! Shop deep deals on 100+ bulk picks while you can."
category={"veggie"}
/>
<CollectionCarcousel
data={dataTest}
itemKey="product-6"
title="VEGGIE"
subtitle="Last call! Shop deep deals on 100+ bulk picks while you can."
category={"veggie"}
/>
</div>
)
}
export default FreshProducts

View File

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

View File

@@ -108,6 +108,14 @@ export const CATEGORY = [
},
]
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',
},
]

View File

@@ -1,3 +1,7 @@
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
}
@@ -9,3 +13,17 @@ export function removeItem<T>(arr: Array<T>, value: T): Array<T> {
}
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
}