@@ -8,14 +8,9 @@ import {
88 Reset ,
99 Tooltip ,
1010} from "@radix-ui/themes" ;
11- import { atom , useAtom , useAtomValue , useSetAtom } from "jotai" ;
12- import {
13- setSearchLeaderSlotsAtom ,
14- SearchType ,
15- searchTypeAtom ,
16- searchLeaderSlotsAtom ,
17- } from "./atoms" ;
18- import { useMount , useUnmount } from "react-use" ;
11+ import { atom , useAtomValue , useSetAtom } from "jotai" ;
12+ import { setSearchLeaderSlotsAtom , searchLeaderSlotsAtom } from "./atoms" ;
13+ import { useMount } from "react-use" ;
1914import {
2015 currentLeaderSlotAtom ,
2116 leaderSlotsAtom ,
@@ -26,32 +21,45 @@ import { useDebouncedCallback } from "use-debounce";
2621import NextSlotStatus from "../Overview/SlotPerformance/NextSlotStatus" ;
2722import styles from "./search.module.css" ;
2823import { skippedSlotsAtom } from "../../api/atoms" ;
29- import { useState } from "react" ;
24+ import { useCallback , useEffect , useState } from "react" ;
3025import * as Toggle from "@radix-ui/react-toggle" ;
26+ import { SearchTypeEnum } from "../../routes/leaderSchedule" ;
27+ import {
28+ useSearchTextSearchParam ,
29+ useSearchTypeSearchParam ,
30+ } from "./useSearchParams" ;
3131
3232const isVisibleAtom = atom ( ( get ) => ! ! get ( currentLeaderSlotAtom ) ) ;
3333
3434export default function Search ( ) {
3535 const isVisible = useAtomValue ( isVisibleAtom ) ;
3636 const setSearch = useSetAtom ( setSearchLeaderSlotsAtom ) ;
37- const [ localSearch , setLocalSearch ] = useState ( "" ) ;
3837
39- const setSearchType = useSetAtom ( searchTypeAtom ) ;
4038 const setSlotOverride = useSetAtom ( slotOverrideAtom ) ;
4139
40+ const { searchType } = useSearchTypeSearchParam ( ) ;
41+ const { searchText, setSearchText } = useSearchTextSearchParam ( ) ;
42+ const [ localValue , setLocalValue ] = useState ( searchText ) ;
43+
4244 const debouncedSetSearch = useDebouncedCallback ( ( value : string ) => {
4345 setSearch ( value ) ;
44- } , 1000 ) ;
46+ setSearchText ( value ) ;
47+ } , 1_000 ) ;
48+
49+ if ( ! debouncedSetSearch . isPending ( ) && localValue !== searchText ) {
50+ setLocalValue ( searchText ) ;
51+ }
4552
4653 const reset = ( ) => {
47- setLocalSearch ( "" ) ;
54+ setSearchText ( "" ) ;
4855 setSlotOverride ( undefined ) ;
4956 setSearch ( "" ) ;
5057 } ;
5158
52- useMount ( reset ) ;
53- useUnmount ( ( ) => {
54- setSearchType ( SearchType . Text ) ;
59+ useMount ( ( ) => {
60+ if ( searchType === SearchTypeEnum . text ) {
61+ setSearch ( searchText ) ;
62+ }
5563 } ) ;
5664
5765 if ( ! isVisible ) return ;
@@ -64,11 +72,10 @@ export default function Search() {
6472 variant = "soft"
6573 color = "gray"
6674 onChange = { ( e ) => {
67- setSearchType ( SearchType . Text ) ;
68- setLocalSearch ( e . currentTarget . value ) ;
75+ setLocalValue ( e . currentTarget . value ) ;
6976 debouncedSetSearch ( e . currentTarget . value ) ;
7077 } }
71- value = { localSearch }
78+ value = { localValue }
7279 >
7380 < TextField . Slot >
7481 < MagnifyingGlassIcon
@@ -77,7 +84,7 @@ export default function Search() {
7784 style = { { color : "#AFB2C2" } }
7885 />
7986 </ TextField . Slot >
80- { localSearch && (
87+ { localValue && (
8188 < TextField . Slot >
8289 < IconButton size = "1" variant = "ghost" >
8390 < Cross1Icon
@@ -107,16 +114,6 @@ function SkipRate() {
107114 let value = "-" ;
108115
109116 if ( skipRate !== undefined ) {
110- // if (skipRate.slots_processed)
111- // if (skipRate.slots_processed === 0 || skipRate.slots_skipped === 0) {
112- // value = "0";
113- // } else {
114- // const skipRatePct = skipRate.slots_skipped / skipRate.slots_processed;
115- // value = (skipRatePct * 100).toLocaleString(undefined, {
116- // minimumFractionDigits: 0,
117- // maximumFractionDigits: 2,
118- // });
119- // }
120117 value = ( skipRate . skip_rate * 100 ) . toLocaleString ( undefined , {
121118 minimumFractionDigits : 0 ,
122119 maximumFractionDigits : 2 ,
@@ -140,29 +137,41 @@ interface MySlotsProps {
140137}
141138
142139function MySlots ( { resetSearchText } : MySlotsProps ) {
143- const slots = useAtomValue ( leaderSlotsAtom ) ;
140+ const leaderSlots = useAtomValue ( leaderSlotsAtom ) ;
144141 const setSearch = useSetAtom ( searchLeaderSlotsAtom ) ;
145142 const setSlotOverride = useSetAtom ( slotOverrideAtom ) ;
146143
147- const [ searchType , setSearchType ] = useAtom ( searchTypeAtom ) ;
144+ const { searchType, setSearchType } = useSearchTypeSearchParam ( ) ;
145+
146+ const slotCount = ( leaderSlots ?. length ?? 0 ) * 4 ;
148147
149- const slotCount = ( slots ?. length ?? 0 ) * 4 ;
148+ const setMySlots = useCallback ( ( ) => {
149+ setSearch ( leaderSlots ) ;
150+ } , [ setSearch , leaderSlots ] ) ;
151+
152+ useEffect ( ( ) => {
153+ if ( searchType === SearchTypeEnum . mySlots ) {
154+ setSearch ( leaderSlots ) ;
155+ }
156+ // On mount / data load
157+ // eslint-disable-next-line react-hooks/exhaustive-deps
158+ } , [ leaderSlots , setSearch ] ) ;
150159
151160 const handleClick = ( ) => {
152161 resetSearchText ( ) ;
153162
154163 setSlotOverride ( undefined ) ;
155164
156- if ( searchType === SearchType . MySlots ) {
157- setSearchType ( SearchType . Text ) ;
165+ if ( searchType === SearchTypeEnum . mySlots ) {
166+ setSearchType ( SearchTypeEnum . text ) ;
158167 } else {
159- setSearchType ( SearchType . MySlots ) ;
160- setSearch ( slots ) ;
168+ setSearchType ( SearchTypeEnum . mySlots ) ;
169+ setMySlots ( ) ;
161170 }
162171 } ;
163172
164- const isSelected = searchType === SearchType . MySlots ;
165- const isDisabled = ! slots ?. length ;
173+ const isSelected = searchType === SearchTypeEnum . mySlots ;
174+ const isDisabled = ! leaderSlots ?. length ;
166175
167176 return (
168177 < Tooltip content = "Number of slots this validator is leader in the current epoch. Toggle to filter" >
@@ -193,26 +202,37 @@ function SkippedSlots({ resetSearchText }: SkippedSlotsProps) {
193202 const setSearch = useSetAtom ( searchLeaderSlotsAtom ) ;
194203 const setSlotOverride = useSetAtom ( slotOverrideAtom ) ;
195204
196- const [ searchType , setSearchType ] = useAtom ( searchTypeAtom ) ;
205+ const { searchType, setSearchType } = useSearchTypeSearchParam ( ) ;
197206
198207 const skippedCount = skippedSlots ?. length ?? 0 ;
199208
209+ const setSkippedSlots = useCallback ( ( ) => {
210+ const slotStarts = skippedSlots ?. map ( ( slot ) => slot - ( slot % 4 ) ) ;
211+ setSearch ( [ ...new Set ( slotStarts ) ] ) ;
212+ } , [ setSearch , skippedSlots ] ) ;
213+
214+ useEffect ( ( ) => {
215+ if ( searchType === SearchTypeEnum . skippedSlots ) {
216+ setSkippedSlots ( ) ;
217+ }
218+ // On mount / data load
219+ // eslint-disable-next-line react-hooks/exhaustive-deps
220+ } , [ setSkippedSlots ] ) ;
221+
200222 const handleClick = ( ) => {
201223 resetSearchText ( ) ;
202224
203225 setSlotOverride ( undefined ) ;
204226
205- if ( searchType === SearchType . SkippedSlots ) {
206- setSearchType ( SearchType . Text ) ;
227+ if ( searchType === SearchTypeEnum . skippedSlots ) {
228+ setSearchType ( SearchTypeEnum . text ) ;
207229 } else if ( skippedSlots ?. length ) {
208- setSearchType ( SearchType . SkippedSlots ) ;
209-
210- const slotStarts = skippedSlots ?. map ( ( slot ) => slot - ( slot % 4 ) ) ;
211- setSearch ( [ ...new Set ( slotStarts ) ] ) ;
230+ setSearchType ( SearchTypeEnum . skippedSlots ) ;
231+ setSkippedSlots ( ) ;
212232 }
213233 } ;
214234
215- const isSelected = searchType === SearchType . SkippedSlots ;
235+ const isSelected = searchType === SearchTypeEnum . skippedSlots ;
216236 const isDisabled = ! skippedSlots ?. length ;
217237
218238 return (
@@ -224,7 +244,7 @@ function SkippedSlots({ resetSearchText }: SkippedSlotsProps) {
224244 onClick = { handleClick }
225245 aria-label = "Toggle skipped slots"
226246 pressed = { isSelected }
227- disabled = { isDisabled }
247+ disabled = { ! isSelected && isDisabled }
228248 >
229249 < Text className = { styles . label } > My Skipped Slots</ Text >
230250 < Text > { skippedCount } </ Text >
0 commit comments