feat: sort select in mii list

This commit is contained in:
trafficlunar 2025-04-10 11:38:39 +01:00
parent cc506f2619
commit b5b431028a
2 changed files with 65 additions and 18 deletions

View file

@ -6,6 +6,7 @@ import { prisma } from "@/lib/prisma";
import Carousel from "./carousel"; import Carousel from "./carousel";
import LikeButton from "./like-button"; import LikeButton from "./like-button";
import SortSelect from "./sort-select";
interface Props { interface Props {
searchParams: Promise<{ [key: string]: string | string[] | undefined }>; searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
@ -18,18 +19,16 @@ export default async function MiiList({ searchParams, userId, where }: Props) {
const session = await auth(); const session = await auth();
const resolvedSearchParams = await searchParams; const resolvedSearchParams = await searchParams;
// sort search param // Sort search param
const orderBy: { createdAt?: Prisma.SortOrder; likes?: Prisma.SortOrder } = {}; // Defaults to newest
const orderBy: Prisma.MiiOrderByWithRelationInput =
resolvedSearchParams.sort === "newest"
? { createdAt: "desc" }
: resolvedSearchParams.sort === "likes"
? { likedBy: { _count: "desc" } }
: { createdAt: "desc" };
if (resolvedSearchParams.sort === "newest") { // Tag search param
orderBy.createdAt = "desc";
} else if (resolvedSearchParams.sort === "likes") {
orderBy.likes = "desc";
} else {
orderBy.createdAt = "desc"; // Default to newest if no valid sort is provided
}
// tag search param
const rawTags = resolvedSearchParams.tags; const rawTags = resolvedSearchParams.tags;
const tagFilter = const tagFilter =
typeof rawTags === "string" typeof rawTags === "string"
@ -115,13 +114,7 @@ export default async function MiiList({ searchParams, userId, where }: Props) {
<span>todo</span> <span>todo</span>
</div> </div>
<div className="pill gap-2"> <SortSelect />
<label htmlFor="sort">Sort:</label>
<select name="sort">
<option value="likes">Likes</option>
<option value="newest">Newest</option>
</select>
</div>
</div> </div>
</div> </div>

View file

@ -0,0 +1,54 @@
"use client";
import { Icon } from "@iconify/react";
import { useSelect } from "downshift";
import { redirect, useSearchParams } from "next/navigation";
type Sort = "likes" | "newest";
const items = ["likes", "newest"];
export default function SortSelect() {
const searchParams = useSearchParams();
const currentSort = (searchParams.get("sort") as Sort) || "newest";
const { isOpen, getToggleButtonProps, getMenuProps, getItemProps, highlightedIndex, selectedItem } = useSelect({
items,
selectedItem: currentSort,
onSelectedItemChange: ({ selectedItem }) => {
if (!selectedItem) return;
redirect(`?sort=${selectedItem}`);
},
});
return (
<div className="relative w-full">
{/* Toggle button to open the dropdown */}
<button type="button" {...getToggleButtonProps()} className="pill input w-full gap-1 !justify-between">
<span>Sort by </span>
{selectedItem || "Select a way to sort"}
<Icon icon="tabler:chevron-down" className="ml-2 size-5" />
</button>
{/* Dropdown menu */}
<ul
{...getMenuProps()}
className={`absolute z-50 w-full bg-orange-200 border-2 border-orange-400 rounded-lg mt-1 shadow-lg max-h-60 overflow-y-auto ${
isOpen ? "block" : "hidden"
}`}
>
{isOpen &&
items.map((item, index) => (
<li
key={item}
{...getItemProps({ item, index })}
className={`px-4 py-1 cursor-pointer text-sm ${highlightedIndex === index ? "bg-black/15" : ""}`}
>
{item}
</li>
))}
</ul>
</div>
);
}