Skip to content

Commit

Permalink
Merge pull request #1 from AtomicSearch/feature/refactoring-add-react…
Browse files Browse the repository at this point in the history
…-router-dom-and-instant-search

Feature/refactoring add react router dom and instant search
  • Loading branch information
pH-7 authored May 3, 2024
2 parents 859dc6b + ee9f9ff commit 9e72118
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 92 deletions.
79 changes: 16 additions & 63 deletions client/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,71 +1,24 @@
import { usePubSub } from "create-pubsub/react";
import {
promptPubSub,
responsePubSub,
searchResultsPubSub,
urlsDescriptionsPubSub,
} from "../modules/pubSub";
import { SearchForm } from "./SearchForm";
import { Toaster } from "react-hot-toast";
import { SettingsButton } from "./SettingsButton";
import Markdown from "markdown-to-jsx";
import { getDisableAiResponseSetting } from "../modules/pubSub";
import { SearchResultsList } from "./SearchResultsList";
import { useEffect } from "react";
import { prepareTextGeneration } from "../modules/textGeneration";
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';

export function App() {
const [query, updateQuery] = usePubSub(promptPubSub);
const [response] = usePubSub(responsePubSub);
const [searchResults] = usePubSub(searchResultsPubSub);
const [urlsDescriptions] = usePubSub(urlsDescriptionsPubSub);
import { SearchPage } from "../pages/search/SearchPage";
import { ComparisonPage } from "../pages/static/ComparisonPage";

useEffect(() => {
prepareTextGeneration();
}, []);
function InnerApp() {

return (
<>
<SearchForm query={query} updateQuery={updateQuery} />
{!getDisableAiResponseSetting() && response.length > 0 && (
<div
style={{
backgroundColor: "var(--background)",
borderRadius: "6px",
padding: "10px 25px",
}}
>
<Markdown>{response}</Markdown>
</div>
)}
{searchResults.length > 0 && (
<div>
<SearchResultsList
searchResults={searchResults}
urlsDescriptions={urlsDescriptions}
/>
</div>
)}
<div
style={
searchResults.length === 0
? {
position: "fixed",
bottom: 0,
left: 0,
right: 0,
display: "flex",
justifyContent: "center",
}
: {
display: "flex",
justifyContent: "center",
}
}
>
<SettingsButton />
</div>
<Toaster />
<Routes>
<Route path="/" element={<SearchPage />} />
<Route path="/comparison-google" element={<ComparisonPage />} />
</Routes>
</>
);
}

export const App = () => {
return (
<Router>
<InnerApp />
</Router>
);
}
54 changes: 25 additions & 29 deletions client/components/SearchForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useEffect, useRef, FormEvent, useState, useCallback } from "react";
import { useEffect, useRef, useState, useCallback } from "react";
import { useNavigate } from 'react-router-dom';
import TextareaAutosize from "react-textarea-autosize";
import { getRandomQuerySuggestion } from "../modules/querySuggestions";
import { debounce } from "../utils/debounce";

