diff options
-rw-r--r-- | components/tag.tsx | 2 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | pages/search.tsx | 52 | ||||
-rw-r--r-- | yarn.lock | 5 |
4 files changed, 46 insertions, 14 deletions
diff --git a/components/tag.tsx b/components/tag.tsx index 48c75ce..477b8e2 100644 --- a/components/tag.tsx +++ b/components/tag.tsx @@ -5,7 +5,7 @@ export default function Tags(props: { }) { return <div className="tags"> <span>Tags:</span> - {props.tags.map(tag => <Tag name={tag}/>)} + {props.tags.map(tag => <Tag key={Math.random().toString()} name={tag}/>)} </div> } diff --git a/package.json b/package.json index 2671cdc..636b466 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "dependencies": { "@material-ui/core": "^4.11.3", "@material-ui/icons": "^4.11.2", + "fuse.js": "^6.4.6", "next": "10.0.9", "react": "17.0.2", "react-dom": "17.0.2", diff --git a/pages/search.tsx b/pages/search.tsx index 8053d4a..af9bfeb 100644 --- a/pages/search.tsx +++ b/pages/search.tsx @@ -1,21 +1,20 @@ import { useState, useEffect } from 'react'; +import Fuse from 'fuse.js'; import Navbar from '../components/navbar'; -import { FormEvent } from 'react'; -import { ArticleMeta } from './post/[id]'; import Tags from '../components/tag' import SearchOutlinedIcon from '@material-ui/icons/SearchOutlined'; -function SearchBar(props: { - searchFunction: (event?: FormEvent<HTMLFormElement>) => void; -}) { +function SearchBar(props: { searchFunction: () => void }) { return <div className="searchBar"> - <form onSubmit={props.searchFunction}> - <input className="input" placeholder="Search for posts..." autoComplete="off"/> - <button className="button" onClick={() => props.searchFunction()}><SearchOutlinedIcon/></button> - <input type="submit" style={{ display: "none" }}/> - </form> + <input + className="input" + id="searchInput" + placeholder="Search for posts..." + onChange={() => props.searchFunction()} + autoComplete="off"/> + <button className="button" onClick={() => props.searchFunction()}><SearchOutlinedIcon/></button> </div> } @@ -54,12 +53,39 @@ function Posts(props: { posts: Array<Post> }) { export default function SearchPage() { var [posts, setPosts] = useState<PostsInfo>({ posts: [], valid_tags: [] }); + var [query, setQuery] = useState(""); + var [visiblePosts, setVisiblePosts] = useState<Array<Post>>([]); + + var fuse = new Fuse(posts.posts, { + keys: [ + "title", + "subtitle", + "author", + "date", + "urlname", + "tags" + ], + isCaseSensitive: false + }) useEffect(() => {(async () => { + var query = new URLSearchParams(window.location.search).get("q") || ""; + if(query) + (document.getElementById("searchInput") as HTMLInputElement).value = query; + setQuery(query); + var posts = await fetch("/posts.json"); setPosts(await posts.json()); })()}, []); + useEffect(() => { + if(query.length == 0) { + setVisiblePosts(posts.posts) + } else { + setVisiblePosts(fuse.search(query).map(res => res.item)) + } + }, [query]); + return <div> <div className="centeredPage"> <div className="titleWrapper"> @@ -71,10 +97,10 @@ export default function SearchPage() { </div> </div> <div className="contentWrapper"> - <SearchBar searchFunction={(event?: FormEvent<HTMLFormElement>) => { - event?.preventDefault(); + <SearchBar searchFunction={() => { + setTimeout(() => setQuery((document.getElementById("searchInput") as HTMLInputElement).value)); }}/> - <Posts posts={posts.posts}/> + <Posts posts={visiblePosts}/> </div> </div> </div> @@ -834,6 +834,11 @@ fsevents@~2.3.1: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== +fuse.js@^6.4.6: + version "6.4.6" + resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-6.4.6.tgz#62f216c110e5aa22486aff20be7896d19a059b79" + integrity sha512-/gYxR/0VpXmWSfZOIPS3rWwU8SHgsRTwWuXhyb2O6s7aRuVtHtxCkR33bNYu3wyLyNx/Wpv0vU7FZy8Vj53VNw== + get-orientation@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/get-orientation/-/get-orientation-1.1.2.tgz#20507928951814f8a91ded0a0e67b29dfab98947" |