feat: tags
Signed-off-by: Filipe Medeiros <hello@filipesm.eu>
This commit is contained in:
parent
95bea24ec1
commit
2b51277f1d
|
@ -2,11 +2,13 @@ import Card, {
|
||||||
CardCta,
|
CardCta,
|
||||||
CardDescription,
|
CardDescription,
|
||||||
CardEyebrow,
|
CardEyebrow,
|
||||||
|
CardTags,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from '@/components/server/Card'
|
} from '@/components/server/Card'
|
||||||
import SimpleLayout from '@/components/server/SimpleLayout'
|
import SimpleLayout from '@/components/server/SimpleLayout'
|
||||||
import formatDate from '@/lib/formatDate'
|
import formatDate from '@/lib/formatDate'
|
||||||
import { getFirstBlogPosts } from '@/lib/notion/content/blogPosts'
|
import { getFirstBlogPosts } from '@/lib/notion/content/blogPosts'
|
||||||
|
import { SelectColor } from '@/lib/notion/types'
|
||||||
import richTextAsPlainText from '@/lib/notion/utils/richTextToPlainText'
|
import richTextAsPlainText from '@/lib/notion/utils/richTextToPlainText'
|
||||||
|
|
||||||
export const revalidate = 600
|
export const revalidate = 600
|
||||||
|
@ -16,11 +18,13 @@ function BlogPost({
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
publishDate,
|
publishDate,
|
||||||
|
topics,
|
||||||
}: {
|
}: {
|
||||||
slug: string
|
slug: string
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
publishDate: string
|
publishDate: string
|
||||||
|
topics: { name: string; color: SelectColor }[]
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<article className="md:grid md:grid-cols-4 md:items-baseline">
|
<article className="md:grid md:grid-cols-4 md:items-baseline">
|
||||||
|
@ -35,6 +39,16 @@ function BlogPost({
|
||||||
{formatDate(publishDate)}
|
{formatDate(publishDate)}
|
||||||
</CardEyebrow>
|
</CardEyebrow>
|
||||||
<CardDescription>{description}</CardDescription>
|
<CardDescription>{description}</CardDescription>
|
||||||
|
<CardTags>
|
||||||
|
{topics.map((topic) => (
|
||||||
|
<span
|
||||||
|
key={topic.name}
|
||||||
|
className={`notion-color-${topic.color} rounded bg-[var(--light-bg)] p-1 text-[var(--light-text)] dark:bg-[var(--dark-bg)] dark:text-[var(--dark-text)]`}
|
||||||
|
>
|
||||||
|
{topic.name}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</CardTags>
|
||||||
<CardCta>Lê o artigo</CardCta>
|
<CardCta>Lê o artigo</CardCta>
|
||||||
</Card>
|
</Card>
|
||||||
<CardEyebrow
|
<CardEyebrow
|
||||||
|
@ -65,6 +79,9 @@ export default async function Blog() {
|
||||||
description={richTextAsPlainText(
|
description={richTextAsPlainText(
|
||||||
blogPost.properties.Description.rich_text,
|
blogPost.properties.Description.rich_text,
|
||||||
)}
|
)}
|
||||||
|
topics={blogPost.properties.Topics.multi_select.map(
|
||||||
|
({ name, color }) => ({ name, color }),
|
||||||
|
)}
|
||||||
slug={richTextAsPlainText(blogPost.properties.Slug.rich_text)}
|
slug={richTextAsPlainText(blogPost.properties.Slug.rich_text)}
|
||||||
publishDate={richTextAsPlainText(
|
publishDate={richTextAsPlainText(
|
||||||
blogPost.properties.PublishDate.date?.start ??
|
blogPost.properties.PublishDate.date?.start ??
|
||||||
|
|
|
@ -2,12 +2,38 @@ import { PropsWithChildren } from 'react'
|
||||||
|
|
||||||
import Header from '@/components/client/Header'
|
import Header from '@/components/client/Header'
|
||||||
import Footer from '@/components/server/Footer'
|
import Footer from '@/components/server/Footer'
|
||||||
|
import colorMap from '@/lib/notion/utils/colorMap'
|
||||||
|
|
||||||
import './globals.css'
|
import './globals.css'
|
||||||
|
|
||||||
|
const notionColorsCssVars = Object.entries(colorMap)
|
||||||
|
.map(([name, colors]) =>
|
||||||
|
[
|
||||||
|
`--notion-${name}-dark-text:${colors.dark.text};`,
|
||||||
|
`--notion-${name}-dark-bg:${colors.dark.bg};`,
|
||||||
|
`--notion-${name}-light-text:${colors.light.text};`,
|
||||||
|
`--notion-${name}-light-bg:${colors.light.bg};`,
|
||||||
|
].join(''),
|
||||||
|
)
|
||||||
|
.join('')
|
||||||
|
|
||||||
|
const notionEachColorClass = Object.entries(colorMap)
|
||||||
|
.map(
|
||||||
|
([name]) =>
|
||||||
|
`.notion-color-${name}{--dark-text:var(--notion-${name}-dark-text);--dark-bg:var(--notion-${name}-dark-bg);--light-text:var(--notion-${name}-light-text);--light-bg:var(--notion-${name}-light-bg);}`,
|
||||||
|
)
|
||||||
|
.join('')
|
||||||
|
|
||||||
export default function BaseLayout({ children }: PropsWithChildren) {
|
export default function BaseLayout({ children }: PropsWithChildren) {
|
||||||
return (
|
return (
|
||||||
<html className="h-full antialiased" lang="pt-PT">
|
<html className="h-full antialiased" lang="pt-PT">
|
||||||
|
<head>
|
||||||
|
<style
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: `:root{${notionColorsCssVars}} ${notionEachColorClass}`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
<body className="flex h-full flex-col bg-zinc-50 font-serif dark:bg-black">
|
<body className="flex h-full flex-col bg-zinc-50 font-serif dark:bg-black">
|
||||||
<div className="fixed inset-0 flex justify-center sm:px-8">
|
<div className="fixed inset-0 flex justify-center sm:px-8">
|
||||||
<div className="flex w-full max-w-7xl lg:px-8">
|
<div className="flex w-full max-w-7xl lg:px-8">
|
||||||
|
|
26
app/page.tsx
26
app/page.tsx
|
@ -1,12 +1,13 @@
|
||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import Image, { ImageProps } from 'next/image'
|
import Image, { ImageProps } from 'next/image'
|
||||||
import { type ElementType } from 'react'
|
import { type ElementType, Fragment } from 'react'
|
||||||
|
|
||||||
import Button from '@/components/client/Button'
|
import Button from '@/components/client/Button'
|
||||||
import Card, {
|
import Card, {
|
||||||
CardCta,
|
CardCta,
|
||||||
CardDescription,
|
CardDescription,
|
||||||
CardEyebrow,
|
CardEyebrow,
|
||||||
|
CardTags,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from '@/components/server/Card'
|
} from '@/components/server/Card'
|
||||||
import Container from '@/components/server/Container'
|
import Container from '@/components/server/Container'
|
||||||
|
@ -25,6 +26,8 @@ import FarfetchLogo from '@/images/logos/farfetch.png'
|
||||||
import ThreeSigmaLogo from '@/images/logos/threeSigma.png'
|
import ThreeSigmaLogo from '@/images/logos/threeSigma.png'
|
||||||
import formatDate from '@/lib/formatDate'
|
import formatDate from '@/lib/formatDate'
|
||||||
import { getFirstBlogPosts } from '@/lib/notion/content/blogPosts'
|
import { getFirstBlogPosts } from '@/lib/notion/content/blogPosts'
|
||||||
|
import { SelectColor } from '@/lib/notion/types'
|
||||||
|
import colorMap from '@/lib/notion/utils/colorMap'
|
||||||
import richTextAsPlainText from '@/lib/notion/utils/richTextToPlainText'
|
import richTextAsPlainText from '@/lib/notion/utils/richTextToPlainText'
|
||||||
|
|
||||||
function BriefcaseIcon(props: IconProps) {
|
function BriefcaseIcon(props: IconProps) {
|
||||||
|
@ -68,11 +71,14 @@ function BlogPost({
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
publishDate,
|
publishDate,
|
||||||
|
topics,
|
||||||
}: {
|
}: {
|
||||||
slug: string
|
slug: string
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
publishDate: string
|
publishDate: string
|
||||||
|
|
||||||
|
topics: { name: string; color: SelectColor }[]
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Card as="article">
|
<Card as="article">
|
||||||
|
@ -81,6 +87,16 @@ function BlogPost({
|
||||||
{formatDate(publishDate)}
|
{formatDate(publishDate)}
|
||||||
</CardEyebrow>
|
</CardEyebrow>
|
||||||
<CardDescription>{description}</CardDescription>
|
<CardDescription>{description}</CardDescription>
|
||||||
|
<CardTags>
|
||||||
|
{topics.map((topic) => (
|
||||||
|
<span
|
||||||
|
key={topic.name}
|
||||||
|
className={`notion-color-${topic.color} rounded bg-[var(--light-bg)] p-1 text-[var(--light-text)] dark:bg-[var(--dark-bg)] dark:text-[var(--dark-text)]`}
|
||||||
|
>
|
||||||
|
{topic.name}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</CardTags>
|
||||||
<CardCta>Lê o artigo</CardCta>
|
<CardCta>Lê o artigo</CardCta>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
@ -241,8 +257,6 @@ function Resume() {
|
||||||
export default async function Home() {
|
export default async function Home() {
|
||||||
const { results: blogPosts } = await getFirstBlogPosts()
|
const { results: blogPosts } = await getFirstBlogPosts()
|
||||||
|
|
||||||
console.log(blogPosts)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Container className="mt-9">
|
<Container className="mt-9">
|
||||||
|
@ -302,6 +316,12 @@ export default async function Home() {
|
||||||
description={richTextAsPlainText(
|
description={richTextAsPlainText(
|
||||||
blogPost.properties.Description.rich_text,
|
blogPost.properties.Description.rich_text,
|
||||||
)}
|
)}
|
||||||
|
topics={blogPost.properties.Topics.multi_select.map(
|
||||||
|
({ name, color }) => ({
|
||||||
|
name,
|
||||||
|
color,
|
||||||
|
}),
|
||||||
|
)}
|
||||||
slug={richTextAsPlainText(blogPost.properties.Slug.rich_text)}
|
slug={richTextAsPlainText(blogPost.properties.Slug.rich_text)}
|
||||||
publishDate={richTextAsPlainText(
|
publishDate={richTextAsPlainText(
|
||||||
blogPost.properties.PublishDate.date?.start ??
|
blogPost.properties.PublishDate.date?.start ??
|
||||||
|
|
|
@ -56,6 +56,10 @@ export function CardDescription({ children }: PropsWithChildren) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function CardTags({ children }: PropsWithChildren) {
|
||||||
|
return <div className="z-10 mt-2 flex gap-1 text-sm">{children}</div>
|
||||||
|
}
|
||||||
|
|
||||||
export function CardCta({ children }: PropsWithChildren) {
|
export function CardCta({ children }: PropsWithChildren) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -103,9 +107,11 @@ export default function Card({
|
||||||
as: Component = 'div',
|
as: Component = 'div',
|
||||||
className,
|
className,
|
||||||
children,
|
children,
|
||||||
}: PropsWithChildren<{ className?: string; as?: ElementType }>) {
|
id,
|
||||||
|
}: PropsWithChildren<{ id?: string; className?: string; as?: ElementType }>) {
|
||||||
return (
|
return (
|
||||||
<Component
|
<Component
|
||||||
|
id={id}
|
||||||
className={clsx(className, 'group relative flex flex-col items-start')}
|
className={clsx(className, 'group relative flex flex-col items-start')}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
44
lib/notion/utils/colorMap.ts
Normal file
44
lib/notion/utils/colorMap.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
const colorMap = {
|
||||||
|
default: {
|
||||||
|
dark: { text: '#FFFFFF', bg: '#2F3437' },
|
||||||
|
light: { text: '#37352F', bg: '#FFFFFF' },
|
||||||
|
},
|
||||||
|
gray: {
|
||||||
|
dark: { text: '#979A9B', bg: '#454B4E' },
|
||||||
|
light: { text: '#9B9A97', bg: '#EBECED' },
|
||||||
|
},
|
||||||
|
brown: {
|
||||||
|
dark: { text: '#937264', bg: '#434040' },
|
||||||
|
light: { text: '#64473A', bg: '#E9E5E3' },
|
||||||
|
},
|
||||||
|
orange: {
|
||||||
|
dark: { text: '#FFA344', bg: '#594A3A' },
|
||||||
|
light: { text: '#D9730D', bg: '#FAEBDD' },
|
||||||
|
},
|
||||||
|
yellow: {
|
||||||
|
dark: { text: '#FFDC49', bg: '#59563B' },
|
||||||
|
light: { text: '#DFAB01', bg: '#FBF3DB' },
|
||||||
|
},
|
||||||
|
green: {
|
||||||
|
dark: { text: '#4DAB9A', bg: '#354C4B' },
|
||||||
|
light: { text: '#0F7B6C', bg: '#DDEDEA' },
|
||||||
|
},
|
||||||
|
blue: {
|
||||||
|
dark: { text: '#529CCA', bg: '#364954' },
|
||||||
|
light: { text: '#0B6E99', bg: '#DDEBF1' },
|
||||||
|
},
|
||||||
|
purple: {
|
||||||
|
dark: { text: '#9A6DD7', bg: '#443F57' },
|
||||||
|
light: { text: '#6940A5', bg: '#EAE4F2' },
|
||||||
|
},
|
||||||
|
pink: {
|
||||||
|
dark: { text: '#E255A1', bg: '#533B4C' },
|
||||||
|
light: { text: '#AD1A72', bg: '#F4DFEB' },
|
||||||
|
},
|
||||||
|
red: {
|
||||||
|
dark: { text: '#FF7369', bg: '#594141' },
|
||||||
|
light: { text: '#E03E3E', bg: '#FBE4E4' },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default colorMap
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue