mirror of
https://github.com/vercel/commerce.git
synced 2025-07-22 20:26:49 +00:00
Merge pull request #88 from KieIO/feature/m4-get-blog-list
Feature/m4 get blog list
This commit is contained in:
@@ -9,6 +9,10 @@ import type {
|
|||||||
GetAllProductsOperation,
|
GetAllProductsOperation,
|
||||||
GetProductOperation,
|
GetProductOperation,
|
||||||
} from '../types/product'
|
} from '../types/product'
|
||||||
|
import type {
|
||||||
|
GetAllBlogsOperation,
|
||||||
|
GetFeaturedBlogsOperation
|
||||||
|
} from '../types/blogs'
|
||||||
import type { APIProvider, CommerceAPI } from '.'
|
import type { APIProvider, CommerceAPI } from '.'
|
||||||
import { GetAllCollectionsOperation } from '@commerce/types/collection';
|
import { GetAllCollectionsOperation } from '@commerce/types/collection';
|
||||||
|
|
||||||
@@ -27,7 +31,8 @@ export const OPERATIONS = [
|
|||||||
'getProduct',
|
'getProduct',
|
||||||
'getAllFacets',
|
'getAllFacets',
|
||||||
'getAllCollections',
|
'getAllCollections',
|
||||||
|
'getAllBlogs',
|
||||||
|
'getFeaturedBlog'
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
export const defaultOperations = OPERATIONS.reduce((ops, k) => {
|
export const defaultOperations = OPERATIONS.reduce((ops, k) => {
|
||||||
@@ -144,6 +149,41 @@ export type Operations<P extends APIProvider> = {
|
|||||||
): Promise<T['data']>
|
): Promise<T['data']>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getAllBlogs: {
|
||||||
|
<T extends GetAllBlogsOperation>(opts: {
|
||||||
|
variables?: T['variables']
|
||||||
|
config?: P['config']
|
||||||
|
preview?: boolean
|
||||||
|
}): Promise<T['data']>
|
||||||
|
|
||||||
|
<T extends GetAllBlogsOperation>(
|
||||||
|
opts: {
|
||||||
|
variables?: T['variables']
|
||||||
|
config?: P['config']
|
||||||
|
preview?: boolean
|
||||||
|
} & OperationOptions
|
||||||
|
): Promise<T['data']>
|
||||||
|
}
|
||||||
|
|
||||||
|
getFeaturedBlog: {
|
||||||
|
<T extends GetFeaturedBlogsOperation>(opts: {
|
||||||
|
variables?: T['variables']
|
||||||
|
config?: P['config']
|
||||||
|
preview?: boolean
|
||||||
|
}): Promise<T['data']>
|
||||||
|
|
||||||
|
<T extends GetFeaturedBlogsOperation>(
|
||||||
|
opts: {
|
||||||
|
variables?: T['variables']
|
||||||
|
config?: P['config']
|
||||||
|
preview?: boolean
|
||||||
|
} & OperationOptions
|
||||||
|
): Promise<T['data']>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
getProduct: {
|
getProduct: {
|
||||||
<T extends GetProductOperation>(opts: {
|
<T extends GetProductOperation>(opts: {
|
||||||
variables: T['variables']
|
variables: T['variables']
|
||||||
|
31
framework/commerce/types/blogs.ts
Normal file
31
framework/commerce/types/blogs.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { Asset, BlogTranslation, Maybe, Product } from './../../vendure/schema.d';
|
||||||
|
|
||||||
|
export type BlogList = Node &{
|
||||||
|
id: string
|
||||||
|
featuredAsset?: Maybe<Asset>
|
||||||
|
isPublic:Boolean
|
||||||
|
translations: BlogTranslation[]
|
||||||
|
authorName: string
|
||||||
|
authorAvatarAsset:Asset[]
|
||||||
|
relevantProducts: Product
|
||||||
|
}
|
||||||
|
export type BlogsType = {
|
||||||
|
items: BlogList
|
||||||
|
totalItems: number
|
||||||
|
}
|
||||||
|
export type GetAllBlogsOperation<T extends BlogsType = BlogsType> = {
|
||||||
|
data: { items: T['items'][] }
|
||||||
|
variables: {
|
||||||
|
take?: number
|
||||||
|
skip?: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type GetFeaturedBlogsOperation<T extends BlogsType = BlogsType> = {
|
||||||
|
data: { items: T['items'][] }
|
||||||
|
variables: {
|
||||||
|
take?: number
|
||||||
|
skip?: number
|
||||||
|
}
|
||||||
|
}
|
@@ -11,7 +11,8 @@ import getProduct from './operations/get-product'
|
|||||||
import getSiteInfo from './operations/get-site-info'
|
import getSiteInfo from './operations/get-site-info'
|
||||||
import login from './operations/login'
|
import login from './operations/login'
|
||||||
import fetchGraphqlApi from './utils/fetch-graphql-api'
|
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 {}
|
export interface VendureConfig extends CommerceAPIConfig {}
|
||||||
|
|
||||||
@@ -44,6 +45,8 @@ const operations = {
|
|||||||
getProduct,
|
getProduct,
|
||||||
getAllFacets,
|
getAllFacets,
|
||||||
getAllCollections,
|
getAllCollections,
|
||||||
|
getAllBlogs,
|
||||||
|
getFeaturedBlog
|
||||||
}
|
}
|
||||||
|
|
||||||
export const provider = { config, operations }
|
export const provider = { config, operations }
|
||||||
|
61
framework/vendure/api/operations/get-all-blogs.ts
Normal file
61
framework/vendure/api/operations/get-all-blogs.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import { OperationContext } from '@commerce/api/operations'
|
||||||
|
import { Provider, VendureConfig } from '..'
|
||||||
|
import { GetAllBlogsQuery,BlogList } from '../../schema'
|
||||||
|
import { getAllBlogsQuery } from '../../utils/queries/get-all-blog-query'
|
||||||
|
|
||||||
|
export type BlogVariables = {
|
||||||
|
excludeBlogIds?: string[],
|
||||||
|
take?: number,
|
||||||
|
skip?:number
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function getAllBlogsOperation({
|
||||||
|
commerce,
|
||||||
|
}: OperationContext<Provider>) {
|
||||||
|
async function getAllBlogs(opts?: {
|
||||||
|
variables?: BlogVariables
|
||||||
|
config?: Partial<VendureConfig>
|
||||||
|
preview?: boolean
|
||||||
|
}): Promise<{ blogs: GetAllBlogsQuery[],totalItems:number }>
|
||||||
|
|
||||||
|
async function getAllBlogs({
|
||||||
|
query = getAllBlogsQuery,
|
||||||
|
variables: { ...vars } = {},
|
||||||
|
config: cfg,
|
||||||
|
}: {
|
||||||
|
query?: string
|
||||||
|
variables?: BlogVariables
|
||||||
|
config?: Partial<VendureConfig>
|
||||||
|
preview?: boolean
|
||||||
|
} = {}): Promise<{ blogs: GetAllBlogsQuery[] | any[] ,totalItems?:number }> {
|
||||||
|
|
||||||
|
const config = commerce.getConfig(cfg)
|
||||||
|
const variables = {
|
||||||
|
excludeBlogIds: vars.excludeBlogIds,
|
||||||
|
options: {
|
||||||
|
take: vars.take,
|
||||||
|
skip: vars.skip,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const { data } = await config.fetch<GetAllBlogsQuery>(query, {
|
||||||
|
variables,
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
blogs: 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,
|
||||||
|
isFeatured: val.isFeatured,
|
||||||
|
authorName: val.authorName,
|
||||||
|
authorAvatarAsset : val.authorAvatarAsset?.preview,
|
||||||
|
createdAt: val.createdAt
|
||||||
|
})),
|
||||||
|
totalItems: data?.blogs?.totalItems || null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAllBlogs
|
||||||
|
}
|
56
framework/vendure/api/operations/get-featured-blog.ts
Normal file
56
framework/vendure/api/operations/get-featured-blog.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { OperationContext } from '@commerce/api/operations'
|
||||||
|
import { Provider, VendureConfig } from '..'
|
||||||
|
import { GetFeaturedBlogQuery,BlogList } from '../../schema'
|
||||||
|
import { getFeatuedBlogsQuery } from '../../utils/queries/get-featued-query'
|
||||||
|
|
||||||
|
export type BlogVariables = {
|
||||||
|
take?: number,
|
||||||
|
skip?:number
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function getFeaturedBlogOperation({
|
||||||
|
commerce,
|
||||||
|
}: OperationContext<Provider>) {
|
||||||
|
async function getFeaturedBlog(opts?: {
|
||||||
|
variables?: BlogVariables
|
||||||
|
config?: Partial<VendureConfig>
|
||||||
|
preview?: boolean
|
||||||
|
}): Promise<{ featuredBlogs: GetFeaturedBlogQuery[],totalItems:number }>
|
||||||
|
|
||||||
|
async function getFeaturedBlog({
|
||||||
|
query = getFeatuedBlogsQuery,
|
||||||
|
variables: { ...vars } = {},
|
||||||
|
config: cfg,
|
||||||
|
}: {
|
||||||
|
query?: string
|
||||||
|
variables?: BlogVariables
|
||||||
|
config?: Partial<VendureConfig>
|
||||||
|
preview?: boolean
|
||||||
|
} = {}): Promise<{ featuredBlogs: GetFeaturedBlogQuery[] | any[] ,totalItems?:number }> {
|
||||||
|
const config = commerce.getConfig(cfg)
|
||||||
|
const variables = {
|
||||||
|
options: {
|
||||||
|
take: vars.take,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const { data } = await config.fetch<GetFeaturedBlogQuery>(query, {
|
||||||
|
variables,
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
featuredBlogs: data?.featuredBlogs?.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 getFeaturedBlog
|
||||||
|
}
|
50
framework/vendure/schema.d.ts
vendored
50
framework/vendure/schema.d.ts
vendored
@@ -2371,6 +2371,55 @@ export type Product = Node & {
|
|||||||
customFields?: Maybe<Scalars['JSON']>
|
customFields?: Maybe<Scalars['JSON']>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type BlogList = Node &{
|
||||||
|
id: ID!
|
||||||
|
createdAt: DateTime!
|
||||||
|
updatedAt: DateTime!
|
||||||
|
featuredAsset?: Maybe<Asset>
|
||||||
|
isPublish:Boolean
|
||||||
|
translations: Array<BlogTranslation>
|
||||||
|
authorName: Scalars['String']
|
||||||
|
authorAvatarAsset:Asset
|
||||||
|
relevantProducts: Product
|
||||||
|
isFeatured: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BlogTranslation = {
|
||||||
|
__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' } & {
|
||||||
|
items: Array<{ __typename?: 'Blog' } & BlogList!>,
|
||||||
|
'totalItems'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export type GetFeaturedBlogQuery = PaginatedList & {
|
||||||
|
id:string,
|
||||||
|
featuredBlogs: { __typename?: 'BlogList' } & {
|
||||||
|
items: Array<{ __typename?: 'Blog' } & BlogList!>,
|
||||||
|
'totalItems'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type QueryBlogs = {
|
||||||
|
excludeBlogIds:Array,
|
||||||
|
options: BlogListOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BlogListOptions = {
|
||||||
|
skip?: Maybe<Scalars['Int']>
|
||||||
|
take?: Maybe<Scalars['Int']>
|
||||||
|
}
|
||||||
|
|
||||||
export type ProductTranslation = {
|
export type ProductTranslation = {
|
||||||
__typename?: 'ProductTranslation'
|
__typename?: 'ProductTranslation'
|
||||||
id: Scalars['ID']
|
id: Scalars['ID']
|
||||||
@@ -3485,3 +3534,4 @@ export type SearchQuery = { __typename?: 'Query' } & {
|
|||||||
'totalItems'
|
'totalItems'
|
||||||
> & { items: Array<{ __typename?: 'SearchResult' } & SearchResultFragment> }
|
> & { items: Array<{ __typename?: 'SearchResult' } & SearchResultFragment> }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { Cart } from '@commerce/types/cart'
|
import { Cart } from '@commerce/types/cart'
|
||||||
import { ProductCard, Product } from '@commerce/types/product'
|
import { ProductCard, Product } from '@commerce/types/product'
|
||||||
import { CartFragment, SearchResultFragment,Favorite } from '../schema'
|
import { CartFragment, SearchResultFragment,Favorite, BlogList } from '../schema'
|
||||||
|
|
||||||
export function normalizeSearchResult(item: SearchResultFragment): ProductCard {
|
export function normalizeSearchResult(item: SearchResultFragment): ProductCard {
|
||||||
return {
|
return {
|
||||||
@@ -83,4 +83,19 @@ export function normalizeProductCard(product: Product): ProductCard {
|
|||||||
facetValueIds: product.facetValueIds,
|
facetValueIds: product.facetValueIds,
|
||||||
collectionIds: product.collectionIds,
|
collectionIds: product.collectionIds,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeBlogList(blog: BlogList) {
|
||||||
|
return {
|
||||||
|
id: blog.id,
|
||||||
|
title: blog.translations[0]?.title,
|
||||||
|
imageSrc: blog.featuredAsset?.preview ?? null,
|
||||||
|
slug: blog.translations[0]?.slug,
|
||||||
|
description: blog.translations[0]?.description,
|
||||||
|
isPublish: blog.isPublish,
|
||||||
|
isFeatured:blog.isFeatured,
|
||||||
|
authorName: blog.authorName,
|
||||||
|
authorAvatarAsset : blog.authorAvatarAsset?.preview,
|
||||||
|
createdAt: blog.createdAt
|
||||||
|
}
|
||||||
}
|
}
|
26
framework/vendure/utils/queries/get-all-blog-query.ts
Normal file
26
framework/vendure/utils/queries/get-all-blog-query.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
export const getAllBlogsQuery = /* GraphQL */ `
|
||||||
|
query GetBlogs($excludeBlogIds: [ID]!, $options: BlogListOptions) {
|
||||||
|
blogs(excludeBlogIds: $excludeBlogIds, options: $options) {
|
||||||
|
totalItems
|
||||||
|
items {
|
||||||
|
id
|
||||||
|
isPublish
|
||||||
|
isFeatured
|
||||||
|
authorName
|
||||||
|
createdAt
|
||||||
|
authorAvatarAsset{
|
||||||
|
preview
|
||||||
|
}
|
||||||
|
featuredAsset {
|
||||||
|
preview
|
||||||
|
}
|
||||||
|
translations {
|
||||||
|
title
|
||||||
|
slug
|
||||||
|
description
|
||||||
|
content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
25
framework/vendure/utils/queries/get-featued-query.ts
Normal file
25
framework/vendure/utils/queries/get-featued-query.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
export const getFeatuedBlogsQuery = /* GraphQL */ `
|
||||||
|
query GetFeaturedBlogs($options: BlogListOptions) {
|
||||||
|
featuredBlogs( options: $options){
|
||||||
|
items {
|
||||||
|
id
|
||||||
|
isPublish
|
||||||
|
isFeatured
|
||||||
|
authorName
|
||||||
|
createdAt
|
||||||
|
authorAvatarAsset{
|
||||||
|
preview
|
||||||
|
}
|
||||||
|
featuredAsset {
|
||||||
|
preview
|
||||||
|
}
|
||||||
|
translations {
|
||||||
|
title
|
||||||
|
slug
|
||||||
|
description
|
||||||
|
content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
3
next-env.d.ts
vendored
3
next-env.d.ts
vendored
@@ -1,6 +1,3 @@
|
|||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/types/global" />
|
/// <reference types="next/types/global" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
|
||||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
|
||||||
|
@@ -1,14 +1,91 @@
|
|||||||
|
import commerce from '@lib/api/commerce';
|
||||||
|
import { GetStaticPropsContext } from 'next';
|
||||||
import { Layout } from 'src/components/common';
|
import { Layout } from 'src/components/common';
|
||||||
import { BlogsList, FeaturedCardBlog, BlogHeading, BlogBreadCrumb } from 'src/components/modules/blogs';
|
import { BlogCardProps } from 'src/components/common/CardBlog/CardBlog';
|
||||||
|
import { BlogBreadCrumb, BlogHeading, BlogsList, FeaturedCardBlog } from 'src/components/modules/blogs';
|
||||||
|
import { DEFAULT_BLOG_PAGE_SIZE } from "src/utils/constanst.utils";
|
||||||
|
import { getAllPromies } from 'src/utils/funtion.utils';
|
||||||
|
import { PromiseWithKey } from 'src/utils/types.utils';
|
||||||
|
|
||||||
export default function BlogsPage() {
|
interface Props {
|
||||||
|
blogs?: BlogCardProps[],
|
||||||
|
featuredBlog?: BlogCardProps[],
|
||||||
|
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();
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<>
|
<>
|
||||||
<BlogBreadCrumb />
|
<BlogBreadCrumb />
|
||||||
<BlogHeading />
|
<BlogHeading />
|
||||||
<FeaturedCardBlog />
|
<FeaturedCardBlog
|
||||||
<BlogsList />
|
title={featuredBlog?.[0]?.title}
|
||||||
|
slug={featuredBlog?.[0]?.slug}
|
||||||
|
imgSrc={featuredBlog?.[0]?.imageSrc ?? ''}
|
||||||
|
content={featuredBlog?.[0]?.description}
|
||||||
|
imgAuthor={featuredBlog?.[0]?.authorAvatarAsset}
|
||||||
|
authorName={featuredBlog?.[0]?.authorName}
|
||||||
|
date={fullDate}
|
||||||
|
/>
|
||||||
|
<BlogsList blogList={blogs} total={totalItems} idFeatured={featuredBlog?.[0]?.id} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
BlogsPage.Layout = Layout
|
|
||||||
|
|
||||||
|
export async function getStaticProps({
|
||||||
|
preview,
|
||||||
|
locale,
|
||||||
|
locales,
|
||||||
|
}: GetStaticPropsContext) {
|
||||||
|
const config = { locale, locales }
|
||||||
|
let promisesWithKey = [] as PromiseWithKey[]
|
||||||
|
let props = {} as any;
|
||||||
|
|
||||||
|
const {featuredBlogs} = await commerce.getFeaturedBlog({
|
||||||
|
variables: {
|
||||||
|
take: 1
|
||||||
|
},
|
||||||
|
config,
|
||||||
|
preview,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Blogs
|
||||||
|
const idFeaturedBlog = featuredBlogs?.[0]?.id;
|
||||||
|
const blogsPromise = commerce.getAllBlogs({
|
||||||
|
variables: {
|
||||||
|
excludeBlogIds: [idFeaturedBlog],
|
||||||
|
take: DEFAULT_BLOG_PAGE_SIZE
|
||||||
|
},
|
||||||
|
config,
|
||||||
|
preview,
|
||||||
|
})
|
||||||
|
promisesWithKey.push({ key: 'blogsResult', promise: blogsPromise })
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
})
|
||||||
|
|
||||||
|
props.featuredBlog = featuredBlogs;
|
||||||
|
|
||||||
|
console.log(props)
|
||||||
|
return {
|
||||||
|
props,
|
||||||
|
revalidate: 60
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BlogsPage.Layout = Layout
|
||||||
|
@@ -12,6 +12,7 @@ import { CODE_FACET_DISCOUNT, CODE_FACET_FEATURED,COLLECTION_SLUG_SPICE } from '
|
|||||||
import { getAllFacetValueIdsByParentCode, getAllFacetValuesForFeatuedProducts, getAllPromies, getFreshFacetId } from 'src/utils/funtion.utils';
|
import { getAllFacetValueIdsByParentCode, getAllFacetValuesForFeatuedProducts, getAllPromies, getFreshFacetId } from 'src/utils/funtion.utils';
|
||||||
import { PromiseWithKey } from 'src/utils/types.utils';
|
import { PromiseWithKey } from 'src/utils/types.utils';
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
featuredAndDiscountFacetsValue: FacetValue[],
|
featuredAndDiscountFacetsValue: FacetValue[],
|
||||||
freshProducts: ProductCard[],
|
freshProducts: ProductCard[],
|
||||||
@@ -63,7 +64,7 @@ export async function getStaticProps({
|
|||||||
|
|
||||||
|
|
||||||
props.featuredAndDiscountFacetsValue = getAllFacetValuesForFeatuedProducts(facets)
|
props.featuredAndDiscountFacetsValue = getAllFacetValuesForFeatuedProducts(facets)
|
||||||
|
|
||||||
// fresh products
|
// fresh products
|
||||||
const freshProductvariables: ProductVariables = {}
|
const freshProductvariables: ProductVariables = {}
|
||||||
const freshFacetId = getFreshFacetId(facets)
|
const freshFacetId = getFreshFacetId(facets)
|
||||||
|
@@ -6,17 +6,20 @@ import { ImgWithLink } from '..'
|
|||||||
import s from './CardBlog.module.scss'
|
import s from './CardBlog.module.scss'
|
||||||
|
|
||||||
export interface BlogCardProps extends BlogProps {
|
export interface BlogCardProps extends BlogProps {
|
||||||
// todo: edit when intergrate API
|
isPublish?:Boolean,
|
||||||
|
isFeatured?:Boolean,
|
||||||
|
authorAvatarAsset?:string,
|
||||||
|
authorName?:string,
|
||||||
|
createdAt?:string
|
||||||
}
|
}
|
||||||
|
|
||||||
const CardBlog = ({ imageSrc, title, description, slug }: BlogCardProps) => {
|
const CardBlog = ({ imageSrc, title, description, slug }: BlogCardProps) => {
|
||||||
return (
|
return (
|
||||||
<div className={s.cardBlogWarpper}>
|
<div className={s.cardBlogWarpper}>
|
||||||
<Link href={`${ROUTE.BLOG_DETAIL}/${slug}`}>
|
<Link href={`${ROUTE.BLOG_DETAIL}/${slug}`}>
|
||||||
<a>
|
<a>
|
||||||
<div className={s.image}>
|
<div className={s.image}>
|
||||||
<ImgWithLink src={imageSrc} alt="image cardblog" />
|
<ImgWithLink src={imageSrc ?? ''} alt={title} />
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
|
@@ -0,0 +1,18 @@
|
|||||||
|
.listBlogCardSkeleton {
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 90%;
|
||||||
|
justify-content: space-between;
|
||||||
|
div{
|
||||||
|
min-width: 32rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wrap {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
overflow: unset;
|
||||||
|
> div {
|
||||||
|
margin-bottom: 1.6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,20 @@
|
|||||||
|
import classNames from 'classnames'
|
||||||
|
import { ProductCardSkeleton } from '..'
|
||||||
|
import s from './ListBlogCardSkeleton.module.scss'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
count?: number
|
||||||
|
isWrap?: boolean,
|
||||||
|
}
|
||||||
|
const ListBlogCardSkeleton = ({ count = 3, isWrap }: Props) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classNames(s.listBlogCardSkeleton, { [s.wrap]: isWrap })}>
|
||||||
|
{
|
||||||
|
Array.from(Array(count).keys()).map(item => <ProductCardSkeleton key={item} />)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ListBlogCardSkeleton
|
@@ -1,7 +1,7 @@
|
|||||||
.listProductCardSkeleton {
|
.listProductCardSkeleton {
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&.wrap {
|
&.wrap {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
overflow: unset;
|
overflow: unset;
|
||||||
@@ -9,4 +9,11 @@
|
|||||||
margin-bottom: 1.6rem;
|
margin-bottom: 1.6rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.isBlog{
|
||||||
|
width: 90%;
|
||||||
|
justify-content: space-between;
|
||||||
|
div{
|
||||||
|
min-width: 32rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,15 +4,14 @@ import s from './ListProductCardSkeleton.module.scss'
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
count?: number
|
count?: number
|
||||||
isWrap?: boolean
|
isWrap?: boolean,
|
||||||
}
|
}
|
||||||
const ListProductCardSkeleton = ({ count = 5, isWrap }: Props) => {
|
const ListProductCardSkeleton = ({ count = 3, isWrap }: Props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(s.listProductCardSkeleton, { [s.wrap]: isWrap })}>
|
<div className={classNames(s.listProductCardSkeleton, { [s.wrap]: isWrap })}>
|
||||||
{
|
{
|
||||||
Array.from(Array(count).keys()).map(item => <ProductCardSkeleton key={item} />)
|
Array.from(Array(count).keys()).map(item => <ProductCardSkeleton key={item} />)
|
||||||
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@@ -1,14 +1,16 @@
|
|||||||
import SkeletonImage from "../SkeletonCommon/SkeletonImage/SkeletonImage"
|
import SkeletonImage from "../SkeletonCommon/SkeletonImage/SkeletonImage"
|
||||||
import SkeletonParagraph from "../SkeletonCommon/SkeletonParagraph/SkeletonParagraph"
|
import SkeletonParagraph from "../SkeletonCommon/SkeletonParagraph/SkeletonParagraph"
|
||||||
import s from './ProductCardSkeleton.module.scss'
|
import s from './ProductCardSkeleton.module.scss'
|
||||||
|
type Props = {
|
||||||
const ProductCardSkeleton = ({ }) => {
|
isBlog?:boolean
|
||||||
|
}
|
||||||
|
const ProductCardSkeleton = ({isBlog=false }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={s.productCardSkeleton}>
|
<div className={s.productCardSkeleton}>
|
||||||
<SkeletonImage />
|
<SkeletonImage />
|
||||||
<div className={s.content}>
|
<div className={s.content}>
|
||||||
<SkeletonParagraph rows={3} />
|
<SkeletonParagraph rows={isBlog ? 2 : 3} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@@ -55,4 +55,5 @@ export { default as FormForgot} from './ForgotPassword/FormForgot/FormForgot'
|
|||||||
export { default as FormResetPassword} from './ForgotPassword/FormResetPassword/FormResetPassword'
|
export { default as FormResetPassword} from './ForgotPassword/FormResetPassword/FormResetPassword'
|
||||||
export { default as ProductCardSkeleton} from './ProductCardSkeleton/ProductCardSkeleton'
|
export { default as ProductCardSkeleton} from './ProductCardSkeleton/ProductCardSkeleton'
|
||||||
export { default as ListProductCardSkeleton} from './ListProductCardSkeleton/ListProductCardSkeleton'
|
export { default as ListProductCardSkeleton} from './ListProductCardSkeleton/ListProductCardSkeleton'
|
||||||
|
export { default as ListBlogCardSkeleton} from './ListBlogCardSkeleton/ListBlogCardSkeleton'
|
||||||
|
|
||||||
|
1
src/components/hooks/blog/index.ts
Normal file
1
src/components/hooks/blog/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export {default as useGetBlogList }from "./useGetBlogList"
|
18
src/components/hooks/blog/useGetBlogList.tsx
Normal file
18
src/components/hooks/blog/useGetBlogList.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { GetAllBlogsQuery, QueryBlogs,BlogList } from '@framework/schema'
|
||||||
|
import { normalizeBlogList } 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 useGetBlogList = (options?: QueryBlogs) => {
|
||||||
|
const { data, isValidating, ...rest } = useSWR<GetAllBlogsQuery>([getAllBlogsQuery, options], gglFetcher)
|
||||||
|
|
||||||
|
return {
|
||||||
|
blogs: data?.blogs?.items?.map((blog:BlogList)=>normalizeBlogList(blog)),
|
||||||
|
totalItems: data?.blogs?.totalItems || null,
|
||||||
|
loading: isValidating,
|
||||||
|
...rest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useGetBlogList
|
@@ -1,151 +1,96 @@
|
|||||||
import React, { useState } from 'react'
|
import { useRouter } from 'next/router'
|
||||||
|
import React, { useEffect, useState,useRef, useMemo } from 'react'
|
||||||
import CardBlog, { BlogCardProps } from 'src/components/common/CardBlog/CardBlog'
|
import CardBlog, { BlogCardProps } from 'src/components/common/CardBlog/CardBlog'
|
||||||
import PaginationCommon from 'src/components/common/PaginationCommon/PaginationCommon'
|
import PaginationCommon from 'src/components/common/PaginationCommon/PaginationCommon'
|
||||||
|
import { DEFAULT_BLOG_PAGE_SIZE, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'
|
||||||
import s from "./BlogsList.module.scss"
|
import s from "./BlogsList.module.scss"
|
||||||
import { DEFAULT_BLOG_PAGE_SIZE } from 'src/utils/constanst.utils'
|
import { QueryBlogs } from '@framework/schema'
|
||||||
|
import { useGetBlogList } from 'src/components/hooks/blog'
|
||||||
|
import { getPageFromQuery } from 'src/utils/funtion.utils'
|
||||||
|
import { ListBlogCardSkeleton } from 'src/components/common'
|
||||||
|
|
||||||
interface BlogsListProps {
|
interface BlogsListProps {
|
||||||
data?: BlogCardProps[],
|
blogList?: BlogCardProps[],
|
||||||
|
total?: number,
|
||||||
|
idFeatured?:string
|
||||||
}
|
}
|
||||||
|
|
||||||
const BLOGSLIST_DATA = [
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133185783-8100ef4e-7a72-4dc1-bb12-2ca46b56b393.png",
|
|
||||||
title: "1",
|
|
||||||
description: "The DEBM diet stands for "+"Delicious Happy Fun Diet"+". This diet was popularized by Robert...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133185911-df505d10-fdcd-4312-add3-7c62ad8af71e.png",
|
|
||||||
title: "2",
|
|
||||||
description: "Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133185959-7ad75580-ca6d-4684-83d9-3f64500bbc97.png",
|
|
||||||
title: "3",
|
|
||||||
description: "Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133186410-d8718d90-82fb-46cb-a0f2-0ec96356ae89.png",
|
|
||||||
title: "4",
|
|
||||||
description: "The DEBM diet stands for "+"Delicious Happy Fun Diet"+". This diet was popularized by Robert...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133186474-b2d89bbc-32ed-4174-a05e-3d388c0a39ff.png",
|
|
||||||
title: "5",
|
|
||||||
description: "Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133186545-d860f4ee-222c-4d72-a876-808af0f397a0.png",
|
|
||||||
title: "6",
|
|
||||||
description: "Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133185783-8100ef4e-7a72-4dc1-bb12-2ca46b56b393.png",
|
|
||||||
title: "7",
|
|
||||||
description: "The DEBM diet stands for "+"Delicious Happy Fun Diet"+". This diet was popularized by Robert...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133185911-df505d10-fdcd-4312-add3-7c62ad8af71e.png",
|
|
||||||
title: "8",
|
|
||||||
description: "Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133185959-7ad75580-ca6d-4684-83d9-3f64500bbc97.png",
|
|
||||||
title: "9",
|
|
||||||
description: "Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133186545-d860f4ee-222c-4d72-a876-808af0f397a0.png",
|
|
||||||
title: "10",
|
|
||||||
description: "Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133186410-d8718d90-82fb-46cb-a0f2-0ec96356ae89.png",
|
|
||||||
title: "11",
|
|
||||||
description: "The DEBM diet stands for "+"Delicious Happy Fun Diet"+". This diet was popularized by Robert...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133186474-b2d89bbc-32ed-4174-a05e-3d388c0a39ff.png",
|
|
||||||
title: "12",
|
|
||||||
description: "Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133185783-8100ef4e-7a72-4dc1-bb12-2ca46b56b393.png",
|
|
||||||
title: "13",
|
|
||||||
description: "The DEBM diet stands for "+"Delicious Happy Fun Diet"+". This diet was popularized by Robert...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133185911-df505d10-fdcd-4312-add3-7c62ad8af71e.png",
|
|
||||||
title: "14",
|
|
||||||
description: "Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133185959-7ad75580-ca6d-4684-83d9-3f64500bbc97.png",
|
|
||||||
title: "15",
|
|
||||||
description: "Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133186410-d8718d90-82fb-46cb-a0f2-0ec96356ae89.png",
|
|
||||||
title: "16",
|
|
||||||
description: "The DEBM diet stands for "+"Delicious Happy Fun Diet"+". This diet was popularized by Robert...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133186545-d860f4ee-222c-4d72-a876-808af0f397a0.png",
|
|
||||||
title: "17",
|
|
||||||
description: "Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
imageSrc: "https://user-images.githubusercontent.com/46085455/133186474-b2d89bbc-32ed-4174-a05e-3d388c0a39ff.png",
|
|
||||||
title: "18",
|
|
||||||
description: "Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...",
|
|
||||||
slug: "happy-diet"
|
|
||||||
},
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
const BlogsList = ({ data = BLOGSLIST_DATA }:BlogsListProps) => {
|
|
||||||
const [currentPage, setCurrentPage] = useState(0)
|
const BlogsList = ({ blogList,total,idFeatured }:BlogsListProps) => {
|
||||||
|
|
||||||
|
const DEFAULT_BLOGS_ARGS = useMemo(()=> ({
|
||||||
|
excludeBlogIds: [idFeatured],
|
||||||
|
options:{
|
||||||
|
skip: 1, take: DEFAULT_BLOG_PAGE_SIZE
|
||||||
|
}
|
||||||
|
}),[idFeatured]);
|
||||||
|
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const [initialQueryFlag, setInitialQueryFlag] = useState<boolean>(true)
|
||||||
|
|
||||||
|
const [optionQueryBlog, setOptionQueryBlog] = useState<QueryBlogs>(DEFAULT_BLOGS_ARGS)
|
||||||
|
const { blogs, totalItems, loading } = useGetBlogList(optionQueryBlog);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const onPageChange = (page:number) => {
|
const onPageChange = (page:number) => {
|
||||||
setCurrentPage(page)
|
router.push({
|
||||||
|
pathname: ROUTE.BLOGS,
|
||||||
|
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 QueryBlogs;
|
||||||
|
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 = blogList;
|
||||||
|
}else{
|
||||||
|
data = blogs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<div className={s.wrapper}>
|
<div className={s.wrapper}>
|
||||||
|
{(!initialQueryFlag && loading && !blogs) && <ListBlogCardSkeleton count={DEFAULT_BLOG_PAGE_SIZE} isWrap />}
|
||||||
<div className={s.list}>
|
<div className={s.list}>
|
||||||
|
|
||||||
{
|
{
|
||||||
data.slice(currentPage*DEFAULT_BLOG_PAGE_SIZE,(currentPage+1)*DEFAULT_BLOG_PAGE_SIZE).map((product,index)=> {
|
data?.map((product,index)=> {
|
||||||
return(
|
return(
|
||||||
<div className={s.card} key={`${product.title}-${index}`}>
|
<div className={s.card} key={`${product.title}-${index}`}>
|
||||||
<CardBlog {...product} />
|
{product.isPublish && <CardBlog {...product} /> }
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className={s.pagination}>
|
<div className={s.pagination}>
|
||||||
<PaginationCommon total={data.length} pageSize={DEFAULT_BLOG_PAGE_SIZE} onChange={onPageChange}/>
|
<PaginationCommon total={totalItems !== undefined ? totalItems : total} pageSize={DEFAULT_BLOG_PAGE_SIZE} onChange={onPageChange}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BlogsList
|
export default BlogsList
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
import s from './FeaturedCardBlog.module.scss'
|
import s from './FeaturedCardBlog.module.scss'
|
||||||
import { Author, DateTime, ImgWithLink } from 'src/components/common'
|
import { Author, DateTime, ImgWithLink } from 'src/components/common'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import { ROUTE } from 'src/utils/constanst.utils'
|
||||||
interface FeaturedCardBlogProps{
|
interface FeaturedCardBlogProps{
|
||||||
title?: string,
|
title?: string,
|
||||||
|
slug?:string,
|
||||||
content?: string,
|
content?: string,
|
||||||
imgSrc?: string,
|
imgSrc?: string,
|
||||||
imgAuthor?: string,
|
imgAuthor?: string,
|
||||||
@@ -10,33 +12,31 @@ interface FeaturedCardBlogProps{
|
|||||||
authorName?: string,
|
authorName?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
const FEATURED_DATA = {
|
|
||||||
title: "Flammekueche with green asparagus",
|
|
||||||
content: "Traditionally, the Flammekueche is made with rapeseed oil, which, contrary to popular belief, is indeed an oil that can be cooked hot and is not limited to seasoning. It is important to vary the oils in the kitchen to take advantage of the benefits of each. Rapeseed oil is an oil rich in omega 3 which participate in the proper functioning of the cardiovascular system as well as in vitamins E which contributes to the protection of cells against oxidative stress. In short, oils are your friends 😉",
|
|
||||||
imgSrc: "https://user-images.githubusercontent.com/46085455/133186666-1ea8081f-4319-4617-8644-d20ed14b1825.png",
|
|
||||||
imgAuthor: "https://user-images.githubusercontent.com/46085455/133186783-d0c71d43-b7bc-44b6-b560-818c71bd162f.png",
|
|
||||||
date: "APRIL 30, 2021",
|
|
||||||
author: "Alessandro Del Piero"
|
|
||||||
}
|
|
||||||
|
|
||||||
const FeaturedCardBlog = ({
|
const FeaturedCardBlog = ({
|
||||||
title = FEATURED_DATA.title,
|
title,
|
||||||
content = FEATURED_DATA.content,
|
slug,
|
||||||
imgSrc = FEATURED_DATA.imgSrc,
|
content,
|
||||||
imgAuthor = FEATURED_DATA.imgAuthor,
|
imgSrc = '',
|
||||||
date = FEATURED_DATA.date,
|
imgAuthor = '',
|
||||||
authorName = FEATURED_DATA.author
|
date = '',
|
||||||
|
authorName = ''
|
||||||
}: FeaturedCardBlogProps) => {
|
}: FeaturedCardBlogProps) => {
|
||||||
return (
|
return (
|
||||||
<section className={s.featuredCard}>
|
<section className={s.featuredCard}>
|
||||||
<div className={s.featuredCardWrapper}>
|
<div className={s.featuredCardWrapper}>
|
||||||
<div className={s.left}>
|
<Link href={`${ROUTE.BLOG_DETAIL}/${slug}`}>
|
||||||
<ImgWithLink src={imgSrc} alt="image feature card"/>
|
<a>
|
||||||
</div>
|
<div className={s.left}>
|
||||||
|
<ImgWithLink src={imgSrc} alt="image feature card"/>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
<div className={s.right}>
|
<div className={s.right}>
|
||||||
<div className={s.titleWrapper}>
|
<div className={s.titleWrapper}>
|
||||||
<DateTime date={date}/>
|
<DateTime date={date }/>
|
||||||
<a className={s.title}>{title}</a>
|
<Link href={`${ROUTE.BLOG_DETAIL}/${slug}`}>
|
||||||
|
<a className={s.title}>{title}</a>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<Author name={authorName} image={imgAuthor}/>
|
<Author name={authorName} image={imgAuthor}/>
|
||||||
<div className={s.content}>{content}</div>
|
<div className={s.content}>{content}</div>
|
||||||
|
@@ -184,6 +184,8 @@ export const FEATURED = [
|
|||||||
|
|
||||||
export const DEFAULT_BLOG_PAGE_SIZE = 6;
|
export const DEFAULT_BLOG_PAGE_SIZE = 6;
|
||||||
|
|
||||||
|
export const DEFAULT_FEATURED_BLOG_PAGE_SIZE = 1;
|
||||||
|
|
||||||
export const FILTER_PAGE = [ROUTE.HOME, ROUTE.PRODUCTS]
|
export const FILTER_PAGE = [ROUTE.HOME, ROUTE.PRODUCTS]
|
||||||
|
|
||||||
export const STATE_OPTIONS = [
|
export const STATE_OPTIONS = [
|
||||||
|
@@ -143,6 +143,10 @@ export function getAllPromies(promies: PromiseWithKey[]) {
|
|||||||
return promies.map(item => item.promise)
|
return promies.map(item => item.promise)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getIdFeaturedBlog(blog: BlogList) {
|
||||||
|
return blog?.id
|
||||||
|
}
|
||||||
|
|
||||||
export const FilterOneVatiant = (products:ProductCard[]) => {
|
export const FilterOneVatiant = (products:ProductCard[]) => {
|
||||||
let idList:string[] = []
|
let idList:string[] = []
|
||||||
let filtedProduct: ProductCard[]=[]
|
let filtedProduct: ProductCard[]=[]
|
||||||
@@ -173,4 +177,4 @@ export function getProductVariant(product: Product, opts: SelectedOptions) {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
return variant
|
return variant
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,7 @@ export interface BlogProps {
|
|||||||
title: string
|
title: string
|
||||||
slug: string
|
slug: string
|
||||||
description: string
|
description: string
|
||||||
imageSrc: string
|
imageSrc: string | null,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CheckOutForm {
|
export interface CheckOutForm {
|
||||||
|
Reference in New Issue
Block a user