1+ import PropTypes from 'prop-types' ;
12import { useState } from 'react' ;
23import { useSelector } from 'react-redux' ;
4+ import { availablePreferences , availableSkills , formatSkillName } from './FilerData.js' ;
35import RankedUserList from './RankedUserList' ;
46import styles from './style/CommunityMembersPage.module.css' ;
5- import { availableSkills , availablePreferences , formatSkillName } from './FilerData.js' ;
67
78function Accordion ( { title, children, defaultOpen = false , darkMode } ) {
89 const [ open , setOpen ] = useState ( defaultOpen ) ;
@@ -26,6 +27,7 @@ function Accordion({ title, children, defaultOpen = false, darkMode }) {
2627function CommunityMembersPage ( ) {
2728 const [ selectedSkills , setSelectedSkills ] = useState ( [ ] ) ;
2829 const [ selectedPreferences , setSelectedPreferences ] = useState ( [ ] ) ;
30+ const [ searchQuery , setSearchQuery ] = useState ( '' ) ;
2931 const darkMode = useSelector ( state => state . theme . darkMode ) ;
3032
3133 const toggleItem = ( item , selectedArray , setSelectedArray ) => {
@@ -44,7 +46,7 @@ function CommunityMembersPage() {
4446 key = { skillKey }
4547 onClick = { ( ) => toggleItem ( skillKey , selectedSkills , setSelectedSkills ) }
4648 type = "button"
47- className = { `${ ` ${ styles . skillButton } ` } ${ isSelected ? styles . selected : '' } ` }
49+ className = { `${ styles . skillButton } ${ isSelected ? styles . selected : '' } ` }
4850 >
4951 { formattedName }
5052 </ button >
@@ -62,7 +64,7 @@ function CommunityMembersPage() {
6264 key = { pref }
6365 onClick = { ( ) => toggleItem ( pref , selectedPreferences , setSelectedPreferences ) }
6466 type = "button"
65- className = { `${ ` ${ styles . preferenceButton } ` } ${ isSelected ? styles . selected : '' } ` }
67+ className = { `${ styles . preferenceButton } ${ isSelected ? styles . selected : '' } ` }
6668 >
6769 { pref }
6870 </ button >
@@ -71,10 +73,33 @@ function CommunityMembersPage() {
7173 </ div >
7274 ) ;
7375
76+ const hasFilters =
77+ selectedSkills . length > 0 || selectedPreferences . length > 0 || searchQuery . trim ( ) . length > 0 ;
78+
7479 return (
7580 < div className = { `${ styles . container } ${ darkMode ? styles . darkMode : '' } ` } >
7681 < h1 className = { `${ styles . title } ` } > Community Member Filters</ h1 >
7782
83+ { /* Search Bar */ }
84+ < div className = { `${ styles . searchContainer } ${ darkMode ? styles . darkSearch : '' } ` } >
85+ < input
86+ type = "text"
87+ placeholder = "Search members by name or skill..."
88+ value = { searchQuery }
89+ onChange = { e => setSearchQuery ( e . target . value ) }
90+ className = { `${ styles . searchInput } ${ darkMode ? styles . darkSearchInput : '' } ` }
91+ />
92+ { searchQuery && (
93+ < button
94+ type = "button"
95+ className = { `${ styles . clearButton } ${ darkMode ? styles . darkClearButton : '' } ` }
96+ onClick = { ( ) => setSearchQuery ( '' ) }
97+ >
98+ ✕
99+ </ button >
100+ ) }
101+ </ div >
102+
78103 < Accordion title = "Filter by Skills" defaultOpen darkMode = { darkMode } >
79104 { renderSkillButtons ( ) }
80105 </ Accordion >
@@ -84,19 +109,26 @@ function CommunityMembersPage() {
84109 </ Accordion >
85110
86111 < div >
87- { selectedSkills . length > 0 || selectedPreferences . length > 0 ? (
112+ { hasFilters ? (
88113 < RankedUserList
89114 selectedSkills = { selectedSkills }
90115 selectedPreferences = { selectedPreferences }
116+ searchQuery = { searchQuery . trim ( ) }
91117 />
92118 ) : (
93119 < p className = { `${ styles . message } ` } >
94- Select skills or preferences above to see filtered members.
120+ Search or select skills and preferences above to see filtered members.
95121 </ p >
96122 ) }
97123 </ div >
98124 </ div >
99125 ) ;
100126}
127+ Accordion . propTypes = {
128+ title : PropTypes . string . isRequired ,
129+ children : PropTypes . node . isRequired ,
130+ defaultOpen : PropTypes . bool ,
131+ darkMode : PropTypes . bool ,
132+ } ;
101133
102134export default CommunityMembersPage ;
0 commit comments