■ ■ ■ ■ ■ ■
packages/web/src/components/layouts/SearchResults/SearchResults.tsx
1 | | - | import React from 'react'; |
| 1 | + | import React, { useState } from 'react'; |
2 | 2 | | import styles from './SearchResults.module.scss'; |
3 | 3 | | import Header from 'components/ui/Header/Header'; |
4 | 4 | | import Footer from 'components/ui/Footer/Footer'; |
5 | 5 | | import Container from 'components/ui/Container/Container'; |
6 | 6 | | import { Icon } from '../../ui/Icon/Icon'; |
7 | | - | import ChipGroup from '../../ui/ChipGroup/ChipGroup'; |
8 | 7 | | import PackagePreview from '../../ui/PackagePreview/PackagePreview'; |
9 | 8 | | import SearchBar from '../../ui/SearchBar/SearchBar'; |
10 | | - | import Badge from '../../ui/Badge/Badge'; |
11 | | - | import Person from 'components/ui/Person/Person'; |
12 | | - | import Checkbox from '../../ui/Checkbox/Checkbox'; |
13 | 9 | | import SearchedResource from '../../ui/SearchedResource/SearchedResource'; |
14 | 10 | | import { CardProps } from '../../ui/Card/Card'; |
15 | 11 | | import CardGroup from '../../ui/CardGroup/CardGroup'; |
16 | 12 | | import CardList from '../../ui/CardList/CardList'; |
17 | 13 | | import CardGroups from 'components/ui/CardGroups/CardGroups'; |
| 14 | + | import SidebarCategory from '../../ui/SidebarCategory/SidebarCategory'; |
| 15 | + | import { Button } from '../../ui'; |
18 | 16 | | |
19 | 17 | | export default function SearchResults() { |
20 | 18 | | // TODO: mock date, remove later |
| skipped 101 lines |
122 | 120 | | }, |
123 | 121 | | ]; |
124 | 122 | | |
| 123 | + | const keyWords = { |
| 124 | + | fullList: [ |
| 125 | + | { |
| 126 | + | id: '#art', |
| 127 | + | name: '#art', |
| 128 | + | }, |
| 129 | + | { |
| 130 | + | id: '#angular', |
| 131 | + | name: '#angular', |
| 132 | + | }, |
| 133 | + | { |
| 134 | + | id: '#moment', |
| 135 | + | name: '#moment', |
| 136 | + | }, |
| 137 | + | { |
| 138 | + | id: '#date', |
| 139 | + | name: '#date', |
| 140 | + | }, |
| 141 | + | { |
| 142 | + | id: '#react', |
| 143 | + | name: '#react', |
| 144 | + | }, |
| 145 | + | { |
| 146 | + | id: '#parse', |
| 147 | + | name: '#parse', |
| 148 | + | }, |
| 149 | + | { |
| 150 | + | id: '#fb', |
| 151 | + | name: '#fb', |
| 152 | + | }, |
| 153 | + | ], |
| 154 | + | featuredItems: ['#moment', '#date', '#react', '#parse', '#fb'], |
| 155 | + | }; |
| 156 | + | |
| 157 | + | const vulnerabilities = ['Vulnerabilities', 'Outdated', 'Duplicate']; |
| 158 | + | |
| 159 | + | const authors = { |
| 160 | + | fullList: [ |
| 161 | + | { |
| 162 | + | id: 'acdlite', |
| 163 | + | name: 'acdlite', |
| 164 | + | }, |
| 165 | + | { |
| 166 | + | id: 'gaearon', |
| 167 | + | name: 'gaearon', |
| 168 | + | }, |
| 169 | + | { |
| 170 | + | id: 'sophiebits', |
| 171 | + | name: 'sophiebits', |
| 172 | + | }, |
| 173 | + | { |
| 174 | + | id: 'trueadm', |
| 175 | + | name: 'trueadm', |
| 176 | + | }, |
| 177 | + | ], |
| 178 | + | featuredItems: ['acdlite', 'gaearon', 'sophiebits', 'trueadm'], |
| 179 | + | }; |
| 180 | + | |
| 181 | + | const [selectedKeywords, setSelectedKeywords] = useState<string[] | []>([]); |
| 182 | + | const [selectedProblems, setSelectedProblems] = useState<string[] | []>([]); |
| 183 | + | const [selectedAuthors, setSelectedAuthors] = useState<string[] | []>([]); |
| 184 | + | |
| 185 | + | const handleFiltersChange = ( |
| 186 | + | name: string, |
| 187 | + | state: string[] | [], |
| 188 | + | setState: React.SetStateAction<any> |
| 189 | + | ) => { |
| 190 | + | const temp = [...state]; |
| 191 | + | |
| 192 | + | if (temp.includes(name)) { |
| 193 | + | const filtered = temp.filter((item) => item !== name); |
| 194 | + | setState(filtered); |
| 195 | + | } else { |
| 196 | + | temp.push(name); |
| 197 | + | setState(temp); |
| 198 | + | } |
| 199 | + | }; |
| 200 | + | |
| 201 | + | const handleKeywordsChange = (name: string) => { |
| 202 | + | handleFiltersChange(name, selectedKeywords, setSelectedKeywords); |
| 203 | + | }; |
| 204 | + | |
| 205 | + | const handleProblemsChange = (name: string) => { |
| 206 | + | handleFiltersChange(name, selectedProblems, setSelectedProblems); |
| 207 | + | }; |
| 208 | + | |
| 209 | + | const handleAuthorsChange = (name: string) => { |
| 210 | + | handleFiltersChange(name, selectedAuthors, setSelectedAuthors); |
| 211 | + | }; |
| 212 | + | |
| 213 | + | const resetFilters = () => { |
| 214 | + | setSelectedKeywords([]); |
| 215 | + | setSelectedProblems([]); |
| 216 | + | setSelectedAuthors([]); |
| 217 | + | }; |
| 218 | + | |
| 219 | + | const isChanged = |
| 220 | + | selectedKeywords.length > 0 || selectedProblems.length > 0 || selectedAuthors.length > 0; |
| 221 | + | |
125 | 222 | | return ( |
126 | 223 | | <> |
127 | 224 | | <Header> |
| skipped 20 lines |
148 | 245 | | </div> |
149 | 246 | | <div className={styles.metaItem}> |
150 | 247 | | <span className={styles.metaIcon}> |
151 | | - | <Icon kind='search' width={24} height={24} /> |
| 248 | + | <Icon kind='search' width={24} height={24} color='#212121' /> |
152 | 249 | | </span> |
153 | 250 | | <span className={styles.metaText}>50 scripts found</span> |
154 | 251 | | </div> |
| skipped 19 lines |
174 | 271 | | </div> |
175 | 272 | | |
176 | 273 | | <div className={styles.sidebarItem}> |
177 | | - | <div className={styles.sidebarItemTop}> |
178 | | - | <div className={styles.sidebarItemTitle}>Keywords</div> |
179 | | - | <div className={styles.sidebarItemAction}> |
180 | | - | <Icon kind='search' width={24} height={24} /> |
181 | | - | </div> |
182 | | - | </div> |
183 | | - | |
184 | | - | <ChipGroup chips={['#moment', '#date', '#react', '#parse', '#fb']} /> |
185 | | - | <span role='button' className={styles.viewAll}> |
186 | | - | View All |
187 | | - | </span> |
| 274 | + | <SidebarCategory |
| 275 | + | category={keyWords} |
| 276 | + | selectedKeywords={selectedKeywords} |
| 277 | + | selectHandler={handleKeywordsChange} |
| 278 | + | renderComponent='chip' |
| 279 | + | searchable |
| 280 | + | /> |
188 | 281 | | </div> |
189 | 282 | | |
190 | 283 | | <div className={styles.sidebarItem}> |
191 | | - | <div className={styles.sidebarItemTop}> |
192 | | - | <div className={styles.sidebarItemTitle}> |
193 | | - | Problem |
194 | | - | <span className={styles.sidebarItemCounter}> |
195 | | - | <Badge content={1} /> |
196 | | - | </span> |
197 | | - | </div> |
198 | | - | </div> |
199 | | - | |
200 | | - | <div className={styles.checkboxGroup}> |
201 | | - | <Checkbox label='Vulnerabilities' checked /> |
202 | | - | <Checkbox label='Outdated' /> |
203 | | - | <Checkbox label='Duplicate' /> |
204 | | - | </div> |
| 284 | + | <SidebarCategory |
| 285 | + | simpleCategory={vulnerabilities} |
| 286 | + | selectedKeywords={selectedProblems} |
| 287 | + | selectHandler={handleProblemsChange} |
| 288 | + | renderComponent='checkbox' |
| 289 | + | /> |
205 | 290 | | </div> |
206 | 291 | | |
207 | 292 | | <div className={styles.sidebarItem}> |
208 | | - | <div className={styles.sidebarItemTop}> |
209 | | - | <div className={styles.sidebarItemTitle}>Authors</div> |
210 | | - | <div className={styles.sidebarItemAction}> |
211 | | - | <Icon kind='search' width={24} height={24} /> |
212 | | - | </div> |
213 | | - | </div> |
| 293 | + | <SidebarCategory |
| 294 | + | category={authors} |
| 295 | + | selectedKeywords={selectedAuthors} |
| 296 | + | selectHandler={handleAuthorsChange} |
| 297 | + | renderComponent='person' |
| 298 | + | searchable |
| 299 | + | /> |
| 300 | + | </div> |
214 | 301 | | |
215 | | - | <div className={styles.authors}> |
216 | | - | <Person image='https://via.placeholder.com/36' name='acdlite' checked /> |
217 | | - | <Person image='https://via.placeholder.com/36' name='gaearon' /> |
218 | | - | <Person image='https://via.placeholder.com/36' name='sophiebits' /> |
219 | | - | <Person image='https://via.placeholder.com/36' name='trueadm' /> |
| 302 | + | {isChanged && ( |
| 303 | + | <div className={styles.sidebarItem}> |
| 304 | + | <Button variant='secondary' size='small' onClick={resetFilters}> |
| 305 | + | Reset filters |
| 306 | + | </Button> |
220 | 307 | | </div> |
221 | | - | |
222 | | - | <span role='button' className={styles.viewAll}> |
223 | | - | View All |
224 | | - | </span> |
225 | | - | </div> |
| 308 | + | )} |
226 | 309 | | </aside> |
227 | 310 | | |
228 | 311 | | <div className={styles.packages}> |
| 312 | + | <PackagePreview |
| 313 | + | name='@team-griffin/react-heading-section@team-griffin/react-heading-section' |
| 314 | + | version='3.0.0 - 4.16.4' |
| 315 | + | /> |
229 | 316 | | <PackagePreview |
230 | 317 | | name='@team-griffin/react-heading-section@team-griffin/react-heading-section' |
231 | 318 | | version='3.0.0 - 4.16.4' |
| skipped 20 lines |