From 448ea7e74191a7a614863d8bf16bee850ae532eb Mon Sep 17 00:00:00 2001 From: Diogo Soares <32431609+DiogoSoaress@users.noreply.github.com> Date: Wed, 16 Oct 2024 16:01:01 +0100 Subject: [PATCH 1/2] refactor: move Contentful Entry types to util file --- src/components/Blog/BlogHome/index.tsx | 5 +---- src/components/Blog/Card/index.tsx | 2 +- src/components/Blog/FeaturedPost/index.tsx | 2 +- src/components/Blog/Post/index.tsx | 8 ++++---- src/components/Pressroom/AboutUs/index.tsx | 2 +- src/components/Pressroom/index.tsx | 7 ++----- src/config/types.ts | 5 +++++ src/hooks/useBlogPost.ts | 2 +- src/lib/contentful/__test__/isPressRelease.test.ts | 2 +- src/lib/contentful/isDraft.ts | 2 +- src/lib/contentful/isPressRelease.ts | 2 +- 11 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/components/Blog/BlogHome/index.tsx b/src/components/Blog/BlogHome/index.tsx index 0dab2a761..0e34bdb5d 100644 --- a/src/components/Blog/BlogHome/index.tsx +++ b/src/components/Blog/BlogHome/index.tsx @@ -4,17 +4,14 @@ import Card from '@/components/Blog/Card' import FeaturedPost from '@/components/Blog/FeaturedPost' import SearchFilterResults from '@/components/Blog/SearchFilterResults' import type { TypeBlogHomeSkeleton } from '@/contentful/types' -import type { Entry } from 'contentful' import { isEntryTypePost } from '@/lib/typeGuards' import { useClientEntry } from '@/hooks/useClientEntry' -import type { PostEntryCollection } from '@/config/types' +import type { BlogHomeEntry, PostEntryCollection } from '@/config/types' const categories = ['Announcements', 'Ecosystem', 'Community', 'Insights', 'Build'] const TRENDING_POSTS_COUNT = 3 -export type BlogHomeEntry = Entry - export type BlogHomeProps = { blogHome: BlogHomeEntry allPosts: PostEntryCollection diff --git a/src/components/Blog/Card/index.tsx b/src/components/Blog/Card/index.tsx index 59431e73b..64ca92730 100644 --- a/src/components/Blog/Card/index.tsx +++ b/src/components/Blog/Card/index.tsx @@ -6,7 +6,7 @@ import { calculateReadingTimeInMin } from '@/components/Blog/utils/calculateRead import Tags from '@/components/Blog/Tags' import CategoryIcon from '@/public/images/Blog/category-icon.svg' import { isAsset } from '@/lib/typeGuards' -import { type BlogPostEntry } from '@/components/Blog/Post' +import type { BlogPostEntry } from '@/config/types' import { AppRoutes } from '@/config/routes' const Card = (props: BlogPostEntry) => { diff --git a/src/components/Blog/FeaturedPost/index.tsx b/src/components/Blog/FeaturedPost/index.tsx index 4ea943dba..b0527b7a3 100644 --- a/src/components/Blog/FeaturedPost/index.tsx +++ b/src/components/Blog/FeaturedPost/index.tsx @@ -4,7 +4,7 @@ import { Box, Grid, Link, Typography } from '@mui/material' import css from './styles.module.css' import { formatBlogDate } from '@/components/Blog/utils/formatBlogDate' import { calculateReadingTimeInMin } from '@/components/Blog/utils/calculateReadingTime' -import { type BlogPostEntry } from '@/components/Blog/Post' +import type { BlogPostEntry } from '@/config/types' import { isAsset } from '@/lib/typeGuards' import CategoryIcon from '@/public/images/Blog/category-icon.svg' import { AppRoutes } from '@/config/routes' diff --git a/src/components/Blog/Post/index.tsx b/src/components/Blog/Post/index.tsx index 41d949e6e..c587fe618 100644 --- a/src/components/Blog/Post/index.tsx +++ b/src/components/Blog/Post/index.tsx @@ -1,7 +1,7 @@ import Image from 'next/image' import { Box, Button, Container, Divider, Grid, Typography } from '@mui/material' import { type Entry } from 'contentful' -import type { TypeAuthorSkeleton, TypePostSkeleton } from '@/contentful/types' +import type { TypeAuthorSkeleton } from '@/contentful/types' import { formatBlogDate } from '@/components/Blog/utils/formatBlogDate' import { calculateReadingTimeInMin } from '@/components/Blog/utils/calculateReadingTime' import { isAsset, isEntryTypeAuthor, isEntryTypePost } from '@/lib/typeGuards' @@ -20,10 +20,10 @@ import css from '../styles.module.css' import { PRESS_RELEASE_TAG, containsTag } from '@/lib/containsTag' import { COMMS_EMAIL } from '@/config/constants' import { useBlogPost } from '@/hooks/useBlogPost' +import type { InferGetStaticPropsType } from 'next' +import type { getStaticProps } from '@/pages/blog/[slug]' -export type BlogPostEntry = Entry - -const BlogPost = ({ blogPost }: { blogPost: BlogPostEntry }) => { +const BlogPost = ({ blogPost }: InferGetStaticPropsType) => { const { data: post } = useBlogPost(blogPost.sys.id, blogPost) const { title, excerpt, content, coverImage, authors, tags, category, date, relatedPosts, metaTags } = post.fields diff --git a/src/components/Pressroom/AboutUs/index.tsx b/src/components/Pressroom/AboutUs/index.tsx index fe4a4b8c8..bc896a9f1 100644 --- a/src/components/Pressroom/AboutUs/index.tsx +++ b/src/components/Pressroom/AboutUs/index.tsx @@ -6,7 +6,7 @@ import { Box, Typography } from '@mui/material' // const TOTAL_ASSETS_STORED = 'https://dune.com/queries/2893829/4821383' const TOTAL_ASSETS_FALLBACK = '$100B+' -const AboutUs = ({ totalAssets }: { totalAssets: number }) => { +const AboutUs = ({ totalAssets }: { totalAssets: number | null }) => { const totalAssetsStr = totalAssets ? `~$${formatValue(totalAssets)}` : TOTAL_ASSETS_FALLBACK // const totalAssetsLink = ( // diff --git a/src/components/Pressroom/index.tsx b/src/components/Pressroom/index.tsx index 63203a113..7bd3f1353 100644 --- a/src/components/Pressroom/index.tsx +++ b/src/components/Pressroom/index.tsx @@ -21,18 +21,15 @@ import { isEntryTypeSimpleBaseBlock, } from '@/lib/typeGuards' import { Container } from '@mui/material' -import type { Entry } from 'contentful' import { useClientEntry } from '@/hooks/useClientEntry' -import type { PostEntryCollection } from '@/config/types' +import type { PostEntryCollection, PressRoomEntry } from '@/config/types' import { isPublishedPressRelease } from '@/lib/contentful/isPressRelease' import { useAllPosts } from '@/hooks/useAllPosts' -export type PressRoomEntry = Entry - export type PressRoomProps = { pressRoom: PressRoomEntry allPosts: PostEntryCollection - totalAssets: number + totalAssets: number | null } const PressRoom = ({ pressRoom, allPosts, totalAssets }: PressRoomProps) => { diff --git a/src/config/types.ts b/src/config/types.ts index e196aacb5..ff60cd172 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -1,12 +1,17 @@ import type { TypeBaseBlockSkeleton, + TypeBlogHomeSkeleton, TypeButtonSkeleton, TypeLandingPageSkeleton, TypePostSkeleton, + TypePressRoomSkeleton, } from '@/contentful/types' import type { Entry, EntryCollection } from 'contentful' export type BaseBlockEntry = Entry export type ButtonEntry = Entry export type LandingPageEntry = Entry +export type PressRoomEntry = Entry +export type BlogHomeEntry = Entry +export type BlogPostEntry = Entry export type PostEntryCollection = EntryCollection diff --git a/src/hooks/useBlogPost.ts b/src/hooks/useBlogPost.ts index 36f0fcd50..acba521ff 100644 --- a/src/hooks/useBlogPost.ts +++ b/src/hooks/useBlogPost.ts @@ -1,6 +1,6 @@ import useSWR from 'swr' import client from '@/lib/contentful' -import { type BlogPostEntry } from '@/components/Blog/Post' +import type { BlogPostEntry } from '@/config/types' import { type TypePostSkeleton } from '@/contentful/types' const postFetcher = (id: string) => client.getEntry(id) diff --git a/src/lib/contentful/__test__/isPressRelease.test.ts b/src/lib/contentful/__test__/isPressRelease.test.ts index 31240d9ca..d00a192e2 100644 --- a/src/lib/contentful/__test__/isPressRelease.test.ts +++ b/src/lib/contentful/__test__/isPressRelease.test.ts @@ -1,5 +1,5 @@ import { isPressReleasePost, isPublishedPressRelease } from '@/lib/contentful/isPressRelease' -import type { BlogPostEntry } from '@/components/Blog/Post' +import type { BlogPostEntry } from '@/config/types' import type { TypePostFields } from '@/contentful/types' describe('isPressReleasePost', () => { diff --git a/src/lib/contentful/isDraft.ts b/src/lib/contentful/isDraft.ts index 146e8ee1e..0350c6366 100644 --- a/src/lib/contentful/isDraft.ts +++ b/src/lib/contentful/isDraft.ts @@ -1,3 +1,3 @@ -import type { BlogPostEntry } from '@/components/Blog/Post' +import type { BlogPostEntry } from '@/config/types' export const isDraft = (post: BlogPostEntry) => post.fields.isDraft diff --git a/src/lib/contentful/isPressRelease.ts b/src/lib/contentful/isPressRelease.ts index 6c49600c4..e38c71181 100644 --- a/src/lib/contentful/isPressRelease.ts +++ b/src/lib/contentful/isPressRelease.ts @@ -1,6 +1,6 @@ import { containsTag, PRESS_RELEASE_TAG } from '@/lib/containsTag' import { isDraft } from '@/lib/contentful/isDraft' -import type { BlogPostEntry } from '@/components/Blog/Post' +import type { BlogPostEntry } from '@/config/types' export const isPressReleasePost = (post: BlogPostEntry) => containsTag(post.fields.tags, PRESS_RELEASE_TAG) From 239318deec375fbebf2f662f64341ea8e79981d3 Mon Sep 17 00:00:00 2001 From: Diogo Soares <32431609+DiogoSoaress@users.noreply.github.com> Date: Wed, 16 Oct 2024 16:10:24 +0100 Subject: [PATCH 2/2] refactor: let a component define a page layout to overwrite the default --- src/components/Blog/Post/index.tsx | 9 ++++++--- src/components/common/Page/index.tsx | 6 +++++- src/components/common/PageLayout/index.tsx | 12 +----------- src/pages/[slug].tsx | 9 ++++----- src/pages/_app.tsx | 17 +++++++++++------ src/pages/blog/[slug].tsx | 8 ++++---- src/pages/blog/index.tsx | 5 +++-- src/pages/press.tsx | 5 +++-- 8 files changed, 37 insertions(+), 34 deletions(-) diff --git a/src/components/Blog/Post/index.tsx b/src/components/Blog/Post/index.tsx index c587fe618..1afc9aae3 100644 --- a/src/components/Blog/Post/index.tsx +++ b/src/components/Blog/Post/index.tsx @@ -20,10 +20,13 @@ import css from '../styles.module.css' import { PRESS_RELEASE_TAG, containsTag } from '@/lib/containsTag' import { COMMS_EMAIL } from '@/config/constants' import { useBlogPost } from '@/hooks/useBlogPost' -import type { InferGetStaticPropsType } from 'next' -import type { getStaticProps } from '@/pages/blog/[slug]' +import type { BlogPostEntry } from '@/config/types' -const BlogPost = ({ blogPost }: InferGetStaticPropsType) => { +export type BlogPostProps = { + blogPost: BlogPostEntry +} + +const BlogPost = ({ blogPost }: BlogPostProps) => { const { data: post } = useBlogPost(blogPost.sys.id, blogPost) const { title, excerpt, content, coverImage, authors, tags, category, date, relatedPosts, metaTags } = post.fields diff --git a/src/components/common/Page/index.tsx b/src/components/common/Page/index.tsx index de9015e46..4b4ec7f85 100644 --- a/src/components/common/Page/index.tsx +++ b/src/components/common/Page/index.tsx @@ -3,7 +3,11 @@ import { isEntryType, isEntryTypeBaseBlock } from '@/lib/typeGuards' import MetaTags from '@/components/common/MetaTagsContentful' import { type LandingPageEntry } from '@/config/types' -const Page = ({ landingPage }: { landingPage: LandingPageEntry }) => { +export type LandingPageProps = { + landingPage: LandingPageEntry +} + +const Page = ({ landingPage }: LandingPageProps) => { const { metaTags, content } = landingPage.fields return ( diff --git a/src/components/common/PageLayout/index.tsx b/src/components/common/PageLayout/index.tsx index 3cd46adb3..0ca80afd3 100644 --- a/src/components/common/PageLayout/index.tsx +++ b/src/components/common/PageLayout/index.tsx @@ -1,22 +1,12 @@ import { type ReactElement } from 'react' import Header from '@/components/common/Header' -import HeaderCampaigns from '@/components/common/HeaderCampaigns' import Footer from '@/components/common/Footer' import css from './styles.module.css' -import { useRouter } from 'next/router' const PageLayout = ({ children }: { children: ReactElement }): ReactElement => { - const router = useRouter() - - const selectHeader = () => { - const isCampaignsPage = router.pathname.startsWith('/campaigns') - - return isCampaignsPage ? :
- } - return (
- {selectHeader()} +
{children} diff --git a/src/pages/[slug].tsx b/src/pages/[slug].tsx index d7bd1748b..e5248af67 100644 --- a/src/pages/[slug].tsx +++ b/src/pages/[slug].tsx @@ -1,16 +1,15 @@ -import type { GetStaticPaths, GetStaticProps } from 'next' +import type { GetStaticPaths, GetStaticProps, InferGetStaticPropsType, NextPage } from 'next' import client from '@/lib/contentful' import { type TypeLandingPageSkeleton } from '@/contentful/types' -import Page from '@/components/common/Page' -import { type LandingPageEntry } from '@/config/types' +import Page, { type LandingPageProps } from '@/components/common/Page' -const LandingPage = (props: { landingPage: LandingPageEntry }) => { +const LandingPage: NextPage> = (props) => { if (!props.landingPage) return null return } -export const getStaticProps: GetStaticProps = async ({ params }) => { +export const getStaticProps: GetStaticProps = async ({ params }) => { const slug = params?.slug as string const landingPageEntries = await client.getEntries({ diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 6be8d010f..fbf5efa38 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -6,7 +6,8 @@ import { CssBaseline } from '@mui/material' import { CacheProvider } from '@emotion/react' import type { EmotionCache } from '@emotion/react' import type { AppProps } from 'next/app' -import type { ReactElement } from 'react' +import type { ReactElement, ReactNode } from 'react' +import type { NextPage } from 'next' import { createEmotionCache } from '@/styles/emotion' import { CookieBannerContextProvider } from '@/contexts/CookieBannerContext' @@ -42,13 +43,21 @@ const InitHooks = () => { return null } +export type NextPageWithLayout

= NextPage & { + getLayout?: (page: ReactElement) => ReactNode +} + const App = ({ Component, pageProps, emotionCache = clientSideEmotionCache, }: AppProps & { + Component: NextPageWithLayout emotionCache?: EmotionCache }): ReactElement => { + // Use the layout defined at the page level, if available or the default layout + const getLayout = Component.getLayout ?? ((page) => {page}) + return ( @@ -57,11 +66,7 @@ const App = ({ - - - - - + {getLayout()} diff --git a/src/pages/blog/[slug].tsx b/src/pages/blog/[slug].tsx index 5b9d8f5b9..8c7fc3da4 100644 --- a/src/pages/blog/[slug].tsx +++ b/src/pages/blog/[slug].tsx @@ -1,15 +1,15 @@ -import BlogPost, { type BlogPostEntry } from '@/components/Blog/Post' +import BlogPost, { type BlogPostProps } from '@/components/Blog/Post' import { type TypePostSkeleton } from '@/contentful/types' import client from '@/lib/contentful' -import type { GetStaticProps } from 'next' +import type { GetStaticProps, InferGetStaticPropsType, NextPage } from 'next' -const Page = (props: { blogPost: BlogPostEntry }) => { +const Page: NextPage> = (props) => { if (!props.blogPost) return null return } -export const getStaticProps: GetStaticProps = async ({ params }) => { +export const getStaticProps: GetStaticProps = async ({ params }) => { const slug = params?.slug as string const content = await client.getEntries({ diff --git a/src/pages/blog/index.tsx b/src/pages/blog/index.tsx index 0b9acf6f1..7d28f9c32 100644 --- a/src/pages/blog/index.tsx +++ b/src/pages/blog/index.tsx @@ -2,12 +2,13 @@ import client from '@/lib/contentful' import BlogHome, { type BlogHomeProps } from '@/components/Blog/BlogHome' import type { TypeBlogHomeSkeleton, TypePostSkeleton } from '@/contentful/types' import { isEntryTypePost } from '@/lib/typeGuards' +import type { GetStaticProps, InferGetStaticPropsType, NextPage } from 'next' -const Blog = (props: BlogHomeProps) => { +const Blog: NextPage> = (props) => { return } -export const getStaticProps = async () => { +export const getStaticProps: GetStaticProps = async () => { const allPosts = await client.getEntries({ content_type: 'post', // order by date, most recent first diff --git a/src/pages/press.tsx b/src/pages/press.tsx index 925a8c625..5b1e0bc9d 100644 --- a/src/pages/press.tsx +++ b/src/pages/press.tsx @@ -2,12 +2,13 @@ import client from '@/lib/contentful' import PressRoom, { type PressRoomProps } from '@/components/Pressroom' import type { TypePressRoomSkeleton, TypePostSkeleton } from '@/contentful/types' import { fetchTotalAssets } from '@/hooks/useSafeStats' +import type { GetStaticProps, InferGetStaticPropsType, NextPage } from 'next' -const PressroomPage = (props: PressRoomProps) => { +const PressroomPage: NextPage> = (props) => { return } -export const getStaticProps = async () => { +export const getStaticProps: GetStaticProps = async () => { const allPosts = await client.getEntries({ content_type: 'post', // order by date, most recent first