@@ -18,6 +18,27 @@ type HomePageProps = {
18
18
} ;
19
19
20
20
const HomePage : React . FunctionComponent < HomePageProps > = ( { topPoliticians } ) => {
21
+ const [ search , setSearch ] = React . useState ( '' ) ;
22
+ const [ searchResults , setSearchResults ] = React . useState ( [ ] ) ;
23
+ const fetchingTimeout = React . useRef ( null ) ;
24
+
25
+ React . useEffect ( ( ) => {
26
+ if ( fetchingTimeout . current != null ) {
27
+ clearTimeout ( fetchingTimeout . current ) ;
28
+ fetchingTimeout . current = null ;
29
+ }
30
+ fetchingTimeout . current = setTimeout ( ( ) => {
31
+ console . log ( 'fetching...' ) ;
32
+ console . log ( fetchingTimeout ) ;
33
+ fetch ( '/api/politicians?search=' + search )
34
+ . then ( res => res . json ( ) )
35
+ . then ( data => setSearchResults ( data . results ) ) ;
36
+ fetchingTimeout . current = null ;
37
+ } , 100 ) ;
38
+ } , [ search ] ) ;
39
+
40
+ const displayedResults = search ? searchResults : topPoliticians ;
41
+
21
42
return (
22
43
< div className = 'flex flex-col items-center bg-gray-200 min-h-screen' >
23
44
< Head >
@@ -32,17 +53,22 @@ const HomePage: React.FunctionComponent<HomePageProps> = ({ topPoliticians }) =>
32
53
< span > * Ratings are technically calculated using Trueskill, not ELO</ span >
33
54
< span > ** Ratings are purely for entertainment purposes</ span >
34
55
</ div >
56
+ < input
57
+ className = 'rounded-lg text-2xl font-big-noodle w-5/6 px-5 py-3'
58
+ placeholder = 'Search...' value = { search }
59
+ onChange = { e => setSearch ( e . target . value ) }
60
+ />
35
61
< div className = 'rounded-lg bg-gray-100 font-big-noodle w-5/6 my-5' >
36
62
< ul >
37
63
{
38
- topPoliticians . map ( ( politician , idx ) => (
64
+ displayedResults . map ( ( politician , idx ) => (
39
65
< Link key = { idx } href = { `/politician/${ politician . name } ` } >
40
66
< a >
41
67
< li className = 'flex flex-row items-center rounded-lg hover:bg-gray-300 cursor-pointer text-2xl p-3' >
42
68
{ idx + 1 } .
43
69
< Rating rating = { politician . rating . mu } />
44
70
< div className = 'w-3 h-3 mx-2' style = {
45
- { backgroundColor : partyToColor ( politician . latestContest . candidates . find ( candidate => candidate . name . includes ( politician . name ) ) . party || 'None' ) }
71
+ { backgroundColor : partyToColor ( politician . latestContest . candidates . find ( candidate => candidate . name . includes ( politician . name ) ) . party ) }
46
72
} />
47
73
{ politician . name }
48
74
</ li >
@@ -62,9 +88,7 @@ export async function getServerSideProps() {
62
88
const collection = await db . collection ( 'politicians' ) ;
63
89
const topPoliticians = await collection
64
90
. aggregate ( [
65
- { $match : { } } ,
66
91
{ $sort : { 'rating.mu' : - 1 } } ,
67
- { $limit : 100 } ,
68
92
{ $project : { 'name' : 1 , 'rating' : 1 , 'latestContest' : { $arrayElemAt : [ '$contests' , - 1 ] } } } ,
69
93
{
70
94
$lookup : {
@@ -75,7 +99,27 @@ export async function getServerSideProps() {
75
99
}
76
100
} ,
77
101
{ $project : { 'name' : 1 , 'rating' : 1 , 'latestContest' : { $arrayElemAt : [ '$latestContest' , 0 ] } } } ,
78
- { $project : { '_id' : 0 , 'latestContest' : { '_id' : 0 } } }
102
+ { $project : { '_id' : 0 , 'latestContest' : { '_id' : 0 } } } ,
103
+ {
104
+ $group : {
105
+ '_id' : null ,
106
+ 'politician' : {
107
+ $push : {
108
+ 'name' : '$name' ,
109
+ 'latestContest' : '$latestContest' ,
110
+ 'rating' : '$rating'
111
+ }
112
+ }
113
+ }
114
+ } ,
115
+ {
116
+ $unwind : {
117
+ path : '$politician' ,
118
+ includeArrayIndex : 'ranking'
119
+ }
120
+ } ,
121
+ { $project : { name : '$politician.name' , latestContest : '$politician.latestContest' , rating : '$politician.rating' , ranking : 1 , _id : 0 } } ,
122
+ { $limit : 100 }
79
123
] )
80
124
. toArray ( ) ;
81
125
0 commit comments