1- import React , { useState , useEffect } from 'react' ;
1+ import { useState , useEffect } from 'react' ;
22import { useLocation } from 'react-router-dom' ;
33import TopBar from '../components/shared/TopBar' ;
44import SearchHeader from '../components/shared/SearchHeader' ;
55import SearchForm from '../components/shared/SearchForm' ;
66import AdvancedFiltersDrawer from '../components/shared/AdvancedFiltersDrawer' ;
77import SearchResultsList from '../components/shared/SearchResultsList' ;
8- import ModalDropdown from '../components/shared/ModalDropdown' ;
98import MultiSelectModalDropdown from '../components/shared/MultiSelectModalDropdown/MultiSelectModalDropdown' ;
109import useDropdownSearch from '../hooks/useDropdownSearch' ;
1110import ApiCallInfoBox from '../components/shared/ApiCallInfoBox' ;
@@ -17,10 +16,9 @@ const SearchPageLight = ({ darkMode = true }) => {
1716 const location = useLocation ( ) ;
1817 // Main search/filter state
1918 const [ searchKeyword , setSearchKeyword ] = useState ( "" ) ;
20- const [ author , setAuthor ] = useState ( "" ) ;
21- const [ authorObject , setAuthorObject ] = useState ( null ) ;
22- const [ institution , setInstitution ] = useState ( "" ) ;
23- const [ institutionObject , setInstitutionObject ] = useState ( null ) ;
19+ // Multi-select for authors and institutions
20+ const [ selectedAuthors , setSelectedAuthors ] = useState ( [ ] ) ;
21+ const [ selectedInstitutions , setSelectedInstitutions ] = useState ( [ ] ) ;
2422 // Advanced filters
2523 const [ publicationYear , setPublicationYear ] = useState ( "" ) ;
2624 const [ startYear , setStartYear ] = useState ( "" ) ;
@@ -135,10 +133,8 @@ const SearchPageLight = ({ darkMode = true }) => {
135133 // Function to clear all search fields
136134 const clearAllFields = ( ) => {
137135 setSearchKeyword ( "" ) ;
138- setAuthor ( "" ) ;
139- setAuthorObject ( null ) ;
140- setInstitution ( "" ) ;
141- setInstitutionObject ( null ) ;
136+ setSelectedAuthors ( [ ] ) ;
137+ setSelectedInstitutions ( [ ] ) ;
142138 setPublicationYear ( "" ) ;
143139 setStartYear ( "" ) ;
144140 setEndYear ( "" ) ;
@@ -210,17 +206,13 @@ const SearchPageLight = ({ darkMode = true }) => {
210206 }
211207 } ;
212208
213- // Fetch institution details by ID
209+ // Fetch institution details by ID (for URL param support)
214210 const fetchInstitutionById = async ( institutionId ) => {
215211 try {
216212 const response = await fetch ( `${ OPENALEX_API_BASE } /institutions/I${ institutionId } ` ) ;
217213 if ( response . ok ) {
218214 const institutionData = await response . json ( ) ;
219- setInstitution ( institutionData . display_name ) ;
220- setInstitutionObject ( {
221- id : institutionData . id ,
222- display_name : institutionData . display_name
223- } ) ;
215+ setSelectedInstitutions ( [ { id : institutionData . id , display_name : institutionData . display_name } ] ) ;
224216 }
225217 } catch ( error ) {
226218 console . error ( 'Failed to fetch institution details:' , error ) ;
@@ -239,8 +231,8 @@ const SearchPageLight = ({ darkMode = true }) => {
239231 // Track user inputs for disclaimer
240232 const inputs = [ ] ;
241233 if ( searchKeyword . trim ( ) ) inputs . push ( { category : 'Keywords' , value : searchKeyword . trim ( ) } ) ;
242- if ( authorObject && authorObject . display_name ) inputs . push ( { category : 'Author ' , value : authorObject . display_name } ) ;
243- if ( institutionObject && institutionObject . display_name ) inputs . push ( { category : 'Institution ' , value : institutionObject . display_name } ) ;
234+ if ( selectedAuthors . length > 0 ) inputs . push ( { category : 'Authors ' , value : selectedAuthors . map ( a => a . display_name ) . join ( ', ' ) } ) ;
235+ if ( selectedInstitutions . length > 0 ) inputs . push ( { category : 'Institutions ' , value : selectedInstitutions . map ( i => i . display_name ) . join ( ', ' ) } ) ;
244236 if ( selectedPublicationTypes . length > 0 ) inputs . push ( { category : 'Publication Types' , value : selectedPublicationTypes . map ( pt => pt . display_name ) . join ( ', ' ) } ) ;
245237 if ( publicationYear . trim ( ) ) inputs . push ( { category : 'Publication Year' , value : publicationYear . trim ( ) } ) ;
246238 if ( startYear . trim ( ) && endYear . trim ( ) ) inputs . push ( { category : 'Year Range' , value : `${ startYear . trim ( ) } -${ endYear . trim ( ) } ` } ) ;
@@ -254,15 +246,17 @@ const SearchPageLight = ({ darkMode = true }) => {
254246 // Format: title_and_abstract.search:keyword (OpenAlex handles multi-word automatically)
255247 filters . push ( `title_and_abstract.search:${ keyword } ` ) ;
256248 }
257- if ( authorObject && authorObject . id ) {
258- // Use the author object if available (from dropdown)
259- const authorId = authorObject . id . split ( '/' ) . pop ( ) ;
260- filters . push ( `authorships.author.id:A${ authorId } ` ) ;
249+ if ( selectedAuthors . length > 0 ) {
250+ selectedAuthors . forEach ( a => {
251+ const authorId = 'A' + a . id . split ( '/' ) . pop ( ) ;
252+ filters . push ( `authorships.author.id:${ authorId } ` ) ;
253+ } ) ;
261254 }
262- if ( institutionObject && institutionObject . id ) {
263- // Use the institution object if available (from URL params or dropdown)
264- const instId = institutionObject . id . split ( '/' ) . pop ( ) ;
265- filters . push ( `authorships.institutions.id:I${ instId } ` ) ;
255+ if ( selectedInstitutions . length > 0 ) {
256+ selectedInstitutions . forEach ( i => {
257+ const institutionId = 'I' + i . id . split ( '/' ) . pop ( ) ;
258+ filters . push ( `authorships.institutions.id:${ institutionId } ` ) ;
259+ } ) ;
266260 }
267261 if ( selectedPublicationTypes . length > 0 ) {
268262 // Handle multiple publication types
@@ -368,19 +362,17 @@ const SearchPageLight = ({ darkMode = true }) => {
368362 < SearchForm
369363 searchKeyword = { searchKeyword }
370364 setSearchKeyword = { setSearchKeyword }
371- author = { author }
372- setAuthor = { setAuthor }
373- setAuthorObject = { setAuthorObject }
374- institution = { institution }
375- setInstitution = { setInstitution }
376- setInstitutionObject = { setInstitutionObject }
365+ selectedAuthors = { selectedAuthors }
366+ setSelectedAuthors = { setSelectedAuthors }
367+ selectedInstitutions = { selectedInstitutions }
368+ setSelectedInstitutions = { setSelectedInstitutions }
377369 onSearch = { handleSearch }
378370 onOpenAdvancedFilters = { ( ) => setShowAdvanced ( true ) }
379- onAuthorClick = { ( ) => {
371+ onAuthorsClick = { ( ) => {
380372 setShowAuthorModal ( true ) ;
381373 clearAuthorSuggestions ( ) ;
382374 } }
383- onInstitutionClick = { ( ) => {
375+ onInstitutionsClick = { ( ) => {
384376 setShowInstitutionModal ( true ) ;
385377 clearInstitutionSuggestions ( ) ;
386378 } }
@@ -515,33 +507,39 @@ const SearchPageLight = ({ darkMode = true }) => {
515507 </ div >
516508 ) }
517509
518- { /* Author Modal Dropdown */ }
519- < ModalDropdown
510+ { /* Authors Multi-Select Modal */ }
511+ < MultiSelectModalDropdown
520512 isOpen = { showAuthorModal }
521513 onClose = { ( ) => setShowAuthorModal ( false ) }
522- title = "Select Author "
514+ title = "Select Authors "
523515 placeholder = "Type to search authors..."
524516 onSearchChange = { searchAuthors }
525517 suggestions = { authorSuggestions }
526- onSelect = { ( author ) => {
527- setAuthorObject ( author ) ;
528- setAuthor ( author . display_name ) ;
518+ selectedItems = { selectedAuthors }
519+ onSelect = { author => {
520+ setSelectedAuthors ( prev => prev . some ( a => a . id === author . id ) ? prev : [ ...prev , author ] ) ;
521+ } }
522+ onDeselect = { author => {
523+ setSelectedAuthors ( prev => prev . filter ( a => a . id !== author . id ) ) ;
529524 } }
530525 darkMode = { darkMode }
531526 loading = { authorLoading }
532527 />
533528
534- { /* Institution Modal Dropdown */ }
535- < ModalDropdown
529+ { /* Institutions Multi-Select Modal */ }
530+ < MultiSelectModalDropdown
536531 isOpen = { showInstitutionModal }
537532 onClose = { ( ) => setShowInstitutionModal ( false ) }
538- title = "Select Institution "
533+ title = "Select Institutions "
539534 placeholder = "Type to search institutions..."
540535 onSearchChange = { searchInstitutions }
541536 suggestions = { institutionSuggestions }
542- onSelect = { ( institution ) => {
543- setInstitutionObject ( institution ) ;
544- setInstitution ( institution . display_name ) ;
537+ selectedItems = { selectedInstitutions }
538+ onSelect = { institution => {
539+ setSelectedInstitutions ( prev => prev . some ( i => i . id === institution . id ) ? prev : [ ...prev , institution ] ) ;
540+ } }
541+ onDeselect = { institution => {
542+ setSelectedInstitutions ( prev => prev . filter ( i => i . id !== institution . id ) ) ;
545543 } }
546544 darkMode = { darkMode }
547545 loading = { institutionLoading }
0 commit comments