11/* eslint-disable max-lines-per-function */
22import React , { FC , useState , useEffect } from 'react'
3- import { Typography , Form , Select , SelectProps , Input } from 'antd'
3+ import { Form , Select , SelectProps , Input } from 'antd'
44import type { CustomTagProps } from 'rc-select/lib/BaseSelect'
55import { useLocation , useSearchParams } from 'react-router-dom'
66import { getKinds } from 'api/bff/search/getKinds'
77import { getSortedKinds } from 'utils/getSortedKinds'
88import { TKindIndex } from 'localTypes/bff/search'
99import { TKindWithVersion } from 'localTypes/search'
1010import { filterSelectOptions } from 'utils/filterSelectOptions'
11- import { useDebouncedCallback , getArrayParam , setArrayParam } from './utils'
11+ import { useDebouncedCallback , getArrayParam , setArrayParam , getStringParam , setStringParam } from './utils'
1212import { Styled } from './styled'
1313
1414type TSearchProps = {
@@ -23,8 +23,12 @@ export const Search: FC<TSearchProps> = ({ cluster }) => {
2323 const FIELD_NAME = 'kinds'
2424 const FIELD_NAME_STRING = 'name'
2525 const FIELD_NAME_MULTIPLE = 'labels'
26+
2627 const TYPE_SELECTOR = 'TYPE_SELECTOR'
28+
2729 const QUERY_KEY = 'kinds' // the query param name
30+ const NAME_QUERY_KEY = 'name'
31+ const LABELS_QUERY_KEY = 'labels'
2832
2933 const watchedKinds = Form . useWatch < string [ ] | undefined > ( FIELD_NAME , form )
3034 const watchedName = Form . useWatch < string | undefined > ( FIELD_NAME_STRING , form )
@@ -46,14 +50,40 @@ export const Search: FC<TSearchProps> = ({ cluster }) => {
4650
4751 // Apply current values from search params on mount / when URL changes
4852 useEffect ( ( ) => {
49- const fromUrl = getArrayParam ( searchParams , QUERY_KEY )
50- const current = form . getFieldValue ( FIELD_NAME )
53+ const fromKinds = getArrayParam ( searchParams , QUERY_KEY )
54+ const currentKinds = form . getFieldValue ( FIELD_NAME )
55+ const kindsDiffer =
56+ ( fromKinds . length || 0 ) !== ( currentKinds ?. length || 0 ) || fromKinds . some ( ( v , i ) => v !== currentKinds ?. [ i ] )
5157
52- // Only update the form if URL differs from form (prevents loops)
53- const differ = ( fromUrl . length || 0 ) !== ( current ?. length || 0 ) || fromUrl . some ( ( v , i ) => v !== current ?. [ i ] )
58+ // name
59+ const fromName = getStringParam ( searchParams , NAME_QUERY_KEY )
60+ const currentName = form . getFieldValue ( FIELD_NAME_STRING ) as string | undefined
61+ const nameDiffer = ( fromName || '' ) !== ( currentName || '' )
62+
63+ // labels
64+ const fromLabels = getArrayParam ( searchParams , LABELS_QUERY_KEY )
65+ const currentLabels = form . getFieldValue ( FIELD_NAME_MULTIPLE ) as string [ ] | undefined
66+ const labelsDiffer =
67+ ( fromLabels . length || 0 ) !== ( currentLabels ?. length || 0 ) || fromLabels . some ( ( v , i ) => v !== currentLabels ?. [ i ] )
68+
69+ // decide type from params
70+ const currentType = form . getFieldValue ( TYPE_SELECTOR )
71+ let inferredType : string | undefined
72+ if ( fromName ) {
73+ inferredType = 'name'
74+ } else if ( fromLabels . length > 0 ) {
75+ inferredType = 'labels'
76+ }
77+ const typeDiffer = inferredType !== currentType
5478
55- if ( differ ) {
56- form . setFieldsValue ( { [ FIELD_NAME ] : fromUrl } )
79+ // Only update the form if URL differs from form (prevents loops)
80+ if ( kindsDiffer || nameDiffer || labelsDiffer ) {
81+ form . setFieldsValue ( {
82+ [ FIELD_NAME ] : kindsDiffer ? fromKinds : currentKinds ,
83+ [ FIELD_NAME_STRING ] : nameDiffer ? fromName : currentName ,
84+ [ FIELD_NAME_MULTIPLE ] : labelsDiffer ? fromLabels : currentLabels ,
85+ [ TYPE_SELECTOR ] : typeDiffer ? inferredType : currentType ,
86+ } )
5787 }
5888 // eslint-disable-next-line react-hooks/exhaustive-deps
5989 } , [ location . search ] ) // react to back/forward, external URL edits
@@ -64,13 +94,49 @@ export const Search: FC<TSearchProps> = ({ cluster }) => {
6494 setSearchParams ( next , { replace : true } ) // replace to keep history cleaner
6595 } , 250 )
6696
97+ const debouncedPushName = useDebouncedCallback ( ( value : string ) => {
98+ const next = setStringParam ( searchParams , NAME_QUERY_KEY , value )
99+ setSearchParams ( next , { replace : true } )
100+ } , 250 )
101+
102+ const debouncedPushLabels = useDebouncedCallback ( ( values : string [ ] ) => {
103+ const next = setArrayParam ( searchParams , LABELS_QUERY_KEY , values )
104+ setSearchParams ( next , { replace : true } )
105+ } , 250 )
106+
67107 useEffect ( ( ) => {
68108 debouncedPush ( watchedKinds || [ ] )
69109 // eslint-disable-next-line react-hooks/exhaustive-deps
70110 } , [ watchedKinds ] )
71111
72- // eslint-disable-next-line no-console
73- console . log ( kindWithVersion )
112+ useEffect ( ( ) => {
113+ debouncedPushName ( ( watchedName || '' ) . trim ( ) )
114+ // eslint-disable-next-line react-hooks/exhaustive-deps
115+ } , [ watchedName ] )
116+
117+ useEffect ( ( ) => {
118+ debouncedPushLabels ( watchedMultiple || [ ] )
119+ // eslint-disable-next-line react-hooks/exhaustive-deps
120+ } , [ watchedMultiple ] )
121+
122+ useEffect ( ( ) => {
123+ if ( watchedTypedSelector === 'name' ) {
124+ // Clear labels when switching to "name"
125+ const cur = form . getFieldValue ( FIELD_NAME_MULTIPLE ) as string [ ] | undefined
126+ if ( cur ?. length ) {
127+ form . setFieldsValue ( { [ FIELD_NAME_MULTIPLE ] : [ ] } )
128+ }
129+ } else if ( watchedTypedSelector === 'labels' ) {
130+ // Clear name when switching to "labels"
131+ const cur = ( form . getFieldValue ( FIELD_NAME_STRING ) as string | undefined ) ?? ''
132+ if ( cur ) {
133+ form . setFieldsValue ( { [ FIELD_NAME_STRING ] : '' } )
134+ }
135+ }
136+ // Optional: if undefined (e.g., initial), choose a default behavior:
137+ // else { form.setFieldsValue({ [FIELD_NAME_STRING]: '', [FIELD_NAME_MULTIPLE]: [] }) }
138+ // eslint-disable-next-line react-hooks/exhaustive-deps
139+ } , [ watchedTypedSelector ] )
74140
75141 const options : SelectProps [ 'options' ] =
76142 kindWithVersion ?. map ( ( { kind, notUnique, group, version } ) => ( {
@@ -101,7 +167,7 @@ export const Search: FC<TSearchProps> = ({ cluster }) => {
101167 )
102168
103169 return (
104- < Styled . CatContainer >
170+ < div >
105171 < Form form = { form } layout = "vertical" >
106172 < Styled . FormContainer >
107173 < Form . Item name = { FIELD_NAME } label = "Kinds" >
@@ -113,6 +179,7 @@ export const Search: FC<TSearchProps> = ({ cluster }) => {
113179 allowClear
114180 showSearch
115181 tagRender = { tagRender }
182+ maxTagCount = "responsive"
116183 />
117184 </ Form . Item >
118185 < Form . Item name = { TYPE_SELECTOR } label = "Type" >
@@ -163,13 +230,12 @@ export const Search: FC<TSearchProps> = ({ cluster }) => {
163230 />
164231 </ Form . Item >
165232 </ Styled . HideableContainer >
166- { /* Example of "watching" the value for display or side-effects */ }
167- < div > Current: { ( watchedKinds || [ ] ) . join ( ', ' ) } </ div >
168- < div > Current name: { watchedName } </ div >
169- < div > Current labels: { ( watchedMultiple || [ ] ) . join ( ', ' ) } </ div >
170233 </ Styled . FormContainer >
171234 </ Form >
172- < Typography . Title > To Be Done</ Typography . Title >
173- </ Styled . CatContainer >
235+ { /* Example of "watching" the value for display or side-effects */ }
236+ < div > Current: { ( watchedKinds || [ ] ) . join ( ', ' ) } </ div >
237+ < div > Current name: { watchedName } </ div >
238+ < div > Current labels: { ( watchedMultiple || [ ] ) . join ( ', ' ) } </ div >
239+ </ div >
174240 )
175241}
0 commit comments