From 111e831d3d400fbbfe6db40a412d7357721d808e Mon Sep 17 00:00:00 2001 From: Quangnhankie Date: Fri, 15 Oct 2021 11:54:14 +0700 Subject: [PATCH 1/4] feat: get-blog-list --- framework/commerce/api/operations.ts | 23 ++- framework/commerce/types/blogs.ts | 26 +++ framework/vendure/api/index.ts | 3 +- .../vendure/api/operations/get-all-blogs.ts | 52 +++++ framework/vendure/schema.d.ts | 41 ++++ .../utils/queries/get-all-blog-query.ts | 20 ++ pages/blogs.tsx | 68 ++++++- pages/index.tsx | 3 +- src/components/common/CardBlog/CardBlog.tsx | 6 +- .../ListProductCardSkeleton.module.scss | 2 +- .../ListProductCardSkeleton.tsx | 2 +- src/components/hooks/blog/index.ts | 1 + src/components/hooks/blog/useGetBlogList.tsx | 24 +++ .../modules/blogs/BlogsList/BlogsList.tsx | 188 ++++++------------ src/utils/types.utils.ts | 2 +- 15 files changed, 321 insertions(+), 140 deletions(-) create mode 100644 framework/commerce/types/blogs.ts create mode 100644 framework/vendure/api/operations/get-all-blogs.ts create mode 100644 framework/vendure/utils/queries/get-all-blog-query.ts create mode 100644 src/components/hooks/blog/index.ts create mode 100644 src/components/hooks/blog/useGetBlogList.tsx diff --git a/framework/commerce/api/operations.ts b/framework/commerce/api/operations.ts index ca9b325c2..1065653bd 100644 --- a/framework/commerce/api/operations.ts +++ b/framework/commerce/api/operations.ts @@ -9,6 +9,9 @@ import type { GetAllProductsOperation, GetProductOperation, } from '../types/product' +import type { + GetAllBlogsOperation +} from '../types/blogs' import type { APIProvider, CommerceAPI } from '.' import { GetAllCollectionsOperation } from '@commerce/types/collection'; @@ -27,7 +30,7 @@ export const OPERATIONS = [ 'getProduct', 'getAllFacets', 'getAllCollections', - + 'getAllBlogs' ] as const export const defaultOperations = OPERATIONS.reduce((ops, k) => { @@ -144,6 +147,24 @@ export type Operations

= { ): Promise } + + getAllBlogs: { + (opts: { + variables?: T['variables'] + config?: P['config'] + preview?: boolean + }): Promise + + ( + opts: { + variables?: T['variables'] + config?: P['config'] + preview?: boolean + } & OperationOptions + ): Promise + } + + getProduct: { (opts: { variables: T['variables'] diff --git a/framework/commerce/types/blogs.ts b/framework/commerce/types/blogs.ts new file mode 100644 index 000000000..f138b964e --- /dev/null +++ b/framework/commerce/types/blogs.ts @@ -0,0 +1,26 @@ +import { SearchResultSortParameter } from "@framework/schema"; +import { Asset, BlogTranslation, Maybe, Product } from './../../vendure/schema.d'; + +export type BlogList = Node &{ + id: string + featuredAsset?: Maybe + isHidden:Boolean + translations: Array + authorName: string + authorAvatarAsset:Array + relevantProducts: Product +} +export type BlogsType = { + items: BlogList + totalItems: number +} +export type GetAllBlogsOperation = { + data: { items: T['items'][] } + variables: { + take?: number + skip?: number + sort?: SearchResultSortParameter + } + } + + \ No newline at end of file diff --git a/framework/vendure/api/index.ts b/framework/vendure/api/index.ts index 95ec47d66..6f73c680e 100644 --- a/framework/vendure/api/index.ts +++ b/framework/vendure/api/index.ts @@ -11,7 +11,7 @@ import getProduct from './operations/get-product' import getSiteInfo from './operations/get-site-info' import login from './operations/login' import fetchGraphqlApi from './utils/fetch-graphql-api' - +import getAllBlogs from './operations/get-all-blogs' export interface VendureConfig extends CommerceAPIConfig {} @@ -44,6 +44,7 @@ const operations = { getProduct, getAllFacets, getAllCollections, + getAllBlogs } export const provider = { config, operations } diff --git a/framework/vendure/api/operations/get-all-blogs.ts b/framework/vendure/api/operations/get-all-blogs.ts new file mode 100644 index 000000000..3612a751d --- /dev/null +++ b/framework/vendure/api/operations/get-all-blogs.ts @@ -0,0 +1,52 @@ +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 = { take?: number,skip?:number } + +export default function getAllBlogsOperation({ + commerce, +}: OperationContext) { + async function getAllBlogs(opts?: { + variables?: BlogVariables + config?: Partial + preview?: boolean + }): Promise<{ blogs: GetAllBlogsQuery,totalItems:number }> + + async function getAllBlogs({ + query = getAllBlogsQuery, + variables: { ...vars } = {}, + config: cfg, + }: { + query?: string + variables?: BlogVariables + config?: Partial + preview?: boolean + } = {}): Promise<{ blogs: GetAllBlogsQuery | any[] ,totalItems?:number }> { + const config = commerce.getConfig(cfg) + const variables = { + options: { + take: vars.take, + skip: vars.skip, + }, + } + const { data } = await config.fetch(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, + isHidden: val.isHidden + })), + totalItems: data?.blogs?.totalItems || null + } + } + + return getAllBlogs +} diff --git a/framework/vendure/schema.d.ts b/framework/vendure/schema.d.ts index 9ab352944..362436170 100644 --- a/framework/vendure/schema.d.ts +++ b/framework/vendure/schema.d.ts @@ -2312,6 +2312,46 @@ export type Product = Node & { customFields?: Maybe } +export type BlogList = Node &{ + id: ID! + createdAt: DateTime! + updatedAt: DateTime! + featuredAsset?: Maybe + isHidden:Boolean + translations: Array + authorName: Scalars['String'] + authorAvatarAsset:Array + relevantProducts: Product +} + +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 QueryBlogs = { + options: BlogListOptions +} + +export type BlogListOptions = { + skip?: Maybe + take?: Maybe +} + export type ProductTranslation = { __typename?: 'ProductTranslation' id: Scalars['ID'] @@ -3364,3 +3404,4 @@ export type SearchQuery = { __typename?: 'Query' } & { 'totalItems' > & { items: Array<{ __typename?: 'SearchResult' } & SearchResultFragment> } } + diff --git a/framework/vendure/utils/queries/get-all-blog-query.ts b/framework/vendure/utils/queries/get-all-blog-query.ts new file mode 100644 index 000000000..d7a4a294a --- /dev/null +++ b/framework/vendure/utils/queries/get-all-blog-query.ts @@ -0,0 +1,20 @@ +export const getAllBlogsQuery = /* GraphQL */ ` +query GetBlogs ($options: BlogListOptions){ + blogs(options: $options){ + totalItems + items { + id + isHidden + featuredAsset { + preview + } + translations { + title + slug + description + content + } + } + } +} +` diff --git a/pages/blogs.tsx b/pages/blogs.tsx index 84e56b55d..f46a2214b 100644 --- a/pages/blogs.tsx +++ b/pages/blogs.tsx @@ -1,14 +1,72 @@ +import commerce from '@lib/api/commerce'; +import { GetStaticPropsContext } from 'next'; 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 { + blogsResult: { blogs: BlogCardProps[] }, + totalItems: number +} +export default function BlogsPage({blogsResult,totalItems}:Props) { return( <> - - + + ) } -BlogsPage.Layout = Layout \ No newline at end of file + + +export async function getStaticProps({ + preview, + locale, + locales, +}: GetStaticPropsContext) { + const config = { locale, locales } + let promisesWithKey = [] as PromiseWithKey[] + let props = {} as any; + + + // Blogs + const blogsPromise = commerce.getAllBlogs({ + variables: { + 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 + }) + + return { + props, + revalidate: 60 + } + } catch (err) { + + } +} + + +BlogsPage.Layout = Layout diff --git a/pages/index.tsx b/pages/index.tsx index 010094de4..f4619a195 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -10,12 +10,12 @@ import { CODE_FACET_DISCOUNT, CODE_FACET_FEATURED } from 'src/utils/constanst.ut import { getAllFacetValueIdsByParentCode, getAllFacetValuesForFeatuedProducts, getAllPromies, getFreshFacetId } from 'src/utils/funtion.utils'; import { PromiseWithKey } from 'src/utils/types.utils'; + interface Props { featuredAndDiscountFacetsValue: FacetValue[], freshProducts: ProductCard[], featuredProducts: ProductCard[], collections: Collection[] - } export default function Home({ featuredAndDiscountFacetsValue, freshProducts, featuredProducts, @@ -99,7 +99,6 @@ export async function getStaticProps({ }) promisesWithKey.push({ key: 'collections', promise: collectionsPromise, keyResult: 'collections' }) - try { const promises = getAllPromies(promisesWithKey) const rs = await Promise.all(promises) diff --git a/src/components/common/CardBlog/CardBlog.tsx b/src/components/common/CardBlog/CardBlog.tsx index a44f45494..c5c87ba12 100644 --- a/src/components/common/CardBlog/CardBlog.tsx +++ b/src/components/common/CardBlog/CardBlog.tsx @@ -7,16 +7,16 @@ import s from './CardBlog.module.scss' export interface BlogCardProps extends BlogProps { // todo: edit when intergrate API - + isHidden:Boolean } const CardBlog = ({ imageSrc, title, description, slug }: BlogCardProps) => { return (

- +
- +
diff --git a/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.module.scss b/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.module.scss index f8dfec116..5503dccf7 100644 --- a/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.module.scss +++ b/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.module.scss @@ -1,7 +1,7 @@ .listProductCardSkeleton { display: flex; overflow: hidden; - + &.wrap { flex-wrap: wrap; overflow: unset; diff --git a/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.tsx b/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.tsx index 218f9fb11..9ab255477 100644 --- a/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.tsx +++ b/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.tsx @@ -6,7 +6,7 @@ type Props = { count?: number isWrap?: boolean } -const ListProductCardSkeleton = ({ count = 5, isWrap }: Props) => { +const ListProductCardSkeleton = ({ count = 3, isWrap }: Props) => { return (
diff --git a/src/components/hooks/blog/index.ts b/src/components/hooks/blog/index.ts new file mode 100644 index 000000000..e8359671a --- /dev/null +++ b/src/components/hooks/blog/index.ts @@ -0,0 +1 @@ +export {default as useGetBlogList }from "./useGetBlogList" \ No newline at end of file diff --git a/src/components/hooks/blog/useGetBlogList.tsx b/src/components/hooks/blog/useGetBlogList.tsx new file mode 100644 index 000000000..ebbe6162b --- /dev/null +++ b/src/components/hooks/blog/useGetBlogList.tsx @@ -0,0 +1,24 @@ +import { GetAllBlogsQuery, QueryBlogs,BlogList } from '@framework/schema' +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, options], gglFetcher) + console.log(isValidating); + 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, + isHidden: val.isHidden + })), + totalItems: data?.blogs?.totalItems || null, + loading: isValidating, + ...rest + } +} + +export default useGetBlogList diff --git a/src/components/modules/blogs/BlogsList/BlogsList.tsx b/src/components/modules/blogs/BlogsList/BlogsList.tsx index 9b7ddc1e0..4586f5acd 100644 --- a/src/components/modules/blogs/BlogsList/BlogsList.tsx +++ b/src/components/modules/blogs/BlogsList/BlogsList.tsx @@ -1,151 +1,89 @@ -import React, { useState } from 'react' +import { useRouter } from 'next/router' +import React, { useEffect, useState } from 'react' import CardBlog, { BlogCardProps } from 'src/components/common/CardBlog/CardBlog' 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 { 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 { ListProductCardSkeleton } from 'src/components/common' interface BlogsListProps { - data?: BlogCardProps[], + blogList?: BlogCardProps[], + total?: number } -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 onPageChange = (page:number) => { - setCurrentPage(page) +const DEFAULT_BLOGS_ARGS = { + options:{ + skip: 1, take: DEFAULT_BLOG_PAGE_SIZE } - +} + +const BlogsList = ({ blogList,total }:BlogsListProps) => { + const router = useRouter(); + const [initialQueryFlag, setInitialQueryFlag] = useState(true) + + const [optionQueryBlog, setOptionQueryBlog] = useState(DEFAULT_BLOGS_ARGS) + const { blogs, totalItems, loading } = useGetBlogList(optionQueryBlog); + + // console.log(blogs); + + + const onPageChange = (page:number) => { + router.push({ + pathname: ROUTE.BLOGS, + query: { + ...router.query, + [QUERY_KEY.PAGE]: page + } + }, + undefined, { shallow: true } + ) + } + + // skip + useEffect(() => { + 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); + console.log(query) + },[router.query]) + + + let data; + if(initialQueryFlag == true){ + data = blogList; + }else{ + data = blogs + } + return (
+ {(!initialQueryFlag && loading && !blogs) && }
+ { - data.slice(currentPage*DEFAULT_BLOG_PAGE_SIZE,(currentPage+1)*DEFAULT_BLOG_PAGE_SIZE).map((product,index)=> { - return( + data?.map((product,index)=> { + return(
- + {!product.isHidden && }
) }) }
- +
) } -export default BlogsList \ No newline at end of file +export default BlogsList + + diff --git a/src/utils/types.utils.ts b/src/utils/types.utils.ts index 59243b80f..a07f23aab 100644 --- a/src/utils/types.utils.ts +++ b/src/utils/types.utils.ts @@ -29,7 +29,7 @@ export interface BlogProps { title: string slug: string description: string - imageSrc: string + imageSrc: string | null, } export interface CheckOutForm { From dd31beb260425cc9c68ad02771d8694df2ab10e0 Mon Sep 17 00:00:00 2001 From: Quangnhankie Date: Mon, 18 Oct 2021 22:54:55 +0700 Subject: [PATCH 2/4] fix code --- framework/commerce/api/operations.ts | 23 +++++++- framework/commerce/types/blogs.ts | 12 +++- framework/vendure/api/index.ts | 4 +- .../vendure/api/operations/get-all-blogs.ts | 15 ++++- .../api/operations/get-featured-blog.ts | 56 +++++++++++++++++++ framework/vendure/schema.d.ts | 12 +++- .../utils/queries/get-all-blog-query.ts | 38 +++++++------ .../utils/queries/get-featued-query.ts | 25 +++++++++ pages/blogs.tsx | 44 +++++++++++---- pages/index.tsx | 2 +- src/components/common/CardBlog/CardBlog.tsx | 7 ++- .../ListProductCardSkeleton.module.scss | 7 +++ .../ListProductCardSkeleton.tsx | 9 +-- .../ProductCardSkeleton.tsx | 8 ++- src/components/hooks/blog/useGetBlogList.tsx | 8 ++- .../modules/blogs/BlogsList/BlogsList.tsx | 10 ++-- src/utils/constanst.utils.ts | 2 + src/utils/funtion.utils.ts | 8 ++- 18 files changed, 236 insertions(+), 54 deletions(-) create mode 100644 framework/vendure/api/operations/get-featured-blog.ts create mode 100644 framework/vendure/utils/queries/get-featued-query.ts diff --git a/framework/commerce/api/operations.ts b/framework/commerce/api/operations.ts index 1065653bd..898c322e3 100644 --- a/framework/commerce/api/operations.ts +++ b/framework/commerce/api/operations.ts @@ -10,7 +10,8 @@ import type { GetProductOperation, } from '../types/product' import type { - GetAllBlogsOperation + GetAllBlogsOperation, + GetFeaturedOperation } from '../types/blogs' import type { APIProvider, CommerceAPI } from '.' import { GetAllCollectionsOperation } from '@commerce/types/collection'; @@ -30,7 +31,8 @@ export const OPERATIONS = [ 'getProduct', 'getAllFacets', 'getAllCollections', - 'getAllBlogs' + 'getAllBlogs', + 'getFeaturedBlog' ] as const export const defaultOperations = OPERATIONS.reduce((ops, k) => { @@ -149,6 +151,22 @@ export type Operations

= { getAllBlogs: { + (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'] config?: P['config'] @@ -165,6 +183,7 @@ export type Operations

= { } + getProduct: { (opts: { variables: T['variables'] diff --git a/framework/commerce/types/blogs.ts b/framework/commerce/types/blogs.ts index f138b964e..9b6ce14c1 100644 --- a/framework/commerce/types/blogs.ts +++ b/framework/commerce/types/blogs.ts @@ -19,8 +19,14 @@ export type GetAllBlogsOperation = { variables: { take?: number skip?: number - sort?: SearchResultSortParameter } - } +} - \ No newline at end of file + +export type GetFeaturedOperation = { + data: { items: T['items'][] } + variables: { + take?: number + skip?: number + } +} \ No newline at end of file diff --git a/framework/vendure/api/index.ts b/framework/vendure/api/index.ts index 6f73c680e..edf67d14f 100644 --- a/framework/vendure/api/index.ts +++ b/framework/vendure/api/index.ts @@ -12,6 +12,7 @@ import getSiteInfo from './operations/get-site-info' 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 {} @@ -44,7 +45,8 @@ const operations = { getProduct, getAllFacets, getAllCollections, - getAllBlogs + getAllBlogs, + getFeaturedBlog } export const provider = { config, operations } diff --git a/framework/vendure/api/operations/get-all-blogs.ts b/framework/vendure/api/operations/get-all-blogs.ts index 3612a751d..3a1d01399 100644 --- a/framework/vendure/api/operations/get-all-blogs.ts +++ b/framework/vendure/api/operations/get-all-blogs.ts @@ -3,7 +3,11 @@ import { Provider, VendureConfig } from '..' import { GetAllBlogsQuery,BlogList } from '../../schema' import { getAllBlogsQuery } from '../../utils/queries/get-all-blog-query' -export type BlogVariables = { take?: number,skip?:number } +export type BlogVariables = { + excludeBlogIds?: string[], + take?: number, + skip?:number +} export default function getAllBlogsOperation({ commerce, @@ -24,8 +28,10 @@ export default function getAllBlogsOperation({ config?: Partial preview?: boolean } = {}): Promise<{ blogs: GetAllBlogsQuery | any[] ,totalItems?:number }> { + console.log(vars.excludeBlogIds) const config = commerce.getConfig(cfg) const variables = { + excludeBlogIds: vars.excludeBlogIds, options: { take: vars.take, skip: vars.skip, @@ -34,7 +40,6 @@ export default function getAllBlogsOperation({ const { data } = await config.fetch(query, { variables, }) - return { blogs: data?.blogs?.items?.map((val:BlogList)=>({ id: val.id, @@ -42,7 +47,11 @@ export default function getAllBlogsOperation({ imageSrc: val.featuredAsset?.preview ?? null, slug: val.translations[0]?.slug, description: val.translations[0]?.description, - isHidden: val.isHidden + isPublish: val.isPublish, + isFeatured: val.isFeatured, + authorName: val.authorName, + authorAvatarAsset : val.authorAvatarAsset?.preview, + createdAt: val.createdAt })), totalItems: data?.blogs?.totalItems || null } diff --git a/framework/vendure/api/operations/get-featured-blog.ts b/framework/vendure/api/operations/get-featured-blog.ts new file mode 100644 index 000000000..6dc05c1be --- /dev/null +++ b/framework/vendure/api/operations/get-featured-blog.ts @@ -0,0 +1,56 @@ +import { OperationContext } from '@commerce/api/operations' +import { Provider, VendureConfig } from '..' +import { GetFeaturedBlogQuery,BlogList } from '../../schema' +import { getFeatuedBlogQuery } from '../../utils/queries/get-featued-query' + +export type BlogVariables = { + take?: number, + skip?:number +} + +export default function getFeaturedBlogOperation({ + commerce, +}: OperationContext) { + async function getFeaturedBlog(opts?: { + variables?: BlogVariables + config?: Partial + preview?: boolean + }): Promise<{ featuredBlogs: GetFeaturedBlogQuery,totalItems:number }> + + async function getFeaturedBlog({ + query = getFeatuedBlogQuery, + variables: { ...vars } = {}, + config: cfg, + }: { + query?: string + variables?: BlogVariables + config?: Partial + preview?: boolean + } = {}): Promise<{ featuredBlogs: GetFeaturedBlogQuery | any[] ,totalItems?:number }> { + const config = commerce.getConfig(cfg) + const variables = { + options: { + take: vars.take, + }, + } + const { data } = await config.fetch(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 +} diff --git a/framework/vendure/schema.d.ts b/framework/vendure/schema.d.ts index 362436170..5b4b58757 100644 --- a/framework/vendure/schema.d.ts +++ b/framework/vendure/schema.d.ts @@ -2317,11 +2317,12 @@ export type BlogList = Node &{ createdAt: DateTime! updatedAt: DateTime! featuredAsset?: Maybe - isHidden:Boolean + isPublish:Boolean translations: Array authorName: Scalars['String'] - authorAvatarAsset:Array + authorAvatarAsset:Asset relevantProducts: Product + isFeatured: Boolean } export type BlogTranslation = { @@ -2342,8 +2343,15 @@ export type GetAllBlogsQuery = PaginatedList & { 'totalItems' } } +export type GetFeaturedBlogQuery = PaginatedList & { + featuredBlogs: { __typename?: 'BlogList' } & { + items: Array<{ __typename?: 'Blog' } & BlogList!>, + 'totalItems' + } +} export type QueryBlogs = { + excludeBlogIds:Array, options: BlogListOptions } diff --git a/framework/vendure/utils/queries/get-all-blog-query.ts b/framework/vendure/utils/queries/get-all-blog-query.ts index d7a4a294a..57c17ace7 100644 --- a/framework/vendure/utils/queries/get-all-blog-query.ts +++ b/framework/vendure/utils/queries/get-all-blog-query.ts @@ -1,20 +1,26 @@ export const getAllBlogsQuery = /* GraphQL */ ` -query GetBlogs ($options: BlogListOptions){ - blogs(options: $options){ - totalItems - items { - id - isHidden - featuredAsset { - preview - } - translations { - title - slug - description - content - } - } +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 + } } + } } ` diff --git a/framework/vendure/utils/queries/get-featued-query.ts b/framework/vendure/utils/queries/get-featued-query.ts new file mode 100644 index 000000000..63ed82736 --- /dev/null +++ b/framework/vendure/utils/queries/get-featued-query.ts @@ -0,0 +1,25 @@ +export const getFeatuedBlogQuery = /* GraphQL */ ` + query GetFeaturedBlog($options: BlogListOptions) { + featuredBlogs( options: $options){ + items { + id + isPublish + isFeatured + authorName + createdAt + authorAvatarAsset{ + preview + } + featuredAsset { + preview + } + translations { + title + slug + description + content + } + } + } + } +` \ No newline at end of file diff --git a/pages/blogs.tsx b/pages/blogs.tsx index f46a2214b..7e8a2b64a 100644 --- a/pages/blogs.tsx +++ b/pages/blogs.tsx @@ -3,26 +3,33 @@ import { GetStaticPropsContext } from 'next'; import { Layout } from 'src/components/common'; 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 { DEFAULT_BLOG_PAGE_SIZE,DEFAULT_FEATURED_BLOG_PAGE_SIZE } from "src/utils/constanst.utils"; import { getAllPromies } from 'src/utils/funtion.utils'; import { PromiseWithKey } from 'src/utils/types.utils'; - +import { getIdFeaturedBlog } from 'src/utils/funtion.utils'; interface Props { - blogsResult: { blogs: BlogCardProps[] }, + blogsResult: { blogs?: BlogCardProps[],featuredBlogs?: BlogCardProps[] }, totalItems: number } export default function BlogsPage({blogsResult,totalItems}:Props) { + + // let date = new Date(blogsResult?.featuredBlogs[0]?.createdAt ?? '' ); + // let fullDate = date.toLocaleString('en-us', { month: 'long' }) + " " + date.getDate()+","+date.getFullYear(); + return( <> - + {/* */} ) @@ -39,16 +46,32 @@ export async function getStaticProps({ let props = {} as any; + const {featuredBlogs} = await commerce.getFeaturedBlog({ + variables: { + take: DEFAULT_BLOG_PAGE_SIZE + }, + config, + preview, + }) + + + // console.log(featuredBlogs[0].id); + // promisesWithKey.push({ key: 'blogsResult', promise: FeaturedBlogPromise }) + + // Blogs + const idBlog = featuredBlogs[0].id; const blogsPromise = commerce.getAllBlogs({ variables: { - take: DEFAULT_BLOG_PAGE_SIZE + excludeBlogIds: [idBlog], + take: DEFAULT_BLOG_PAGE_SIZE }, config, preview, }) promisesWithKey.push({ key: 'blogsResult', promise: blogsPromise }) + try { const promises = getAllPromies(promisesWithKey) @@ -58,7 +81,8 @@ export async function getStaticProps({ props[item.key] = item.keyResult ? rs[index][item.keyResult] : rs[index] return null }) - + props['blogsResult']['featuredBlog'] = featuredBlogs; + return { props, revalidate: 60 diff --git a/pages/index.tsx b/pages/index.tsx index f4619a195..d1c5c39f8 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -56,7 +56,7 @@ export async function getStaticProps({ preview, }) props.featuredAndDiscountFacetsValue = getAllFacetValuesForFeatuedProducts(facets) - + // fresh products const freshProductvariables: ProductVariables = {} const freshFacetId = getFreshFacetId(facets) diff --git a/src/components/common/CardBlog/CardBlog.tsx b/src/components/common/CardBlog/CardBlog.tsx index c5c87ba12..27a6c32b5 100644 --- a/src/components/common/CardBlog/CardBlog.tsx +++ b/src/components/common/CardBlog/CardBlog.tsx @@ -6,8 +6,11 @@ import { ImgWithLink } from '..' import s from './CardBlog.module.scss' export interface BlogCardProps extends BlogProps { - // todo: edit when intergrate API - isHidden:Boolean + isPublish?:Boolean, + isFeatured?:Boolean, + authorAvatarAsset?:string, + authorName?:string, + createdAt?:string } const CardBlog = ({ imageSrc, title, description, slug }: BlogCardProps) => { diff --git a/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.module.scss b/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.module.scss index 5503dccf7..9ce1dfb77 100644 --- a/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.module.scss +++ b/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.module.scss @@ -9,4 +9,11 @@ margin-bottom: 1.6rem; } } + &.isBlog{ + width: 90%; + justify-content: space-between; + div{ + min-width: 32rem; + } + } } diff --git a/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.tsx b/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.tsx index 9ab255477..9063f1968 100644 --- a/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.tsx +++ b/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.tsx @@ -4,14 +4,15 @@ import s from './ListProductCardSkeleton.module.scss' type Props = { count?: number - isWrap?: boolean + isWrap?: boolean, + isBlog?:boolean } -const ListProductCardSkeleton = ({ count = 3, isWrap }: Props) => { +const ListProductCardSkeleton = ({ count = 3, isWrap,isBlog=false }: Props) => { return ( -

+
{ - Array.from(Array(count).keys()).map(item => ) + Array.from(Array(count).keys()).map(item => ) }
diff --git a/src/components/common/ProductCardSkeleton/ProductCardSkeleton.tsx b/src/components/common/ProductCardSkeleton/ProductCardSkeleton.tsx index 52c4b0fea..373099314 100644 --- a/src/components/common/ProductCardSkeleton/ProductCardSkeleton.tsx +++ b/src/components/common/ProductCardSkeleton/ProductCardSkeleton.tsx @@ -1,14 +1,16 @@ import SkeletonImage from "../SkeletonCommon/SkeletonImage/SkeletonImage" import SkeletonParagraph from "../SkeletonCommon/SkeletonParagraph/SkeletonParagraph" import s from './ProductCardSkeleton.module.scss' - -const ProductCardSkeleton = ({ }) => { +type Props = { + isBlog?:boolean +} +const ProductCardSkeleton = ({isBlog=false }) => { return (
- +
) diff --git a/src/components/hooks/blog/useGetBlogList.tsx b/src/components/hooks/blog/useGetBlogList.tsx index ebbe6162b..d844ae911 100644 --- a/src/components/hooks/blog/useGetBlogList.tsx +++ b/src/components/hooks/blog/useGetBlogList.tsx @@ -5,7 +5,7 @@ import useSWR from 'swr' const useGetBlogList = (options?: QueryBlogs) => { const { data, isValidating, ...rest } = useSWR([getAllBlogsQuery, options], gglFetcher) - console.log(isValidating); + return { blogs: data?.blogs?.items?.map((val:BlogList)=>({ id: val.id, @@ -13,7 +13,11 @@ const useGetBlogList = (options?: QueryBlogs) => { imageSrc: val.featuredAsset?.preview ?? null, slug: val.translations[0]?.slug, description: val.translations[0]?.description, - isHidden: val.isHidden + isPublish: val.isPublish, + isFeatured:val.isFeatured, + authorName: val.authorName, + authorAvatarAsset : val.authorAvatarAsset?.preview, + createdAt: val.createdAt })), totalItems: data?.blogs?.totalItems || null, loading: isValidating, diff --git a/src/components/modules/blogs/BlogsList/BlogsList.tsx b/src/components/modules/blogs/BlogsList/BlogsList.tsx index 4586f5acd..28c2ee729 100644 --- a/src/components/modules/blogs/BlogsList/BlogsList.tsx +++ b/src/components/modules/blogs/BlogsList/BlogsList.tsx @@ -15,19 +15,20 @@ interface BlogsListProps { } const DEFAULT_BLOGS_ARGS = { + excludeBlogIds: ["28"], options:{ skip: 1, take: DEFAULT_BLOG_PAGE_SIZE } } const BlogsList = ({ blogList,total }:BlogsListProps) => { + const router = useRouter(); const [initialQueryFlag, setInitialQueryFlag] = useState(true) const [optionQueryBlog, setOptionQueryBlog] = useState(DEFAULT_BLOGS_ARGS) const { blogs, totalItems, loading } = useGetBlogList(optionQueryBlog); - // console.log(blogs); const onPageChange = (page:number) => { @@ -49,7 +50,7 @@ const BlogsList = ({ blogList,total }:BlogsListProps) => { query.options.skip = page * DEFAULT_BLOG_PAGE_SIZE; setOptionQueryBlog(query); setInitialQueryFlag(false); - console.log(query) + },[router.query]) @@ -59,18 +60,19 @@ const BlogsList = ({ blogList,total }:BlogsListProps) => { }else{ data = blogs } + console.log(blogList); return (
- {(!initialQueryFlag && loading && !blogs) && } + {(!initialQueryFlag && loading && !blogs) && }
{ data?.map((product,index)=> { return(
- {!product.isHidden && } + {product.isPublish && }
) }) diff --git a/src/utils/constanst.utils.ts b/src/utils/constanst.utils.ts index 7d0cf9ba5..9d1fb6b66 100644 --- a/src/utils/constanst.utils.ts +++ b/src/utils/constanst.utils.ts @@ -171,6 +171,8 @@ export const FEATURED = [ 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 STATE_OPTIONS = [ diff --git a/src/utils/funtion.utils.ts b/src/utils/funtion.utils.ts index 408d9d0fd..2b473c9e2 100644 --- a/src/utils/funtion.utils.ts +++ b/src/utils/funtion.utils.ts @@ -1,3 +1,4 @@ +import { BlogList } from '@framework/schema'; import { Facet } from "@commerce/types/facet"; import { Collection, FacetValue, SearchResultSortParameter } from './../../framework/vendure/schema.d'; import { CODE_FACET_DISCOUNT, CODE_FACET_FEATURED, CODE_FACET_FEATURED_VARIANT, PRODUCT_SORT_OPTION_VALUE } from "./constanst.utils"; @@ -127,4 +128,9 @@ export const getCategoryNameFromCollectionId = (colelctions: Collection[], colle export function getAllPromies(promies: PromiseWithKey[]) { return promies.map(item => item.promise) -} \ No newline at end of file +} + +export function getIdFeaturedBlog(blog: BlogList) { + return blog?.id +} + From 29b56ec6a39831bc727932aae2663055a0284fb6 Mon Sep 17 00:00:00 2001 From: Quangnhankie Date: Thu, 21 Oct 2021 12:21:18 +0700 Subject: [PATCH 3/4] bug: fix type --- framework/commerce/api/operations.ts | 8 ++++---- framework/commerce/types/blogs.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/framework/commerce/api/operations.ts b/framework/commerce/api/operations.ts index 898c322e3..9f2682d7e 100644 --- a/framework/commerce/api/operations.ts +++ b/framework/commerce/api/operations.ts @@ -151,13 +151,13 @@ export type Operations

= { getAllBlogs: { - (opts: { + (opts: { variables?: T['variables'] config?: P['config'] preview?: boolean }): Promise - ( + ( opts: { variables?: T['variables'] config?: P['config'] @@ -167,13 +167,13 @@ export type Operations

= { } getFeaturedBlog: { - (opts: { + (opts: { variables?: T['variables'] config?: P['config'] preview?: boolean }): Promise - ( + ( opts: { variables?: T['variables'] config?: P['config'] diff --git a/framework/commerce/types/blogs.ts b/framework/commerce/types/blogs.ts index 9b6ce14c1..14feeb561 100644 --- a/framework/commerce/types/blogs.ts +++ b/framework/commerce/types/blogs.ts @@ -4,7 +4,7 @@ import { Asset, BlogTranslation, Maybe, Product } from './../../vendure/schema.d export type BlogList = Node &{ id: string featuredAsset?: Maybe - isHidden:Boolean + isPublic:Boolean translations: Array authorName: string authorAvatarAsset:Array From e4ad5bef4bdcf322cca4d2b2a50dfc7d42b6328a Mon Sep 17 00:00:00 2001 From: Quangnhankie Date: Thu, 21 Oct 2021 16:10:58 +0700 Subject: [PATCH 4/4] :bug: bug: fix code follow by review Ly Tran :%s --- framework/commerce/api/operations.ts | 6 ++-- framework/commerce/types/blogs.ts | 7 ++-- .../api/operations/get-featured-blog.ts | 4 +-- framework/vendure/utils/normalize.ts | 17 +++++++++- .../utils/queries/get-featued-query.ts | 4 +-- pages/blogs.tsx | 32 ++++++++++--------- src/components/common/CardBlog/CardBlog.tsx | 2 +- .../ListBlogCardSkeleton.module.scss | 18 +++++++++++ .../ListBlogCardSkeleton.tsx | 20 ++++++++++++ .../ListProductCardSkeleton.tsx | 8 ++--- src/components/common/index.ts | 1 + src/components/hooks/blog/useGetBlogList.tsx | 14 ++------ .../modules/blogs/BlogsList/BlogsList.tsx | 11 ++++--- 13 files changed, 94 insertions(+), 50 deletions(-) create mode 100644 src/components/common/ListBlogCardSkeleton/ListBlogCardSkeleton.module.scss create mode 100644 src/components/common/ListBlogCardSkeleton/ListBlogCardSkeleton.tsx diff --git a/framework/commerce/api/operations.ts b/framework/commerce/api/operations.ts index 9f2682d7e..efbbce35d 100644 --- a/framework/commerce/api/operations.ts +++ b/framework/commerce/api/operations.ts @@ -11,7 +11,7 @@ import type { } from '../types/product' import type { GetAllBlogsOperation, - GetFeaturedOperation + GetFeaturedBlogsOperation } from '../types/blogs' import type { APIProvider, CommerceAPI } from '.' import { GetAllCollectionsOperation } from '@commerce/types/collection'; @@ -167,13 +167,13 @@ export type Operations

= { } getFeaturedBlog: { - (opts: { + (opts: { variables?: T['variables'] config?: P['config'] preview?: boolean }): Promise - ( + ( opts: { variables?: T['variables'] config?: P['config'] diff --git a/framework/commerce/types/blogs.ts b/framework/commerce/types/blogs.ts index 14feeb561..fcdca972d 100644 --- a/framework/commerce/types/blogs.ts +++ b/framework/commerce/types/blogs.ts @@ -1,13 +1,12 @@ -import { SearchResultSortParameter } from "@framework/schema"; import { Asset, BlogTranslation, Maybe, Product } from './../../vendure/schema.d'; export type BlogList = Node &{ id: string featuredAsset?: Maybe isPublic:Boolean - translations: Array + translations: BlogTranslation[] authorName: string - authorAvatarAsset:Array + authorAvatarAsset:Asset[] relevantProducts: Product } export type BlogsType = { @@ -23,7 +22,7 @@ export type GetAllBlogsOperation = { } -export type GetFeaturedOperation = { +export type GetFeaturedBlogsOperation = { data: { items: T['items'][] } variables: { take?: number diff --git a/framework/vendure/api/operations/get-featured-blog.ts b/framework/vendure/api/operations/get-featured-blog.ts index 8f26e4288..727db46ed 100644 --- a/framework/vendure/api/operations/get-featured-blog.ts +++ b/framework/vendure/api/operations/get-featured-blog.ts @@ -1,7 +1,7 @@ import { OperationContext } from '@commerce/api/operations' import { Provider, VendureConfig } from '..' import { GetFeaturedBlogQuery,BlogList } from '../../schema' -import { getFeatuedBlogQuery } from '../../utils/queries/get-featued-query' +import { getFeatuedBlogsQuery } from '../../utils/queries/get-featued-query' export type BlogVariables = { take?: number, @@ -18,7 +18,7 @@ export default function getFeaturedBlogOperation({ }): Promise<{ featuredBlogs: GetFeaturedBlogQuery[],totalItems:number }> async function getFeaturedBlog({ - query = getFeatuedBlogQuery, + query = getFeatuedBlogsQuery, variables: { ...vars } = {}, config: cfg, }: { diff --git a/framework/vendure/utils/normalize.ts b/framework/vendure/utils/normalize.ts index 871352070..c095ec030 100644 --- a/framework/vendure/utils/normalize.ts +++ b/framework/vendure/utils/normalize.ts @@ -1,6 +1,6 @@ import { Cart } from '@commerce/types/cart' 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 { return { @@ -83,4 +83,19 @@ export function normalizeProductCard(product: Product): ProductCard { facetValueIds: product.facetValueIds, 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 + } } \ No newline at end of file diff --git a/framework/vendure/utils/queries/get-featued-query.ts b/framework/vendure/utils/queries/get-featued-query.ts index 63ed82736..ff0a77e5b 100644 --- a/framework/vendure/utils/queries/get-featued-query.ts +++ b/framework/vendure/utils/queries/get-featued-query.ts @@ -1,5 +1,5 @@ -export const getFeatuedBlogQuery = /* GraphQL */ ` - query GetFeaturedBlog($options: BlogListOptions) { +export const getFeatuedBlogsQuery = /* GraphQL */ ` + query GetFeaturedBlogs($options: BlogListOptions) { featuredBlogs( options: $options){ items { id diff --git a/pages/blogs.tsx b/pages/blogs.tsx index 7c3483a94..715d9fe24 100644 --- a/pages/blogs.tsx +++ b/pages/blogs.tsx @@ -8,27 +8,29 @@ import { getAllPromies } from 'src/utils/funtion.utils'; import { PromiseWithKey } from 'src/utils/types.utils'; interface Props { - blogsResult: { blogs?: BlogCardProps[],featuredBlog?: BlogCardProps[] }, + blogs?: BlogCardProps[], + featuredBlog?: BlogCardProps[], totalItems: number } -export default function BlogsPage({blogsResult,totalItems}:Props) { - let date = new Date(blogsResult.featuredBlog?.[0]?.createdAt ?? '' ); +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( <> - + ) } @@ -43,17 +45,16 @@ export async function getStaticProps({ let promisesWithKey = [] as PromiseWithKey[] let props = {} as any; - const {featuredBlogs} = await commerce.getFeaturedBlog({ variables: { - take: DEFAULT_BLOG_PAGE_SIZE + take: 1 }, config, preview, }) // Blogs - const idFeaturedBlog = featuredBlogs[0].id; + const idFeaturedBlog = featuredBlogs?.[0]?.id; const blogsPromise = commerce.getAllBlogs({ variables: { excludeBlogIds: [idFeaturedBlog], @@ -74,8 +75,9 @@ export async function getStaticProps({ return null }) - props['blogsResult']['featuredBlog'] = featuredBlogs; + props.featuredBlog = featuredBlogs; + console.log(props) return { props, revalidate: 60 diff --git a/src/components/common/CardBlog/CardBlog.tsx b/src/components/common/CardBlog/CardBlog.tsx index 27a6c32b5..babf2e987 100644 --- a/src/components/common/CardBlog/CardBlog.tsx +++ b/src/components/common/CardBlog/CardBlog.tsx @@ -19,7 +19,7 @@ const CardBlog = ({ imageSrc, title, description, slug }: BlogCardProps) => {

diff --git a/src/components/common/ListBlogCardSkeleton/ListBlogCardSkeleton.module.scss b/src/components/common/ListBlogCardSkeleton/ListBlogCardSkeleton.module.scss new file mode 100644 index 000000000..2f6541e7e --- /dev/null +++ b/src/components/common/ListBlogCardSkeleton/ListBlogCardSkeleton.module.scss @@ -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; + } + } + +} diff --git a/src/components/common/ListBlogCardSkeleton/ListBlogCardSkeleton.tsx b/src/components/common/ListBlogCardSkeleton/ListBlogCardSkeleton.tsx new file mode 100644 index 000000000..015a97374 --- /dev/null +++ b/src/components/common/ListBlogCardSkeleton/ListBlogCardSkeleton.tsx @@ -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 ( +
+ { + Array.from(Array(count).keys()).map(item => ) + } +
+ ) +} + +export default ListBlogCardSkeleton diff --git a/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.tsx b/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.tsx index 9063f1968..20447851a 100644 --- a/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.tsx +++ b/src/components/common/ListProductCardSkeleton/ListProductCardSkeleton.tsx @@ -5,15 +5,13 @@ import s from './ListProductCardSkeleton.module.scss' type Props = { count?: number isWrap?: boolean, - isBlog?:boolean } -const ListProductCardSkeleton = ({ count = 3, isWrap,isBlog=false }: Props) => { +const ListProductCardSkeleton = ({ count = 3, isWrap }: Props) => { return ( -
+
{ - Array.from(Array(count).keys()).map(item => ) - + Array.from(Array(count).keys()).map(item => ) }
) diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 2b7724b73..e2c28e186 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -55,4 +55,5 @@ export { default as FormForgot} from './ForgotPassword/FormForgot/FormForgot' export { default as FormResetPassword} from './ForgotPassword/FormResetPassword/FormResetPassword' export { default as ProductCardSkeleton} from './ProductCardSkeleton/ProductCardSkeleton' export { default as ListProductCardSkeleton} from './ListProductCardSkeleton/ListProductCardSkeleton' +export { default as ListBlogCardSkeleton} from './ListBlogCardSkeleton/ListBlogCardSkeleton' diff --git a/src/components/hooks/blog/useGetBlogList.tsx b/src/components/hooks/blog/useGetBlogList.tsx index d844ae911..9db7a3a5a 100644 --- a/src/components/hooks/blog/useGetBlogList.tsx +++ b/src/components/hooks/blog/useGetBlogList.tsx @@ -1,4 +1,5 @@ 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' @@ -7,18 +8,7 @@ const useGetBlogList = (options?: QueryBlogs) => { const { data, isValidating, ...rest } = useSWR([getAllBlogsQuery, options], gglFetcher) 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 - })), + blogs: data?.blogs?.items?.map((blog:BlogList)=>normalizeBlogList(blog)), totalItems: data?.blogs?.totalItems || null, loading: isValidating, ...rest diff --git a/src/components/modules/blogs/BlogsList/BlogsList.tsx b/src/components/modules/blogs/BlogsList/BlogsList.tsx index dd88d073b..d9dbf26ed 100644 --- a/src/components/modules/blogs/BlogsList/BlogsList.tsx +++ b/src/components/modules/blogs/BlogsList/BlogsList.tsx @@ -1,5 +1,5 @@ import { useRouter } from 'next/router' -import React, { useEffect, useState,useRef } from 'react' +import React, { useEffect, useState,useRef, useMemo } from 'react' import CardBlog, { BlogCardProps } from 'src/components/common/CardBlog/CardBlog' import PaginationCommon from 'src/components/common/PaginationCommon/PaginationCommon' import { DEFAULT_BLOG_PAGE_SIZE, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils' @@ -7,7 +7,7 @@ import s from "./BlogsList.module.scss" import { QueryBlogs } from '@framework/schema' import { useGetBlogList } from 'src/components/hooks/blog' import { getPageFromQuery } from 'src/utils/funtion.utils' -import { ListProductCardSkeleton } from 'src/components/common' +import { ListBlogCardSkeleton } from 'src/components/common' interface BlogsListProps { blogList?: BlogCardProps[], @@ -19,12 +19,13 @@ interface BlogsListProps { const BlogsList = ({ blogList,total,idFeatured }:BlogsListProps) => { - const DEFAULT_BLOGS_ARGS = { + const DEFAULT_BLOGS_ARGS = useMemo(()=> ({ excludeBlogIds: [idFeatured], options:{ skip: 1, take: DEFAULT_BLOG_PAGE_SIZE } - } + }),[idFeatured]); + const router = useRouter(); const [initialQueryFlag, setInitialQueryFlag] = useState(true) @@ -69,7 +70,7 @@ const BlogsList = ({ blogList,total,idFeatured }:BlogsListProps) => { return (
- {(!initialQueryFlag && loading && !blogs) && } + {(!initialQueryFlag && loading && !blogs) && }
{