blog contentful
This commit is contained in:
parent
bdbe4f4b04
commit
ed756d0646
3
.env
3
.env
|
@ -1,3 +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
|
||||||
|
CONTENTFUL_ACCESS_TOKEN = s99GWKfpDKkNwiEJ3pN7US_tmqsGvDlaex-sOJwpzuc
|
||||||
|
CONTENTFUL_PREVIEW_ACCESS_TOKEN = Z9WOKpLDbKNj7xVOmT_VXYNLH0AZwISFvQsq0PQlHfE
|
|
@ -12,11 +12,13 @@
|
||||||
"@ant-design/cssinjs": "^1.18.1",
|
"@ant-design/cssinjs": "^1.18.1",
|
||||||
"@ant-design/icons": "^5.2.6",
|
"@ant-design/icons": "^5.2.6",
|
||||||
"@ant-design/nextjs-registry": "^1.0.0",
|
"@ant-design/nextjs-registry": "^1.0.0",
|
||||||
|
"@contentful/rich-text-react-renderer": "^15.22.9",
|
||||||
"agora-rtc-react": "^2.1.0",
|
"agora-rtc-react": "^2.1.0",
|
||||||
"agora-rtc-sdk-ng": "^4.20.2",
|
"agora-rtc-sdk-ng": "^4.20.2",
|
||||||
"antd": "^5.12.1",
|
"antd": "^5.12.1",
|
||||||
"antd-img-crop": "^4.21.0",
|
"antd-img-crop": "^4.21.0",
|
||||||
"axios": "^1.6.5",
|
"axios": "^1.6.5",
|
||||||
|
"contentful": "^10.13.3",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"next": "14.0.3",
|
"next": "14.0.3",
|
||||||
|
|
|
@ -1,150 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import type { Metadata } from 'next';
|
|
||||||
import { notFound } from 'next/navigation';
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
title: 'Bbuddy - Blog item',
|
|
||||||
description: 'Bbuddy desc blog item'
|
|
||||||
};
|
|
||||||
|
|
||||||
export function generateStaticParams() {
|
|
||||||
return [{ blogId: 'news-1' }, { blogId: 'news-2' }];
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function BlogItem({ params }: { params: { blogId: string } }) {
|
|
||||||
if (!params?.blogId) notFound();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="b-news-page">
|
|
||||||
<div className="b-inner">
|
|
||||||
<h1 className="b-news-page__title">6 learnings from Shivpuri to Silicon Valley</h1>
|
|
||||||
<div className="news-item__badge">Leadership & Management</div>
|
|
||||||
<div className="b-news-page__text">
|
|
||||||
{`news id ${params.blogId}`}<br />
|
|
||||||
I’m excited to kick off this series of newsletters where I’ll be sharing my experiences, learnings,
|
|
||||||
and best practices which helped me to grow both in my personal and professional life. My hope is to
|
|
||||||
give back to the community and help anyone connect directly with me who may have got impacted with
|
|
||||||
recent layoffs, dealing with immigration challenges.
|
|
||||||
</div>
|
|
||||||
<div className="b-news-page__image">
|
|
||||||
<img className="" src="/images/news1.png" alt="" />
|
|
||||||
</div>
|
|
||||||
<div className="news-item__info">
|
|
||||||
<div className="news-item__info__author">
|
|
||||||
<img className="" src="/images/author.png" alt="" />
|
|
||||||
<div className="news-item__info__author__inner">
|
|
||||||
<div className="news-item__info__name">Sonali Garg</div>
|
|
||||||
<div className="news-item__info__date">February 6th, 2023</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 className="b-news-page__inner">
|
|
||||||
<h2 className="title-h2">
|
|
||||||
This is not about layoffs, it's about living with whatever life throws at you..
|
|
||||||
</h2>
|
|
||||||
<p className="b-news-page__text">
|
|
||||||
Over the past few months, as the macro-economic events have unfolded, I have heard voices filled
|
|
||||||
with anxiety, helplessness and general lack of confidence to deal with this ambiguity from my
|
|
||||||
mentees, colleagues, friends and family. I was laid off from Meta last November and I firmly
|
|
||||||
believe this is nothing but a bump in the road that might seem like a steep climb in the
|
|
||||||
short-term. I may not have all the answers but this has inspired me to share my story. If you
|
|
||||||
are looking for a sob story, you can stop reading now. Ever wondered what it takes for a girl
|
|
||||||
born into a conservative family in a small sleepy town in India, who lost one of her parents at
|
|
||||||
age 17, earned her living while pursuing engineering, moved to the UK by herself and ended up
|
|
||||||
working in big tech in Silicon valley? My goal with this series of posts is to inspire and share
|
|
||||||
my mental models that helped me throughout my professional and personal life.
|
|
||||||
</p>
|
|
||||||
<p className="b-news-page__text">
|
|
||||||
After completing my engineering, I started my career at a small software company in Bhopal and
|
|
||||||
then worked for TCS(Tata Consultancy Services), one of the largest IT-outsourcing companies in
|
|
||||||
the world for almost 5 years. Over the past 14 years, I have worked for big tech companies like
|
|
||||||
Meta (Facebook) and Google, wore multiple hats, led strategic programs, scaled multi
|
|
||||||
billion-dollar businesses, built teams and helped achieve business operational excellence.
|
|
||||||
Throughout my career, I’ve dealt with several challenges from execution to scale to building a
|
|
||||||
high performance team. A lot of my early struggles were about how to assimilate in a new
|
|
||||||
culture, create a network in a new environment, earn trust, create and nurture work
|
|
||||||
relationships into fruitful friendships and so on.
|
|
||||||
</p>
|
|
||||||
<p className="b-news-page__text">
|
|
||||||
I was born in a conservative family in a small town called ‘Shivpuri’, also known as ‘Mini
|
|
||||||
Kashmir’ because of its natural beauty. My father was a civil engineer working on Madikheda Dam
|
|
||||||
on Sindh river and was a strict disciplinarian. He was gone from dawn to dusk and was always
|
|
||||||
focused. My mother was a teacher in a school that was about 30 kms from our home. We (me and my
|
|
||||||
sister) would often be left with neighbors to be taken care of and this led us to become
|
|
||||||
independent at an early age. Our otherwise slow paced, simple life with only a few families
|
|
||||||
around in the government quarters that were set up to support construction of the dam was filled
|
|
||||||
with natural beauty, wildlife and a community of close friends. Our lives were balanced and
|
|
||||||
while my parents worked hard to provide basic needs, we were satisfied. There were only a few
|
|
||||||
schools with Hindi being the prevalent language as the medium of teaching. There were no
|
|
||||||
colleges for advanced studies and most girls did not go to college often married off by their
|
|
||||||
18th birthday. Generally speaking, we had a joyous childhood with just the basics. While most
|
|
||||||
folks we interacted with were not highly educated nor ambitious, earned lower middle class
|
|
||||||
salaries and lacked exposure to the outside world but there was plenty to learn from them.
|
|
||||||
People had learnt to stick together in good and bad times. They embodied the old school
|
|
||||||
qualities of hard work, dedication and commitment. Be willing to give it all- hard work,
|
|
||||||
dedication and commitment.
|
|
||||||
</p>
|
|
||||||
<p className="b-news-page__text">
|
|
||||||
In 2003, my father passed away suddenly and we found ourselves in crisis. My mother was a
|
|
||||||
teacher and she did not have time to deal with her grief. Rather, she was struggling to garner
|
|
||||||
support to get transferred to a school in Bhopal, capital of Madhya Pradesh to be closer to our
|
|
||||||
maternal grandparents. As we uprooted ourselves from Shivpuri to Bhopal, one of my father’s
|
|
||||||
loyal friends came to help load the moving truck. While he had nothing to gain out of us, he
|
|
||||||
continued to serve us until the last day in Shivpuri. Remember, in crisis your team matters more
|
|
||||||
than any other time. Advocate for them ruthlessly in good and bad times, they will come through
|
|
||||||
in crisis.
|
|
||||||
</p>
|
|
||||||
<p className="b-news-page__text">
|
|
||||||
Eventually we found our footing, my mother’s job was transferred to a local school in Bhopal and
|
|
||||||
I got admission in a government engineering college. My sister was still attending high school
|
|
||||||
and both of us were teaching tuition classes to middle school students in the evenings to make
|
|
||||||
ends meet. I also started a tiffin service for a few out of town students while attending
|
|
||||||
college to pay for my transportation and cost of supplies. We refused to give up. Persevere when
|
|
||||||
all else fails.
|
|
||||||
</p>
|
|
||||||
<p className="b-news-page__text">
|
|
||||||
Our 5 years went by quickly in Bhopal as we worked towards improving our financial situation and
|
|
||||||
I completed my Bachelors in Computer Science. This was the time I first stepped out to live in a
|
|
||||||
metropolitan city, Mumbai for my job at TCS. This was a paradigm shift from Bhopal and I was
|
|
||||||
blown away to meet so many talented folks in Mumbai. In my head, I did not belong in this place.
|
|
||||||
I had imposter syndrome and felt like an outsider trying to make it in a new city. Most people I
|
|
||||||
met were fluent in more than 1 language, well-dressed, communicated openly and with confidence,
|
|
||||||
and presented themselves well. I was always in a dilemma when it came to adopting values. It
|
|
||||||
took me a while to adjust to it but I was still not confident about my work and communication
|
|
||||||
while my hard skills that I learnt in engineering were top notch. I kept questioning my
|
|
||||||
abilities but persisted. This was not the first time I was out of my comfort zone. Persist, when
|
|
||||||
in discomfort.
|
|
||||||
</p>
|
|
||||||
<p className="b-news-page__text">
|
|
||||||
I worked with multiple global companies who were clients of TCS and was presented an opportunity
|
|
||||||
to move to Scotland, UK for an year to work for GE, who was also a client. This was my first
|
|
||||||
opportunity to explore a different culture, food, music, languages etc. I remember working on my
|
|
||||||
english when in Mumbai, in preparation for my UK trip. It was really difficult to understand the
|
|
||||||
accent in the UK, even though language was not a barrier. I still remember certain words would
|
|
||||||
just not get across no matter how hard some of my colleagues tried and they would end up using
|
|
||||||
signs to convey. Be prepared, opportunities come to those who are prepared.
|
|
||||||
</p>
|
|
||||||
<p className="b-news-page__text">
|
|
||||||
In 2013, I came to the US on a dependent visa after marriage and quickly realized the curse of
|
|
||||||
H4 visa. I paved my path by going back to school at UC Berkeley and then jumped back into
|
|
||||||
building my career from scratch. While working in the US over the past years, I realized college
|
|
||||||
degrees with good grades and certifications definitely help you to get your foot in the door but
|
|
||||||
are not enough to be successful in your career. As I was again starting from scratch in a new
|
|
||||||
culture, determined to do whatever it takes, having done this a few times before, it doesn’t
|
|
||||||
scare me as much. Never be afraid to start from zero again!
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
import React from 'react';
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
import { draftMode } from 'next/headers'
|
||||||
|
import { notFound } from 'next/navigation';
|
||||||
|
import {fetchBlogPost, fetchBlogPosts, Widget} from "../../../../lib/contentful/blogPosts";
|
||||||
|
import Util from "node:util";
|
||||||
|
import RichText from "../../../../lib/contentful/RichText";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Bbuddy - Blog item',
|
||||||
|
description: 'Bbuddy desc blog item'
|
||||||
|
};
|
||||||
|
|
||||||
|
interface BlogPostPageParams {
|
||||||
|
slug: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BlogPostPageProps {
|
||||||
|
params: BlogPostPageParams
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateStaticParams(): Promise<BlogPostPageParams[]> {
|
||||||
|
const blogPosts = await fetchBlogPosts({ preview: false })
|
||||||
|
|
||||||
|
return blogPosts.map((post) => ({ slug: post.slug }))
|
||||||
|
}
|
||||||
|
function renderWidget (widget: Widget) {
|
||||||
|
switch (widget.type){
|
||||||
|
case 'widgetParagraph':
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h2 className="title-h2">
|
||||||
|
{widget.widget.subTitle}
|
||||||
|
</h2>
|
||||||
|
<RichText document={widget.widget.body} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
case 'widgetMedia':
|
||||||
|
return (
|
||||||
|
<img src={widget.widget.file?.src}/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function BlogItem({params}: { params: BlogPostPageParams }) {
|
||||||
|
const item = await fetchBlogPost({slug: params.slug, preview: draftMode().isEnabled })
|
||||||
|
console.log('BLOG POST')
|
||||||
|
console.log(Util.inspect(item, {showHidden: false, depth: null, colors: true}))
|
||||||
|
if (!item) notFound();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="b-news-page">
|
||||||
|
<div className="b-inner">
|
||||||
|
<h1 className="b-news-page__title">{item.title}</h1>
|
||||||
|
<div className="news-item__badge">{item.category}</div>
|
||||||
|
<div className="b-news-page__text">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="b-news-page__image">
|
||||||
|
<img className="" src="/images/news1.png" alt="" />
|
||||||
|
</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 className="b-news-page__inner">
|
||||||
|
{item.body.map(renderWidget)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,101 @@
|
||||||
|
import React from 'react';
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
import { draftMode } from 'next/headers'
|
||||||
|
import {unstable_setRequestLocale} from "next-intl/server";
|
||||||
|
import Link from "next/link";
|
||||||
|
import {fetchBlogPosts} from "../../../../../lib/contentful/blogPosts";
|
||||||
|
import {fetchBlogPostCategories} from "../../../../../lib/contentful/blogPostsCategories";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Bbuddy - Blog',
|
||||||
|
description: 'Bbuddy desc blog'
|
||||||
|
};
|
||||||
|
|
||||||
|
interface BlogPostPageParams {
|
||||||
|
slug: string
|
||||||
|
locale: string
|
||||||
|
}
|
||||||
|
interface BlogPostPageProps {
|
||||||
|
params: BlogPostPageParams
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function Blog({params}: { params: BlogPostPageParams }) {
|
||||||
|
unstable_setRequestLocale(params.locale);
|
||||||
|
const data = await fetchBlogPosts({ preview: draftMode().isEnabled, locale: params.locale, category: params.slug })
|
||||||
|
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>
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,12 +1,22 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
|
import * as Util from "node:util";
|
||||||
|
import {fetchBlogPosts} from "../../../lib/contentful/blogPosts";
|
||||||
|
import {unstable_setRequestLocale} from "next-intl/server";
|
||||||
|
import Link from "next/link";
|
||||||
|
import {fetchBlogPostCategories} from "../../../lib/contentful/blogPostsCategories";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'Bbuddy - Blog',
|
title: 'Bbuddy - Blog',
|
||||||
description: 'Bbuddy desc blog'
|
description: 'Bbuddy desc blog'
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Blog() {
|
|
||||||
|
|
||||||
|
export default async function Blog({ params: { locale } }: { params: { locale: string } }) {
|
||||||
|
unstable_setRequestLocale(locale);
|
||||||
|
const data = await fetchBlogPosts(false, locale)
|
||||||
|
const cats = await fetchBlogPostCategories(false)
|
||||||
return (
|
return (
|
||||||
<div className="b-news">
|
<div className="b-news">
|
||||||
<div className="b-news__header">
|
<div className="b-news__header">
|
||||||
|
@ -27,49 +37,39 @@ export default function Blog() {
|
||||||
<div className="b-news__filter ">
|
<div className="b-news__filter ">
|
||||||
<div className="b-inner">
|
<div className="b-inner">
|
||||||
<div className="wrap-filter">
|
<div className="wrap-filter">
|
||||||
<a href="#" className="filter-item">Leadership & Management</a>
|
{
|
||||||
<a href="#" className="filter-item">Professional Development</a>
|
cats.map((cat, i)=>(
|
||||||
<a href="#" className="filter-item">Research & Insights</a>
|
<Link href={'category/'+cat.slug} className="filter-item">{cat.title}</Link>
|
||||||
<a href="#" className="filter-item">Well-Being</a>
|
))
|
||||||
<a href="#" className="filter-item">Diversity & Inclusion</a>
|
}
|
||||||
<a href="#" className="filter-item">Culture</a>
|
|
||||||
<a href="#" className="filter-item">Sales</a>
|
|
||||||
<a href="#" className="filter-item">Collaboration</a>
|
|
||||||
<a href="#" className="filter-item">Hiring</a>
|
|
||||||
<a href="#" className="filter-item active">BBuddy product</a>
|
|
||||||
<a href="#" className="filter-item">Customer Stories</a>
|
|
||||||
<a href="#" className="filter-item">Coaching</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="b-news__result-list">
|
<div className="b-news__result-list">
|
||||||
<div className="b-inner">
|
<div className="b-inner">
|
||||||
<div className="news-list">
|
<div className="news-list">
|
||||||
<a href="#" className="news-item">
|
{data.map((item, i) => (
|
||||||
|
<li key={'blog'+i} className="list-sidebar__item">
|
||||||
|
<Link href={`${item.slug}`} className="news-item">
|
||||||
<div className="news-item__image">
|
<div className="news-item__image">
|
||||||
<img className="" src="/images/news.png" alt="" />
|
<img className="" src={item.listImage?.src} alt={item.listImage?.alt}/>
|
||||||
</div>
|
</div>
|
||||||
<div className="news-item__inner">
|
<div className="news-item__inner">
|
||||||
<div className="">
|
<div className="">
|
||||||
<div className="news-item__title">
|
<div className="news-item__title">
|
||||||
6 learnings from Shivpuri to Silicon Valley
|
{item.title}
|
||||||
</div>
|
</div>
|
||||||
<div className="news-item__badge">Leadership & Management</div>
|
<div className="news-item__badge">{item.category}</div>
|
||||||
<div className="news-item__text">
|
<div className="news-item__text">
|
||||||
I’m excited to kick off this series of newsletters where I’ll be sharing my
|
{item.excerpt}
|
||||||
experiences,
|
|
||||||
learnings, and best practices which helped me to grow both in my personal and
|
|
||||||
professional life. My hope is to give back to the community and help anyone
|
|
||||||
connect directly with me who may have got impacted with recent layoffs,
|
|
||||||
dealing with immigration challenges.
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="news-item__info">
|
<div className="news-item__info">
|
||||||
<div className="news-item__info__author">
|
<div className="news-item__info__author">
|
||||||
<img className="" src="/images/author.png" alt="" />
|
<img className="" src={item.author.avatar.src} alt=""/>
|
||||||
<div className="news-item__info__author__inner">
|
<div className="news-item__info__author__inner">
|
||||||
<div className="news-item__info__name">Sonali Garg</div>
|
<div className="news-item__info__name">{item.author.name}</div>
|
||||||
<div className="news-item__info__date">February 6th, 2023</div>
|
<div className="news-item__info__date">{item.createdAt}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="news-item__info__counter">
|
<div className="news-item__info__counter">
|
||||||
|
@ -84,127 +84,9 @@ export default function Blog() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</Link>
|
||||||
<a href="#" className="news-item">
|
</li>
|
||||||
<div className="news-item__image">
|
))}
|
||||||
<img className="" src="/images/news.png" alt="" />
|
|
||||||
</div>
|
|
||||||
<div className="news-item__inner">
|
|
||||||
<div className="">
|
|
||||||
<div className="news-item__title">
|
|
||||||
6 learnings from Shivpuri to Silicon Valley
|
|
||||||
</div>
|
|
||||||
<div className="news-item__badge">Leadership & Management</div>
|
|
||||||
<div className="news-item__text">
|
|
||||||
I’m excited to kick off this series of newsletters where I’ll be sharing my
|
|
||||||
experiences,
|
|
||||||
learnings, and best practices which helped me to grow both in my personal and
|
|
||||||
professional life. My hope is to give back to the community and help anyone
|
|
||||||
connect directly with me who may have got impacted with recent layoffs,
|
|
||||||
dealing with immigration challenges.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="news-item__info">
|
|
||||||
<div className="news-item__info__author">
|
|
||||||
<img className="" src="/images/author.png" alt="" />
|
|
||||||
<div className="news-item__info__author__inner">
|
|
||||||
<div className="news-item__info__name">Sonali Garg</div>
|
|
||||||
<div className="news-item__info__date">February 6th, 2023</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>
|
|
||||||
</a>
|
|
||||||
<a href="#" className="news-item">
|
|
||||||
<div className="news-item__image">
|
|
||||||
<img className="" src="/images/news.png" alt="" />
|
|
||||||
</div>
|
|
||||||
<div className="news-item__inner">
|
|
||||||
<div className="">
|
|
||||||
<div className="news-item__title">
|
|
||||||
6 learnings from Shivpuri to Silicon Valley
|
|
||||||
</div>
|
|
||||||
<div className="news-item__badge">Leadership & Management</div>
|
|
||||||
<div className="news-item__text">
|
|
||||||
I’m excited to kick off this series of newsletters where I’ll be sharing my
|
|
||||||
experiences,
|
|
||||||
learnings, and best practices which helped me to grow both in my personal and
|
|
||||||
professional life. My hope is to give back to the community and help anyone
|
|
||||||
connect directly with me who may have got impacted with recent layoffs,
|
|
||||||
dealing with immigration challenges.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="news-item__info">
|
|
||||||
<div className="news-item__info__author">
|
|
||||||
<img className="" src="/images/author.png" alt="" />
|
|
||||||
<div className="news-item__info__author__inner">
|
|
||||||
<div className="news-item__info__name">Sonali Garg</div>
|
|
||||||
<div className="news-item__info__date">February 6th, 2023</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>
|
|
||||||
</a>
|
|
||||||
<a href="#" className="news-item">
|
|
||||||
<div className="news-item__image">
|
|
||||||
<img className="" src="/images/news.png" alt="" />
|
|
||||||
</div>
|
|
||||||
<div className="news-item__inner">
|
|
||||||
<div className="">
|
|
||||||
<div className="news-item__title">
|
|
||||||
6 learnings from Shivpuri to Silicon Valley
|
|
||||||
</div>
|
|
||||||
<div className="news-item__badge">Leadership & Management</div>
|
|
||||||
<div className="news-item__text">
|
|
||||||
I’m excited to kick off this series of newsletters where I’ll be sharing my
|
|
||||||
experiences,
|
|
||||||
learnings, and best practices which helped me to grow both in my personal and
|
|
||||||
professional life. My hope is to give back to the community and help anyone
|
|
||||||
connect directly with me who may have got impacted with recent layoffs,
|
|
||||||
dealing with immigration challenges.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="news-item__info">
|
|
||||||
<div className="news-item__info__author">
|
|
||||||
<img className="" src="/images/author.png" alt="" />
|
|
||||||
<div className="news-item__info__author__inner">
|
|
||||||
<div className="news-item__info__name">Sonali Garg</div>
|
|
||||||
<div className="news-item__info__date">February 6th, 2023</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>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { Document as RichTextDocument } from '@contentful/rich-text-types'
|
||||||
|
import { documentToReactComponents } from '@contentful/rich-text-react-renderer'
|
||||||
|
|
||||||
|
type RichTextProps = {
|
||||||
|
document: RichTextDocument | null
|
||||||
|
}
|
||||||
|
|
||||||
|
function RichText({ document }: RichTextProps) {
|
||||||
|
if (!document) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>{documentToReactComponents(document)}</>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RichText
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { parseContentfulContentImage } from './contentImage'
|
||||||
|
import {Author, AuthorEntry} from "../../types/author";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export function parseContentfulAuthor(authorEntry?: AuthorEntry<any, any>): Author | null {
|
||||||
|
if (!authorEntry) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: authorEntry.fields.name || '',
|
||||||
|
avatar: parseContentfulContentImage(authorEntry.fields.avatar),
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
import { Entry } from 'contentful'
|
||||||
|
import contentfulClient from './contentfulClient'
|
||||||
|
import { parseContentfulContentImage } from './contentImage'
|
||||||
|
import {BlogPost, BlogPostEntry, BlogPostSkeleton} from "../../types/blogPost";
|
||||||
|
import {parseContentfulAuthor} from "./authors";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import {WidgetMedia, WidgetMediaEntry} from "../../types/blogWidgets/widgetMedia";
|
||||||
|
import {WidgetParagraph} from "../../types/blogWidgets/widgetParagraph";
|
||||||
|
import entry from "next/dist/server/typescript/rules/entry";
|
||||||
|
import Util from "node:util";
|
||||||
|
|
||||||
|
type PostEntry = BlogPostEntry<undefined, string>//Entry<BlogPostSkeleton, undefined, string>
|
||||||
|
type widgetEnum = WidgetParagraph | WidgetMedia
|
||||||
|
export type Widget = {
|
||||||
|
widget: widgetEnum
|
||||||
|
type: string
|
||||||
|
}
|
||||||
|
type WidgetEntry = WidgetMediaEntry<undefined, string> | WidgetParagraph<undefined, string>
|
||||||
|
function parseWidgets(entries?: Array<WidgetEntry>): Array<Widget> | null {
|
||||||
|
if (!entries || !entries.length) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return entries.map((entry: WidgetEntry) => {
|
||||||
|
const wType = entry.sys.contentType.sys.id
|
||||||
|
let wObj = {} as widgetEnum
|
||||||
|
switch (wType){
|
||||||
|
case 'widgetParagraph':
|
||||||
|
wObj = {
|
||||||
|
subTitle: entry.fields.subTitle,
|
||||||
|
body: entry.fields.body
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case 'widgetMedia':
|
||||||
|
wObj = {
|
||||||
|
decription: entry.fields.decription || '',
|
||||||
|
file: parseContentfulContentImage(entry.fields.file)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: wType,
|
||||||
|
widget: wObj
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseContentfulBlogPost(entry?: PostEntry): BlogPost | null {
|
||||||
|
if (!entry) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: entry.fields.title || '',
|
||||||
|
slug: entry.fields.slug,
|
||||||
|
excerpt: entry.fields.excerpt || '',
|
||||||
|
listImage: parseContentfulContentImage(entry.fields.listImage),
|
||||||
|
author: parseContentfulAuthor(entry.fields.author),
|
||||||
|
createdAt: dayjs(entry.sys.createdAt).format('MMM DD, YYYY'),
|
||||||
|
category: entry.fields.category.fields.title,
|
||||||
|
body: parseWidgets(entry.fields.body) || []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FetchBlogPostsOptions {
|
||||||
|
preview: boolean
|
||||||
|
local?: string
|
||||||
|
category?: string
|
||||||
|
}
|
||||||
|
export async function fetchBlogPosts({ preview, category }: FetchBlogPostsOptions): Promise<BlogPost[]> {
|
||||||
|
const contentful = contentfulClient({ preview })
|
||||||
|
const query = {
|
||||||
|
content_type: 'blogPost',
|
||||||
|
select: ['fields.title', 'fields.excerpt', 'fields.author', 'fields.listImage', 'fields.author', 'fields.category', 'sys.createdAt', 'fields.slug'],
|
||||||
|
order: ['sys.createdAt'],
|
||||||
|
}
|
||||||
|
if (category){
|
||||||
|
query['fields.category.fields.slug'] = category
|
||||||
|
query['fields.category.sys.contentType.sys.id']='blogPostCategory'
|
||||||
|
}
|
||||||
|
const blogPostsResult = await contentful.getEntries<BlogPostSkeleton>(query)
|
||||||
|
|
||||||
|
return blogPostsResult.items.map((blogPostEntry) => parseContentfulBlogPost(blogPostEntry) as BlogPost)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FetchBlogPostOptions {
|
||||||
|
slug: string
|
||||||
|
preview: boolean
|
||||||
|
}
|
||||||
|
export async function fetchBlogPost({ slug, preview }: FetchBlogPostOptions): Promise<BlogPost | null> {
|
||||||
|
const contentful = contentfulClient({ preview })
|
||||||
|
|
||||||
|
const blogPostsResult = await contentful.getEntries<BlogPostSkeleton>({
|
||||||
|
content_type: 'blogPost',
|
||||||
|
'fields.slug': slug,
|
||||||
|
include: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
return parseContentfulBlogPost(blogPostsResult.items[0])
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { Entry } from 'contentful'
|
||||||
|
import contentfulClient from './contentfulClient'
|
||||||
|
import { parseContentfulContentImage } from './contentImage'
|
||||||
|
import {BlogPost, BlogPostEntry, BlogPostSkeleton} from "../../types/blogPost";
|
||||||
|
import {parseContentfulAuthor} from "./authors";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import {BlogPostCategory, BlogPostCategoryEntry, BlogPostCategorySkeleton} from "../../types/blogPostCategory";
|
||||||
|
|
||||||
|
type ListEntry = BlogPostCategoryEntry<undefined, string>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export function parseContentfulBlogPostCategory(entry?: ListEntry): BlogPostCategory | null {
|
||||||
|
if (!entry) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
title: entry.fields.title || '',
|
||||||
|
slug: entry.fields.slug || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FetchListOptions {
|
||||||
|
preview: boolean
|
||||||
|
local?: string
|
||||||
|
}
|
||||||
|
export async function fetchBlogPostCategories({ preview }: FetchListOptions): Promise<BlogPostCategory[]> {
|
||||||
|
const contentful = contentfulClient({ preview })
|
||||||
|
|
||||||
|
const results = await contentful.getEntries<BlogPostCategorySkeleton>({
|
||||||
|
content_type: 'blogPostCategory',
|
||||||
|
order: ['fields.title'],
|
||||||
|
})
|
||||||
|
|
||||||
|
return results.items.map((entry) => parseContentfulBlogPostCategory(entry) as BlogPostCategory)
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { Asset, AssetLink } from 'contentful'
|
||||||
|
|
||||||
|
export interface ContentImage {
|
||||||
|
src: string
|
||||||
|
alt: string
|
||||||
|
width: number
|
||||||
|
height: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseContentfulContentImage(
|
||||||
|
asset?: Asset<undefined, string> | { sys: AssetLink }
|
||||||
|
): ContentImage | null {
|
||||||
|
if (!asset) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!('fields' in asset)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
src: asset.fields.file?.url || '',
|
||||||
|
alt: asset.fields.description || '',
|
||||||
|
width: asset.fields.file?.details.image?.width || 0,
|
||||||
|
height: asset.fields.file?.details.image?.height || 0,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { createClient } from 'contentful'
|
||||||
|
|
||||||
|
const { CONTENTFUL_SPACE_ID, CONTENTFUL_ACCESS_TOKEN, CONTENTFUL_PREVIEW_ACCESS_TOKEN } = process.env
|
||||||
|
|
||||||
|
// This is the standard Contentful client. It fetches
|
||||||
|
// content that has been published.
|
||||||
|
const client = createClient({
|
||||||
|
space: CONTENTFUL_SPACE_ID!,
|
||||||
|
accessToken: CONTENTFUL_ACCESS_TOKEN!,
|
||||||
|
})
|
||||||
|
|
||||||
|
// This is a Contentful client that's been configured
|
||||||
|
// to fetch drafts and unpublished content.
|
||||||
|
const previewClient = createClient({
|
||||||
|
space: CONTENTFUL_SPACE_ID!,
|
||||||
|
accessToken: CONTENTFUL_PREVIEW_ACCESS_TOKEN!,
|
||||||
|
host: 'preview.contentful.com',
|
||||||
|
})
|
||||||
|
|
||||||
|
// This little helper will let us switch between the two
|
||||||
|
// clients easily:
|
||||||
|
export default function contentfulClient({ preview = false }) {
|
||||||
|
if (preview) {
|
||||||
|
return previewClient
|
||||||
|
}
|
||||||
|
|
||||||
|
return client
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import type { ChainModifiers, Entry, EntryFieldTypes, EntrySkeletonType, LocaleCode } from 'contentful'
|
||||||
|
import {BlogPostFields} from "./blogPost";
|
||||||
|
import {ContentImage} from "../lib/contentful/contentImage";
|
||||||
|
|
||||||
|
export interface AuthorFields {
|
||||||
|
name: EntryFieldTypes.Symbol
|
||||||
|
avatar: EntryFieldTypes.AssetLink
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Author {
|
||||||
|
name: string
|
||||||
|
avatar: ContentImage | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AuthorSkeleton = EntrySkeletonType<AuthorFields, 'author'>
|
||||||
|
export type AuthorEntry<Modifiers extends ChainModifiers, Locales extends LocaleCode> = Entry<
|
||||||
|
AuthorSkeleton,
|
||||||
|
Modifiers,
|
||||||
|
Locales
|
||||||
|
>
|
|
@ -0,0 +1,39 @@
|
||||||
|
import type { ChainModifiers, Entry, EntryFieldTypes, EntrySkeletonType, LocaleCode } from 'contentful'
|
||||||
|
import {Author, AuthorSkeleton} from "./author";
|
||||||
|
import {ContentImage} from "../lib/contentful/contentImage";
|
||||||
|
import {BlogPostCategorySkeleton} from "./blogPostCategory";
|
||||||
|
import {WidgetMedia, WidgetMediaSkeleton} from "./blogWidgets/widgetMedia";
|
||||||
|
import {WidgetParagraph, WidgetParagraphSkeleton} from "./blogWidgets/widgetParagraph";
|
||||||
|
|
||||||
|
export interface BlogPostFields {
|
||||||
|
title?: EntryFieldTypes.Symbol
|
||||||
|
slug: EntryFieldTypes.Symbol
|
||||||
|
excerpt: EntryFieldTypes.Symbol
|
||||||
|
listImage?: EntryFieldTypes.AssetLink
|
||||||
|
author?: AuthorSkeleton
|
||||||
|
category: BlogPostCategorySkeleton
|
||||||
|
createdAt?: EntryFieldTypes.Date
|
||||||
|
body?: Array<WidgetMediaSkeleton | WidgetParagraphSkeleton>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BlogPostFields extends BlogPostFields{
|
||||||
|
body: Array<WidgetMediaSkeleton | WidgetParagraphSkeleton>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BlogPost {
|
||||||
|
title: string
|
||||||
|
slug: string
|
||||||
|
excerpt: string
|
||||||
|
listImage: ContentImage | null
|
||||||
|
author: Author | null
|
||||||
|
category: string
|
||||||
|
createdAt: string
|
||||||
|
body: Array<WidgetMedia | WidgetParagraph>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BlogPostSkeleton = EntrySkeletonType<BlogPostFields, 'blogPost'>
|
||||||
|
export type BlogPostEntry<Modifiers extends ChainModifiers, Locales extends LocaleCode> = Entry<
|
||||||
|
BlogPostSkeleton,
|
||||||
|
Modifiers,
|
||||||
|
Locales
|
||||||
|
>
|
|
@ -0,0 +1,20 @@
|
||||||
|
import type { ChainModifiers, Entry, EntryFieldTypes, EntrySkeletonType, LocaleCode } from 'contentful'
|
||||||
|
import {BlogPostFields} from "./blogPost";
|
||||||
|
import {ContentImage} from "../lib/contentful/contentImage";
|
||||||
|
|
||||||
|
export interface BlogPostCategoryFields {
|
||||||
|
title: EntryFieldTypes.Symbol
|
||||||
|
slug: EntryFieldTypes.Symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BlogPostCategory {
|
||||||
|
title: string
|
||||||
|
slug: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BlogPostCategorySkeleton = EntrySkeletonType<BlogPostCategoryFields, 'blogPostCategory'>
|
||||||
|
export type BlogPostCategoryEntry<Modifiers extends ChainModifiers, Locales extends LocaleCode> = Entry<
|
||||||
|
BlogPostCategorySkeleton,
|
||||||
|
Modifiers,
|
||||||
|
Locales
|
||||||
|
>
|
|
@ -0,0 +1,20 @@
|
||||||
|
import type { ChainModifiers, Entry, EntryFieldTypes, EntrySkeletonType, LocaleCode } from 'contentful'
|
||||||
|
import {BlogPostFields} from "./blogPost";
|
||||||
|
import {ContentImage} from "../lib/contentful/contentImage";
|
||||||
|
|
||||||
|
export interface WidgetMediaFields {
|
||||||
|
decription?: EntryFieldTypes.Symbol
|
||||||
|
file?: EntryFieldTypes.AssetLink
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WidgetMedia {
|
||||||
|
file: ContentImage | null
|
||||||
|
decription: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type WidgetMediaSkeleton = EntrySkeletonType<WidgetMediaFields, 'WidgetMedia'>
|
||||||
|
export type WidgetMediaEntry<Modifiers extends ChainModifiers, Locales extends LocaleCode> = Entry<
|
||||||
|
WidgetMediaSkeleton,
|
||||||
|
Modifiers,
|
||||||
|
Locales
|
||||||
|
>
|
|
@ -0,0 +1,20 @@
|
||||||
|
import type { ChainModifiers, Entry, EntryFieldTypes, EntrySkeletonType, LocaleCode } from 'contentful'
|
||||||
|
import {BlogPostFields} from "./blogPost";
|
||||||
|
import {ContentImage} from "../lib/contentful/contentImage";
|
||||||
|
import { Document as RichTextDocument } from '@contentful/rich-text-types'
|
||||||
|
export interface WidgetParagraphFields {
|
||||||
|
subTitle?: EntryFieldTypes.Symbol
|
||||||
|
body?: EntryFieldTypes.RichText
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WidgetParagraph {
|
||||||
|
subTitle: string
|
||||||
|
body: RichTextDocument | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type WidgetParagraphSkeleton = EntrySkeletonType<WidgetParagraphFields, 'WidgetParagraph'>
|
||||||
|
export type WidgetParagraphEntry<Modifiers extends ChainModifiers, Locales extends LocaleCode> = Entry<
|
||||||
|
WidgetParagraphSkeleton,
|
||||||
|
Modifiers,
|
||||||
|
Locales
|
||||||
|
>
|
Loading…
Reference in New Issue