Skip to content

Commit

Permalink
project library v1.5
Browse files Browse the repository at this point in the history
  • Loading branch information
kalidiagne committed Oct 31, 2024
1 parent 7d8b9d4 commit df3c767
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 99 deletions.
33 changes: 18 additions & 15 deletions app/[lang]/projects/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Suspense } from "react"
import { Metadata } from "next"

import { AppContent } from "@/components/ui/app-content"
import { Label } from "@/components/ui/label"
import { Divider } from "@/components/divider"
import { PageHeader } from "@/components/page-header"
import ProjectFiltersBar from "@/components/project/project-filters-bar"
import { ProjectList } from "@/components/project/project-list"
import { ProjectResultBar } from "@/components/project/project-result-bar"
Expand All @@ -19,22 +20,24 @@ export default async function ProjectsPage({ params: { lang } }: any) {

return (
<Divider.Section>
<PageHeader
title={t("title")}
subtitle={t("subtitle")}
showDivider={false}
>
<div className="bg-cover-gradient">
<AppContent className="flex flex-col gap-4 py-10">
<Label.PageTitle label={t("title")} />
<h6 className="font-sans text-base font-normal text-tuatara-950 md:text-[18px] md:leading-[27px] md:max-w-[700px]">
{t("subtitle")}
</h6>
</AppContent>
</div>

<AppContent className="flex flex-col gap-10 py-10">
<Suspense fallback={<div>Loading...</div>}>
<ProjectFiltersBar lang={lang} />
<div className="flex flex-col gap-4">
<ProjectFiltersBar lang={lang} />
<ProjectResultBar lang={lang} />
</div>
</Suspense>
</PageHeader>

<div className="w-full bg-white pb-28">
<div className="container flex flex-col py-8 gap-14">
<ProjectResultBar lang={lang} />
<ProjectList lang={lang} />
</div>
</div>
<ProjectList lang={lang} />
</AppContent>
</Divider.Section>
)
}
3 changes: 2 additions & 1 deletion app/i18n/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@
"connectWithUsOnPlatform": "Connect with us on {{platform}}",
"addResource": "Add a resource",
"notCurrentlyActive": "Not Currently Active",
"inactive": "Inactive",
"joinOurDiscord": "Join our discord",
"prevBrandImage": "Previous branding",
"editThisPage": "Edit this page",
"contents": "Contents"
}
}
6 changes: 3 additions & 3 deletions app/i18n/locales/en/projects-page.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"title": "Explore the library",
"subtitle": "PSE supports projects working on theoretical cryptography research, protocol development, open source tooling, experimental applications, and more."
}
"title": "Explore our Project Library",
"subtitle": "Everything PSE works on is public and open source. All of our projects, whether research or development, are resources you can learn from and build with."
}
90 changes: 60 additions & 30 deletions components/project/project-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,23 @@ const TagsIconMapping: Record<string, any> = {
research: <Icons.readme height={12} width={12} />,
}

