added suggestion to search

This commit is contained in:
Niklas 2020-04-24 00:01:04 +02:00
parent a5d72902e1
commit bb86ffac8b
7 changed files with 172 additions and 14 deletions

View File

@ -1,30 +1,80 @@
import * as React from "react"; import * as React from "react";
import "../style/search.scss"; import "../style/search.scss";
import Sugestion from "./Sugestion";
import { Suggestion, SuggestionType } from "../types/suggestion";
import getGoogleSuggestions from "../functions/getGoogleSuggestions";
class Search extends React.Component { interface State {
sugestions: Suggestion[];
}
class Search extends React.Component<{}, State> {
private searchInput = React.createRef<HTMLInputElement>() private searchInput = React.createRef<HTMLInputElement>()
constructor(props) { constructor(props) {
super(props); super(props);
this.state = {
sugestions: []
};
} }
handleQuery(query: string) { handleQuery(query: string) {
this.search(query); this.search(query);
} }
search(query: string){ search(query: string) {
const url = new URL("https://duckduckgo.com/"); const url = new URL("https://duckduckgo.com/");
const param = new URLSearchParams(); const param = new URLSearchParams();
param.append("q",query); param.append("q", query);
url.search = param.toString(); url.search = param.toString();
window.location.href = url.toString(); window.location.href = url.toString();
} }
onKeyDown(event: React.KeyboardEvent) { async sugest(input: string) {
if (input === "") {
this.setState({
sugestions: []
});
} else {
const results = await getGoogleSuggestions(input);
const newSuggestionState: Suggestion[] = results.suggestions.map((e) => {
return {
display: e,
type: SuggestionType.QUERY
};
});
this.setState({
sugestions: newSuggestionState
});
}
}
onKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {
if (event.key === 'Enter') { if (event.key === 'Enter') {
this.handleQuery(this.searchInput.current.value); this.handleQuery(this.searchInput.current.value);
} else if (event.key === "ArrowDown") {
console.log("down");
} else if (event.key === "ArrowUp") {
console.log("up");
}
}
onChange() {
this.sugest(this.searchInput.current.value);
}
onSugestionClick(e: Suggestion) {
if (e.type === SuggestionType.QUERY) {
this.search(e.display);
} else {
window.location.href = e.url;
} }
} }
@ -32,9 +82,21 @@ class Search extends React.Component {
return <div className="search-component" > return <div className="search-component" >
<input type="text" <input type="text"
autoFocus autoFocus
onKeyDown={(e)=>this.onKeyDown(e)} onKeyDown={(e) => this.onKeyDown(e)}
onChange={() => this.onChange()}
ref={this.searchInput} ref={this.searchInput}
autoComplete="off"
/> />
<div className="suggestion-area">
{this.state.sugestions.map((e) => {
return <Sugestion
key={e.display}
suggestion={e}
onClick={() => { this.onSugestionClick(e); }}
/>;
})}
</div>
</div>; </div>;
} }

View File

@ -0,0 +1,17 @@
import * as React from "react";
import "../style/suggestion.scss";
import { Suggestion } from "../types/suggestion";
interface Props {
suggestion: Suggestion;
onClick: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
}
const Sugestion = (props: Props) => {
return <div className="suggestion-component" onClick={props.onClick}>
{props.suggestion.display}
</div>;
};
export default Sugestion;

View File

@ -0,0 +1,17 @@
import GoogleSuggestions from "../types/GoogleSuggestions";
export default async (query: string): Promise<GoogleSuggestions> => {
const url = new URL(" http://suggestqueries.google.com/complete/search");
const param = new URLSearchParams();
param.append("q", query);
param.append("client", "firefox"); // TODO check if the result are different on different clients
url.search = param.toString();
const response = await fetch(url.toString());
const results = await response.json();
return {
query: results[0],
suggestions: results[1]
};
};

View File

@ -1,12 +1,19 @@
.search-component{ .search-component{
text-align: center; margin: 2em auto 2em auto;
margin-top: 2em; width: 50%;
margin-bottom: 2em; position: relative;
input[type=text]{ input[type=text]{
width: 40%; width: 100%;
border: none; border: none;
padding: 0.5em 1.5em; padding: 0.5em 1em;
box-sizing: border-box;
}
.suggestion-area{
position: absolute;
right: 0;
left: 0;
} }
} }

12
src/style/suggestion.scss Normal file
View File

@ -0,0 +1,12 @@
.suggestion-component{
padding: 0.2em 1em;
background-color: white;
color: black;
border: 1px solid #d4d4d4;
border-top: none;
cursor: pointer;
&:hover {
background-color: #d4d4d4;
}
}

View File

@ -0,0 +1,31 @@
/*
Example if client == chrome:
[
"hello w",
["hello world","hello world anime","hello world java","hello world c","hello world python","hello world html","hello world mhw","hello welcome home"],
["","","","","","","",""],
[],
{
"google:clientdata":{"bpc":false,"tlw":false},
"google:suggestrelevance":[1250,1050,850,700,601,600,551,550],
"google:suggesttype":["QUERY","QUERY","QUERY","QUERY","QUERY","QUERY","QUERY","QUERY"],
"google:verbatimrelevance":851
}
]
Example if client == firefox:
[
"hello wo",
[
"hello world","hello world anime","hello world java","hello world c","hello world python","hello world html",
"hello world mhw","hello world anime stream","hello world programm","hello world anime ger sub"
]
]
*/
interface GoogleSuggestions {
query: string;
suggestions: string[];
}
export default GoogleSuggestions;

12
src/types/Suggestion.ts Normal file
View File

@ -0,0 +1,12 @@
enum SuggestionType {
QUICK,
QUERY
}
interface Suggestion {
display: string;
type: SuggestionType;
url?: string;
}
export { SuggestionType, Suggestion };