1
- import React , { useMemo } from "react" ;
2
- import styled from "styled-components" ;
3
-
1
+ import React , { useState , useMemo } from "react" ;
2
+ import styled , { css } from "styled-components" ;
4
3
import { useNavigate } from "react-router-dom" ;
5
-
6
- import { DropdownCascader } from "@kleros/ui-components-library" ;
7
-
4
+ import { Card , DropdownCascader , Searchbar } from "@kleros/ui-components-library" ;
8
5
import { isUndefined } from "utils/index" ;
9
-
10
6
import { useCourtTree , rootCourtToItems } from "queries/useCourtTree" ;
11
-
12
7
import { responsiveSize } from "styles/responsiveSize" ;
13
-
8
+ import { landscapeStyle } from "styles/landscapeStyle" ;
14
9
import { StyledSkeleton } from "components/StyledSkeleton" ;
15
-
16
10
import StakeMaintenanceButtons from "./StakeMaintenanceButton" ;
17
11
import { isKlerosUniversity } from "src/consts" ;
18
12
@@ -21,6 +15,8 @@ const Container = styled.div`
21
15
display: flex;
22
16
justify-content: space-between;
23
17
align-items: center;
18
+ gap: 8px 16px;
19
+ flex-wrap: wrap;
24
20
` ;
25
21
26
22
const StyledDropdownCascader = styled ( DropdownCascader ) `
@@ -30,19 +26,98 @@ const StyledDropdownCascader = styled(DropdownCascader)`
30
26
}
31
27
` ;
32
28
29
+ const SearchBarContainer = styled . div `
30
+ display: flex;
31
+ flex-wrap: wrap;
32
+ position: relative;
33
+ ${ landscapeStyle (
34
+ ( ) => css `
35
+ flex: 1;
36
+ `
37
+ ) }
38
+ ` ;
39
+
40
+ const StyledSearchbar = styled ( Searchbar ) `
41
+ width: 100%;
42
+ input {
43
+ font-size: 16px;
44
+ height: 45px;
45
+ padding-top: 0px;
46
+ padding-bottom: 0px;
47
+ }
48
+ ` ;
49
+
50
+ const SearchResultsContainer = styled . div `
51
+ position: absolute;
52
+ margin-top: 45px;
53
+ max-height: 400px;
54
+ width: 100%;
55
+ flex-direction: column;
56
+ border-radius: 4px;
57
+ overflow-y: auto;
58
+ z-index: 1;
59
+ background-color: ${ ( { theme } ) => theme . whiteBackground } ;
60
+ ` ;
61
+
62
+ const StyledCard = styled ( Card ) `
63
+ height: auto;
64
+ width: 100%;
65
+ padding: 16px;
66
+ color: ${ ( { theme } ) => theme . primaryText } ;
67
+ cursor: pointer;
68
+ ` ;
69
+
70
+ function flattenCourts ( court ) {
71
+ return court ? [ court , ...( court . children || [ ] ) . flatMap ( flattenCourts ) ] : [ ] ;
72
+ }
73
+
33
74
const TopSearch : React . FC = ( ) => {
34
75
const { data } = useCourtTree ( ) ;
35
76
const navigate = useNavigate ( ) ;
36
77
const items = useMemo ( ( ) => ! isUndefined ( data ) && [ rootCourtToItems ( data . court ) ] , [ data ] ) ;
37
78
const isUniversity = isKlerosUniversity ( ) ;
79
+ const [ search , setSearch ] = useState ( "" ) ;
80
+ const filteredCourts = useMemo (
81
+ ( ) =>
82
+ data ?. court ? flattenCourts ( data . court ) . filter ( ( c ) => c . name . toLowerCase ( ) . includes ( search . toLowerCase ( ) ) ) : [ ] ,
83
+ [ data , search ]
84
+ ) ;
85
+
38
86
return (
39
87
< Container >
40
88
{ items ? (
41
- < StyledDropdownCascader
42
- items = { items }
43
- onSelect = { ( path : string | number ) => navigate ( path . toString ( ) ) }
44
- placeholder = "Select Court"
45
- />
89
+ < >
90
+ < StyledDropdownCascader
91
+ items = { items }
92
+ onSelect = { ( path ) => navigate ( path . toString ( ) ) }
93
+ placeholder = "Select Court"
94
+ />
95
+ < SearchBarContainer >
96
+ < StyledSearchbar
97
+ dir = "auto"
98
+ type = "text"
99
+ placeholder = "Search"
100
+ value = { search }
101
+ onChange = { ( e ) => setSearch ( e . target . value ) }
102
+ />
103
+ { search && filteredCourts . length > 0 && (
104
+ < SearchResultsContainer >
105
+ { filteredCourts . map ( ( court ) => (
106
+ < StyledCard
107
+ hover
108
+ key = { court . id }
109
+ onClick = { ( ) => {
110
+ navigate ( `/courts/${ court . id } ` ) ;
111
+ setSearch ( "" ) ;
112
+ } }
113
+ >
114
+ { court . name }
115
+ </ StyledCard >
116
+ ) ) }
117
+ </ SearchResultsContainer >
118
+ ) }
119
+ </ SearchBarContainer >
120
+ </ >
46
121
) : (
47
122
< StyledSkeleton width = { 240 } height = { 42 } />
48
123
) }
0 commit comments