working search bar
parent
5bff592068
commit
d1a33be5e1
|
@ -6878,6 +6878,11 @@
|
|||
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
|
||||
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
|
||||
},
|
||||
"fuse.js": {
|
||||
"version": "6.4.6",
|
||||
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.4.6.tgz",
|
||||
"integrity": "sha512-/gYxR/0VpXmWSfZOIPS3rWwU8SHgsRTwWuXhyb2O6s7aRuVtHtxCkR33bNYu3wyLyNx/Wpv0vU7FZy8Vj53VNw=="
|
||||
},
|
||||
"gensync": {
|
||||
"version": "1.0.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"@testing-library/user-event": "^12.8.3",
|
||||
"axios": "^0.24.0",
|
||||
"express": "^4.17.1",
|
||||
"fuse.js": "^6.4.6",
|
||||
"jQuery": "^1.7.4",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
|
|
91
src/App.js
91
src/App.js
|
@ -1,6 +1,8 @@
|
|||
import React, { useState, useEffect, Component } from 'react';
|
||||
import LangDropdown from './components/LangDropdown';
|
||||
import SearchBar from './components/SearchBar';
|
||||
import axios from 'axios';
|
||||
import Fuse from 'fuse.js';
|
||||
|
||||
function makeBook(author, hLang, cLang, title, url)
|
||||
{
|
||||
|
@ -87,11 +89,27 @@ class SubmitButton extends Component{
|
|||
}
|
||||
}
|
||||
|
||||
// Sorts search results by their score
|
||||
function sortByScore(results){
|
||||
results.sort(function(a,b){
|
||||
return a.score - b.score;
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
function App() {
|
||||
const [ data, setData ] = useState(undefined);
|
||||
const [ loading, setLoading ] = useState(true); //Determines whether to show spinner
|
||||
const [ searchTerm, setSearchTerm ] = useState('');
|
||||
const [ searchResults, setSearchResults ] = useState([]);
|
||||
let resultsList = null; // the html string containing the search results
|
||||
|
||||
useEffect( // runs the first time the page renders
|
||||
const setSearch = (term) => { // Lets a child set the value of the search term
|
||||
setSearchTerm(term);
|
||||
};
|
||||
|
||||
// fetches data the first time the page renders
|
||||
useEffect(
|
||||
() => {
|
||||
async function fetchData() {
|
||||
setLoading(true);
|
||||
|
@ -103,25 +121,70 @@ function App() {
|
|||
},
|
||||
[]
|
||||
);
|
||||
|
||||
// fires when searchTerm changes
|
||||
// THIS IS THE MAIN SEARCH FUNCTION CURRENTLY
|
||||
useEffect(
|
||||
() => {
|
||||
if(data){
|
||||
let result = [];
|
||||
data.children[0].children.forEach( (document) => {
|
||||
document.sections.forEach( (section) => {
|
||||
const fuseOptions = {
|
||||
findAllMatches: true,
|
||||
shouldSort: false,
|
||||
includeScore: true,
|
||||
threshold: 0.3,
|
||||
keys: ['title']
|
||||
};
|
||||
let fuse = new Fuse(section.entries, fuseOptions);
|
||||
let fuseResult = fuse.search(searchTerm);
|
||||
result = result.concat(fuseResult);
|
||||
section.subsections.forEach( (subsection) => {
|
||||
let fuse = new Fuse(subsection.entries, fuseOptions);
|
||||
let fuseResult = fuse.search(searchTerm);
|
||||
result = result.concat(fuseResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
result = sortByScore(result);
|
||||
setSearchResults(result);
|
||||
}
|
||||
},
|
||||
[ searchTerm ]
|
||||
)
|
||||
|
||||
if(loading){ //still fetching resource
|
||||
const buildList = () => {
|
||||
|
||||
};
|
||||
|
||||
if(loading){ // if still fetching resource
|
||||
return(
|
||||
<h1>Loading...</h1>
|
||||
);
|
||||
}
|
||||
else{ // resource fetched
|
||||
console.log(data);
|
||||
return(
|
||||
<div>
|
||||
<div id="frontPage">
|
||||
<h1>Free Programming Books</h1>
|
||||
<input type="text"></input>
|
||||
<LangDropdown data={data}/>
|
||||
<SubmitButton/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
if(searchTerm && searchResults.length !== 0){
|
||||
resultsList =
|
||||
searchResults &&
|
||||
searchResults.map((entry) => {
|
||||
return (<li><a href={entry.item.url}>{entry.item.title}</a></li>)
|
||||
});
|
||||
}
|
||||
console.log(data);
|
||||
return(
|
||||
<div>
|
||||
<div id="frontPage">
|
||||
<h1>Free Programming Books</h1>
|
||||
{/* <input type="text"></input> */}
|
||||
<SearchBar setSearch={setSearch}/>
|
||||
<LangDropdown data={data}/>
|
||||
<SubmitButton/>
|
||||
<ol>
|
||||
{resultsList}
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ function LangDropdown({ data }){
|
|||
return(
|
||||
|
||||
<select name="languages" id="languages">
|
||||
<option key="allLangs" value="allLangs">All Languages</option>
|
||||
{options}
|
||||
</select>
|
||||
)
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import React from 'react';
|
||||
|
||||
function SearchBar(props){
|
||||
const handleChange = (e) => {
|
||||
props.setSearch(e.target.value);
|
||||
}
|
||||
|
||||
return(
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
name="searchBar"
|
||||
>
|
||||
<input autoComplete="off" type="text" name="searchTerm" onChange={handleChange} />
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default SearchBar;
|
Loading…
Reference in New Issue