Merge remote-tracking branch 'origin/blog' into develop
This commit is contained in:
commit
c563818e91
6
.env
6
.env
|
@ -1,6 +1,6 @@
|
||||||
NEXT_PUBLIC_SERVER_BASE_URL=https://api.bbuddy.expert/api
|
NEXT_PUBLIC_SERVER_BASE_URL=https://api.bbuddy.expert/api
|
||||||
NEXT_PUBLIC_AGORA_APPID=ed90c9dc42634e5687d4e2e0766b363f
|
NEXT_PUBLIC_AGORA_APPID=ed90c9dc42634e5687d4e2e0766b363f
|
||||||
|
|
||||||
CONTENTFUL_SPACE_ID = voxpxjq7y7vf
|
NEXT_PUBLIC_CONTENTFUL_SPACE_ID = voxpxjq7y7vf
|
||||||
CONTENTFUL_ACCESS_TOKEN = s99GWKfpDKkNwiEJ3pN7US_tmqsGvDlaex-sOJwpzuc
|
NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN = s99GWKfpDKkNwiEJ3pN7US_tmqsGvDlaex-sOJwpzuc
|
||||||
CONTENTFUL_PREVIEW_ACCESS_TOKEN = Z9WOKpLDbKNj7xVOmT_VXYNLH0AZwISFvQsq0PQlHfE
|
NEXT_PUBLIC_CONTENTFUL_PREVIEW_ACCESS_TOKEN = Z9WOKpLDbKNj7xVOmT_VXYNLH0AZwISFvQsq0PQlHfE
|
||||||
|
|
|
@ -6,11 +6,6 @@ import {fetchBlogPost, fetchBlogPosts, Widget} from "../../../../lib/contentful/
|
||||||
import Util from "node:util";
|
import Util from "node:util";
|
||||||
import RichText from "../../../../lib/contentful/RichText";
|
import RichText from "../../../../lib/contentful/RichText";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: 'Bbuddy - Blog item',
|
|
||||||
description: 'Bbuddy desc blog item'
|
|
||||||
};
|
|
||||||
|
|
||||||
interface BlogPostPageParams {
|
interface BlogPostPageParams {
|
||||||
slug: string
|
slug: string
|
||||||
}
|
}
|
||||||
|
@ -19,11 +14,19 @@ interface BlogPostPageProps {
|
||||||
params: BlogPostPageParams
|
params: BlogPostPageParams
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateStaticParams(): Promise<BlogPostPageParams[]> {
|
export async function generateMetadata({ params }: BlogPostPageProps, parent: ResolvingMetadata): Promise<Metadata> {
|
||||||
const blogPosts = await fetchBlogPosts({ preview: false })
|
const blogPost = await fetchBlogPost({ slug: params.slug, preview: draftMode().isEnabled })
|
||||||
|
|
||||||
return blogPosts.map((post) => ({ slug: post.slug }))
|
if (!blogPost) {
|
||||||
|
return notFound()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: blogPost.title
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function renderWidget (widget: Widget) {
|
function renderWidget (widget: Widget) {
|
||||||
switch (widget.type){
|
switch (widget.type){
|
||||||
case 'widgetParagraph':
|
case 'widgetParagraph':
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {unstable_setRequestLocale} from "next-intl/server";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import {fetchBlogPosts} from "../../../../../lib/contentful/blogPosts";
|
import {fetchBlogPosts} from "../../../../../lib/contentful/blogPosts";
|
||||||
import {fetchBlogPostCategories} from "../../../../../lib/contentful/blogPostsCategories";
|
import {fetchBlogPostCategories} from "../../../../../lib/contentful/blogPostsCategories";
|
||||||
|
import {BlogPosts} from "../../../../../components/BlogPosts/BlogPosts";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'Bbuddy - Blog',
|
title: 'Bbuddy - Blog',
|
||||||
|
@ -19,83 +20,10 @@ interface BlogPostPageProps {
|
||||||
params: BlogPostPageParams
|
params: BlogPostPageParams
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function Blog({params}: { params: BlogPostPageParams }) {
|
export default async function Blog({params, searchParams}: { params: BlogPostPageParams, searhParams?: {page: number} }) {
|
||||||
unstable_setRequestLocale(params.locale);
|
unstable_setRequestLocale(params.locale);
|
||||||
const data = await fetchBlogPosts({ preview: draftMode().isEnabled, locale: params.locale, category: params.slug })
|
const page = searchParams.page || undefined
|
||||||
const cats = await fetchBlogPostCategories(false)
|
|
||||||
return (
|
return (
|
||||||
<div className="b-news">
|
<BlogPosts basePath={'/'+params.locale+'/blog/'} locale={params.locale} currentCat={params.slug} page={page}/>
|
||||||
<div className="b-news__header">
|
|
||||||
<div className="b-inner">
|
|
||||||
<h1 className="title-h1">
|
|
||||||
Mentorship, Career <br/>
|
|
||||||
Development & Coaching.
|
|
||||||
</h1>
|
|
||||||
<div className="wrap-text">
|
|
||||||
<p className="">The ins-and-outs of building a career in tech, gaining <br/> experience</p>
|
|
||||||
<p className="">from a mentor, and getting your feet wet with coaching.</p>
|
|
||||||
</div>
|
|
||||||
<div className="b-news__header__img">
|
|
||||||
<img className="" src="/images/news-top.png" alt=""/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="b-news__filter ">
|
|
||||||
<div className="b-inner">
|
|
||||||
<div className="wrap-filter">
|
|
||||||
{
|
|
||||||
cats.map((cat, i)=>(
|
|
||||||
<Link key={'blogCat'+i} href={'/'+params.locale+'/blog/category/'+cat.slug} className={"filter-item"+(cat.slug === params.slug ? ' active' : '')}>{cat.title}</Link>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="b-news__result-list">
|
|
||||||
<div className="b-inner">
|
|
||||||
<div className="news-list">
|
|
||||||
{data.map((item, i) => (
|
|
||||||
<li key={'blogPost'+i} className="list-sidebar__item">
|
|
||||||
<Link href={'/'+params.locale+'/blog/'+item.slug} className="news-item">
|
|
||||||
<div className="news-item__image">
|
|
||||||
<img className="" src={item.listImage?.src} alt={item.listImage?.alt}/>
|
|
||||||
</div>
|
|
||||||
<div className="news-item__inner">
|
|
||||||
<div className="">
|
|
||||||
<div className="news-item__title">
|
|
||||||
{item.title}
|
|
||||||
</div>
|
|
||||||
<div className="news-item__badge">{item.category}</div>
|
|
||||||
<div className="news-item__text">
|
|
||||||
{item.excerpt}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="news-item__info">
|
|
||||||
<div className="news-item__info__author">
|
|
||||||
<img className="" src={item.author.avatar.src} alt=""/>
|
|
||||||
<div className="news-item__info__author__inner">
|
|
||||||
<div className="news-item__info__name">{item.author.name}</div>
|
|
||||||
<div className="news-item__info__date">{item.createdAt}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="news-item__info__counter">
|
|
||||||
<div className="news-item__info__like">
|
|
||||||
<img className="" src="/images/heart-outline.svg" alt=""/>
|
|
||||||
165
|
|
||||||
</div>
|
|
||||||
<div className="news-item__info__share">
|
|
||||||
<img className="" src="/images/share-social.svg" alt=""/>
|
|
||||||
Share
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,91 +5,39 @@ import {fetchBlogPosts} from "../../../lib/contentful/blogPosts";
|
||||||
import {unstable_setRequestLocale} from "next-intl/server";
|
import {unstable_setRequestLocale} from "next-intl/server";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import {fetchBlogPostCategories} from "../../../lib/contentful/blogPostsCategories";
|
import {fetchBlogPostCategories} from "../../../lib/contentful/blogPostsCategories";
|
||||||
|
import {CustomPagination} from "../../../components/view/CustomPagination";
|
||||||
export const metadata: Metadata = {
|
import {DEFAULT_PAGE_SIZE} from "../../../constants/common";
|
||||||
title: 'Bbuddy - Blog',
|
import {BlogPosts} from "../../../components/BlogPosts/BlogPosts";
|
||||||
description: 'Bbuddy desc blog'
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
interface BlogPostPageParams {
|
||||||
|
slug: string
|
||||||
|
}
|
||||||
|
|
||||||
export default async function Blog({ params: { locale } }: { params: { locale: string } }) {
|
interface BlogPostPageProps {
|
||||||
|
params: BlogPostPageParams
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateStaticParams(): Promise<BlogPostPageParams[]> {
|
||||||
|
const blogPosts = await fetchBlogPosts({ preview: false })
|
||||||
|
|
||||||
|
return blogPosts.data.map((post) => ({ slug: post.slug }))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default async function Blog({ params: { locale }, searchParams }: { params: { locale: string }, searhParams?: {page: number} }) {
|
||||||
unstable_setRequestLocale(locale);
|
unstable_setRequestLocale(locale);
|
||||||
const data = await fetchBlogPosts(false, locale)
|
const pageSize = DEFAULT_PAGE_SIZE
|
||||||
const cats = await fetchBlogPostCategories(false)
|
const page = searchParams.page || undefined
|
||||||
|
// BlogPosts('/'+locale+'/blog/', locale, pageSize)
|
||||||
return (
|
return (
|
||||||
<div className="b-news">
|
|
||||||
<div className="b-news__header">
|
<BlogPosts
|
||||||
<div className="b-inner">
|
basePath={'/'+locale+'/blog/'}
|
||||||
<h1 className="title-h1">
|
locale={locale}
|
||||||
Mentorship, Career <br/>
|
pageSize={pageSize}
|
||||||
Development & Coaching.
|
page={page}
|
||||||
</h1>
|
>
|
||||||
<div className="wrap-text">
|
</BlogPosts>
|
||||||
<p className="">The ins-and-outs of building a career in tech, gaining <br/> experience</p>
|
|
||||||
<p className="">from a mentor, and getting your feet wet with coaching.</p>
|
|
||||||
</div>
|
|
||||||
<div className="b-news__header__img">
|
|
||||||
<img className="" src="/images/news-top.png" alt=""/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="b-news__filter ">
|
|
||||||
<div className="b-inner">
|
|
||||||
<div className="wrap-filter">
|
|
||||||
{
|
|
||||||
cats.map((cat, i)=>(
|
|
||||||
<Link href={'category/'+cat.slug} className="filter-item">{cat.title}</Link>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="b-news__result-list">
|
|
||||||
<div className="b-inner">
|
|
||||||
<div className="news-list">
|
|
||||||
{data.map((item, i) => (
|
|
||||||
<li key={'blog'+i} className="list-sidebar__item">
|
|
||||||
<Link href={`${item.slug}`} className="news-item">
|
|
||||||
<div className="news-item__image">
|
|
||||||
<img className="" src={item.listImage?.src} alt={item.listImage?.alt}/>
|
|
||||||
</div>
|
|
||||||
<div className="news-item__inner">
|
|
||||||
<div className="">
|
|
||||||
<div className="news-item__title">
|
|
||||||
{item.title}
|
|
||||||
</div>
|
|
||||||
<div className="news-item__badge">{item.category}</div>
|
|
||||||
<div className="news-item__text">
|
|
||||||
{item.excerpt}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="news-item__info">
|
|
||||||
<div className="news-item__info__author">
|
|
||||||
<img className="" src={item.author.avatar.src} alt=""/>
|
|
||||||
<div className="news-item__info__author__inner">
|
|
||||||
<div className="news-item__info__name">{item.author.name}</div>
|
|
||||||
<div className="news-item__info__date">{item.createdAt}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="news-item__info__counter">
|
|
||||||
<div className="news-item__info__like">
|
|
||||||
<img className="" src="/images/heart-outline.svg" alt=""/>
|
|
||||||
165
|
|
||||||
</div>
|
|
||||||
<div className="news-item__info__share">
|
|
||||||
<img className="" src="/images/share-social.svg" alt=""/>
|
|
||||||
Share
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import {fetchBlogPosts} from "../lib/contentful/blogPosts";
|
||||||
|
|
||||||
|
export default async function sitemap() {
|
||||||
|
const paths = [
|
||||||
|
{
|
||||||
|
url: process.env.NEXT_PUBLIC_HOST,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: "monthly",
|
||||||
|
priority: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
const blogPosts = await fetchBlogPosts({ preview: false })
|
||||||
|
|
||||||
|
blogPosts.data.forEach((item) => {
|
||||||
|
|
||||||
|
paths.push({
|
||||||
|
url: `${process.env.NEXT_PUBLIC_HOST}${item.slug}`,
|
||||||
|
lastModified: item.createdAt.split('T')[0],
|
||||||
|
changeFrequency: 'daily',
|
||||||
|
priority: '1.0'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return paths
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
'use client';
|
||||||
|
import React, {useState} from "react";
|
||||||
|
import {Languages} from "../../types/tags";
|
||||||
|
import {BlogPostCategory} from "../../types/blogPostCategory";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
languages?: Languages;
|
||||||
|
basePath: string;
|
||||||
|
locale: string;
|
||||||
|
cats: BlogPostCategory[],
|
||||||
|
slug: string
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BlogPostCategories = ({ basePath = '/', cats = [], slug = '' }: Props) => {
|
||||||
|
const [currentCat, setCurrentCat] = useState<String>(slug);
|
||||||
|
return (
|
||||||
|
<div className="b-news__filter ">
|
||||||
|
<div className="b-inner">
|
||||||
|
<div className="wrap-filter">
|
||||||
|
{
|
||||||
|
cats.map((cat, i)=>(
|
||||||
|
<Link
|
||||||
|
href={ basePath+'category/'+cat.slug} key={'blogCat'+i}
|
||||||
|
className={"filter-item"+(cat.slug === currentCat ? ' active' : '')}
|
||||||
|
>
|
||||||
|
{cat.title}
|
||||||
|
</Link>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { DEFAULT_PAGE_SIZE } from '../../constants/common';
|
||||||
|
import {getLanguages} from "../../actions/tags";
|
||||||
|
import {fetchBlogPosts} from "../../lib/contentful/blogPosts";
|
||||||
|
import {fetchBlogPostCategories} from "../../lib/contentful/blogPostsCategories";
|
||||||
|
import {BlogPostsList} from "./BlogPostsList";
|
||||||
|
import {BlogPostCategories} from "./BlogPostCategories";
|
||||||
|
|
||||||
|
type PostsProps = {
|
||||||
|
basePath: string;
|
||||||
|
locale: string;
|
||||||
|
pageSize?: number;
|
||||||
|
currentCat: string;
|
||||||
|
page?: number
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BlogPosts = async ({ basePath = '/', locale, pageSize = DEFAULT_PAGE_SIZE, currentCat = '', page = 1 }: PostsProps) => {
|
||||||
|
const languages = await getLanguages(locale);
|
||||||
|
const {data, total} = await fetchBlogPosts({preview: false, category: currentCat, page: page})
|
||||||
|
const cats = await fetchBlogPostCategories(false)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="b-news">
|
||||||
|
<div className="b-news__header">
|
||||||
|
<div className="b-inner">
|
||||||
|
<h1 className="title-h1">
|
||||||
|
Mentorship, Career <br/>
|
||||||
|
Development & Coaching
|
||||||
|
</h1>
|
||||||
|
<div className="wrap-text">
|
||||||
|
<p className="">The ins-and-outs of building a career in tech, gaining <br/> experience</p>
|
||||||
|
<p className="">from a mentor, and getting your feet wet with coaching.</p>
|
||||||
|
</div>
|
||||||
|
<div className="b-news__header__img">
|
||||||
|
<img className="" src="/images/news-top.png" alt=""/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<BlogPostCategories
|
||||||
|
slug={currentCat}
|
||||||
|
cats={cats}
|
||||||
|
basePath={basePath}
|
||||||
|
locale={locale}
|
||||||
|
/>
|
||||||
|
<BlogPostsList
|
||||||
|
data={data}
|
||||||
|
total={total}
|
||||||
|
basePath={basePath}
|
||||||
|
locale={locale}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { DEFAULT_PAGE_SIZE } from '../../constants/common';
|
||||||
|
import {Languages, SearchData} from "../../types/tags";
|
||||||
|
import {BlogPost} from "../../types/blogPost";
|
||||||
|
import Link from "next/link";
|
||||||
|
import {CustomPagination} from "../view/CustomPagination";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
searchData?: SearchData;
|
||||||
|
languages?: Languages;
|
||||||
|
basePath: string;
|
||||||
|
locale: string;
|
||||||
|
data: BlogPost[],
|
||||||
|
total: number
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BlogPostsList = ({ basePath = '/', locale, pageSize = DEFAULT_PAGE_SIZE, data = [], total= 0 }: Props) => {
|
||||||
|
const currentPage = 1
|
||||||
|
const onChangePage = (page: number) => {
|
||||||
|
router.push(page === 1 ? basePath : basePath+'?page='+page);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="b-news__result-list">
|
||||||
|
<div className="b-inner">
|
||||||
|
<div className="news-list">
|
||||||
|
{data.map((item, i) => (
|
||||||
|
<li key={'blog'+i} className="list-sidebar__item">
|
||||||
|
<Link href={`${item.slug}`} className="news-item">
|
||||||
|
<div className="news-item__image">
|
||||||
|
<img className="" src={item.listImage?.src} alt={item.listImage?.alt}/>
|
||||||
|
</div>
|
||||||
|
<div className="news-item__inner">
|
||||||
|
<div className="">
|
||||||
|
<div className="news-item__title">
|
||||||
|
{item.title}
|
||||||
|
</div>
|
||||||
|
<div className="news-item__badge">{item.category}</div>
|
||||||
|
<div className="news-item__text">
|
||||||
|
{item.excerpt}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="news-item__info">
|
||||||
|
<div className="news-item__info__author">
|
||||||
|
<img className="" src={item.author.avatar.src} alt=""/>
|
||||||
|
<div className="news-item__info__author__inner">
|
||||||
|
<div className="news-item__info__name">{item.author.name}</div>
|
||||||
|
<div className="news-item__info__date">{item.createdAt}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="news-item__info__counter">
|
||||||
|
<div className="news-item__info__like">
|
||||||
|
<img className="" src="/images/heart-outline.svg" alt=""/>
|
||||||
|
165
|
||||||
|
</div>
|
||||||
|
<div className="news-item__info__share">
|
||||||
|
<img className="" src="/images/share-social.svg" alt=""/>
|
||||||
|
Share
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{total > pageSize && (
|
||||||
|
<CustomPagination
|
||||||
|
total={total}
|
||||||
|
pageSize={pageSize}
|
||||||
|
onChange={onChangePage}
|
||||||
|
current={currentPage}
|
||||||
|
/>)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
|
@ -8,7 +8,9 @@ import {WidgetMedia, WidgetMediaEntry} from "../../types/blogWidgets/widgetMedia
|
||||||
import {WidgetParagraph} from "../../types/blogWidgets/widgetParagraph";
|
import {WidgetParagraph} from "../../types/blogWidgets/widgetParagraph";
|
||||||
import entry from "next/dist/server/typescript/rules/entry";
|
import entry from "next/dist/server/typescript/rules/entry";
|
||||||
import Util from "node:util";
|
import Util from "node:util";
|
||||||
|
import {DEFAULT_PAGE_SIZE} from "../../constants/common";
|
||||||
|
|
||||||
|
const pageSize = DEFAULT_PAGE_SIZE
|
||||||
type PostEntry = BlogPostEntry<undefined, string>//Entry<BlogPostSkeleton, undefined, string>
|
type PostEntry = BlogPostEntry<undefined, string>//Entry<BlogPostSkeleton, undefined, string>
|
||||||
type widgetEnum = WidgetParagraph | WidgetMedia
|
type widgetEnum = WidgetParagraph | WidgetMedia
|
||||||
export type Widget = {
|
export type Widget = {
|
||||||
|
@ -65,8 +67,12 @@ interface FetchBlogPostsOptions {
|
||||||
preview: boolean
|
preview: boolean
|
||||||
local?: string
|
local?: string
|
||||||
category?: string
|
category?: string
|
||||||
|
page?: number
|
||||||
}
|
}
|
||||||
export async function fetchBlogPosts({ preview, category }: FetchBlogPostsOptions): Promise<BlogPost[]> {
|
export async function fetchBlogPosts({ preview, category, page }: FetchBlogPostsOptions): Promise<{
|
||||||
|
total: number;
|
||||||
|
data: BlogPost[]
|
||||||
|
}> {
|
||||||
const contentful = contentfulClient({ preview })
|
const contentful = contentfulClient({ preview })
|
||||||
const query = {
|
const query = {
|
||||||
content_type: 'blogPost',
|
content_type: 'blogPost',
|
||||||
|
@ -77,9 +83,19 @@ export async function fetchBlogPosts({ preview, category }: FetchBlogPostsOption
|
||||||
query['fields.category.fields.slug'] = category
|
query['fields.category.fields.slug'] = category
|
||||||
query['fields.category.sys.contentType.sys.id']='blogPostCategory'
|
query['fields.category.sys.contentType.sys.id']='blogPostCategory'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(page){
|
||||||
|
query['limit'] = pageSize
|
||||||
|
query['skip'] = pageSize * (page - 1)
|
||||||
|
}
|
||||||
|
|
||||||
const blogPostsResult = await contentful.getEntries<BlogPostSkeleton>(query)
|
const blogPostsResult = await contentful.getEntries<BlogPostSkeleton>(query)
|
||||||
|
|
||||||
return blogPostsResult.items.map((blogPostEntry) => parseContentfulBlogPost(blogPostEntry) as BlogPost)
|
const data = blogPostsResult.items.map((blogPostEntry) => parseContentfulBlogPost(blogPostEntry) as BlogPost)
|
||||||
|
return {
|
||||||
|
total: blogPostsResult.total,
|
||||||
|
data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FetchBlogPostOptions {
|
interface FetchBlogPostOptions {
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import { createClient } from 'contentful'
|
import { createClient } from 'contentful'
|
||||||
|
|
||||||
const { CONTENTFUL_SPACE_ID, CONTENTFUL_ACCESS_TOKEN, CONTENTFUL_PREVIEW_ACCESS_TOKEN } = process.env
|
const { NEXT_PUBLIC_CONTENTFUL_SPACE_ID, NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN, NEXT_PUBLIC_CONTENTFUL_PREVIEW_ACCESS_TOKEN } = process.env
|
||||||
|
|
||||||
// This is the standard Contentful client. It fetches
|
// This is the standard Contentful client. It fetches
|
||||||
// content that has been published.
|
// content that has been published.
|
||||||
const client = createClient({
|
const client = createClient({
|
||||||
space: CONTENTFUL_SPACE_ID!,
|
space: NEXT_PUBLIC_CONTENTFUL_SPACE_ID!,
|
||||||
accessToken: CONTENTFUL_ACCESS_TOKEN!,
|
accessToken: NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN!,
|
||||||
})
|
})
|
||||||
|
|
||||||
// This is a Contentful client that's been configured
|
// This is a Contentful client that's been configured
|
||||||
// to fetch drafts and unpublished content.
|
// to fetch drafts and unpublished content.
|
||||||
const previewClient = createClient({
|
const previewClient = createClient({
|
||||||
space: CONTENTFUL_SPACE_ID!,
|
space: NEXT_PUBLIC_CONTENTFUL_SPACE_ID!,
|
||||||
accessToken: CONTENTFUL_PREVIEW_ACCESS_TOKEN!,
|
accessToken: NEXT_PUBLIC_CONTENTFUL_PREVIEW_ACCESS_TOKEN!,
|
||||||
host: 'preview.contentful.com',
|
host: 'preview.contentful.com',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue