parent
e2fb99853c
commit
26bfc9c7e6
6 changed files with 342 additions and 97 deletions
@ -0,0 +1,77 @@ |
|||||||
|
import { ArrowDownWideNarrow, Check, ChevronDown } from 'lucide-react'; |
||||||
|
import { useRef, useState } from 'react'; |
||||||
|
import { useOutsideClick } from '../../hooks/use-outside-click'; |
||||||
|
import type { SortByValues } from './DiscoverRoadmaps'; |
||||||
|
|
||||||
|
const sortingLabels: { label: string; value: SortByValues }[] = [ |
||||||
|
{ |
||||||
|
label: 'Newest', |
||||||
|
value: 'createdAt', |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: 'Oldest', |
||||||
|
value: '-createdAt', |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: 'Highest Rated', |
||||||
|
value: 'rating', |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: 'Lowest Rated', |
||||||
|
value: '-rating', |
||||||
|
}, |
||||||
|
]; |
||||||
|
|
||||||
|
type DiscoverRoadmapSortingProps = { |
||||||
|
sortBy: SortByValues; |
||||||
|
onSortChange: (sortBy: SortByValues) => void; |
||||||
|
}; |
||||||
|
|
||||||
|
export function DiscoverRoadmapSorting(props: DiscoverRoadmapSortingProps) { |
||||||
|
const { sortBy, onSortChange } = props; |
||||||
|
|
||||||
|
const [isOpen, setIsOpen] = useState(false); |
||||||
|
const dropdownRef = useRef(null); |
||||||
|
|
||||||
|
const selectedValue = sortingLabels.find((item) => item.value === sortBy); |
||||||
|
|
||||||
|
useOutsideClick(dropdownRef, () => { |
||||||
|
setIsOpen(false); |
||||||
|
}); |
||||||
|
|
||||||
|
return ( |
||||||
|
<div |
||||||
|
className="min-auto relative flex flex-shrink-0 sm:min-w-[140px]" |
||||||
|
ref={dropdownRef} |
||||||
|
> |
||||||
|
<button |
||||||
|
className="py-15 flex w-full items-center justify-between gap-2 rounded-md border px-2 text-sm" |
||||||
|
onClick={() => setIsOpen(!isOpen)} |
||||||
|
> |
||||||
|
<span>{selectedValue?.label}</span> |
||||||
|
|
||||||
|
<span> |
||||||
|
<ChevronDown className="ml-4 h-3.5 w-3.5" /> |
||||||
|
</span> |
||||||
|
</button> |
||||||
|
|
||||||
|
{isOpen && ( |
||||||
|
<div className="absolute right-0 top-10 z-10 min-w-40 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg"> |
||||||
|
{sortingLabels.map((item) => ( |
||||||
|
<button |
||||||
|
key={item.value} |
||||||
|
className="flex w-full items-center gap-2 px-4 py-2 text-sm hover:bg-gray-100" |
||||||
|
onClick={() => { |
||||||
|
onSortChange(item.value); |
||||||
|
setIsOpen(false); |
||||||
|
}} |
||||||
|
> |
||||||
|
<span>{item.label}</span> |
||||||
|
{item.value === sortBy && <Check className="ml-auto h-4 w-4" />} |
||||||
|
</button> |
||||||
|
))} |
||||||
|
</div> |
||||||
|
)} |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
@ -1,27 +1,8 @@ |
|||||||
--- |
--- |
||||||
import { roadmapApi } from '../api/roadmap'; |
|
||||||
import BaseLayout from '../layouts/BaseLayout.astro'; |
import BaseLayout from '../layouts/BaseLayout.astro'; |
||||||
import { DiscoverRoadmaps } from '../components/DiscoverRoadmaps/DiscoverRoadmaps'; |
import { DiscoverRoadmaps } from '../components/DiscoverRoadmaps/DiscoverRoadmaps'; |
||||||
import { DiscoverError } from '../components/DiscoverRoadmaps/DiscoverError'; |
|
||||||
|
|
||||||
export const prerender = false; |
|
||||||
|
|
||||||
const roadmapApiClient = roadmapApi(Astro); |
|
||||||
|
|
||||||
const { error, response: roadmaps } = |
|
||||||
await roadmapApiClient.listShowcaseRoadmap(); |
|
||||||
const searchParams = Astro.url.searchParams.toString(); |
|
||||||
--- |
--- |
||||||
|
|
||||||
<BaseLayout title='Discover Custom Roadmaps'> |
<BaseLayout title='Discover Custom Roadmaps'> |
||||||
{error && <DiscoverError message={error.message} />} |
<DiscoverRoadmaps client:load /> |
||||||
{ |
|
||||||
roadmaps && ( |
|
||||||
<DiscoverRoadmaps |
|
||||||
roadmapsResponse={roadmaps} |
|
||||||
searchParams={searchParams} |
|
||||||
client:load |
|
||||||
/> |
|
||||||
) |
|
||||||
} |
|
||||||
</BaseLayout> |
</BaseLayout> |
||||||
|
Loading…
Reference in new issue