mirror of
https://github.com/privacy-scaling-explorations/pse.dev.git
synced 2026-04-23 03:01:03 -04:00
add project extra links
This commit is contained in:
@@ -8,6 +8,7 @@ import TwitterVector from "@/public/social-medias/twitter-fill.svg"
|
||||
|
||||
import { Markdown } from "@/components/ui/markdown"
|
||||
import { ProjectTags } from "@/components/project/project-detail-tags"
|
||||
import ProjectExtraLinks from "@/components/project/project-extra-links"
|
||||
|
||||
type PageProps = {
|
||||
params: { id: string }
|
||||
@@ -103,9 +104,12 @@ export default function ProjectDetailPage({ params }: PageProps) {
|
||||
<div className="mt-8">
|
||||
<ProjectTags project={currProject} />
|
||||
</div>
|
||||
<div className="flex flex-col w-full gap-5 py-10 text-base font-normal leading-relaxed">
|
||||
<div className="flex flex-col w-full gap-5 pt-10 text-base font-normal leading-relaxed">
|
||||
<Markdown>{currProject.description}</Markdown>
|
||||
</div>
|
||||
<div className="py-16">
|
||||
<ProjectExtraLinks project={currProject} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -112,4 +112,20 @@ export const Icons = {
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
externalUrl: (props: LucideProps) => (
|
||||
<svg
|
||||
width="24"
|
||||
height="25"
|
||||
viewBox="0 0 24 25"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
id="Vector"
|
||||
d="M16.0034 9.5141L7.39642 18.1211L5.98242 16.7071L14.5884 8.1001H7.00342V6.1001H18.0034V17.1001H16.0034V9.5141Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
}
|
||||
|
||||
96
components/project/project-extra-links.tsx
Normal file
96
components/project/project-extra-links.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import React from "react"
|
||||
import Link from "next/link"
|
||||
|
||||
import {
|
||||
ActionLinkTypeLink,
|
||||
ProjectExtraLinkType,
|
||||
ProjectInterface,
|
||||
} from "@/lib/types"
|
||||
|
||||
import { Icons } from "../icons"
|
||||
|
||||
const ExtraLinkLabelMapping: Record<
|
||||
ProjectExtraLinkType,
|
||||
{
|
||||
label: string
|
||||
icon?: any
|
||||
}
|
||||
> = {
|
||||
buildWith: {
|
||||
label: "Build With",
|
||||
icon: <Icons.hammer />,
|
||||
},
|
||||
play: {
|
||||
label: "Try it out!",
|
||||
icon: <Icons.hand />,
|
||||
},
|
||||
research: {
|
||||
label: "Dive deeper into the research",
|
||||
icon: <Icons.readme />,
|
||||
},
|
||||
learn: {
|
||||
label: "Learn more",
|
||||
},
|
||||
}
|
||||
|
||||
interface ProjectExtraLinksProps {
|
||||
project: ProjectInterface
|
||||
}
|
||||
|
||||
interface ExtraLinkItemsProps {
|
||||
id: ProjectExtraLinkType
|
||||
links: ActionLinkTypeLink[]
|
||||
}
|
||||
|
||||
const ExtraLinkItems = ({ id, links = [] }: ExtraLinkItemsProps) => {
|
||||
const { label, icon } = ExtraLinkLabelMapping[id]
|
||||
|
||||
if (!links.length) return null // no links hide the section
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
{icon && <span className="text-anakiwa-500">{icon}</span>}
|
||||
<p className="font-sans text-xl font-medium text-tuatara-700">
|
||||
{label}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col items-start gap-2">
|
||||
{links.map(({ label, url }: ActionLinkTypeLink) => {
|
||||
return (
|
||||
<Link
|
||||
href={url}
|
||||
target="_blank"
|
||||
className="flex items-center gap-1 overflow-hidden font-sans font-normal duration-200 ease-in-out border-b-2 border-transparent cursor-pointer text-tuatara-950 hover:border-orange"
|
||||
>
|
||||
{label}
|
||||
<Icons.externalUrl />
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function ProjectExtraLinks({ project }: ProjectExtraLinksProps) {
|
||||
const { extraLinks = {} } = project
|
||||
const hasExtraLinks = Object.keys(extraLinks).length > 0
|
||||
|
||||
if (!hasExtraLinks) return null
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-12 md:gap-16">
|
||||
{Object.entries(ExtraLinkLabelMapping).map(([key]) => {
|
||||
const links = extraLinks[key as ProjectExtraLinkType] ?? []
|
||||
return (
|
||||
<ExtraLinkItems
|
||||
key={key}
|
||||
id={key as ProjectExtraLinkType}
|
||||
links={links}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
15
lib/types.ts
15
lib/types.ts
@@ -1,3 +1,5 @@
|
||||
import { type } from "os"
|
||||
|
||||
export interface NewsInterface {
|
||||
type: string
|
||||
title: string
|
||||
@@ -17,15 +19,12 @@ export type ProjectLinkWebsite =
|
||||
|
||||
export type ProjectLinkType = Partial<Record<ProjectLinkWebsite, string>>
|
||||
export type ProjectExtraLinkType = "buildWith" | "play" | "research" | "learn"
|
||||
|
||||
export type ActionLinkTypeLink = {
|
||||
label: string
|
||||
url: string
|
||||
}
|
||||
export type ActionLinkType = Partial<
|
||||
Record<
|
||||
ProjectExtraLinkType,
|
||||
Array<{
|
||||
label: string
|
||||
url: string
|
||||
}>
|
||||
>
|
||||
Record<ProjectExtraLinkType, Array<ActionLinkTypeLink>>
|
||||
>
|
||||
|
||||
export type ProjectStatusType = "active" | "inactive" | "archived"
|
||||
|
||||
Reference in New Issue
Block a user