const tagCardVariants = cva(
"text-xs font-sans text-tuatara-950 rounded-[3px] py-[2px] px-[6px]",
{
variants: {
variant: {
primary: "bg-[#D8FEA8]",
secondary: "bg-[#C2E8F5]",
},
},
}
)
const projectCardVariants = cva(
"flex cursor-pointer flex-col overflow-hidden rounded-lg transition duration-150 ease-in hover:scale-105",
"flex cursor-pointer flex-col overflow-hidden rounded-lg transition duration-200 ease-in border border-transparent hover:border-anakiwa-500",
{
variants: {
showLinks: {
true: "min-h-[450px]",
true: "min-h-[280px]",
false: "min-h-[200px]",
},
border: {
Expand All @@ -54,20 +65,21 @@ export default function ProjectCard({
const { t } = useTranslation(lang, "common")
const router = useRouter()

const { id, image, links, name, tags, imageAlt, projectStatus } = project
const { id, image, links, name, tags, imageAlt, projectStatus, cardTags } =
project ?? {}

const projectNotActive = projectStatus !== "active"
const { content: projectContent } = getProjectById(id, lang)

return (
<div
className={cn(projectCardVariants({ showLinks, border, className }))}
onClick={() => {
router.push(`/projects/${id}`)
}}
>
<div className={cn(projectCardVariants({ showLinks, border, className }))}>
{showBanner && (
<div className="relative flex flex-col border-b border-black/10">
<div
className="relative flex flex-col border-b border-black/10"
onClick={() => {
router.push(`/projects/${id}`)
}}
>
<Image
src={`/project-banners/${image ? image : "fallback.webp"}`}
alt={`${name} banner`}
Expand All @@ -82,34 +94,52 @@ export default function ProjectCard({
)}
</div>
)}
<div className="flex flex-col justify-between h-full p-4 bg-white rounded-b-lg">
<div className="flex flex-col justify-between h-full gap-8 p-4 bg-white rounded-b-lg">
<div className="flex flex-col justify-start gap-2">
<h1 className="text-xl font-bold text-black">{name}</h1>
<h1 className="text-2xl font-bold leading-7 text-black">{name}</h1>
{projectContent?.tldr && (
<div className="flex flex-col gap-4 h-28">
<p className="text-slate-900/80">{projectContent?.tldr}</p>
<div className="flex flex-col h-24 gap-4">
<p className="text-slate-900/80 line-clamp-4">
{projectContent?.tldr}
</p>
</div>
)}
</div>
<div className="flex justify-between mt-auto">
{showLinks && (
<div className="flex items-center justify-start gap-3">
{Object.entries(links ?? {})?.map(([website, url], index) => {
return (
<ProjectLink
key={index}
url={url}
website={website as ProjectLinkWebsite}
/>
)
})}
</div>
)}
<div className="flex flex-col gap-2">
{projectNotActive && (
<span className="ml-auto text-sm font-medium italic leading-[21px] text-tuatara-400">
{t("notCurrentlyActive")}
<span className="text-sm font-medium italic leading-[21px] text-tuatara-400">
{t("inactive")}
</span>
)}
<div className="flex justify-between ">
{showLinks && (
<div className="flex items-center justify-start gap-3">
{Object.entries(links ?? {})?.map(([website, url], index) => {
return (
<ProjectLink
key={index}
url={url}
website={website as ProjectLinkWebsite}
/>
)
})}
</div>
)}
{cardTags && (
<div className="flex items-center gap-1">
{cardTags?.primary && (
<div className={tagCardVariants({ variant: "primary" })}>
{cardTags?.primary}
</div>
)}
{cardTags?.secondary && (
<div className={tagCardVariants({ variant: "secondary" })}>
{cardTags?.secondary}
</div>
)}
</div>
)}
</div>
</div>
</div>
</div>
Expand Down
89 changes: 57 additions & 32 deletions components/project/project-filters-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ export default function ProjectFiltersBar({ lang }: LangProps["params"]) {
const searchParams = useSearchParams()
const [searchQuery, setSearchQuery] = useState("")
const [filterCount, setFilterCount] = useState(0)
const [activeItem, setActiveItem] = useState<string | null>(
ProjectSections?.[0]
)

const { filters, toggleFilter, queryString, activeFilters, onFilterProject } =
useProjectFiltersState((state) => state)
Expand Down Expand Up @@ -296,40 +299,62 @@ export default function ProjectFiltersBar({ lang }: LangProps["params"]) {
</FilterWrapper>
</div>
</Modal>
<div className="flex flex-col gap-6">
<div className="grid items-center justify-between grid-cols-1 gap-3 md:grid-cols-5 md:gap-12">
<div className="col-span-1 grid grid-cols-[1fr_auto] gap-2 md:col-span-3 md:gap-3">
<Input
onChange={(e: ChangeEvent<HTMLInputElement>) =>
setSearchQuery(e?.target?.value)
}
value={searchQuery}
placeholder={t("searchProjectPlaceholder")}
/>
<div className="flex items-center gap-3">
<Badge value={filterCount}>
<Button
onClick={() => setShowModal(true)}
variant="white"
className={cn({
"border-2 border-anakiwa-950": filterCount > 0,
})}
<div className="flex flex-col gap-4">
<nav className="container px-4 mx-auto">
<ul className="flex space-x-6">
{ProjectSections.map((key) => {
return (
<div
key={key}
className={cn(
"relative block px-2 py-1 text-sm font-medium uppercase transition-colors cursor-pointer hover:text-primary",
activeItem === key
? "text-sky-400 after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-full after:bg-sky-400"
: ""
)}
onClick={() => setActiveItem(key)}
>
<div className="flex items-center gap-2">
<Image src={FiltersIcon} alt="filter icon" />
<span className="hidden md:block">{t("filters")}</span>
</div>
</Button>
</Badge>
<button
disabled={!hasActiveFilters}
onClick={clearAllFilters}
className="hidden bg-transparent cursor-pointer opacity-85 text-primary hover:opacity-100 disabled:pointer-events-none disabled:opacity-50 md:block"
>
<div className="flex items-center gap-2 border-b-2 border-black">
<span className="text-sm font-medium">{t("clearAll")}</span>
{key}
</div>
</button>
)
})}
</ul>
</nav>
<div className="flex flex-col gap-6">
<div className="grid items-center justify-between grid-cols-1 gap-3 md:grid-cols-5 md:gap-12">
<div className="col-span-1 grid grid-cols-[1fr_auto] gap-2 md:col-span-3 md:gap-3">
<Input
onChange={(e: ChangeEvent<HTMLInputElement>) =>
setSearchQuery(e?.target?.value)
}
value={searchQuery}
placeholder={t("searchProjectPlaceholder")}
/>
<div className="flex items-center gap-3">
<Badge value={filterCount}>
<Button
onClick={() => setShowModal(true)}
variant="white"
className={cn({
"border-2 border-anakiwa-950": filterCount > 0,
})}
>
<div className="flex items-center gap-2">
<Image src={FiltersIcon} alt="filter icon" />
<span className="hidden md:block">{t("filters")}</span>
</div>
</Button>
</Badge>
<button
disabled={!hasActiveFilters}
onClick={clearAllFilters}
className="hidden bg-transparent cursor-pointer opacity-85 text-primary hover:opacity-100 disabled:pointer-events-none disabled:opacity-50 md:block"
>
<div className="flex items-center gap-2 border-b-2 border-black">
<span className="text-sm font-medium">{t("clearAll")}</span>
</div>
</button>
</div>
</div>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions components/project/project-link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export function ProjectLink({ website, url }: ProjectLinkProps) {
}}
target="_blank"
rel="noopener noreferrer"
className="text-lg"
>
{icon}
</a>
Expand Down
24 changes: 19 additions & 5 deletions components/project/project-links.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,23 @@ import { RiTelegramLine as TelegramIcon } from "react-icons/ri"
import { Icons } from "../icons"

export const ProjectLinkIconMap: Record<string, any> = {
github: <Icons.gitHub size={16} />,
website: <Icons.globe />,
twitter: <Icons.twitter size={18} />,
telegram: <TelegramIcon size={16} />,
discord: <Icons.discord size={16} />,
github: (
<Icons.gitHub size={18} className="duration-200 hover:text-anakiwa-500" />
),
website: (
<Icons.globe
width={22}
height={22}
className="duration-200 hover:text-anakiwa-500"
/>
),
twitter: (
<Icons.twitter size={22} className="duration-200 hover:text-anakiwa-500" />
),
telegram: (
<TelegramIcon size={22} className="duration-200 hover:text-anakiwa-500" />
),
discord: (
<Icons.discord size={20} className="duration-200 hover:text-anakiwa-500" />
),
}
Loading

0 comments on commit df3c767

Please sign in to comment.