export function SearchForm({
query,
Expand All @@ -15,45 +17,42 @@ export function SearchForm({
getRandomQuerySuggestion(),
);

const navigate = useNavigate();

const startSearching = useCallback((queryToEncode: string) => {
updateQuery(queryToEncode);
navigate(`/?q=${encodeURIComponent(queryToEncode)}`);
}, [updateQuery, navigate]);

const debouncedStartSearching = debounce(startSearching, 3000); // 3000ms = 3s

const handleInputChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
const userQueryIsBlank = event.target.value.trim().length === 0;
const userQuery = event.target.value.trim();
const userQueryIsBlank = userQuery.length === 0;
const suggestedQueryIsBlank = suggestedQuery.trim().length === 0;

if (userQueryIsBlank && suggestedQueryIsBlank) {
setSuggestedQuery(getRandomQuerySuggestion());
} else if (!userQueryIsBlank && !suggestedQueryIsBlank) {
setSuggestedQuery("");
}
};

const startSearching = useCallback(() => {
let queryToEncode = suggestedQuery;

if (textAreaRef.current && textAreaRef.current.value.trim().length > 0) {
queryToEncode = textAreaRef.current.value;
// Start searching immediately when user types
if (!userQueryIsBlank) {
debouncedStartSearching(userQuery);
}

self.history.pushState(
null,
"",
`/?q=${encodeURIComponent(queryToEncode)}`,
);

updateQuery(queryToEncode);

location.reload();
}, [suggestedQuery, updateQuery]);

const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
startSearching();
};

useEffect(() => {
const keyboardEventHandler = (event: KeyboardEvent) => {
if (event.code === "Enter" && !event.shiftKey) {
event.preventDefault();
startSearching();
if (textAreaRef.current) {
const userQuery = textAreaRef.current.value.trim();
if (userQuery.length > 0) {
startSearching(userQuery);
}
}
}
};
const textArea = textAreaRef.current;
Expand All @@ -76,7 +75,7 @@ export function SearchForm({
: undefined
}
>
<form onSubmit={handleSubmit} style={{ width: "100%" }}>
<form style={{ width: "100%" }}>
<TextareaAutosize
defaultValue={query}
placeholder={suggestedQuery}
Expand All @@ -86,9 +85,6 @@ export function SearchForm({
minRows={1}
maxRows={6}
/>
<button type="submit" style={{ width: "100%" }}>
Search
</button>
</form>
</div>
);
Expand Down
80 changes: 80 additions & 0 deletions client/pages/search/SearchPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { usePubSub } from "create-pubsub/react";
import {
promptPubSub,
responsePubSub,
searchResultsPubSub,
urlsDescriptionsPubSub,
} from "../../modules/pubSub";
import { SearchForm } from "../../components/SearchForm";
import { Toaster } from "react-hot-toast";
import { SettingsButton } from "../../components/SettingsButton";
import Markdown from "markdown-to-jsx";
import { getDisableAiResponseSetting } from "../../modules/pubSub";
import { SearchResultsList } from "../../components/SearchResultsList";
import { useEffect } from "react";
import { prepareTextGeneration } from "../../modules/textGeneration";
import { useLocation } from 'react-router-dom';

export const SearchPage = () => {
const [query, setQuery] = usePubSub(promptPubSub);
const [response] = usePubSub(responsePubSub);
const [searchResults] = usePubSub(searchResultsPubSub);
const [urlsDescriptions] = usePubSub(urlsDescriptionsPubSub);

useEffect(() => {
prepareTextGeneration();
}, []);

const location = useLocation();

useEffect(() => {
const params = new URLSearchParams(location.search);
const newQuery = params.get('q');
if (newQuery !== null) {
setQuery(newQuery);
}
}, [location.search, setQuery]);


return (
<>
<SearchForm query={query} updateQuery={setQuery} />
{!getDisableAiResponseSetting() && response.length > 0 && (
<div className="mt-4">
<h2 className="text-lg font-semibold">AI's thoughts:</h2>
<div className="bg-gray-100 p-4 rounded-md mt-2">
<Markdown>{response}</Markdown>
</div>
</div>
)}
{searchResults.length > 0 && (
<div>
<SearchResultsList
searchResults={searchResults}
urlsDescriptions={urlsDescriptions}
/>
</div>
)}
<div
style={
searchResults.length === 0
? {
position: "fixed",
bottom: 0,
left: 0,
right: 0,
display: "flex",
justifyContent: "center",
}
: {
display: "flex",
justifyContent: "center",
}
}
>
<SettingsButton />
</div>
<Toaster />
</>
);
};
10 changes: 10 additions & 0 deletions client/pages/static/ComparisonPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';

export const ComparisonPage = () => {
return (
<div>
<h1>Comparison Page</h1>
{/* Add your comparison logic here */}
</div>
);
};
16 changes: 16 additions & 0 deletions client/utils/debounce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const debounce = <T extends (...args: any[]) => void>(
func: T,
wait: number,
): ((...args: Parameters<T>) => void) => {
let timeout: NodeJS.Timeout;

return (...args: Parameters<T>): void => {
const later = () => {
clearTimeout(timeout);
func(...args);
};

clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
39 changes: 39 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1",
"react-router-dom": "^6.23.0",
"react-textarea-autosize": "^8.5.3",
"react-tooltip": "^5.21.6",
"temp-dir": "^3.0.0",
Expand Down

0 comments on commit 9e72118

Please sign in to comment.