@@ -42,7 +42,9 @@ import { ParamSelector } from "lib/ParamSelector";
4242import { RunnersApiResponse , unknownGoesLast } from "lib/runnerUtils" ;
4343import { useSession } from "next-auth/react" ;
4444import { useRouter } from "next/router" ;
45- import { useMemo , useState } from "react" ;
45+ import { useCallback , useEffect , useMemo , useState } from "react" ;
46+ import debounce from "lodash/debounce" ;
47+ import type { ParsedUrlQuery } from "querystring" ;
4648import useSWR from "swr" ;
4749
4850// Define sort order constants to prevent typos
@@ -71,10 +73,38 @@ export default function RunnersPage() {
7173 const orgParam = typeof org === "string" ? org : null ;
7274
7375 const { data : _session , status : _status } = useSession ( ) ;
74- const [ searchTerm , setSearchTerm ] = useState ( "" ) ;
76+
77+ // Utility function to extract search term from URL query
78+ const getSearchFromQuery = ( query : ParsedUrlQuery ) : string => {
79+ return typeof query . search === "string" ? query . search : "" ;
80+ } ;
81+
82+ // Get search term from URL parameters
83+ const [ searchTerm , setSearchTerm ] = useState ( getSearchFromQuery ( router . query ) ) ;
7584 const [ sortOrder , setSortOrder ] = useState < SortOrder > ( SORT_ALPHABETICAL ) ;
7685 const [ expandedGroup , setExpandedGroup ] = useState < string | null > ( null ) ;
7786
87+ // Sync search state with URL changes
88+ useEffect ( ( ) => {
89+ const searchParam = router . query . search ;
90+ const newSearchTerm = getSearchFromQuery ( { search : searchParam } ) ;
91+ setSearchTerm ( newSearchTerm ) ;
92+ } , [ router . query . search ] ) ;
93+
94+ // Debounced function to update search in URL
95+ const updateSearchInUrl = useCallback (
96+ debounce ( ( newSearchTerm : string ) => {
97+ const query = { ...router . query } ;
98+ if ( newSearchTerm ) {
99+ query . search = newSearchTerm ;
100+ } else {
101+ delete query . search ;
102+ }
103+ router . push ( { pathname : router . pathname , query } , undefined , { shallow : true } ) ;
104+ } , 300 ) ,
105+ [ router ]
106+ ) ;
107+
78108 // Handle URL editing for organization
79109 const handleOrgSubmit = ( newOrg : string ) => {
80110 if ( ! newOrg ) return ;
@@ -192,7 +222,11 @@ export default function RunnersPage() {
192222 variant = "outlined"
193223 placeholder = "Search runners by name, ID, OS, or labels..."
194224 value = { searchTerm }
195- onChange = { ( e ) => setSearchTerm ( e . target . value ) }
225+ onChange = { ( e ) => {
226+ const value = e . target . value ;
227+ setSearchTerm ( value ) ; // Immediate UI update
228+ updateSearchInUrl ( value ) ; // Debounced URL update
229+ } }
196230 sx = { { maxWidth : 600 , mb : 2 } }
197231 />
198232
0 commit comments