mirror of
https://github.com/vercel/commerce.git
synced 2025-07-22 12:24:18 +00:00
✨ feat: get recipe list
:%s
This commit is contained in:
@@ -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 {
|
||||
@@ -16,9 +17,7 @@ import type {
|
||||
GetBlogDetailOperation,
|
||||
GetRelevantBlogsOperation
|
||||
} from '../types/blogs'
|
||||
import type {
|
||||
GetAllRecipesOperation
|
||||
} from '../types/recipes'
|
||||
|
||||
|
||||
import type { APIProvider, CommerceAPI } from '.'
|
||||
import { GetAllCollectionsOperation } from '@commerce/types/collection';
|
||||
@@ -43,7 +42,9 @@ export const OPERATIONS = [
|
||||
'getAllBlogPaths',
|
||||
'getBlogDetail',
|
||||
'getRelevantBlogs',
|
||||
'getAllRecipes'
|
||||
'getAllRecipes',
|
||||
'getAllRecipePaths',
|
||||
'getRecipeDetail'
|
||||
] as const
|
||||
|
||||
export const defaultOperations = OPERATIONS.reduce((ops, k) => {
|
||||
@@ -84,14 +85,14 @@ export type Operations<P extends APIProvider> = {
|
||||
): Promise<T['data']>
|
||||
}
|
||||
|
||||
getPage: {
|
||||
<T extends GetPageOperation>(opts: {
|
||||
getRecipeDetail: {
|
||||
<T extends GetRecipeDetailOperation>(opts: {
|
||||
variables: T['variables']
|
||||
config?: P['config']
|
||||
preview?: boolean
|
||||
}): Promise<T['data']>
|
||||
|
||||
<T extends GetPageOperation>(
|
||||
<T extends GetRecipeDetailOperation>(
|
||||
opts: {
|
||||
variables: T['variables']
|
||||
config?: P['config']
|
||||
@@ -159,6 +160,35 @@ export type Operations<P extends APIProvider> = {
|
||||
): Promise<T['data']>
|
||||
}
|
||||
|
||||
getAllRecipePaths: {
|
||||
<T extends GetAllRecipePathsOperation>(opts: {
|
||||
variables?: T['variables']
|
||||
config?: P['config']
|
||||
}): Promise<T['data']>
|
||||
|
||||
<T extends GetAllRecipePathsOperation>(
|
||||
opts: {
|
||||
variables?: T['variables']
|
||||
config?: P['config']
|
||||
} & OperationOptions
|
||||
): Promise<T['data']>
|
||||
}
|
||||
|
||||
getAllRecipe: {
|
||||
<T extends GetAllRecipePathsOperation>(opts: {
|
||||
variables?: T['variables']
|
||||
config?: P['config']
|
||||
}): Promise<T['data']>
|
||||
|
||||
<T extends GetAllRecipePathsOperation>(
|
||||
opts: {
|
||||
variables?: T['variables']
|
||||
config?: P['config']
|
||||
} & OperationOptions
|
||||
): Promise<T['data']>
|
||||
}
|
||||
|
||||
|
||||
getAllProducts: {
|
||||
<T extends GetAllProductsOperation>(opts: {
|
||||
variables?: T['variables']
|
||||
|
@@ -29,4 +29,17 @@ export type GetAllRecipesOperation<T extends RecipesType = RecipesType> = {
|
||||
take?: number
|
||||
id?: SortRecipes
|
||||
}
|
||||
}
|
||||
export type GetAllRecipePathsOperation<
|
||||
T extends RecipesType = RecipesType
|
||||
> = {
|
||||
data: { recipes: Pick<T['items'], 'translations'>[] }
|
||||
variables: { first?: number }
|
||||
}
|
||||
|
||||
export type GetRecipeDetailOperation<T extends RecipesType = RecipesType> = {
|
||||
data: T['items'],
|
||||
variables: {
|
||||
slug?: string
|
||||
}
|
||||
}
|
@@ -15,6 +15,9 @@ 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'
|
||||
|
||||
@@ -54,7 +57,9 @@ const operations = {
|
||||
getBlogDetail,
|
||||
getAllBlogPaths,
|
||||
getRelevantBlogs,
|
||||
getAllRecipes
|
||||
getAllRecipes,
|
||||
getAllRecipePaths,
|
||||
getRecipeDetail
|
||||
}
|
||||
|
||||
export const provider = { config, operations }
|
||||
|
53
framework/vendure/api/operations/get-all-recipe-paths.ts
Normal file
53
framework/vendure/api/operations/get-all-recipe-paths.ts
Normal file
@@ -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<Provider>) {
|
||||
async function getAllRecipePaths<
|
||||
T extends GetAllRecipesPathsOperation
|
||||
>(opts?: {
|
||||
variables?: T['variables']
|
||||
config?: BigcommerceConfig
|
||||
}): Promise<T['data']>
|
||||
|
||||
async function getAllRecipePaths<T extends GetAllRecipesPathsOperation>(
|
||||
opts: {
|
||||
variables?: T['variables']
|
||||
config?: BigcommerceConfig
|
||||
} & OperationOptions
|
||||
): Promise<T['data']>
|
||||
|
||||
async function getAllRecipePaths<T extends GetAllRecipesPathsOperation>({
|
||||
query = getAllBlogPathsQuery,
|
||||
variables,
|
||||
config: cfg,
|
||||
}: {
|
||||
query?: string
|
||||
variables?: T['variables']
|
||||
config?: BigcommerceConfig
|
||||
} = {}): Promise<T['data']> {
|
||||
const config = commerce.getConfig(cfg)
|
||||
|
||||
const { data } = await config.fetch<GetAllRecipePathsQuery>(query, {
|
||||
variables,
|
||||
})
|
||||
|
||||
const recipes = data.blogs.items;
|
||||
|
||||
return {
|
||||
recipes: recipes?.map(val=>val.translations.map((p:RecipeTranslation) => ({ path: `/${p.slug}` })))
|
||||
}
|
||||
}
|
||||
|
||||
return getAllRecipePaths
|
||||
}
|
@@ -1,14 +1,13 @@
|
||||
import { OperationContext } from '@commerce/api/operations'
|
||||
import { Provider, VendureConfig } from '..'
|
||||
import { GetAllRecipesQuery,BlogList,SortRecipes } from '../../schema'
|
||||
import { BlogList, GetAllRecipesQuery } from '../../schema'
|
||||
import { getAllBlogsQuery } from '../../utils/queries/get-all-blog-query'
|
||||
|
||||
export type RecipesVariables = {
|
||||
excludeBlogIds?: string[],
|
||||
take?: number,
|
||||
sort?: {
|
||||
id?: string
|
||||
}
|
||||
take?:number,
|
||||
id?: string,
|
||||
isPublish?:Boolean
|
||||
}
|
||||
|
||||
export default function getAllRecipesOperation({
|
||||
@@ -19,7 +18,7 @@ export default function getAllRecipesOperation({
|
||||
config?: Partial<VendureConfig>
|
||||
preview?: boolean
|
||||
}): Promise<{ recipes: GetAllRecipesQuery[],totalItems:number }>
|
||||
|
||||
|
||||
async function getAllRecipes({
|
||||
query = getAllBlogsQuery,
|
||||
variables: { ...vars } = {},
|
||||
@@ -30,20 +29,27 @@ export default function getAllRecipesOperation({
|
||||
config?: Partial<VendureConfig>
|
||||
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.sort?.id
|
||||
id: vars?.id
|
||||
},
|
||||
filter:{
|
||||
isPublish: {
|
||||
eq:vars.isPublish
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const { data } = await config.fetch<GetAllRecipesQuery>(query, {
|
||||
variables,
|
||||
})
|
||||
|
||||
return {
|
||||
recipes: data?.blogs?.items?.map((val:BlogList)=>({
|
||||
id: val.id,
|
||||
@@ -52,7 +58,6 @@ export default function getAllRecipesOperation({
|
||||
slug: val.translations[0]?.slug,
|
||||
description: val.translations[0]?.description,
|
||||
isPublish: val.isPublish,
|
||||
isFeatured: val.isFeatured,
|
||||
authorName: val.authorName,
|
||||
authorAvatarAsset : val.authorAvatarAsset?.preview ?? null,
|
||||
createdAt: val.createdAt
|
||||
|
98
framework/vendure/api/operations/get-recipe-detail.ts
Normal file
98
framework/vendure/api/operations/get-recipe-detail.ts
Normal file
@@ -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<Provider>) {
|
||||
|
||||
async function getRecipeDetail({
|
||||
query = getBlogDetailQuery,
|
||||
variables,
|
||||
config: cfg,
|
||||
}: {
|
||||
query?: string
|
||||
variables: { slug: string }
|
||||
config?: Partial<VendureConfig>
|
||||
preview?: boolean
|
||||
}): Promise<{recipeDetail: RecipeList | any }> {
|
||||
const config = commerce.getConfig(cfg)
|
||||
const { data } = await config.fetch<GetRecipeQuery>(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<Provider>) {
|
||||
|
||||
// async function getRecipeDetail(opts?: {
|
||||
// variables?: RecipeVariables
|
||||
// config?: Partial<VendureConfig>
|
||||
// preview?: boolean
|
||||
// }): Promise<{ recipeDetail: RecipeList}>
|
||||
|
||||
// async function getRecipeDetail({
|
||||
// query = getBlogDetailQuery,
|
||||
// variables: { ...vars } = {},
|
||||
// config: cfg,
|
||||
// }: {
|
||||
// query?: string
|
||||
// variables?: RecipeVariables
|
||||
// config?: Partial<VendureConfig>
|
||||
// preview?: boolean
|
||||
// } = {}): Promise<{ recipeDetail: RecipeList | any }> {
|
||||
|
||||
// const config = commerce.getConfig(cfg)
|
||||
// const variables = {
|
||||
// slug: vars.slug
|
||||
// }
|
||||
// const { data } = await config.fetch<GetRecipeQuery>(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
|
||||
// }
|
39
framework/vendure/schema.d.ts
vendored
39
framework/vendure/schema.d.ts
vendored
@@ -2433,6 +2433,12 @@ export type GetBlogQuery = { __typename?: 'Query' } & {
|
||||
>
|
||||
}
|
||||
|
||||
export type GetRecipeQuery = { __typename?: 'Query' } & {
|
||||
recipeDetail?: Maybe<
|
||||
{ __typename?: 'Recipe' } & RecipeList
|
||||
>
|
||||
}
|
||||
|
||||
|
||||
export type BlogTranslation = {
|
||||
__typename?: 'BlogTranslation'
|
||||
@@ -2445,6 +2451,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' } & {
|
||||
@@ -2481,6 +2499,20 @@ export type QueryBlogs = {
|
||||
options: BlogListOptions
|
||||
}
|
||||
|
||||
export type QueryRecipes = {
|
||||
excludeBlogIds?:Maybe<Array>,
|
||||
options: RecipeListOptions
|
||||
}
|
||||
|
||||
export type RecipeListOptions = {
|
||||
skip?: Maybe<Scalars['Int']>
|
||||
take?: Maybe<Scalars['Int']>
|
||||
sort?: RecipesSort
|
||||
}
|
||||
export type RecipesSort = {
|
||||
id?: Maybe<Scalars['String']>
|
||||
}
|
||||
|
||||
export type BlogListOptions = {
|
||||
skip?: Maybe<Scalars['Int']>
|
||||
take?: Maybe<Scalars['Int']>
|
||||
@@ -3455,6 +3487,13 @@ export type GetAllBlogPathsQuery = { __typename?: 'Query' } & {
|
||||
}
|
||||
}
|
||||
|
||||
export type GetAllRecipePathsQuery = { __typename?: 'Query' } & {
|
||||
recipes: { __typename?: 'Recipes' } & {
|
||||
items: Array<{ __typename?: 'Recipe' } & Pick<RecipeList,'slug','translations'>>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export type GetAllProductsQueryVariables = Exact<{
|
||||
input: SearchInput
|
||||
}>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { Cart } from '@commerce/types/cart'
|
||||
import { ProductCard, Product } from '@commerce/types/product'
|
||||
import { CartFragment, SearchResultFragment,Favorite, BlogList } from '../schema'
|
||||
import { CartFragment, SearchResultFragment,Favorite, BlogList, RecipeList } from '../schema'
|
||||
|
||||
export function normalizeSearchResult(item: SearchResultFragment): ProductCard {
|
||||
return {
|
||||
@@ -98,4 +98,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
|
||||
}
|
||||
}
|
@@ -13,7 +13,7 @@ interface Props {
|
||||
totalItems: number
|
||||
}
|
||||
export default function BlogsPage({ blogs, featuredBlog, totalItems }:Props) {
|
||||
console.log(blogs)
|
||||
|
||||
let date = new Date(featuredBlog?.[0]?.createdAt ?? '' );
|
||||
let fullDate = date.toLocaleString('en-us', { month: 'long' }) + " " + date.getDate()+","+date.getFullYear();
|
||||
|
||||
|
@@ -14,7 +14,6 @@ interface Props {
|
||||
facets: Facet[],
|
||||
collections: Collection[],
|
||||
productsResult: { products: ProductCard[], totalItems: number },
|
||||
|
||||
}
|
||||
|
||||
export default function Products({ facets, collections, productsResult }: Props) {
|
||||
|
@@ -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 <div className="page-recipe-detail">
|
||||
<RecipeDetail ingredients={INGREDIENT_DATA_TEST} />
|
||||
<RecommendedRecipes data={RECIPE_DATA_TEST} />
|
||||
<RecipeDetail ingredients={INGREDIENT_DATA_TEST}
|
||||
{...recipe.recipeDetail}
|
||||
/>
|
||||
<RecommendedRecipes data={relevant?.relevantBlogs} />
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
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<string[]>((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
|
||||
|
@@ -9,14 +9,14 @@ import { getAllPromies } from 'src/utils/funtion.utils';
|
||||
import { RecipeCardProps } from 'src/components/common/RecipeCard/RecipeCard';
|
||||
|
||||
interface Props {
|
||||
recipesResult ?: {recipes: RecipeCardProps[],totalItems?: number} , // it will chang when have recipes Props
|
||||
recipesResult: {recipes: RecipeCardProps[] ,totalItems?: number},
|
||||
|
||||
}
|
||||
export default function RecipeListPage({recipesResult}:Props) {
|
||||
return (
|
||||
<>
|
||||
<RecipeListBanner />
|
||||
<RecipesList recipes={recipesResult?.recipes} total={recipesResult?.totalItems || 0}/>
|
||||
<RecipesList recipeList={recipesResult.recipes} total={recipesResult.totalItems ?? 0}/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -32,13 +32,12 @@ export async function getStaticProps({
|
||||
let props = {} as any;
|
||||
|
||||
|
||||
const recipesPromise = commerce.getAllRecipes({
|
||||
const recipesPromise = commerce.getAllRecipes({
|
||||
variables: {
|
||||
excludeBlogIds: [],
|
||||
take: DEFAULT_BLOG_PAGE_SIZE,
|
||||
sort: {
|
||||
id: "DESC"
|
||||
}
|
||||
id: 'DESC',
|
||||
isPublish:true
|
||||
},
|
||||
config,
|
||||
preview,
|
||||
@@ -46,6 +45,7 @@ export async function getStaticProps({
|
||||
promisesWithKey.push({ key: 'recipesResult', promise: recipesPromise})
|
||||
|
||||
|
||||
|
||||
try {
|
||||
const promises = getAllPromies(promisesWithKey)
|
||||
const rs = await Promise.all(promises)
|
||||
@@ -54,7 +54,7 @@ export async function getStaticProps({
|
||||
props[item.key] = item.keyResult ? rs[index][item.keyResult] : rs[index]
|
||||
return null
|
||||
})
|
||||
|
||||
|
||||
return {
|
||||
props,
|
||||
revalidate: 60
|
||||
|
@@ -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 (
|
||||
<section className={s.recipeDetail}>
|
||||
<RecipeDetailInfo />
|
||||
<RecipeDetailInfo {...rest} />
|
||||
<RecipeIngredient data={ingredients} />
|
||||
</section >
|
||||
)
|
||||
|
@@ -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 (
|
||||
<section className={s.recipeDetailInfo}>
|
||||
<div className={s.img}>
|
||||
<ImgWithLink src="https://user-images.githubusercontent.com/76729908/131634880-8ae1437b-d3f8-421e-a546-d5a4f9a28e5f.png" alt="Recipe" />
|
||||
<ImgWithLink src= {rest.imageSrc ?? ''} alt={rest.title} />
|
||||
</div>
|
||||
<div className={s.recipeInfo}>
|
||||
<div className={s.top}>
|
||||
<h1 className={s.name}>
|
||||
Crispy Fried Calamari
|
||||
{rest.title}
|
||||
</h1>
|
||||
<RecipeBriefInfo />
|
||||
</div>
|
||||
|
@@ -30,10 +30,10 @@ const RESPONSIVE: ResponsiveType = {
|
||||
},
|
||||
}
|
||||
interface Props {
|
||||
data: RecipeCardProps[],
|
||||
data?: RecipeCardProps[],
|
||||
}
|
||||
|
||||
const RecommendedRecipes = ({ data }: Props) => {
|
||||
const RecommendedRecipes = ({ data=[] }: Props) => {
|
||||
return (
|
||||
<div className={s.recommendedRecipes}>
|
||||
<div className={s.infoProducts}>
|
||||
|
1
src/components/hooks/recipe/index.ts
Normal file
1
src/components/hooks/recipe/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export {default as useGetRecipeList } from "./useGetRecipeList"
|
18
src/components/hooks/recipe/useGetRecipeList.tsx
Normal file
18
src/components/hooks/recipe/useGetRecipeList.tsx
Normal file
@@ -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<GetAllRecipesQuery>([getAllBlogsQuery, options], gglFetcher)
|
||||
|
||||
return {
|
||||
reicpes: data?.blogs?.items?.map((recipe:RecipeList)=>normalizeRecipeList(recipe)),
|
||||
totalItems: data?.blogs?.totalItems || null,
|
||||
loading: isValidating,
|
||||
...rest
|
||||
}
|
||||
}
|
||||
|
||||
export default useGetRecipeList
|
@@ -18,7 +18,7 @@ interface BlogsListProps {
|
||||
|
||||
|
||||
const BlogsList = ({ blogList,total,idFeatured }:BlogsListProps) => {
|
||||
console.log(blogList)
|
||||
|
||||
const DEFAULT_BLOGS_ARGS = useMemo(()=> ({
|
||||
excludeBlogIds: [idFeatured],
|
||||
options:{
|
||||
|
@@ -1,220 +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{
|
||||
recipes?: RecipeCardProps[],
|
||||
total:number
|
||||
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<boolean>(true)
|
||||
const [optionQueryBlog, setOptionQueryBlog] = useState<QueryRecipes>(DEFAULT_BLOGS_ARGS)
|
||||
const { reicpes, totalItems, loading } = useGetRecipeList(optionQueryBlog)
|
||||
|
||||
|
||||
const RecipesList = ({ recipes,total }:Props) => {
|
||||
console.log(recipes)
|
||||
return (
|
||||
<>
|
||||
<div className={s.recipesListWrapper}>
|
||||
<div className={s.breadcrumb}>
|
||||
<BreadcrumbCommon crumbs={BREADCRUMB} />
|
||||
</div>
|
||||
<div className={s.recipesListPageMain}>
|
||||
|
||||
<div className={s.categories}>
|
||||
<MenuNavigation categories={CATEGORY} heading="Categories"/>
|
||||
</div>
|
||||
|
||||
<div className={s.recipesList}>
|
||||
<HeadingCommon align='left'>SPECIAL RECIPES</HeadingCommon>
|
||||
|
||||
<div className={s.boxSelect}>
|
||||
<div className={s.categorySelectCate}>
|
||||
<label htmlFor="">Categories</label>
|
||||
<div className={s.select}>
|
||||
<SelectCommon options={CATEGORYSELECT} placeholder="Categories"/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.categorySelectSort}>
|
||||
<label htmlFor="" >Sort By</label>
|
||||
<div className={s.select}>
|
||||
<SelectCommon options={OPTIONSLECT} placeholder="Sort By" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={s.inner}>
|
||||
<div className={s.boxItem}>
|
||||
{recipes?.map((item,index) => (
|
||||
<div key={index} className={s.item}>
|
||||
<RecipeCard slug={item.slug} imageSrc={item.imageSrc} title={item.title} description={item.description}/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.recipesPagination}>
|
||||
<PaginationCommon pageSize={DEFAULT_PAGESIZE_RECIPELIST} total={total}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</>
|
||||
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 (
|
||||
<>
|
||||
<div className={s.recipesListWrapper}>
|
||||
<div className={s.breadcrumb}>
|
||||
<BreadcrumbCommon crumbs={BREADCRUMB} />
|
||||
</div>
|
||||
<div className={s.recipesListPageMain}>
|
||||
<div className={s.categories}>
|
||||
<MenuNavigation categories={CATEGORY} heading="Categories" />
|
||||
</div>
|
||||
|
||||
<div className={s.recipesList}>
|
||||
<HeadingCommon align="left">SPECIAL RECIPES</HeadingCommon>
|
||||
|
||||
<div className={s.boxSelect}>
|
||||
<div className={s.categorySelectCate}>
|
||||
<label htmlFor="">Categories</label>
|
||||
<div className={s.select}>
|
||||
<SelectCommon
|
||||
options={CATEGORYSELECT}
|
||||
placeholder="Categories"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.categorySelectSort}>
|
||||
<label htmlFor="">Sort By</label>
|
||||
<div className={s.select}>
|
||||
<SelectCommon options={OPTIONSLECT} placeholder="Sort By" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={s.inner}>
|
||||
<div className={s.boxItem}>
|
||||
{(!initialQueryFlag && loading && !data) && <ListBlogCardSkeleton count={DEFAULT_PAGESIZE_RECIPELIST} isWrap />}
|
||||
{data?.map((item, index) => (
|
||||
<div key={index} className={s.item}>
|
||||
<RecipeCard
|
||||
slug={item.slug}
|
||||
imageSrc={item.imageSrc}
|
||||
title={item.title}
|
||||
description={item.description}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.recipesPagination}>
|
||||
<PaginationCommon
|
||||
pageSize={DEFAULT_PAGESIZE_RECIPELIST}
|
||||
total={totalItems !== undefined ? totalItems : total}
|
||||
onChange={onPageChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default RecipesList
|
||||
|
@@ -24,6 +24,10 @@ export interface RecipeProps {
|
||||
slug: string
|
||||
description: string
|
||||
imageSrc: string
|
||||
content?: string,
|
||||
imgAuthor?: string,
|
||||
date?: string,
|
||||
authorName?: string,
|
||||
}
|
||||
|
||||
export interface BlogProps {
|
||||
|
Reference in New Issue
Block a user