2
0
Files
bot/apps/landing-page/pages/blog/[slug].tsx
2022-02-09 18:52:36 +01:00

203 lines
5.7 KiB
TypeScript

import { GetStaticPropsContext } from 'next'
import { NotionBlock, NotionText } from 'notion-blocks-chakra-ui'
import React from 'react'
import { getPage, getBlocks, getFullDatabase } from '../../lib/notion'
import Image from 'next/image'
import {
Stack,
Container,
Button,
VStack,
Heading,
HStack,
Text,
} from '@chakra-ui/react'
import {
Page,
Block,
TitlePropertyValue,
RichTextPropertyValue,
CheckboxPropertyValue,
} from '@notionhq/client/build/src/api-types'
import { Footer } from 'components/common/Footer'
import { Navbar } from 'components/common/Navbar/Navbar'
import { NextChakraLink } from 'components/common/nextChakraAdapters/NextChakraLink'
import { SocialMetaTags } from 'components/common/SocialMetaTags'
export default function Post({
page,
blocks,
}: {
page: Page
blocks: Block[]
}) {
return (
<>
<Stack
alignItems="center"
w="full"
overflowX="hidden"
pb={20}
minH="calc(100vh - 267px)"
spacing={10}
>
{page && (
<SocialMetaTags
title={
(page.properties.Name as TitlePropertyValue).title[0]?.plain_text
}
description={
(page.properties.Description as RichTextPropertyValue)
.rich_text[0]?.plain_text
}
currentUrl={`https://www.typebot.io/blog/${
(page.properties.Slug as RichTextPropertyValue).rich_text[0]
?.plain_text
}`}
imagePreviewUrl={
(page.properties.Thumbnail as RichTextPropertyValue).rich_text[0]
?.plain_text
}
/>
)}
<Navbar />
<Container as="article" maxW="900px">
{((page?.properties?.Published as CheckboxPropertyValue | undefined)
?.checkbox ||
!page) && (
<Button
as={NextChakraLink}
href="/blog"
colorScheme="gray"
variant="outline"
size="sm"
>
{'<'} Blog
</Button>
)}
{page ? (
<>
<VStack>
<Heading as="h1" fontSize="5xl" textAlign="center" mt={6}>
<NotionText
text={(page.properties.Name as TitlePropertyValue).title}
/>
</Heading>
<Heading
fontSize="md"
fontWeight="normal"
textAlign="center"
textColor="gray.500"
>
<NotionText
text={
(page.properties.Description as RichTextPropertyValue)
.rich_text
}
/>
</Heading>
{(page.properties.Author as RichTextPropertyValue | undefined)
?.rich_text[0]?.plain_text && (
<Author
author={
(page.properties.Author as RichTextPropertyValue)
.rich_text[0]?.plain_text
}
/>
)}
</VStack>
<Stack mt={6} spacing={4} maxW="700px" mx="auto">
{blocks.map((block) => (
<NotionBlock key={block.id} block={block} />
))}
</Stack>
</>
) : (
<Text textAlign="center">Blog post not found</Text>
)}
</Container>
</Stack>
<Footer />
</>
)
}
export const getStaticPaths = async () => {
if (!process.env.NOTION_DATABASE_ID)
throw new Error("Couldn't find NOTION_DATABASE_ID")
const database = await getFullDatabase(process.env.NOTION_DATABASE_ID)
return {
paths: database.filter(pageWithSlugAndId).map((page) => ({
params: {
slug: (page.properties.Slug as RichTextPropertyValue).rich_text[0]
.plain_text,
id: page.id,
},
})),
fallback: true,
}
}
const pageWithSlugAndId = (page: Page) =>
(page.properties.Slug as RichTextPropertyValue).rich_text[0]?.plain_text &&
page.id
const Author = ({ author }: { author: string }) => {
return (
<HStack>
<Image
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
src={/\(([^)]+)\)/.exec(author)![0].slice(1, -1)}
width="30px"
height="30px"
className="rounded-full"
alt="Author's picture"
/>
<Text>{author.split(' (')[0]}</Text>
</HStack>
)
}
export const getStaticProps = async (
context: GetStaticPropsContext<{ slug: string; locale: 'fr' | 'en' }>
) => {
if (!process.env.NOTION_DATABASE_ID)
throw new Error("Couldn't find NOTION_DATABASE_ID")
if (!context.params) throw new Error("Couldn't find params")
const { slug } = context.params
const page = await getPage(process.env.NOTION_DATABASE_ID, slug)
if (!page?.id) return
const blocks = await getBlocks(page?.id)
const childBlocks = await Promise.all(
blocks
.filter((block) => block.has_children)
.map(async (block) => {
return {
id: block.id,
children: await getBlocks(block.id),
}
})
)
const blocksWithChildren = blocks.map((block) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
if (block.has_children && !block[block.type].children) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
block[block.type]['children'] = childBlocks.find(
(x) => x.id === block.id
)?.children
}
return block
})
return {
props: {
page,
blocks: blocksWithChildren,
},
revalidate: 1,
}
}