From e455306b2e0088b5a2871779ceaa6bfbd405e9be Mon Sep 17 00:00:00 2001 From: leoferreiralima Date: Mon, 20 May 2024 16:45:58 -0300 Subject: [PATCH] feat: add project list sort fixes #19 --- app/page.tsx | 11 ++++- components/projects/project-list.tsx | 18 ++++--- components/projects/project-sort.tsx | 74 ++++++++++++++++++++++++++++ components/ui/icons/sort.tsx | 18 +++++++ lib/project.ts | 34 +++++++++++++ 5 files changed, 146 insertions(+), 9 deletions(-) create mode 100644 components/projects/project-sort.tsx create mode 100644 components/ui/icons/sort.tsx create mode 100644 lib/project.ts diff --git a/app/page.tsx b/app/page.tsx index 76cd4ed..1a304d6 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,9 +1,16 @@ import ProjectList from "@/components/projects/project-list"; import SearchBar, { SearchBarPlaceholder } from "@/components/ui/search-bar"; +import { ProjectSorts } from "@/lib/project"; import { Twitter } from "@dub/ui"; import { Suspense } from "react"; -export default function Home() { +export default function Home({ + searchParams, +}: { + searchParams?: { + sort?: ProjectSorts; + }; +}) { return ( <>
@@ -45,7 +52,7 @@ export default function Home() { className="animate-fade-up opacity-0" style={{ animationDelay: "0.35s", animationFillMode: "forwards" }} > - +
); diff --git a/components/projects/project-list.tsx b/components/projects/project-list.tsx index 9dacd18..cfcb3a7 100644 --- a/components/projects/project-list.tsx +++ b/components/projects/project-list.tsx @@ -1,24 +1,24 @@ import prisma from "@/lib/prisma"; import { Suspense } from "react"; import ProjectGrid from "./project-grid"; +import ProjectSort from "./project-sort"; +import { ProjectSorts, sortOrderBy } from "@/lib/project"; -export default function ProjectList() { +export default function ProjectList({ sort }: {sort?: ProjectSorts;}) { return ( - + ); } -async function ProjectListRSC() { +async function ProjectListRSC({ sort }: {sort?: ProjectSorts;}) { const featured = ["gallery", "dub", "ui"]; const projects = await prisma.project.findMany({ where: { verified: true, }, - orderBy: { - stars: "desc", - }, + orderBy: sortOrderBy[sort] ?? sortOrderBy.stars, }); const featuredProjects = featured.map((slug) => @@ -35,7 +35,11 @@ async function ProjectListRSC() {
-

All Projects

+
+

All Projects

+ +
+
diff --git a/components/projects/project-sort.tsx b/components/projects/project-sort.tsx new file mode 100644 index 0000000..79c77f5 --- /dev/null +++ b/components/projects/project-sort.tsx @@ -0,0 +1,74 @@ +"use client"; + +import { IconMenu, Popover, Tick, useRouterStuff } from "@dub/ui"; +import { ChevronDown, SortDesc } from "lucide-react"; +import { useSearchParams } from "next/navigation"; +import { useMemo, useState } from "react"; +import Sort from "@/components/ui/icons/sort"; +import { sortOptions } from "@/lib/project"; + + +export default function ProjectSort() { + const [openPopover, setOpenPopover] = useState(false); + const searchParams = useSearchParams(); + const sort = searchParams?.get("sort"); + const { queryParams } = useRouterStuff(); + + const selectedSort = useMemo(() => { + return sortOptions.find((s) => s.slug === sort) || sortOptions[0]; + }, [sort]); + + return ( + + {sortOptions.map(({ display, slug }) => ( + + ))} + + } + openPopover={openPopover} + setOpenPopover={setOpenPopover} + > + + + ); +} diff --git a/components/ui/icons/sort.tsx b/components/ui/icons/sort.tsx new file mode 100644 index 0000000..3ce4b16 --- /dev/null +++ b/components/ui/icons/sort.tsx @@ -0,0 +1,18 @@ +export default function Sort({ className }: { className: string }) { + return ( + + + + ); +} \ No newline at end of file diff --git a/lib/project.ts b/lib/project.ts new file mode 100644 index 0000000..a6dfb7d --- /dev/null +++ b/lib/project.ts @@ -0,0 +1,34 @@ +import { Project } from "@prisma/client"; + +export const sorts = ["stars", "newest", "alphabetical"] as const; + +export type ProjectSorts = typeof sorts[number]; + +export const sortOptions: { display: string, slug: ProjectSorts }[] = [ + { + display: "Number of Stars", + slug: "stars", + }, + { + display: "Newest", + slug: "newest", + }, + { + display: "A to Z", + slug: "alphabetical", + }, +]; + +export type ProjectOrderBy = Record>>; + +export const sortOrderBy: ProjectOrderBy = { + alphabetical: { + name: "asc" + }, + newest: { + createdAt: "desc" + }, + stars: { + stars: "desc" + } +} \ No newline at end of file