11'use client'
22
3- import React from 'react'
3+ import React , { useMemo } from 'react'
44import { GuideItem } from './GuideItem'
55import { cn } from '@/lib/utils'
66import useParams from '@/hooks/useParams'
77import type { Guide } from '@/content'
8+ import {
9+ Select ,
10+ SelectContent ,
11+ SelectItem ,
12+ SelectTrigger ,
13+ SelectValue ,
14+ } from '../ui/select'
815
916interface Props {
1017 className ?: string
1118 allGuides : Guide [ ]
1219}
1320
1421const GuideList : React . FC < Props > = ( { className, allGuides } ) => {
15- const { searchParams } = useParams ( )
22+ const { searchParams, setParams } = useParams ( )
23+ const sortBy = searchParams ?. get ( 'sort' ) || 'published_date'
1624 const selectedTags = searchParams ?. get ( 'tags' ) ?. split ( ',' ) || [ ]
1725 const selectedLangs = searchParams ?. get ( 'langs' ) ?. split ( ',' ) || [ ]
1826
19- const filteredGuides = allGuides
20- . filter ( ( guide ) => {
21- let include = true
27+ const filteredGuides = useMemo ( ( ) => {
28+ return allGuides
29+ . filter ( ( guide ) => {
30+ let include = true
2231
23- if ( selectedLangs . length ) {
24- include = selectedLangs . some ( ( lang ) => guide . languages ?. includes ( lang ) )
25- }
32+ if ( selectedLangs . length ) {
33+ include = selectedLangs . some ( ( lang ) =>
34+ guide . languages ?. includes ( lang ) ,
35+ )
36+ }
2637
27- if ( ! selectedTags . length ) return include
38+ if ( ! selectedTags . length ) return include
2839
29- return include && selectedTags . some ( ( tag ) => guide . tags ?. includes ( tag ) )
30- } )
31- . sort ( ( a , b ) => a . title . localeCompare ( b . title ) )
40+ return include && selectedTags . some ( ( tag ) => guide . tags ?. includes ( tag ) )
41+ } )
42+ . sort ( ( a , b ) => {
43+ if ( sortBy === 'published_date' ) {
44+ const dateDiff =
45+ new Date ( b . published_at ) . getTime ( ) -
46+ new Date ( a . published_at ) . getTime ( )
47+
48+ return dateDiff !== 0 ? dateDiff : a . title . localeCompare ( b . title )
49+ } else if ( sortBy === 'last_updated' ) {
50+ const dateDiff =
51+ new Date ( b . updated_at || b . published_at ) . getTime ( ) -
52+ new Date ( a . updated_at || a . published_at ) . getTime ( )
53+
54+ return dateDiff !== 0 ? dateDiff : a . title . localeCompare ( b . title )
55+ }
56+
57+ return sortBy === 'alpha-reverse'
58+ ? b . title . localeCompare ( a . title )
59+ : a . title . localeCompare ( b . title )
60+ } )
61+ } , [ allGuides , selectedTags , selectedLangs , sortBy ] )
3262
3363 return filteredGuides . length === 0 ? (
3464 < div className = { className } >
@@ -37,13 +67,37 @@ const GuideList: React.FC<Props> = ({ className, allGuides }) => {
3767 </ p >
3868 </ div >
3969 ) : (
40- < ul className = { cn ( 'space-y-4' , className ) } >
41- { filteredGuides . map ( ( guide ) => (
42- < li key = { guide . slug } >
43- < GuideItem guide = { guide } />
44- </ li >
45- ) ) }
46- </ ul >
70+ < div className = { cn ( 'flex flex-col gap-4' , className ) } >
71+ < Select
72+ value = { sortBy }
73+ onValueChange = { ( val ) => {
74+ // This is necessary to fix a ui update delay causing 200ms lag
75+ setTimeout ( ( ) => setParams ( 'sort' , val ) , 0 )
76+ } }
77+ >
78+ < SelectTrigger
79+ aria-label = "Sort options"
80+ className = "ml-auto max-w-52 bg-white/5 text-xs font-medium ring-1 ring-inset ring-zinc-300/10 hover:bg-white/7.5 dark:bg-white/2.5 dark:text-zinc-400 dark:hover:bg-white/5 md:flex"
81+ >
82+ < SelectValue />
83+ </ SelectTrigger >
84+ < SelectContent position = "item-aligned" >
85+ < SelectItem value = "published_date" > Sort by Date Published</ SelectItem >
86+ < SelectItem value = "last_updated" > Sort by Last Updated</ SelectItem >
87+ < SelectItem value = "alpha" > Sort Alphabetically (A-Z)</ SelectItem >
88+ < SelectItem value = "alpha-reverse" >
89+ Sort Alphabetically (Z-A)
90+ </ SelectItem >
91+ </ SelectContent >
92+ </ Select >
93+ < ul className = { 'space-y-4' } >
94+ { filteredGuides . map ( ( guide ) => (
95+ < li key = { guide . slug } >
96+ < GuideItem guide = { guide } />
97+ </ li >
98+ ) ) }
99+ </ ul >
100+ </ div >
47101 )
48102}
49103
0 commit comments