@@ -9,7 +9,8 @@ type ListProps<T> = {
9
9
filter : ( [ id , value ] : [ string , T ] ) => boolean ,
10
10
map : ( [ id , value ] : [ string , T ] ) => JSX . Element ,
11
11
sort : ( [ idA , valueA ] : [ string , T ] , [ idB , valueB ] : [ string , T ] ) => number ,
12
- pinned : string [ ]
12
+ pinned : string [ ] ,
13
+ groupBy ?: keyof T
13
14
}
14
15
15
16
// 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> = {
21
22
// Pinned items (given as a string[] of IDs) are displayed in a separate category above other results.
22
23
export default function List < T > ( props : ListProps < T > ) {
23
24
// 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 ( ) ) ;
26
27
27
28
// Maps content to JSX components, sorting, filtering, and splitting by pinned and unpinned.
28
29
function parseContent ( ) {
@@ -36,9 +37,20 @@ export default function List<T>(props: ListProps<T>) {
36
37
const pinnedContent = parsed . filter ( ( [ id , value ] ) => pinnedIds . includes ( id ) ) ;
37
38
const unpinnedContent = parsed . filter ( ( [ id , value ] ) => ! pinnedIds . includes ( id ) ) ;
38
39
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
+
39
47
return {
40
48
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
+ ] )
42
54
} ;
43
55
}
44
56
@@ -57,10 +69,22 @@ export default function List<T>(props: ListProps<T>) {
57
69
</ MaterialList >
58
70
) }
59
71
{ 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
+ )
64
88
) }
65
89
</ > ) : (
66
90
< NoResults />
0 commit comments