77 lines
2.6 KiB
TypeScript
77 lines
2.6 KiB
TypeScript
"use client";
|
||
|
||
type SortOption = "relevance" | "price-asc" | "price-desc" | "brand-asc";
|
||
|
||
export default function SortBar(props: {
|
||
visibleRange: { start: number; end: number };
|
||
totalCount: number;
|
||
|
||
searchQuery: string;
|
||
setSearchQuery: (v: string) => void;
|
||
|
||
sortBy: SortOption;
|
||
setSortBy: (v: SortOption) => void;
|
||
}) {
|
||
const { visibleRange, totalCount, searchQuery, setSearchQuery, sortBy, setSortBy } = props;
|
||
|
||
return (
|
||
<div className="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
|
||
<div className="text-xs text-zinc-500">
|
||
Showing{" "}
|
||
<span className="font-medium text-zinc-200">
|
||
{visibleRange.start}-{visibleRange.end}
|
||
</span>{" "}
|
||
of{" "}
|
||
<span className="font-medium text-zinc-200">
|
||
{totalCount}
|
||
</span>{" "}
|
||
matching parts
|
||
</div>
|
||
|
||
<div className="flex flex-wrap gap-3">
|
||
<div className="flex items-center gap-2">
|
||
<label htmlFor="part-search" className="text-xs text-zinc-500">
|
||
Search
|
||
</label>
|
||
<div className="relative">
|
||
<input
|
||
id="part-search"
|
||
type="text"
|
||
value={searchQuery}
|
||
onChange={(e) => setSearchQuery(e.target.value)}
|
||
placeholder="Search..."
|
||
className="rounded-md border border-zinc-700 bg-zinc-900/70 px-2 py-1 pr-6 text-xs text-zinc-200 focus:outline-none focus:ring-1 focus:ring-amber-400"
|
||
/>
|
||
{searchQuery && (
|
||
<button
|
||
type="button"
|
||
onClick={() => setSearchQuery("")}
|
||
className="absolute right-1 top-1/2 -translate-y-1/2 text-xs leading-none text-zinc-500 hover:text-zinc-300"
|
||
aria-label="Clear search"
|
||
>
|
||
×
|
||
</button>
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2">
|
||
<label htmlFor="sort-by" className="text-xs text-zinc-500">
|
||
Sort
|
||
</label>
|
||
<select
|
||
id="sort-by"
|
||
value={sortBy}
|
||
onChange={(e) => setSortBy(e.target.value as SortOption)}
|
||
className="rounded-md border border-zinc-700 bg-zinc-900/70 px-2 py-1 text-xs text-zinc-200 focus:outline-none focus:ring-1 focus:ring-amber-400"
|
||
>
|
||
<option value="relevance">Relevance</option>
|
||
<option value="price-asc">Price: Low → High</option>
|
||
<option value="price-desc">Price: High → Low</option>
|
||
<option value="brand-asc">Brand: A → Z</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
} |