@@ -9,7 +9,8 @@ type ListProps<T> = {
99 filter : ( [ id , value ] : [ string , T ] ) => boolean ,
1010 map : ( [ id , value ] : [ string , T ] ) => JSX . Element ,
1111 sort : ( [ idA , valueA ] : [ string , T ] , [ idB , valueB ] : [ string , T ] ) => number ,
12- pinned : string [ ]
12+ pinned : string [ ] ,
13+ groupBy ?: keyof T
1314}
1415
1516// A higher order list component of type T where T is the type of the JSON representation of a list value
@@ -21,8 +22,8 @@ type ListProps<T> = {
2122// Pinned items (given as a string[] of IDs) are displayed in a separate category above other results.
2223export default function List < T > ( props : ListProps < T > ) {
2324 // Filter and map are different for each list, so pass them in as props
24- const { data, filter, map, sort, pinned : pinnedIds } = props ;
25- const [ { pinned, unpinned} , setContent ] = useState ( parseContent ( ) ) ;
25+ const { data, filter, map, sort, pinned : pinnedIds , groupBy } = props ;
26+ const [ { pinned, unpinned, grouped } , setContent ] = useState ( parseContent ( ) ) ;
2627
2728 // Maps content to JSX components, sorting, filtering, and splitting by pinned and unpinned.
2829 function parseContent ( ) {
@@ -36,9 +37,20 @@ export default function List<T>(props: ListProps<T>) {
3637 const pinnedContent = parsed . filter ( ( [ id , value ] ) => pinnedIds . includes ( id ) ) ;
3738 const unpinnedContent = parsed . filter ( ( [ id , value ] ) => ! pinnedIds . includes ( id ) ) ;
3839
40+ const groupedContent = groupBy ? unpinnedContent . reduce ( ( clubs , [ id , club ] ) => {
41+ const group = club [ groupBy ] as string ;
42+ if ( ! clubs [ group ] ) clubs [ group ] = [ ] ;
43+ clubs [ group ] . push ( [ id , club ] ) ;
44+ return clubs ;
45+ } , { } as Record < string , [ string , T ] [ ] > ) : { } ;
46+
3947 return {
4048 pinned : pinnedContent . filter ( filter ) . map ( map ) ,
41- unpinned : unpinnedContent . filter ( filter ) . map ( map )
49+ unpinned : unpinnedContent . filter ( filter ) . map ( map ) ,
50+ grouped : Object . entries ( groupedContent ) . map ( ( [ group , clubs ] ) => [
51+ group ,
52+ clubs . filter ( filter ) . map ( map )
53+ ] )
4254 } ;
4355 }
4456
@@ -57,10 +69,22 @@ export default function List<T>(props: ListProps<T>) {
5769 </ MaterialList >
5870 ) }
5971 { unpinned . length > 0 && pinned . length > 0 && < hr /> }
60- { unpinned . length > 0 && (
61- < MaterialList >
62- { unpinned }
63- </ MaterialList >
72+ { groupBy ? grouped . map ( ( [ group , clubs ] ) => (
73+ clubs . length > 0 && (
74+ < >
75+ < p className = "mt-2 pl-2 text-secondary text-2xl font-bold" > { group } </ p >
76+ < hr className = "mx-2 mt-2 mb-0" />
77+ < MaterialList >
78+ { clubs }
79+ </ MaterialList >
80+ </ >
81+ )
82+ ) ) : (
83+ unpinned . length > 0 && (
84+ < MaterialList >
85+ { unpinned }
86+ </ MaterialList >
87+ )
6488 ) }
6589 </ > ) : (
6690 < NoResults />
0 commit comments