Merge pull request #75 from KieIO/feature/m2-collection

Get all collection
This commit is contained in:
lytrankieio123
2021-10-05 10:31:46 +07:00
committed by GitHub
17 changed files with 230 additions and 38 deletions

View File

@@ -2,8 +2,8 @@
"features": {
"cart": true,
"search": true,
"wishlist": false,
"customerAuth": false,
"customCheckout": false
"wishlist": true,
"customerAuth": true,
"customCheckout": true
}
}

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

@@ -1,4 +1,4 @@
import { CurrencyCode, FacetValue } from './../../vendure/schema.d';
import { CurrencyCode } from './../../vendure/schema.d';
import { FacetValueFilterInput, LogicalOperator, SearchResultSortParameter } from "@framework/schema"
export type ProductImage = {
@@ -59,8 +59,7 @@ export type ProductCard = {
weight?: number
facetValueIds?: string[],
collectionIds?: string[],
// TODO: collection
category?: string,
collection?: string,
isNotSell?: boolean
}

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

@@ -3240,6 +3240,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' } & {

View File

@@ -18,7 +18,6 @@ export function normalizeSearchResult(item: SearchResultFragment): ProductCard {
// 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

@@ -1,28 +1,31 @@
import { ProductCard } from '@commerce/types/product';
import { ProductVariables } from '@framework/api/operations/get-all-products';
import { FacetValue } from '@framework/schema';
import { Collection, FacetValue } from '@framework/schema';
import commerce from '@lib/api/commerce';
import { GetStaticPropsContext } from 'next';
import { Layout } from 'src/components/common';
import { FeaturedProductsCarousel, FreshProducts, HomeBanner, HomeCategories, HomeCollection, HomeCTA, HomeFeature, HomeRecipe, HomeSubscribe, HomeVideo } from 'src/components/modules/home';
import HomeSpice from 'src/components/modules/home/HomeSpice/HomeSpice';
import { CODE_FACET_DISCOUNT, CODE_FACET_FEATURED } from 'src/utils/constanst.utils';
import { getAllFacetValueIdsByParentCode, getAllFacetValuesForFeatuedProducts, getFreshFacetId } from 'src/utils/funtion.utils';
import { getAllFacetValueIdsByParentCode, getAllFacetValuesForFeatuedProducts, getAllPromies, getFreshFacetId } from 'src/utils/funtion.utils';
import { PromiseWithKey } from 'src/utils/types.utils';
interface Props {
featuredAndDiscountFacetsValue: FacetValue[],
freshProducts: ProductCard[],
featuredProducts: ProductCard[],
collections: Collection[]
}
export default function Home({ featuredAndDiscountFacetsValue,
freshProducts, featuredProducts }: Props) {
freshProducts, featuredProducts,
collections }: Props) {
return (
<>
<HomeBanner />
<HomeFeature />
<HomeCategories />
<FreshProducts data={freshProducts} />
<FreshProducts data={freshProducts} collections={collections} />
<HomeCollection />
<HomeVideo />
<HomeSpice />
@@ -44,13 +47,15 @@ export async function getStaticProps({
locales,
}: GetStaticPropsContext) {
const config = { locale, locales }
let promisesWithKey = [] as PromiseWithKey[]
let props = {} as any
const { facets } = await commerce.getAllFacets({
variables: {},
config,
preview,
})
const featuredAndDiscountFacetsValue = getAllFacetValuesForFeatuedProducts(facets)
props.featuredAndDiscountFacetsValue = getAllFacetValuesForFeatuedProducts(facets)
// fresh products
const freshProductvariables: ProductVariables = {}
@@ -63,6 +68,8 @@ export async function getStaticProps({
config,
preview,
})
promisesWithKey.push({ key: 'freshProducts', promise: freshProductsPromise, keyResult: 'products' })
// featured products
const allFeaturedFacetIds = getAllFacetValueIdsByParentCode(facets, CODE_FACET_FEATURED)
@@ -75,28 +82,33 @@ export async function getStaticProps({
config,
preview,
})
promisesWithKey.push({ key: 'featuredProducts', promise: featuredProductsPromise, keyResult: 'products' })
// collection
const collectionsPromise = commerce.getAllCollections({
variables: {},
config,
preview,
})
promisesWithKey.push({ key: 'collections', promise: collectionsPromise, keyResult: 'collections' })
try {
const rs = await Promise.all([
freshProductsPromise,
featuredProductsPromise,
])
const promises = getAllPromies(promisesWithKey)
const rs = await Promise.all(promises)
promisesWithKey.map((item, index) => {
props[item.key] = item.keyResult ? rs[index][item.keyResult] : rs[index]
return null
})
return {
props: {
featuredAndDiscountFacetsValue,
freshProducts: freshFacetId ? rs[0].products : [],
featuredProducts: facetValueIdsForFeaturedProducts.length > 0 ? rs[1].products : []
},
props,
revalidate: 60,
}
} catch (err) {
}
}

View File

@@ -2,6 +2,7 @@ import classNames from 'classnames'
import React from 'react'
import s from './LabelCommon.module.scss'
interface LabelCommonProps extends React.HTMLAttributes<HTMLDivElement> {
children?: React.ReactNode
size?: 'default' | 'large'
shape?: 'half' | 'round' | 'default'
type?: 'default' | 'discount' | 'waiting' | 'delivering' | 'delivered'

View File

@@ -17,7 +17,7 @@ export interface ProductCardProps extends ProductCard {
}
const ProductCardComponent = ({
category,
collection,
name,
slug,
weight,
@@ -45,9 +45,9 @@ const ProductCardComponent = ({
</a>
</Link>
{
category &&
collection &&
<div className={s.productLabel}>
<LabelCommon shape="half">{category}</LabelCommon>
<LabelCommon shape="half">{collection}</LabelCommon>
</div>
}
</div>

View File

@@ -12,7 +12,7 @@ interface ColectionCarcouselProps extends CollectionHeadingProps {
data: ProductCardProps[]
itemKey: string
viewAllLink?: string,
category:string
category?: string
}
const ColectionCarcousel = ({
@@ -21,7 +21,8 @@ const ColectionCarcousel = ({
title,
subtitle,
type,
category
category,
viewAllLink = ROUTE.PRODUCTS,
}: ColectionCarcouselProps) => {
return (
<div className={s.colectionCarcoucelWarpper}>
@@ -34,7 +35,7 @@ const ColectionCarcousel = ({
></CollectionHeading>
</div>
<div className={s.right}>
<ViewAllItem link={`${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=${category}`}/>
<ViewAllItem link={category ? `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=${category}` : viewAllLink} />
</div>
</div>
<div className={s.bot}>

View File

@@ -1,12 +1,32 @@
import { ProductCard } from '@commerce/types/product'
import { Product } from '@framework/schema'
import React from 'react'
import { Collection } from '@framework/schema'
import React, { useMemo } from 'react'
import { OPTION_ALL, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'
import { CollectionCarcousel } from '..'
interface FreshProductsProps {
data: ProductCard[]
collections: Collection[]
}
const FreshProducts = ({ data }: FreshProductsProps) => {
const getCategoryNameFromCollectionId = (colelctions: Collection[], collectionId?: string ) => {
if (!collectionId) {
return ''
}
const collection = colelctions.find(item => item.id === collectionId)
return collection?.name || ''
}
const FreshProducts = ({ data, collections }: FreshProductsProps) => {
const dataWithCategory = useMemo(() => {
return data.map(item => {
return {
...item,
collection: getCategoryNameFromCollectionId(collections, item.collectionIds ? item.collectionIds[0] : undefined)
}
})
}, [data, collections])
if (data.length === 0) {
return null
}
@@ -14,11 +34,11 @@ const FreshProducts = ({ data }: FreshProductsProps) => {
<div className="w-full">
<CollectionCarcousel
type="highlight"
data={data}
data={dataWithCategory}
itemKey="product-1"
title="Fresh Products Today"
subtitle="Last call! Shop deep deals on 100+ bulk picks while you can."
category={"veggie"}
viewAllLink={`${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=${OPTION_ALL}`}
/>
</div>
)

View File

@@ -1,6 +1,7 @@
import { Facet } from "@commerce/types/facet";
import { FacetValue } from './../../framework/vendure/schema.d';
import { CODE_FACET_DISCOUNT, CODE_FACET_FEATURED, CODE_FACET_FEATURED_VARIANT } from "./constanst.utils";
import { PromiseWithKey } from "./types.utils";
export function isMobile() {
return window.innerWidth < 768
@@ -55,4 +56,8 @@ export function getFacetNamesFromIds(facets: FacetValue[], ids?: string[]): stri
const facetItems = facets.filter((item: FacetValue) => ids.includes(item.id))
const names = facetItems.map((item: FacetValue) => item.name)
return names.join(", ")
}
}
export function getAllPromies (promies: PromiseWithKey[]) {
return promies.map(item => item.promise)
}

View File

@@ -50,4 +50,10 @@ export type filterContextType = {
visible: boolean;
open: () => void;
close: () => void;
};
};
export type PromiseWithKey = {
key: string
promise: PromiseLike<any>
keyResult?: string,
}