diff --git a/framework/commerce/api/operations.ts b/framework/commerce/api/operations.ts
index efbbce35d..afd725081 100644
--- a/framework/commerce/api/operations.ts
+++ b/framework/commerce/api/operations.ts
@@ -1,7 +1,8 @@
+import { GetAllRecipePathsOperation, GetRecipeDetailOperation,GetAllRecipesOperation } from './../types/recipes';
import { GetAllFacetsOperation } from './../types/facet';
import type { ServerResponse } from 'http'
import type { LoginOperation } from '../types/login'
-import type { GetAllPagesOperation, GetPageOperation } from '../types/page'
+import type { GetAllPagesOperation } from '../types/page'
import type { GetSiteInfoOperation } from '../types/site'
import type { GetCustomerWishlistOperation } from '../types/wishlist'
import type {
@@ -11,8 +12,13 @@ import type {
} from '../types/product'
import type {
GetAllBlogsOperation,
- GetFeaturedBlogsOperation
+ GetFeaturedBlogsOperation,
+ GetAllBlogPathsOperation,
+ GetBlogDetailOperation,
+ GetRelevantBlogsOperation
} from '../types/blogs'
+
+
import type { APIProvider, CommerceAPI } from '.'
import { GetAllCollectionsOperation } from '@commerce/types/collection';
@@ -32,7 +38,13 @@ export const OPERATIONS = [
'getAllFacets',
'getAllCollections',
'getAllBlogs',
- 'getFeaturedBlog'
+ 'getFeaturedBlog',
+ 'getAllBlogPaths',
+ 'getBlogDetail',
+ 'getRelevantBlogs',
+ 'getAllRecipes',
+ 'getAllRecipePaths',
+ 'getRecipeDetail'
] as const
export const defaultOperations = OPERATIONS.reduce((ops, k) => {
@@ -73,14 +85,14 @@ export type Operations
= {
): Promise
}
- getPage: {
- (opts: {
+ getRecipeDetail: {
+ (opts: {
variables: T['variables']
config?: P['config']
preview?: boolean
}): Promise
- (
+ (
opts: {
variables: T['variables']
config?: P['config']
@@ -133,6 +145,50 @@ export type Operations = {
): Promise
}
+
+ getAllBlogPaths: {
+ (opts: {
+ variables?: T['variables']
+ config?: P['config']
+ }): Promise
+
+ (
+ opts: {
+ variables?: T['variables']
+ config?: P['config']
+ } & OperationOptions
+ ): Promise
+ }
+
+ getAllRecipePaths: {
+ (opts: {
+ variables?: T['variables']
+ config?: P['config']
+ }): Promise
+
+ (
+ opts: {
+ variables?: T['variables']
+ config?: P['config']
+ } & OperationOptions
+ ): Promise
+ }
+
+ getAllRecipe: {
+ (opts: {
+ variables?: T['variables']
+ config?: P['config']
+ }): Promise
+
+ (
+ opts: {
+ variables?: T['variables']
+ config?: P['config']
+ } & OperationOptions
+ ): Promise
+ }
+
+
getAllProducts: {
(opts: {
variables?: T['variables']
@@ -166,6 +222,38 @@ export type Operations = {
): Promise
}
+ getAllRecipes: {
+ (opts: {
+ variables?: T['variables']
+ config?: P['config']
+ preview?: boolean
+ }): Promise
+
+ (
+ opts: {
+ variables?: T['variables']
+ config?: P['config']
+ preview?: boolean
+ } & OperationOptions
+ ): Promise
+ }
+
+ getRelevantBlogs: {
+ (opts: {
+ variables?: T['variables']
+ config?: P['config']
+ preview?: boolean
+ }): Promise
+
+ (
+ opts: {
+ variables?: T['variables']
+ config?: P['config']
+ preview?: boolean
+ } & OperationOptions
+ ): Promise
+ }
+
getFeaturedBlog: {
(opts: {
variables?: T['variables']
@@ -182,6 +270,21 @@ export type Operations = {
): Promise
}
+ getBlogDetail: {
+ (opts: {
+ variables?: T['variables']
+ config?: P['config']
+ preview?: boolean
+ }): Promise
+
+ (
+ opts: {
+ variables?: T['variables']
+ config?: P['config']
+ preview?: boolean
+ } & OperationOptions
+ ): Promise
+ }
getProduct: {
diff --git a/framework/commerce/types/blogs.ts b/framework/commerce/types/blogs.ts
index fcdca972d..7957908b6 100644
--- a/framework/commerce/types/blogs.ts
+++ b/framework/commerce/types/blogs.ts
@@ -14,13 +14,27 @@ export type BlogsType = {
totalItems: number
}
export type GetAllBlogsOperation = {
- data: { items: T['items'][] }
+ data: { items: T['items'][], totalItems: number }
+ variables: {
+ productId: number,
+ take?: number
+ skip?: number
+ }
+}
+export type GetRelevantBlogsOperation = {
+ data: { items: T['items'][], totalItems: number }
variables: {
take?: number
skip?: number
}
}
+export type GetBlogDetailOperation = {
+ data: T['items'],
+ variables: {
+ slug?: string
+ }
+}
export type GetFeaturedBlogsOperation = {
data: { items: T['items'][] }
@@ -28,4 +42,10 @@ export type GetFeaturedBlogsOperation = {
take?: number
skip?: number
}
-}
\ No newline at end of file
+}
+export type GetAllBlogPathsOperation<
+T extends BlogsType = BlogsType
+> = {
+ data: { blogs: Pick[] }
+ variables: { first?: number }
+}
diff --git a/framework/commerce/types/product.ts b/framework/commerce/types/product.ts
index e31f34df9..421100581 100644
--- a/framework/commerce/types/product.ts
+++ b/framework/commerce/types/product.ts
@@ -1,3 +1,4 @@
+import { BlogsType } from './blogs';
import { CurrencyCode } from './../../vendure/schema.d';
import { FacetValueFilterInput, LogicalOperator, SearchResultSortParameter } from "@framework/schema"
@@ -110,6 +111,8 @@ export type GetAllProductPathsOperation<
variables: { first?: number }
}
+
+
export type GetAllProductsOperation = {
data: { products: T['product'][] }
variables: {
diff --git a/framework/commerce/types/recipes.ts b/framework/commerce/types/recipes.ts
new file mode 100644
index 000000000..037855f32
--- /dev/null
+++ b/framework/commerce/types/recipes.ts
@@ -0,0 +1,45 @@
+import { Asset, BlogTranslation, Maybe, Product } from './../../vendure/schema.d';
+
+export type RecipeList = Node &{
+ id: string
+ featuredAsset?: Maybe
+ isPublish:Boolean
+ translations: Array
+ authorName: string
+ authorAvatarAsset:Array
+ relevantProducts: Product
+ link:String
+ minutes:Number
+ people:Number
+}
+export type RecipesType = {
+ items: RecipeList
+ totalItems: number
+}
+
+export enum SortRecipes {
+ ASC = 'ASC',
+ DESC = 'DESC',
+}
+
+export type GetAllRecipesOperation = {
+ data: { items: T['items'][], totalItems: number }
+ variables: {
+ excludeBlogIds:Array,
+ take?: number
+ id?: SortRecipes
+ }
+}
+export type GetAllRecipePathsOperation<
+T extends RecipesType = RecipesType
+> = {
+ data: { recipes: Pick[] }
+ variables: { first?: number }
+}
+
+export type GetRecipeDetailOperation = {
+ data: T['items'],
+ variables: {
+ slug?: string
+ }
+}
\ No newline at end of file
diff --git a/framework/vendure/api/index.ts b/framework/vendure/api/index.ts
index edf67d14f..3d9c9219f 100644
--- a/framework/vendure/api/index.ts
+++ b/framework/vendure/api/index.ts
@@ -1,18 +1,25 @@
import type { CommerceAPIConfig } from '@commerce/api'
import { CommerceAPI, getCommerceApi as commerceApi } from '@commerce/api'
-import getAllFacets from './operations/get-all-facets'
+import getAllBlogs from './operations/get-all-blogs'
import getAllCollections from './operations/get-all-collection'
+import getAllFacets from './operations/get-all-facets'
import getAllPages from './operations/get-all-pages'
import getAllProductPaths from './operations/get-all-product-paths'
import getAllProducts from './operations/get-all-products'
+import getBlogDetail from './operations/get-blog-detail'
import getCustomerWishlist from './operations/get-customer-wishlist'
+import getFeaturedBlog from './operations/get-featured-blog'
import getPage from './operations/get-page'
import getProduct from './operations/get-product'
import getSiteInfo from './operations/get-site-info'
+import getAllBlogPaths from './operations/get-all-blog-paths'
+import getRelevantBlogs from './operations/get-relevant-blogs'
+import getAllRecipes from './operations/get-all-recipes'
+import getAllRecipePaths from './operations/get-all-recipe-paths'
+import getRecipeDetail from './operations/get-recipe-detail'
+
import login from './operations/login'
import fetchGraphqlApi from './utils/fetch-graphql-api'
-import getAllBlogs from './operations/get-all-blogs'
-import getFeaturedBlog from './operations/get-featured-blog'
export interface VendureConfig extends CommerceAPIConfig {}
@@ -46,7 +53,13 @@ const operations = {
getAllFacets,
getAllCollections,
getAllBlogs,
- getFeaturedBlog
+ getFeaturedBlog,
+ getBlogDetail,
+ getAllBlogPaths,
+ getRelevantBlogs,
+ getAllRecipes,
+ getAllRecipePaths,
+ getRecipeDetail
}
export const provider = { config, operations }
diff --git a/framework/vendure/api/operations/get-all-blog-paths.ts b/framework/vendure/api/operations/get-all-blog-paths.ts
new file mode 100644
index 000000000..cdfce36f7
--- /dev/null
+++ b/framework/vendure/api/operations/get-all-blog-paths.ts
@@ -0,0 +1,53 @@
+import { BlogList } from './../../schema.d';
+import { OperationContext,OperationOptions } from '@commerce/api/operations';
+import { BigcommerceConfig } from '../../../bigcommerce/api';
+import type { GetAllBlogPathsQuery,BlogTranslation } from '../../schema';
+import { getAllBlogPathsQuery } from '../../utils/queries/get-all-blog-paths-query';
+import { Provider } from '../index';
+import { GetAllBlogPathsOperation } from './../../../commerce/types/blogs';
+
+export type GetAllBlogPathsResult = {
+ blogs: Array<{ node: { path: string } }>
+}
+
+export default function getAllBlogPathsOperation({
+ commerce,
+}: OperationContext) {
+ async function getAllBlogPaths<
+ T extends GetAllBlogPathsOperation
+ >(opts?: {
+ variables?: T['variables']
+ config?: BigcommerceConfig
+ }): Promise
+
+ async function getAllBlogPaths(
+ opts: {
+ variables?: T['variables']
+ config?: BigcommerceConfig
+ } & OperationOptions
+ ): Promise
+
+ async function getAllBlogPaths({
+ query = getAllBlogPathsQuery,
+ variables,
+ config: cfg,
+ }: {
+ query?: string
+ variables?: T['variables']
+ config?: BigcommerceConfig
+ } = {}): Promise {
+ const config = commerce.getConfig(cfg)
+
+ const { data } = await config.fetch(query, {
+ variables,
+ })
+
+ const blogs = data.blogs.items;
+
+ return {
+ blogs: blogs?.map(val=>val.translations.map((p:BlogTranslation) => ({ path: `/${p.slug}` })))
+ }
+ }
+
+ return getAllBlogPaths
+}
diff --git a/framework/vendure/api/operations/get-all-blogs.ts b/framework/vendure/api/operations/get-all-blogs.ts
index 3dc6565fa..bf3ba7be0 100644
--- a/framework/vendure/api/operations/get-all-blogs.ts
+++ b/framework/vendure/api/operations/get-all-blogs.ts
@@ -6,7 +6,12 @@ import { getAllBlogsQuery } from '../../utils/queries/get-all-blog-query'
export type BlogVariables = {
excludeBlogIds?: string[],
take?: number,
- skip?:number
+ skip?:number,
+ filter?:{
+ isFeatured?:{
+ eq?:Boolean
+ }
+ },
}
export default function getAllBlogsOperation({
@@ -34,7 +39,9 @@ export default function getAllBlogsOperation({
excludeBlogIds: vars.excludeBlogIds,
options: {
take: vars.take,
- skip: vars.skip,
+ filter: {
+ isFeatured: vars.filter?.isFeatured
+ }
},
}
const { data } = await config.fetch(query, {
@@ -51,7 +58,7 @@ export default function getAllBlogsOperation({
isPublish: val.isPublish,
isFeatured: val.isFeatured,
authorName: val.authorName,
- authorAvatarAsset : val.authorAvatarAsset?.preview,
+ authorAvatarAsset : val.authorAvatarAsset?.preview ?? null,
createdAt: val.createdAt
})),
totalItems: data?.blogs?.totalItems || null
diff --git a/framework/vendure/api/operations/get-all-recipe-paths.ts b/framework/vendure/api/operations/get-all-recipe-paths.ts
new file mode 100644
index 000000000..ac09dbd1c
--- /dev/null
+++ b/framework/vendure/api/operations/get-all-recipe-paths.ts
@@ -0,0 +1,53 @@
+import { BlogList } from '../../schema';
+import { OperationContext,OperationOptions } from '@commerce/api/operations';
+import { BigcommerceConfig } from '../../../bigcommerce/api';
+import type { GetAllRecipePathsQuery,RecipeTranslation } from '../../schema';
+import { getAllBlogPathsQuery } from '../../utils/queries/get-all-blog-paths-query';
+import { Provider } from '../index';
+import { GetAllRecipesPathsOperation } from '../../../commerce/types/recipes';
+
+export type GetAllBlogPathsResult = {
+ blogs: Array<{ node: { path: string } }>
+}
+
+export default function getAllRecipePathsOperation({
+ commerce,
+}: OperationContext) {
+ async function getAllRecipePaths<
+ T extends GetAllRecipesPathsOperation
+ >(opts?: {
+ variables?: T['variables']
+ config?: BigcommerceConfig
+ }): Promise
+
+ async function getAllRecipePaths(
+ opts: {
+ variables?: T['variables']
+ config?: BigcommerceConfig
+ } & OperationOptions
+ ): Promise
+
+ async function getAllRecipePaths({
+ query = getAllBlogPathsQuery,
+ variables,
+ config: cfg,
+ }: {
+ query?: string
+ variables?: T['variables']
+ config?: BigcommerceConfig
+ } = {}): Promise {
+ const config = commerce.getConfig(cfg)
+
+ const { data } = await config.fetch(query, {
+ variables,
+ })
+
+ const recipes = data.blogs.items;
+
+ return {
+ recipes: recipes?.map(val=>val.translations.map((p:RecipeTranslation) => ({ path: `/${p.slug}` })))
+ }
+ }
+
+ return getAllRecipePaths
+}
diff --git a/framework/vendure/api/operations/get-all-recipes.ts b/framework/vendure/api/operations/get-all-recipes.ts
new file mode 100644
index 000000000..4998d793e
--- /dev/null
+++ b/framework/vendure/api/operations/get-all-recipes.ts
@@ -0,0 +1,70 @@
+import { OperationContext } from '@commerce/api/operations'
+import { Provider, VendureConfig } from '..'
+import { BlogList, GetAllRecipesQuery } from '../../schema'
+import { getAllBlogsQuery } from '../../utils/queries/get-all-blog-query'
+
+export type RecipesVariables = {
+ excludeBlogIds?: string[],
+ take?:number,
+ id?: string,
+ isPublish?:Boolean
+}
+
+export default function getAllRecipesOperation({
+ commerce,
+}: OperationContext) {
+ async function getAllRecipes(opts?: {
+ variables?: RecipesVariables
+ config?: Partial
+ preview?: boolean
+ }): Promise<{ recipes: GetAllRecipesQuery[],totalItems:number }>
+
+ async function getAllRecipes({
+ query = getAllBlogsQuery,
+ variables: { ...vars } = {},
+ config: cfg,
+ }: {
+ query?: string
+ variables?: RecipesVariables
+ config?: Partial
+ preview?: boolean
+ } = {}): Promise<{ recipes: GetAllRecipesQuery[] | any[] ,totalItems?:number }> {
+
+ const config = commerce.getConfig(cfg)
+ const variables = {
+ excludeBlogIds: vars.excludeBlogIds,
+ options: {
+ take: vars.take,
+ sort: {
+ id: vars?.id
+ },
+ filter:{
+ isPublish: {
+ eq:vars.isPublish
+ }
+ }
+ },
+ }
+
+ const { data } = await config.fetch(query, {
+ variables,
+ })
+
+ return {
+ recipes: data?.blogs?.items?.map((val:BlogList)=>({
+ id: val.id,
+ title: val.translations[0]?.title,
+ imageSrc: val.featuredAsset?.preview ?? null,
+ slug: val.translations[0]?.slug,
+ description: val.translations[0]?.description,
+ isPublish: val.isPublish,
+ authorName: val.authorName,
+ authorAvatarAsset : val.authorAvatarAsset?.preview ?? null,
+ createdAt: val.createdAt
+ })),
+ totalItems: data?.blogs?.totalItems || null
+ }
+ }
+
+ return getAllRecipes
+}
diff --git a/framework/vendure/api/operations/get-blog-detail.ts b/framework/vendure/api/operations/get-blog-detail.ts
new file mode 100644
index 000000000..6b8e92967
--- /dev/null
+++ b/framework/vendure/api/operations/get-blog-detail.ts
@@ -0,0 +1,55 @@
+import { OperationContext } from '@commerce/api/operations'
+import { Provider, VendureConfig } from '..'
+import { GetBlogQuery,BlogList } from '../../schema'
+import { getBlogDetailQuery } from '../../utils/queries/get-blog-detail'
+
+export type BlogVariables = {
+ slug?: string,
+}
+
+export default function getBlogDetailOperation({
+ commerce,
+}: OperationContext) {
+ async function getBlogDetail(opts?: {
+ variables?: BlogVariables
+ config?: Partial
+ preview?: boolean
+ }): Promise<{ blogDetail: BlogList}>
+
+ async function getBlogDetail({
+ query = getBlogDetailQuery,
+ variables: { ...vars } = {},
+ config: cfg,
+ }: {
+ query?: string
+ variables?: BlogVariables
+ config?: Partial
+ preview?: boolean
+ } = {}): Promise<{ blogDetail: BlogList | any }> {
+
+ const config = commerce.getConfig(cfg)
+ const variables = {
+ slug: vars.slug
+ }
+ const { data } = await config.fetch(query, {
+ variables,
+ })
+ return {
+ blogDetail: {
+ id:data?.blog?.id,
+ title: data?.blog?.translations[0].title,
+ imageSrc: data?.blog?.featuredAsset?.preview ?? null,
+ slug: data?.blog?.translations[0]?.slug,
+ description: data?.blog?.translations[0]?.description,
+ isPublish: data?.blog?.isPublish,
+ isFeatured: data?.blog?.isFeatured,
+ authorName: data?.blog?.authorName,
+ authorAvatarAsset : data?.blog?.authorAvatarAsset?.preview,
+ createdAt: data?.blog?.createdAt,
+ relevantProducts: data?.blog?.relevantProducts.map(val=>val.id)
+ }
+ }
+ }
+
+ return getBlogDetail
+}
diff --git a/framework/vendure/api/operations/get-featured-blog.ts b/framework/vendure/api/operations/get-featured-blog.ts
index 727db46ed..cb101d6c4 100644
--- a/framework/vendure/api/operations/get-featured-blog.ts
+++ b/framework/vendure/api/operations/get-featured-blog.ts
@@ -5,7 +5,12 @@ import { getFeatuedBlogsQuery } from '../../utils/queries/get-featued-query'
export type BlogVariables = {
take?: number,
- skip?:number
+ skip?:number,
+ filter?:{
+ isFeatured?:{
+ eq?:Boolean
+ }
+ },
}
export default function getFeaturedBlogOperation({
@@ -31,6 +36,9 @@ export default function getFeaturedBlogOperation({
const variables = {
options: {
take: vars.take,
+ filter: {
+ isFeatured: vars.filter?.isFeatured
+ }
},
}
const { data } = await config.fetch(query, {
@@ -46,7 +54,7 @@ export default function getFeaturedBlogOperation({
isPublish: val.isPublish,
isFeatured: val.isFeatured,
authorName: val.authorName,
- authorAvatarAsset : val.authorAvatarAsset?.preview,
+ authorAvatarAsset : val.authorAvatarAsset?.preview ?? null,
createdAt: val.createdAt
}))
}
diff --git a/framework/vendure/api/operations/get-recipe-detail.ts b/framework/vendure/api/operations/get-recipe-detail.ts
new file mode 100644
index 000000000..e8b2b167f
--- /dev/null
+++ b/framework/vendure/api/operations/get-recipe-detail.ts
@@ -0,0 +1,98 @@
+import { OperationContext } from '@commerce/api/operations'
+import { Provider, VendureConfig } from '..'
+import { GetRecipeQuery, RecipeList } from '../../schema'
+import { getBlogDetailQuery } from '../../utils/queries/get-blog-detail'
+
+
+export default function getRecipeDetailOperation({
+ commerce,
+}: OperationContext) {
+
+ async function getRecipeDetail({
+ query = getBlogDetailQuery,
+ variables,
+ config: cfg,
+ }: {
+ query?: string
+ variables: { slug: string }
+ config?: Partial
+ preview?: boolean
+ }): Promise<{recipeDetail: RecipeList | any }> {
+ const config = commerce.getConfig(cfg)
+ const { data } = await config.fetch(query, {
+ variables,
+ })
+ const recipes = data.blog
+
+ if (recipes) {
+ return {
+ recipeDetail: {
+ id: data?.blog?.id,
+ title: data?.blog?.translations[0].title,
+ imageSrc: data?.blog?.featuredAsset?.preview ?? null,
+ slug: data?.blog?.translations[0]?.slug,
+ description: data?.blog?.translations[0]?.description,
+ isPublish: data?.blog?.isPublish,
+ authorName: data?.blog?.authorName,
+ authorAvatarAsset : data?.blog?.authorAvatarAsset?.preview,
+ createdAt: data?.blog?.createdAt,
+ relevantProducts: data?.blog?.relevantProducts.map(val=>val.id)
+ }
+ }
+ }else{
+ return {recipeDetail:null}
+ }
+ }
+
+ return getRecipeDetail
+}
+
+
+// export type RecipeVariables = {
+// slug?: string,
+// }
+
+// export default function getRecipeDetailOperation({
+// commerce,
+// }: OperationContext) {
+
+// async function getRecipeDetail(opts?: {
+// variables?: RecipeVariables
+// config?: Partial
+// preview?: boolean
+// }): Promise<{ recipeDetail: RecipeList}>
+
+// async function getRecipeDetail({
+// query = getBlogDetailQuery,
+// variables: { ...vars } = {},
+// config: cfg,
+// }: {
+// query?: string
+// variables?: RecipeVariables
+// config?: Partial
+// preview?: boolean
+// } = {}): Promise<{ recipeDetail: RecipeList | any }> {
+
+// const config = commerce.getConfig(cfg)
+// const variables = {
+// slug: vars.slug
+// }
+// const { data } = await config.fetch(query, {
+// variables,
+// })
+// return {
+// id: data?.blog?.id,
+// title: data?.blog?.translations[0].title,
+// imageSrc: data?.blog?.featuredAsset?.preview ?? null,
+// slug: data?.blog?.translations[0]?.slug,
+// description: data?.blog?.translations[0]?.description,
+// isPublish: data?.blog?.isPublish,
+// authorName: data?.blog?.authorName,
+// authorAvatarAsset : data?.blog?.authorAvatarAsset?.preview,
+// createdAt: data?.blog?.createdAt,
+// relevantProducts: data?.blog?.relevantProducts.map(val=>val.id)
+// }
+// }
+
+// return getRecipeDetail
+// }
diff --git a/framework/vendure/api/operations/get-relevant-blogs.ts b/framework/vendure/api/operations/get-relevant-blogs.ts
new file mode 100644
index 000000000..3b9259c6a
--- /dev/null
+++ b/framework/vendure/api/operations/get-relevant-blogs.ts
@@ -0,0 +1,54 @@
+import { OperationContext } from '@commerce/api/operations'
+import { Provider, VendureConfig } from '..'
+import { BlogList,GetRelevantBlogsQuery } from '../../schema'
+import { getRelevantBlogsQuery } from '../../utils/queries/get-relevant-blogs'
+
+export type BlogVariables = {
+ productId?: number,
+}
+
+export default function getRelevantBlogsOperation({
+ commerce,
+}: OperationContext) {
+ async function getRelevantBlogs(opts?: {
+ variables?: BlogVariables
+ config?: Partial
+ preview?: boolean
+ }): Promise<{ relevantBlogs: GetRelevantBlogsQuery[]}>
+
+ async function getRelevantBlogs({
+ query = getRelevantBlogsQuery,
+ variables: { ...vars } = {},
+ config: cfg,
+ }: {
+ query?: string
+ variables?: BlogVariables
+ config?: Partial
+ preview?: boolean
+ } = {}): Promise<{ relevantBlogs: GetRelevantBlogsQuery[] | any[] }> {
+
+ const config = commerce.getConfig(cfg)
+ const variables = {
+ productId: vars.productId,
+ }
+ const { data } = await config.fetch(query, {
+ variables,
+ })
+ return {
+ relevantBlogs: data?.relevantBlogs?.items?.map((val:BlogList)=>({
+ id: val.id,
+ title: val.translations[0]?.title,
+ imageSrc: val.featuredAsset?.preview ?? null,
+ slug: val.translations[0]?.slug,
+ description: val.translations[0]?.description,
+ isPublish: val.isPublish,
+ isFeatured: val.isFeatured,
+ authorName: val.authorName,
+ authorAvatarAsset : val.authorAvatarAsset?.preview,
+ createdAt: val.createdAt
+ })),
+ }
+ }
+
+ return getRelevantBlogs
+}
diff --git a/framework/vendure/schema.d.ts b/framework/vendure/schema.d.ts
index a1a6b7b49..cb3a56ef3 100644
--- a/framework/vendure/schema.d.ts
+++ b/framework/vendure/schema.d.ts
@@ -2388,10 +2388,66 @@ export type BlogList = Node &{
translations: Array
authorName: Scalars['String']
authorAvatarAsset:Asset
- relevantProducts: Product
+ relevantProducts: Product[]
isFeatured: Boolean
}
+export type RecipeList = Node &{
+ id: ID!
+ createdAt: DateTime!
+ updatedAt: DateTime!
+ featuredAsset?: Maybe
+ isPublish:Boolean
+ translations: Array
+ authorName: Scalars['String']
+ authorAvatarAsset:Asset
+ relevantProducts: Product[]
+ link:String
+ minutes:Number
+ people:Number
+}
+
+export enum SortRecipes {
+ ASC = 'ASC',
+ DESC = 'DESC',
+}
+
+export type RecipeTranslation = {
+ __typename?: 'RecipeTranslation'
+ id: Scalars['ID']
+ createdAt: Scalars['DateTime']
+ updatedAt: Scalars['DateTime']
+ languageCode: LanguageCode
+ title: Scalars['String']
+ slug: Scalars['String']
+ description: Scalars['String']
+ content: Scalars['String']
+ Ingredients:Scalars['String']
+ Preparation:Scalars['String']
+}
+
+export type IngredientProducts = {
+ __typename?: 'IngredientProduct'
+ id: Scalars['ID']
+ createdAt: Scalars['DateTime']
+ updatedAt: Scalars['DateTime']
+ product: Product[]
+}
+
+
+export type GetBlogQuery = { __typename?: 'Query' } & {
+ blog?: Maybe<
+ { __typename?: 'Blog' } & BlogList
+ >
+}
+
+export type GetRecipeQuery = { __typename?: 'Query' } & {
+ recipeDetail?: Maybe<
+ { __typename?: 'Recipe' } & RecipeList
+ >
+}
+
+
export type BlogTranslation = {
__typename?: 'BlogTranslation'
id: Scalars['ID']
@@ -2403,6 +2459,18 @@ export type BlogTranslation = {
description: Scalars['String']
content: Scalars['String']
}
+export type RecipeTranslation = {
+ __typename?: 'BlogTranslation'
+ id: Scalars['ID']
+ createdAt: Scalars['DateTime']
+ updatedAt: Scalars['DateTime']
+ languageCode: LanguageCode
+ title: Scalars['String']
+ slug: Scalars['String']
+ description: Scalars['String']
+ content: Scalars['String']
+}
+
export type GetAllBlogsQuery = PaginatedList & {
blogs: { __typename?: 'BlogList' } & {
@@ -2410,6 +2478,21 @@ export type GetAllBlogsQuery = PaginatedList & {
'totalItems'
}
}
+
+export type GetAllRecipesQuery = PaginatedList & {
+ recipes: { __typename?: 'RecipeList' } & {
+ items: Array<{ __typename?: 'Recipe' } & RecipeList!>,
+ 'totalItems'
+ }
+}
+
+
+export type GetRelevantBlogsQuery = PaginatedList & {
+ relevantBlogs: { __typename?: 'BlogList' } & {
+ items: Array<{ __typename?: 'Blog' } & BlogList!>,
+ }
+}
+
export type GetFeaturedBlogQuery = PaginatedList & {
id:string,
featuredBlogs: { __typename?: 'BlogList' } & {
@@ -2418,11 +2501,26 @@ export type GetFeaturedBlogQuery = PaginatedList & {
}
}
+
export type QueryBlogs = {
excludeBlogIds:Array,
options: BlogListOptions
}
+export type QueryRecipes = {
+ excludeBlogIds?:Maybe,
+ options: RecipeListOptions
+}
+
+export type RecipeListOptions = {
+ skip?: Maybe
+ take?: Maybe
+ sort?: RecipesSort
+}
+export type RecipesSort = {
+ id?: Maybe
+}
+
export type BlogListOptions = {
skip?: Maybe
take?: Maybe
@@ -3448,6 +3546,19 @@ export type GetAllProductPathsQuery = { __typename?: 'Query' } & {
items: Array<{ __typename?: 'Product' } & Pick>
}
}
+
+export type GetAllBlogPathsQuery = { __typename?: 'Query' } & {
+ blogs: { __typename?: 'BlogList' } & {
+ items: Array<{ __typename?: 'Blog' } & Pick>
+ }
+}
+
+export type GetAllRecipePathsQuery = { __typename?: 'Query' } & {
+ recipes: { __typename?: 'Recipes' } & {
+ items: Array<{ __typename?: 'Recipe' } & Pick>
+ }
+}
+
export type GetAllProductsQueryVariables = Exact<{
input: SearchInput
diff --git a/framework/vendure/utils/normalize.ts b/framework/vendure/utils/normalize.ts
index b9c55680e..1bda5f098 100644
--- a/framework/vendure/utils/normalize.ts
+++ b/framework/vendure/utils/normalize.ts
@@ -1,6 +1,6 @@
-import { Cart, CartCheckout } from '@commerce/types/cart'
-import { Product, ProductCard } from '@commerce/types/product'
-import { CartFragment, Favorite, SearchResultFragment, ShippingMethod, BlogList } from '../schema'
+import { Cart } from '@commerce/types/cart'
+import { ProductCard, Product } from '@commerce/types/product'
+import { CartFragment, SearchResultFragment,Favorite, BlogList, RecipeList,ShippingMethod } from '../schema'
export function normalizeSearchResult(item: SearchResultFragment): ProductCard {
return {
@@ -155,4 +155,18 @@ export function normalizeBlogList(blog: BlogList) {
authorAvatarAsset : blog.authorAvatarAsset?.preview,
createdAt: blog.createdAt
}
+}
+
+export function normalizeRecipeList(recipe: RecipeList) {
+ return {
+ id: recipe.id,
+ title: recipe.translations[0]?.title,
+ imageSrc: recipe.featuredAsset?.preview ?? null,
+ slug: recipe.translations[0]?.slug,
+ description: recipe.translations[0]?.description,
+ isPublish: recipe.isPublish,
+ authorName: recipe.authorName,
+ authorAvatarAsset : recipe.authorAvatarAsset?.preview,
+ createdAt: recipe.createdAt
+ }
}
\ No newline at end of file
diff --git a/framework/vendure/utils/queries/get-all-blog-paths-query.ts b/framework/vendure/utils/queries/get-all-blog-paths-query.ts
new file mode 100644
index 000000000..69d89ca36
--- /dev/null
+++ b/framework/vendure/utils/queries/get-all-blog-paths-query.ts
@@ -0,0 +1,11 @@
+export const getAllBlogPathsQuery = /* GraphQL */ `
+query getAllBlogPaths($excludeBlogIds: [ID]! = [],$options:BlogListOptions){
+ blogs(excludeBlogIds: $excludeBlogIds,options: $options){
+ items{
+ translations {
+ slug
+ }
+ }
+ }
+}
+`
diff --git a/framework/vendure/utils/queries/get-blog-detail.ts b/framework/vendure/utils/queries/get-blog-detail.ts
new file mode 100644
index 000000000..a8b8fbe53
--- /dev/null
+++ b/framework/vendure/utils/queries/get-blog-detail.ts
@@ -0,0 +1,26 @@
+export const getBlogDetailQuery = /* GraphQL */ `
+query getBlog($slug: String ){
+ blog(slug: $slug){
+ id
+ isPublish
+ isFeatured
+ authorName
+ createdAt
+ authorAvatarAsset{
+ preview
+ }
+ featuredAsset {
+ preview
+ }
+ translations {
+ title
+ slug
+ description
+ content
+ }
+ relevantProducts{
+ id
+ }
+ }
+ }
+`
\ No newline at end of file
diff --git a/framework/vendure/utils/queries/get-relevant-blogs.ts b/framework/vendure/utils/queries/get-relevant-blogs.ts
new file mode 100644
index 000000000..91c8ebe16
--- /dev/null
+++ b/framework/vendure/utils/queries/get-relevant-blogs.ts
@@ -0,0 +1,25 @@
+export const getRelevantBlogsQuery = /* GraphQL */ `
+query relevantBlogs($productId: ID!){
+ relevantBlogs(productId:$productId){
+ items {
+ id
+ isPublish
+ isFeatured
+ authorName
+ createdAt
+ authorAvatarAsset{
+ preview
+ }
+ featuredAsset {
+ preview
+ }
+ translations {
+ title
+ slug
+ description
+ content
+ }
+ }
+ }
+}
+`
diff --git a/pages/blog/[slug].tsx b/pages/blog/[slug].tsx
index 8aaca04a9..26325f5be 100644
--- a/pages/blog/[slug].tsx
+++ b/pages/blog/[slug].tsx
@@ -2,16 +2,111 @@ import { Layout, RelevantBlogPosts } from 'src/components/common';
import BlogContent from 'src/components/modules/blog-detail/BlogContent/BlogContent';
import BlogDetailImg from 'src/components/modules/blog-detail/BlogDetailImg/BlogDetailImg';
import { BLOGS_DATA_TEST } from 'src/utils/demo-data'
+import { GetStaticPropsContext,GetStaticPathsContext } from 'next';
+import { PromiseWithKey } from 'src/utils/types.utils';
+import { getAllPromies } from 'src/utils/funtion.utils';
+import commerce from '@lib/api/commerce';
+import { BlogCardProps } from 'src/components/common/CardBlog/CardBlog';
+import { REVALIDATE_TIME } from 'src/utils/constanst.utils'
+interface Props {
+ blog:{blogDetail?: BlogCardProps},
+ relevant:{relevantBlogs?:BlogCardProps[]}
+}
+export default function BlogDetailPage({blog,relevant}:Props) {
-
-export default function BlogDetailPage() {
+ let date = new Date(blog?.blogDetail?.createdAt ?? '' );
+ let fullDate = date.toLocaleString('en-us', { month: 'long' }) + " " + date.getDate()+","+date.getFullYear();
+
return (
<>
-
-
-
+
+
+ {relevant.relevantBlogs?.length> 0 && }
>
)
}
+
+export async function getStaticProps({
+ params,
+ locale,
+ locales,
+ preview,
+}: GetStaticPropsContext<{ slug: string }> ) {
+ const config = { locale, locales }
+ let promisesWithKey = [] as PromiseWithKey[]
+ let props = {} as any
+
+ // Blog detail
+ const blogDetailPromise = await commerce.getBlogDetail({
+ variables: { slug: params!.slug },
+ config,
+ preview,
+ })
+ props.blog = blogDetailPromise;
+
+ if (!blogDetailPromise) {
+ throw new Error(`Blog with slug '${params!.slug}' not found`)
+ }
+
+ // Relevant Blogs
+ const relevantProductId = blogDetailPromise.blogDetail.relevantProducts?.[0];
+ if (relevantProductId && blogDetailPromise.blogDetail.relevantProducts.length > 0) {
+
+ const relevantBlogs = commerce.getRelevantBlogs({
+ variables: { productId: relevantProductId },
+ config,
+ preview,
+ })
+ promisesWithKey.push({ key: 'relevant', promise: relevantBlogs})
+
+ }else {
+ props.relevantBlogs = [];
+ }
+
+
+ try {
+ 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
+ })
+
+ console.log(props.relevantBlogs);
+ return {
+ props,
+ revalidate: REVALIDATE_TIME,
+ }
+ } catch (err) {
+
+ }
+}
+
+export async function getStaticPaths({ locales }: GetStaticPathsContext) {
+
+ const { blogs } = await commerce.getAllBlogPaths()
+
+ return {
+ paths: locales
+ ? locales.reduce((arr, locale) => {
+ blogs.forEach((blog: any) => {
+ arr.push(`/${locale}/blog/${blog.slug}`)
+ })
+ return arr
+ }, [])
+ : blogs.map((product: any) => `/blog/${product.path}`),
+ fallback: 'blocking',
+ }
+}
+
+
+
BlogDetailPage.Layout = Layout
diff --git a/pages/blogs.tsx b/pages/blogs.tsx
index a9ebf5866..f4be801aa 100644
--- a/pages/blogs.tsx
+++ b/pages/blogs.tsx
@@ -13,7 +13,7 @@ interface Props {
totalItems: number
}
export default function BlogsPage({ blogs, featuredBlog, totalItems }:Props) {
-
+
let date = new Date(featuredBlog?.[0]?.createdAt ?? '' );
let fullDate = date.toLocaleString('en-us', { month: 'long' }) + " " + date.getDate()+","+date.getFullYear();
@@ -21,16 +21,18 @@ export default function BlogsPage({ blogs, featuredBlog, totalItems }:Props) {
<>
-
-
+ { (featuredBlog?.length !=0 ) &&
+
+ }
+
>
)
}
@@ -47,7 +49,12 @@ export async function getStaticProps({
const {featuredBlogs} = await commerce.getFeaturedBlog({
variables: {
- take: 1
+ take: 1,
+ filter: {
+ isFeatured: {
+ eq:true
+ }
+ }
},
config,
preview,
@@ -58,7 +65,12 @@ export async function getStaticProps({
const blogsPromise = commerce.getAllBlogs({
variables: {
excludeBlogIds: [idFeaturedBlog],
- take: DEFAULT_BLOG_PAGE_SIZE
+ take: DEFAULT_BLOG_PAGE_SIZE,
+ filter: {
+ isFeatured: {
+ eq:false
+ }
+ }
},
config,
preview,
diff --git a/pages/products.tsx b/pages/products.tsx
index 4a37ab097..035ab87e6 100644
--- a/pages/products.tsx
+++ b/pages/products.tsx
@@ -14,10 +14,10 @@ interface Props {
facets: Facet[],
collections: Collection[],
productsResult: { products: ProductCard[], totalItems: number },
-
}
export default function Products({ facets, collections, productsResult }: Props) {
+
return (
<>
diff --git a/pages/recipe/[slug].tsx b/pages/recipe/[slug].tsx
index 1f71ba5be..d05de7210 100644
--- a/pages/recipe/[slug].tsx
+++ b/pages/recipe/[slug].tsx
@@ -1,12 +1,98 @@
+import { useRouter } from 'next/router'
import { Layout, RecipeDetail, RecommendedRecipes } from 'src/components/common'
import { INGREDIENT_DATA_TEST, RECIPE_DATA_TEST } from 'src/utils/demo-data'
+import commerce from '@lib/api/commerce';
+import { PromiseWithKey } from 'src/utils/types.utils';
+import { GetStaticPropsContext,GetStaticPathsContext } from 'next';
+import { getAllPromies } from 'src/utils/funtion.utils';
+import { REVALIDATE_TIME } from 'src/utils/constanst.utils'
+import { RecipeCardProps } from 'src/components/common/RecipeCard/RecipeCard';
+interface Props {
+ recipe:{recipeDetail?: RecipeCardProps},
+ relevant:{relevantBlogs?:RecipeCardProps[]}
+}
+export default function Slug({recipe,relevant}:Props) {
-export default function Slug() {
return
-
-
+
+
}
+
+export async function getStaticProps({
+ params,
+ locale,
+ locales,
+ preview,
+}: GetStaticPropsContext<{ slug: string }> ) {
+ const config = { locale, locales }
+ let promisesWithKey = [] as PromiseWithKey[]
+ let props = {} as any
+
+ // Blog detail
+ const recipesPromise = await commerce.getRecipeDetail({
+ variables: { slug: params!.slug },
+ config,
+ preview,
+ })
+ props.recipe = recipesPromise;
+
+ if (recipesPromise.recipeDetail === null) {
+ return { notFound: true };
+ }
+
+ // // Relevant Blogs
+ const relevantProductId = recipesPromise?.recipeDetail?.relevantProducts?.[0];
+ if (relevantProductId && recipesPromise?.recipeDetail?.relevantProducts?.length > 0) {
+
+ const relevantBlogs = commerce.getRelevantBlogs({
+ variables: { productId: relevantProductId },
+ config,
+ preview,
+ })
+ promisesWithKey.push({ key: 'relevant', promise: relevantBlogs})
+
+ }else {
+ props.relevantBlogs = [];
+ }
+
+
+ try {
+ 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,
+ revalidate: REVALIDATE_TIME,
+ }
+ } catch (err) {
+
+ }
+}
+
+export async function getStaticPaths({ locales }: GetStaticPathsContext) {
+
+ const { recipes } = await commerce.getAllRecipePaths()
+ return {
+ paths: locales
+ ? locales.reduce((arr, locale) => {
+ recipes.forEach((blog: any) => {
+ arr.push(`/${locale}/recipe/${blog.slug}`)
+ })
+ return arr
+ }, [])
+ : recipes.map((product: any) => `/recipe/${product.path}`),
+ fallback: 'blocking',
+ }
+}
+
+
Slug.Layout = Layout
diff --git a/pages/recipes.tsx b/pages/recipes.tsx
index a4acece13..7df69a9da 100644
--- a/pages/recipes.tsx
+++ b/pages/recipes.tsx
@@ -1,15 +1,68 @@
import { Layout } from 'src/components/common';
import RecipeListBanner from 'src/components/modules/recipes-list/RecipeListBanner/RecipeListBanner';
import RecipesList from 'src/components/modules/recipes-list/RecipesList/RecipesList';
+import { GetStaticPropsContext } from 'next';
+import { PromiseWithKey } from 'src/utils/types.utils';
+import { DEFAULT_BLOG_PAGE_SIZE } from "src/utils/constanst.utils";
+import commerce from '@lib/api/commerce';
+import { getAllPromies } from 'src/utils/funtion.utils';
+import { RecipeCardProps } from 'src/components/common/RecipeCard/RecipeCard';
-
-export default function RecipeListPage() {
+interface Props {
+ recipesResult: {recipes: RecipeCardProps[] ,totalItems?: number},
+
+}
+export default function RecipeListPage({recipesResult}:Props) {
return (
<>
-
+
>
)
}
+export async function getStaticProps({
+ preview,
+ locale,
+ locales,
+}: GetStaticPropsContext) {
+
+ const config = { locale, locales }
+ let promisesWithKey = [] as PromiseWithKey[]
+ let props = {} as any;
+
+
+ const recipesPromise = commerce.getAllRecipes({
+ variables: {
+ excludeBlogIds: [],
+ take: DEFAULT_BLOG_PAGE_SIZE,
+ id: 'DESC',
+ isPublish:true
+ },
+ config,
+ preview,
+ })
+ promisesWithKey.push({ key: 'recipesResult', promise: recipesPromise})
+
+
+
+ try {
+ 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,
+ revalidate: 60
+ }
+ } catch (err) {
+
+ }
+}
+
+
RecipeListPage.Layout = Layout
diff --git a/src/components/common/Author/Author.module.scss b/src/components/common/Author/Author.module.scss
index 5a2dad969..037d988e7 100644
--- a/src/components/common/Author/Author.module.scss
+++ b/src/components/common/Author/Author.module.scss
@@ -5,7 +5,9 @@
.authorImage {
width:3.2rem;
height:3.2rem;
- border-radius:3.2rem;
+ img{
+ border-radius:3.2rem !important;
+ }
div{
min-width:3.2rem !important;
}
diff --git a/src/components/common/RecipeDetail/RecipeDetail.tsx b/src/components/common/RecipeDetail/RecipeDetail.tsx
index cdec99994..84d3e4f0d 100644
--- a/src/components/common/RecipeDetail/RecipeDetail.tsx
+++ b/src/components/common/RecipeDetail/RecipeDetail.tsx
@@ -1,20 +1,21 @@
import React from 'react'
+import { RecipeProps } from 'src/utils/types.utils'
import { ProductCardProps } from '../ProductCard/ProductCard'
import RecipeDetailInfo from './components/RecipeDetailInfo/RecipeDetailInfo'
import RecipeIngredient from './components/RecipeIngredient/RecipeIngredient'
import s from './RecipeDetail.module.scss'
-interface Props {
+interface Props extends RecipeProps {
className?: string
children?: any,
- ingredients: ProductCardProps[],
+ ingredients: ProductCardProps[]
}
-const RecipeDetail = ({ ingredients }: Props) => {
+const RecipeDetail = ({ ingredients,...rest }: Props) => {
return (
)
diff --git a/src/components/common/RecipeDetail/components/RecipeDetailInfo/RecipeDetailInfo.tsx b/src/components/common/RecipeDetail/components/RecipeDetailInfo/RecipeDetailInfo.tsx
index a853ad869..046fa2b55 100644
--- a/src/components/common/RecipeDetail/components/RecipeDetailInfo/RecipeDetailInfo.tsx
+++ b/src/components/common/RecipeDetail/components/RecipeDetailInfo/RecipeDetailInfo.tsx
@@ -1,24 +1,26 @@
import React from 'react'
import { ImgWithLink } from 'src/components/common'
+import { RecipeProps } from 'src/utils/types.utils'
import RecipeBriefInfo from '../RecipeBriefInfo/RecipeBriefInfo'
import s from './RecipeDetailInfo.module.scss'
-interface Props {
+interface Prop extends RecipeProps {
className?: string
children?: any
}
-const RecipeDetailInfo = ({ }: Props) => {
+const RecipeDetailInfo = ({ ...rest}: Prop) => {
+
return (
- Crispy Fried Calamari
+ {rest.title}
diff --git a/src/components/common/RecommendedRecipes/RecommendedRecipes.tsx b/src/components/common/RecommendedRecipes/RecommendedRecipes.tsx
index aa1df57d4..1b8494eeb 100644
--- a/src/components/common/RecommendedRecipes/RecommendedRecipes.tsx
+++ b/src/components/common/RecommendedRecipes/RecommendedRecipes.tsx
@@ -30,10 +30,10 @@ const RESPONSIVE: ResponsiveType = {
},
}
interface Props {
- data: RecipeCardProps[],
+ data?: RecipeCardProps[],
}
-const RecommendedRecipes = ({ data }: Props) => {
+const RecommendedRecipes = ({ data=[] }: Props) => {
return (
diff --git a/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx
index ab21590c3..c99cd83ac 100644
--- a/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx
+++ b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx
@@ -14,40 +14,7 @@ interface RelevantProps {
bgcolor?: "default" | "cream"
}
-const recipe:BlogCardProps[] = [
-{
- title: "Want to Lose Weight? Here are 10 DEBM Diet Guidelines for Beginners",
- slug: 'have-a-nice-lunch',
- description:"The DEBM diet stands for "+'"Delicious Happy Fun Diet"'+". This diet was popularized by Robert...",
- imageSrc: "https://user-images.githubusercontent.com/46085455/133185783-8100ef4e-7a72-4dc1-bb12-2ca46b56b393.png",
-},{
- title: "9 Ways to Make an Aloe Vera Mask at Home",
- slug: 'have-a-nice-lunch',
- description:"Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...",
- imageSrc: "https://user-images.githubusercontent.com/46085455/133185911-df505d10-fdcd-4312-add3-7c62ad8af71e.png",
-},{
- title: "Don't Buy Wrong, Here Are 7 Ways to Choose a Ripe Dragon Fruit",
- slug: 'have-a-nice-lunch',
- description:"Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...",
- imageSrc: "https://user-images.githubusercontent.com/46085455/133185959-7ad75580-ca6d-4684-83d9-3f64500bbc97.png",
-},{
- title: "Want to Lose Weight? Here are 10 DEBM Diet Guidelines for Beginners",
- slug: 'have-a-nice-lunch',
- description:"The DEBM diet stands for "+'"Delicious Happy Fun Diet"'+". This diet was popularized by Robert...",
- imageSrc: "https://user-images.githubusercontent.com/46085455/133185783-8100ef4e-7a72-4dc1-bb12-2ca46b56b393.png",
-},{
- title: "9 Ways to Make an Aloe Vera Mask at Home",
- slug: 'have-a-nice-lunch',
- description:"Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...",
- imageSrc: "https://user-images.githubusercontent.com/46085455/133185911-df505d10-fdcd-4312-add3-7c62ad8af71e.png",
-},{
- title: "Don't Buy Wrong, Here Are 7 Ways to Choose a Ripe Dragon Fruit",
- slug: 'have-a-nice-lunch',
- description:"Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...",
- imageSrc: "https://user-images.githubusercontent.com/46085455/133185959-7ad75580-ca6d-4684-83d9-3f64500bbc97.png",
-}]
-
- const RelevantBlogPosts = ({ data = recipe, itemKey="detail-relevant", title="Relevant Blog Posts", bgcolor = "default" }: RelevantProps) => {
+ const RelevantBlogPosts = ({ data , itemKey="detail-relevant", title="Relevant Blog Posts", bgcolor = "default" }: RelevantProps) => {
return (
-
+ }
)
diff --git a/src/components/hooks/recipe/index.ts b/src/components/hooks/recipe/index.ts
new file mode 100644
index 000000000..a702a9644
--- /dev/null
+++ b/src/components/hooks/recipe/index.ts
@@ -0,0 +1 @@
+export {default as useGetRecipeList } from "./useGetRecipeList"
\ No newline at end of file
diff --git a/src/components/hooks/recipe/useGetRecipeList.tsx b/src/components/hooks/recipe/useGetRecipeList.tsx
new file mode 100644
index 000000000..1db9052da
--- /dev/null
+++ b/src/components/hooks/recipe/useGetRecipeList.tsx
@@ -0,0 +1,18 @@
+import { GetAllRecipesQuery,QueryRecipes, RecipeList } from '@framework/schema'
+import { normalizeRecipeList } from '@framework/utils/normalize'
+import { getAllBlogsQuery } from '@framework/utils/queries/get-all-blog-query'
+import gglFetcher from 'src/utils/gglFetcher'
+import useSWR from 'swr'
+
+const useGetRecipeList = (options?: QueryRecipes) => {
+ const { data, isValidating, ...rest } = useSWR
([getAllBlogsQuery, options], gglFetcher)
+
+ return {
+ reicpes: data?.blogs?.items?.map((recipe:RecipeList)=>normalizeRecipeList(recipe)),
+ totalItems: data?.blogs?.totalItems || null,
+ loading: isValidating,
+ ...rest
+ }
+}
+
+export default useGetRecipeList
diff --git a/src/components/modules/blog-detail/BlogContent/BlogContent.tsx b/src/components/modules/blog-detail/BlogContent/BlogContent.tsx
index cb9d6b8d8..4a38ab5b1 100644
--- a/src/components/modules/blog-detail/BlogContent/BlogContent.tsx
+++ b/src/components/modules/blog-detail/BlogContent/BlogContent.tsx
@@ -9,57 +9,24 @@ import Link from 'next/link';
interface BlogContentProps {
className?: string
children?: any,
+ title?: string,
+ content?: string,
+ imgAuthor?: string,
+ date?: string,
+ authorName?: string,
}
-const BlogContent = ({}:BlogContentProps) => {
+const BlogContent = ({title,date='',content,imgAuthor='',authorName='' }:BlogContentProps) => {
+
return (
<>
-
-
The Best Sesame Soy Broccoli Salad
+
+ {title}
-
- When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces.
-
-
-
- Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to.
-
-
- This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.
-
-
-
-
-
- What is broccoli salad
-
- When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces.
-
-
-
- Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to.
-
-
- This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.
-
-
-
-
-
- What about broccoli stems?
-
-
- You can eat broccoli stems. In fact, they are delicious. Just use a peeler to peel off the outsides and then trim the stalks into small 1/4”-1/2” cubes.
-
-
-
-
-
-
-
+ {content}
diff --git a/src/components/modules/blog-detail/BlogDetailImg/BlogDetailImg.tsx b/src/components/modules/blog-detail/BlogDetailImg/BlogDetailImg.tsx
index ed9b88a29..57180025a 100644
--- a/src/components/modules/blog-detail/BlogDetailImg/BlogDetailImg.tsx
+++ b/src/components/modules/blog-detail/BlogDetailImg/BlogDetailImg.tsx
@@ -5,7 +5,8 @@ import BreadcrumbCommon from 'src/components/common/BreadcrumbCommon/BreadcrumbC
import s from './BlogDetailImg.module.scss';
interface Props {
className?: string
- children?: any
+ children?: any,
+ imgSrc?:string
}
const CRUMBS =[
@@ -14,14 +15,14 @@ const CRUMBS =[
link:"/blog"
}
]
-const BlogDetailImg = ({}:Props ) => {
+const BlogDetailImg = ({imgSrc = ''}:Props ) => {
return (
<>
>
)
diff --git a/src/components/modules/blogs/BlogsList/BlogsList.tsx b/src/components/modules/blogs/BlogsList/BlogsList.tsx
index d9dbf26ed..245769b6e 100644
--- a/src/components/modules/blogs/BlogsList/BlogsList.tsx
+++ b/src/components/modules/blogs/BlogsList/BlogsList.tsx
@@ -92,5 +92,3 @@ const BlogsList = ({ blogList,total,idFeatured }:BlogsListProps) => {
}
export default BlogsList
-
-
diff --git a/src/components/modules/product-detail/ViewedProducts/ViewedProducts.tsx b/src/components/modules/product-detail/ViewedProducts/ViewedProducts.tsx
index 22190b49a..cb68e50f5 100644
--- a/src/components/modules/product-detail/ViewedProducts/ViewedProducts.tsx
+++ b/src/components/modules/product-detail/ViewedProducts/ViewedProducts.tsx
@@ -8,7 +8,7 @@ import { useLocalStorage } from 'src/components/hooks/useLocalStorage';
interface Props {
data: ProductCardProps[]
}
-const ViewedProducts = ({data}:Props) => {
+const ViewedProducts = ({data = []}:Props) => {
if (data.length===0){
return
}
diff --git a/src/components/modules/recipes-list/RecipesList/RecipesList.tsx b/src/components/modules/recipes-list/RecipesList/RecipesList.tsx
index e91599a2c..1499292f0 100644
--- a/src/components/modules/recipes-list/RecipesList/RecipesList.tsx
+++ b/src/components/modules/recipes-list/RecipesList/RecipesList.tsx
@@ -1,224 +1,303 @@
-import React from 'react';
-import { SelectCommon } from 'src/components/common';
-import BreadcrumbCommon from 'src/components/common/BreadcrumbCommon/BreadcrumbCommon';
-import MenuNavigation from 'src/components/common/MenuNavigation/MenuNavigation';
-import PaginationCommon from 'src/components/common/PaginationCommon/PaginationCommon';
-import { RecipeCardProps } from 'src/components/common/RecipeCard/RecipeCard';
-import { OPTION_ALL, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils';
-import HeadingCommon from "../../../common/HeadingCommon/HeadingCommon";
+import React, { useEffect, useState,useRef, useMemo } from 'react'
+import { SelectCommon } from 'src/components/common'
+import BreadcrumbCommon from 'src/components/common/BreadcrumbCommon/BreadcrumbCommon'
+import MenuNavigation from 'src/components/common/MenuNavigation/MenuNavigation'
+import PaginationCommon from 'src/components/common/PaginationCommon/PaginationCommon'
+import { RecipeCardProps } from 'src/components/common/RecipeCard/RecipeCard'
+import { OPTION_ALL, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'
+import HeadingCommon from '../../../common/HeadingCommon/HeadingCommon'
import { RecipeCard } from 'src/components/common'
+import { DEFAULT_BLOG_PAGE_SIZE } from 'src/utils/constanst.utils'
+import s from './RecipesList.module.scss'
+import { useRouter } from 'next/router'
+import { QueryRecipes } from '@framework/schema'
+import { useGetRecipeList } from 'src/components/hooks/recipe'
+import { getPageFromQuery } from 'src/utils/funtion.utils'
+import { ListBlogCardSkeleton } from 'src/components/common'
-import s from './RecipesList.module.scss';
+const recipe: RecipeCardProps[] = [
+ {
+ title: 'Special Recipe of Vietnamese Phở',
+ description:
+ 'Alright, before we get to the actual recipe, let’s chat for a sec about the ingredients. To make this pho soup recipe, you will need:',
+ imageSrc:
+ 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png',
+ slug: 'special-recipe-of-vietnamese-pho',
+ },
+ {
+ title: 'Original Recipe of Curry',
+ description:
+ 'Chicken curry is common to several countries including India, countries in Asia and the Caribbean. My favorite of them though is this aromatic Indian...',
+ imageSrc:
+ 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png',
+ slug: 'original-recipe-of-curry',
+ },
+ {
+ title: 'The Best Recipe of Beef Noodle Soup',
+ description:
+ 'The broth for Bun Bo Hue is prepared by slowly simmering various types of beef and pork bones (ox tail, beef shank, pork neck bones, pork feet,...',
+ imageSrc:
+ 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png',
+ slug: 'the-best-recipe-of-beef-noodle-soup',
+ },
+ {
+ title: 'Special Recipe of Vietnamese Phở',
+ description:
+ 'Alright, before we get to the actual recipe, let’s chat for a sec about the ingredients. To make this pho soup recipe, you will need:',
+ imageSrc:
+ 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png',
+ slug: 'special-recipe-of-vietnamese-pho',
+ },
+ {
+ title: 'Original Recipe of Curry',
+ description:
+ 'Chicken curry is common to several countries including India, countries in Asia and the Caribbean. My favorite of them though is this aromatic Indian...',
+ imageSrc:
+ 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png',
+ slug: 'original-recipe-of-curry',
+ },
+ {
+ title: 'The Best Recipe of Beef Noodle Soup',
+ description:
+ 'The broth for Bun Bo Hue is prepared by slowly simmering various types of beef and pork bones (ox tail, beef shank, pork neck bones, pork feet,...',
+ imageSrc:
+ 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png',
+ slug: 'the-best-recipe-of-beef-noodle-soup',
+ },
+]
-const recipe:RecipeCardProps[] = [
-{
- title: "Special Recipe of Vietnamese Phở",
- description: "Alright, before we get to the actual recipe, let’s chat for a sec about the ingredients. To make this pho soup recipe, you will need:",
- imageSrc: 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png',
- slug: "special-recipe-of-vietnamese-pho"
-},
-{
- title: "Original Recipe of Curry",
- description: "Chicken curry is common to several countries including India, countries in Asia and the Caribbean. My favorite of them though is this aromatic Indian...",
- imageSrc: 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png',
- slug:"original-recipe-of-curry"
-},
-{
- title: "The Best Recipe of Beef Noodle Soup",
- description: "The broth for Bun Bo Hue is prepared by slowly simmering various types of beef and pork bones (ox tail, beef shank, pork neck bones, pork feet,...",
- imageSrc: 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png',
- slug:"the-best-recipe-of-beef-noodle-soup"
-},
-{
- title: "Special Recipe of Vietnamese Phở",
- description: "Alright, before we get to the actual recipe, let’s chat for a sec about the ingredients. To make this pho soup recipe, you will need:",
- imageSrc: 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png',
- slug: "special-recipe-of-vietnamese-pho"
-},
-{
- title: "Original Recipe of Curry",
- description: "Chicken curry is common to several countries including India, countries in Asia and the Caribbean. My favorite of them though is this aromatic Indian...",
- imageSrc: 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png',
- slug:"original-recipe-of-curry"
-},
-{
- title: "The Best Recipe of Beef Noodle Soup",
- description: "The broth for Bun Bo Hue is prepared by slowly simmering various types of beef and pork bones (ox tail, beef shank, pork neck bones, pork feet,...",
- imageSrc: 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png',
- slug:"the-best-recipe-of-beef-noodle-soup"
-},];
-
-const DEFAULT_PAGESIZE_RECIPELIST = 6;
+const DEFAULT_PAGESIZE_RECIPELIST = 6
const BREADCRUMB = [
- {
- name: 'Special Recipes',
- link: `#`,
- },
-];
+ {
+ name: 'Special Recipes',
+ link: `#`,
+ },
+]
const CATEGORY = [
- {
- name: 'All',
- link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=${OPTION_ALL}`,
- },
- {
- name: 'Malaysian',
- link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=malaysia`,
- },
- {
- name: 'Vietnamese',
- link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=vietnamese`,
- },
- {
- name: 'Thailand',
- link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=thailand`,
- },
- {
- name: 'Indian',
- link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=indian`,
- },
- {
- name: 'Lao',
- link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=lao`,
- },
- {
- name: 'Chinese',
- link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=chinese`,
- },
- {
- name: 'Korean',
- link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=korean`,
- },
- {
- name: 'Japanese',
- link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=japanese`,
- },
- {
- name: 'Western',
- link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=western`,
- },
- ];
+ {
+ name: 'All',
+ link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=${OPTION_ALL}`,
+ },
+ {
+ name: 'Malaysian',
+ link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=malaysia`,
+ },
+ {
+ name: 'Vietnamese',
+ link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=vietnamese`,
+ },
+ {
+ name: 'Thailand',
+ link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=thailand`,
+ },
+ {
+ name: 'Indian',
+ link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=indian`,
+ },
+ {
+ name: 'Lao',
+ link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=lao`,
+ },
+ {
+ name: 'Chinese',
+ link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=chinese`,
+ },
+ {
+ name: 'Korean',
+ link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=korean`,
+ },
+ {
+ name: 'Japanese',
+ link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=japanese`,
+ },
+ {
+ name: 'Western',
+ link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=western`,
+ },
+]
const CATEGORYSELECT = [
-{
+ {
name: 'All',
value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=${OPTION_ALL}`,
-},
-{
+ },
+ {
name: 'Malaysian',
value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=malaysia`,
-},
-{
+ },
+ {
name: 'Vietnamese',
value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=vietnamese`,
-},
-{
+ },
+ {
name: 'Thailand',
value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=thailand`,
-},
-{
+ },
+ {
name: 'Indian',
value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=indian`,
-},
-{
+ },
+ {
name: 'Lao',
value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=lao`,
-},
-{
+ },
+ {
name: 'Chinese',
value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=chinese`,
-},
-{
+ },
+ {
name: 'Korean',
value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=korean`,
-},
-{
+ },
+ {
name: 'Japanese',
value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=japanese`,
-},
-{
+ },
+ {
name: 'Western',
value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=western`,
-},
-];
-
-const OPTIONSLECT=[
- {
- name:"Most Viewed",
- value:"most-viewed"
- },
- {
- name:"Lastest Blogs",
- value:"lastest-blogs"
- },
- {
- name:"Recent Blogs",
- value:"recent-blogs"
- },
-];
+ },
+]
-interface Props{
- data?: RecipeCardProps[],
- recipes?:{
- title:string,
- imageSrc:string,
- description:string,
- slug:string
- }[],
+const OPTIONSLECT = [
+ {
+ name: 'Most Viewed',
+ value: 'most-viewed',
+ },
+ {
+ name: 'Lastest Blogs',
+ value: 'lastest-blogs',
+ },
+ {
+ name: 'Recent Blogs',
+ value: 'recent-blogs',
+ },
+]
+
+interface Props {
+ recipeList?: RecipeCardProps[]
+ total: number
}
+const RecipesList = ({ recipeList, total }: Props) => {
+ const DEFAULT_BLOGS_ARGS = useMemo(
+ () => ({
+ excludeBlogIds: [],
+ options:{
+ take: DEFAULT_BLOG_PAGE_SIZE,
+ sort: {
+ id: 'DESC',
+ },
+ filter:{
+ isPublish: {
+ eq:true
+ }
+ }
+ }
+ }),
+ []
+ )
+ const router = useRouter()
+ const [initialQueryFlag, setInitialQueryFlag] = useState
(true)
+ const [optionQueryBlog, setOptionQueryBlog] = useState(DEFAULT_BLOGS_ARGS)
+ const { reicpes, totalItems, loading } = useGetRecipeList(optionQueryBlog)
+
-const RecipesList = ({ data =recipe}:Props) => {
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
SPECIAL RECIPES
-
-
-
-
-
- {data?.map((item,index) => (
-
-
-
- ))}
-
-
-
-
-
-
-
-
- >
+ const onPageChange = (page: number) => {
+ router.push(
+ {
+ pathname: ROUTE.RECIPES,
+ query: {
+ ...router.query,
+ [QUERY_KEY.PAGE]: page,
+ },
+ },
+ undefined,
+ { shallow: true }
)
+ }
+
+ // skip
+ const firstRender = useRef(true);
+
+ useEffect(() => {
+ firstRender.current = false
+ const query = { ...DEFAULT_BLOGS_ARGS } as QueryRecipes
+ const page = getPageFromQuery(router.query[QUERY_KEY.PAGE] as string)
+ query.options.skip = page * DEFAULT_BLOG_PAGE_SIZE
+ setOptionQueryBlog(query)
+ setInitialQueryFlag(false)
+ }, [router.query])
+
+
+ let data;
+ if(initialQueryFlag == true){
+ data = recipeList;
+ }else{
+ data = reicpes
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
SPECIAL RECIPES
+
+
+
+
+
+ {(!initialQueryFlag && loading && !data) &&
}
+ {data?.map((item, index) => (
+
+
+
+ ))}
+
+
+
+
+
+
+ >
+ )
}
export default RecipesList
diff --git a/src/utils/types.utils.ts b/src/utils/types.utils.ts
index e14a7eb59..2c2722c28 100644
--- a/src/utils/types.utils.ts
+++ b/src/utils/types.utils.ts
@@ -24,9 +24,14 @@ export interface RecipeProps {
slug: string
description: string
imageSrc: string
+ content?: string,
+ imgAuthor?: string,
+ date?: string,
+ authorName?: string,
}
export interface BlogProps {
+ id:string,
title: string
slug: string
description: string