personal-website/app/projetos/page.tsx
Filipe Medeiros afe2d64d22
feat: tags on projects
Signed-off-by: Filipe Medeiros <hello@filipesm.eu>
2023-12-03 12:25:58 +01:00

104 lines
3.9 KiB
XML

import Image from 'next/image'
import Card, {
CardDescription,
CardLink,
CardTags,
} from '@/components/server/Card'
import SimpleLayout from '@/components/server/SimpleLayout'
import Tag from '@/components/server/Tag'
import { IconProps } from '@/components/server/icons'
import {
type Project as ProjectType,
getProjects,
} from '@/lib/notion/content/projects'
import getProxiedAssetUrl from '@/lib/notion/utils/getProxiedAssetUrl'
import richTextAsPlainText from '@/lib/notion/utils/richTextToPlainText'
export const revalidate = 600
function LinkIcon(props: IconProps) {
return (
<svg viewBox="0 0 24 24" aria-hidden="true" {...props}>
<path
d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z"
fill="currentColor"
/>
</svg>
)
}
function Project({ project }: { project: ProjectType }) {
return (
<Card as="li">
<Image
src={getProxiedAssetUrl({
pageId: project.id,
lastEditedTime: project.last_edited_time,
propertyId: project.properties.Logo.id,
})}
height={40}
// this is ugly but it's actually the right way to do this (for UX)
width={40 / (project.properties.LogoRatio.number ?? 1)}
alt=""
className="z-10 h-10 w-auto rounded border border-neutral-300/60 p-2 dark:border-neutral-300/20 dark:bg-neutral-800"
/>
<h2 className="mt-6 text-base font-semibold text-zinc-800 dark:text-zinc-100">
<CardLink href={project.properties.URL.url ?? '#'}>
{richTextAsPlainText(project.properties.Name.title)}
</CardLink>
</h2>
<CardDescription>
{richTextAsPlainText(project.properties.Description.rich_text)}
</CardDescription>
<CardTags>
{project.properties.Tags.multi_select.map(({ name, color }) => (
<Tag key={name} notionColorName={color}>
{name}
</Tag>
))}
</CardTags>
{/* Hacky way but gets the job done and should be the most performant way! Follows the HTML5 spec :P */}
<style
dangerouslySetInnerHTML={{
__html: `#${project.id} { --project-color: ${richTextAsPlainText(
project.properties.Color.rich_text,
)}; }`,
}}
/>
<p
className="relative z-10 mt-6 flex text-sm font-medium text-zinc-400 transition group-hover:text-[var(--project-color)] dark:text-zinc-200"
id={project.id}
>
<LinkIcon className="h-6 w-6 flex-none" />
<span className="ml-2">
{richTextAsPlainText(project.properties.URLName.rich_text)}
</span>
</p>
</Card>
)
}
export default async function Projects() {
const projects = await getProjects()
return (
<SimpleLayout
title="Projetos"
intro="Coisas que fiz ao longo dos anos. Só aquelas das quais me orgulho :)" // TODO
>
<ul
role="list"
className="grid grid-cols-1 gap-x-12 gap-y-16 sm:grid-cols-2 lg:grid-cols-3"
>
{projects.map((project) => (
<Project project={project} key={project.id} />
))}
</ul>
</SimpleLayout>
)
}