2024-04-20 18:21:06 +02:00
|
|
|
/* eslint-disable jsx-a11y/alt-text */
|
2024-04-19 13:20:58 +02:00
|
|
|
'use client'
|
|
|
|
|
|
|
|
import { Link } from '@chakra-ui/next-js'
|
2024-04-23 19:32:46 +02:00
|
|
|
import {
|
|
|
|
Alert,
|
|
|
|
AlertIcon,
|
|
|
|
AlertTitle,
|
|
|
|
Heading,
|
|
|
|
Stack,
|
|
|
|
Text,
|
|
|
|
} from '@chakra-ui/react'
|
2024-04-19 13:20:58 +02:00
|
|
|
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote'
|
|
|
|
import { highlight } from 'sugar-high'
|
2024-04-20 18:21:06 +02:00
|
|
|
import { Tweet } from './Tweet'
|
|
|
|
import { Standard } from '@typebot.io/nextjs'
|
|
|
|
import { EndCta } from '@/components/Homepage/EndCta'
|
2024-04-22 16:04:59 +02:00
|
|
|
import { Table } from './Table'
|
2024-04-22 19:47:43 +02:00
|
|
|
import Image from 'next/image'
|
2024-04-19 13:20:58 +02:00
|
|
|
|
|
|
|
type Props = {
|
|
|
|
metadata: {
|
|
|
|
title: string
|
|
|
|
publishedAt: string
|
|
|
|
}
|
|
|
|
mdxSource: MDXRemoteSerializeResult
|
|
|
|
}
|
|
|
|
|
|
|
|
export const Post = ({ metadata, mdxSource }: Props) => (
|
2024-04-20 18:21:06 +02:00
|
|
|
<Stack spacing={10} my="20" w="full">
|
2024-04-23 19:32:46 +02:00
|
|
|
<Stack mx="auto" w="full" maxW={['full', '46rem']} px={[3, 3, 0]}>
|
2024-04-19 13:20:58 +02:00
|
|
|
<Heading>{metadata.title}</Heading>
|
|
|
|
<Text>{formatDate(metadata.publishedAt)}</Text>
|
|
|
|
</Stack>
|
|
|
|
<Stack
|
|
|
|
mx="auto"
|
|
|
|
spacing={0}
|
|
|
|
as="article"
|
2024-04-22 16:04:59 +02:00
|
|
|
px={3}
|
|
|
|
w="full"
|
|
|
|
className="prose prose-quoteless prose-neutral prose-invert max-w-none"
|
2024-04-19 13:20:58 +02:00
|
|
|
>
|
|
|
|
<MDXRemote
|
|
|
|
{...mdxSource}
|
|
|
|
components={{
|
|
|
|
h1: (props) => <Heading as="h1" {...props} />,
|
2024-04-23 19:32:46 +02:00
|
|
|
h2: (props) => <Heading as="h2" fontSize="3xl" {...props} />,
|
|
|
|
h3: (props) => <Heading as="h3" fontSize="2xl" {...props} />,
|
|
|
|
h4: (props) => <Heading as="h4" fontSize="xl" {...props} />,
|
|
|
|
h5: (props) => <Heading as="h5" fontSize="lg" {...props} />,
|
|
|
|
h6: (props) => <Heading as="h6" fontSize="md" {...props} />,
|
2024-04-19 13:20:58 +02:00
|
|
|
code: ({ children, ...props }) => {
|
|
|
|
const codeHTML = highlight(children?.toString() ?? '')
|
|
|
|
return (
|
|
|
|
<code dangerouslySetInnerHTML={{ __html: codeHTML }} {...props} />
|
|
|
|
)
|
|
|
|
},
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
link: (props: any) => <Link {...props} />,
|
2024-04-20 18:21:06 +02:00
|
|
|
Image: (props) => (
|
2024-04-22 19:47:43 +02:00
|
|
|
<Image {...props} style={{ borderRadius: '.5rem' }} />
|
2024-04-20 18:21:06 +02:00
|
|
|
),
|
2024-04-23 19:32:46 +02:00
|
|
|
Callout: ({ children, title, ...props }) => (
|
2024-04-20 18:21:06 +02:00
|
|
|
<Alert rounded="md" {...props}>
|
|
|
|
<AlertIcon />
|
2024-04-23 19:32:46 +02:00
|
|
|
{title ? <AlertTitle>{title}</AlertTitle> : null}
|
2024-04-20 18:21:06 +02:00
|
|
|
{children}
|
|
|
|
</Alert>
|
|
|
|
),
|
|
|
|
Tweet,
|
2024-04-23 19:32:46 +02:00
|
|
|
Typebot: (props) => (
|
|
|
|
<Standard
|
|
|
|
{...props}
|
|
|
|
typebot={props.typebot}
|
|
|
|
style={{
|
|
|
|
borderRadius: '0.375rem',
|
|
|
|
borderWidth: '1px',
|
|
|
|
height: '533px',
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
),
|
2024-04-20 18:21:06 +02:00
|
|
|
Youtube: ({ id }: { id: string }) => (
|
|
|
|
<div className="w-full">
|
|
|
|
<div
|
|
|
|
style={{
|
|
|
|
position: 'relative',
|
|
|
|
paddingBottom: '64.63195691202873%',
|
|
|
|
height: 0,
|
|
|
|
width: '100%',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<iframe
|
|
|
|
src={`https://www.youtube.com/embed/${id}`}
|
|
|
|
allowFullScreen
|
|
|
|
style={{
|
|
|
|
position: 'absolute',
|
|
|
|
top: 0,
|
|
|
|
left: 0,
|
|
|
|
width: '100%',
|
|
|
|
height: '100%',
|
|
|
|
}}
|
|
|
|
></iframe>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
),
|
|
|
|
Loom: ({ id }: { id: string }) => (
|
|
|
|
<div className="w-full">
|
|
|
|
<div
|
|
|
|
style={{
|
|
|
|
position: 'relative',
|
|
|
|
paddingBottom: '64.63195691202873%',
|
|
|
|
height: 0,
|
|
|
|
width: '100%',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<iframe
|
|
|
|
src={`https://www.loom.com/embed/${id}`}
|
|
|
|
allowFullScreen
|
|
|
|
style={{
|
|
|
|
position: 'absolute',
|
|
|
|
top: 0,
|
|
|
|
left: 0,
|
|
|
|
width: '100%',
|
|
|
|
height: '100%',
|
|
|
|
}}
|
|
|
|
></iframe>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
),
|
|
|
|
Cta: (props) => (
|
|
|
|
<EndCta
|
|
|
|
{...props}
|
|
|
|
style={{ maxWidth: 'none' }}
|
|
|
|
w="full"
|
2024-04-22 16:04:59 +02:00
|
|
|
h="auto"
|
|
|
|
py="0"
|
2024-04-20 18:21:06 +02:00
|
|
|
className="w-full"
|
|
|
|
bgGradient={undefined}
|
2024-04-22 16:04:59 +02:00
|
|
|
polygonsBaseTop="0px"
|
2024-04-20 18:21:06 +02:00
|
|
|
/>
|
|
|
|
),
|
2024-04-22 16:04:59 +02:00
|
|
|
Table,
|
2024-04-19 13:20:58 +02:00
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</Stack>
|
|
|
|
</Stack>
|
|
|
|
)
|
|
|
|
|
|
|
|
function formatDate(date: string) {
|
|
|
|
const currentDate = new Date().getTime()
|
|
|
|
if (!date.includes('T')) {
|
|
|
|
date = `${date}T00:00:00`
|
|
|
|
}
|
|
|
|
const targetDate = new Date(date).getTime()
|
|
|
|
const timeDifference = Math.abs(currentDate - targetDate)
|
|
|
|
const daysAgo = Math.floor(timeDifference / (1000 * 60 * 60 * 24))
|
|
|
|
|
|
|
|
const fullDate = new Date(date).toLocaleString('en-us', {
|
|
|
|
month: 'long',
|
|
|
|
day: 'numeric',
|
|
|
|
year: 'numeric',
|
|
|
|
})
|
|
|
|
|
|
|
|
if (daysAgo < 1) {
|
|
|
|
return 'Today'
|
|
|
|
} else if (daysAgo < 7) {
|
|
|
|
return `${fullDate} (${daysAgo}d ago)`
|
|
|
|
} else if (daysAgo < 30) {
|
|
|
|
const weeksAgo = Math.floor(daysAgo / 7)
|
|
|
|
return `${fullDate} (${weeksAgo}w ago)`
|
|
|
|
} else if (daysAgo < 365) {
|
|
|
|
const monthsAgo = Math.floor(daysAgo / 30)
|
|
|
|
return `${fullDate} (${monthsAgo}mo ago)`
|
|
|
|
} else {
|
|
|
|
const yearsAgo = Math.floor(daysAgo / 365)
|
|
|
|
return `${fullDate} (${yearsAgo}y ago)`
|
|
|
|
}
|
|
|
|
}
|