From 1c45c6934dbe00bd9408f162d89d4257010cdfa5 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 8 May 2023 18:05:39 +0330 Subject: [PATCH] added searching functionality --- components/Modal/DeleteCollection.tsx | 1 + components/Navbar.tsx | 25 ++---- components/Search.tsx | 106 ++++++++++++++++++++++++++ pages/search.tsx | 59 ++++++++++++++ store/search.ts | 47 ++++++++++++ types/global.ts | 11 +++ 6 files changed, 230 insertions(+), 19 deletions(-) create mode 100644 components/Search.tsx create mode 100644 pages/search.tsx create mode 100644 store/search.ts diff --git a/components/Modal/DeleteCollection.tsx b/components/Modal/DeleteCollection.tsx index 5fb0790..634f0b7 100644 --- a/components/Modal/DeleteCollection.tsx +++ b/components/Modal/DeleteCollection.tsx @@ -44,6 +44,7 @@ export default function AddCollection({

setInputField(e.target.value)} type="text" diff --git a/components/Navbar.tsx b/components/Navbar.tsx index c1d6c3b..c04858e 100644 --- a/components/Navbar.tsx +++ b/components/Navbar.tsx @@ -8,7 +8,6 @@ import { signOut } from "next-auth/react"; import { useSession } from "next-auth/react"; import { faPlus, - faMagnifyingGlass, faCircleUser, faSliders, faArrowRightFromBracket, @@ -17,11 +16,12 @@ import { } from "@fortawesome/free-solid-svg-icons"; import { useEffect, useState } from "react"; import Dropdown from "@/components/Dropdown"; -import Modal from "./Modal"; -import AddLink from "./Modal/AddLink"; -import ClickAwayHandler from "./ClickAwayHandler"; -import Sidebar from "./Sidebar"; +import Modal from "@/components/Modal"; +import AddLink from "@/components/Modal/AddLink"; +import ClickAwayHandler from "@/components/ClickAwayHandler"; +import Sidebar from "@/components/Sidebar"; import { useRouter } from "next/router"; +import Search from "@/components/Search"; export default function () { const { data: session } = useSession(); @@ -57,20 +57,7 @@ export default function () { > -
- - -
+
setSearchBox(false)}> +
setSearchBox(true)} + > + + + setSearchQuery(e.target.value)} + onFocus={() => router.push("/search")} + autoFocus={searchBox} + className="border border-sky-100 rounded-md pr-6 w-60 focus:border-sky-500 sm:focus:w-80 hover:border-sky-500 duration-100 outline-none p-1" + /> + {searchBox ? ( +
+

Filter by:

+
+ + + + + +
+
+ ) : null} +
+ + ); +} diff --git a/pages/search.tsx b/pages/search.tsx new file mode 100644 index 0000000..4126896 --- /dev/null +++ b/pages/search.tsx @@ -0,0 +1,59 @@ +// Copyright (C) 2022-present Daniel31x13 +// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3. +// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// You should have received a copy of the GNU General Public License along with this program. If not, see . + +import LinkList from "@/components/LinkList"; +import Dashboard from "@/layouts/Dashboard"; +import useLinkStore from "@/store/links"; +import useSearchSettingsStore from "@/store/search"; +import { ExtendedLink } from "@/types/global"; +import { faSearch } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useEffect, useState } from "react"; + +export default function Links() { + const { links } = useLinkStore(); + + const [filteredLinks, setFilteredLinks] = useState([]); + + const { searchSettings } = useSearchSettingsStore(); + + useEffect(() => { + const { name, url, title, collection, tags } = searchSettings.filter; + + const filter = links.filter((link) => { + const query = searchSettings.query.toLowerCase(); + + if ( + (name && link.name.toLowerCase().includes(query)) || + (url && link.url.toLowerCase().includes(query)) || + (title && link.title.toLowerCase().includes(query)) || + (collection && link.collection.name.toLowerCase().includes(query)) || + (tags && + link.tags.some((tag) => tag.name.toLowerCase().includes(query))) + ) + return true; + }); + + setFilteredLinks(filter); + }, [searchSettings]); + + return ( + +
+
+
+ +

Search Results

+
+
+ {filteredLinks[0] + ? filteredLinks.map((e, i) => { + return ; + }) + : "No results..."} +
+
+ ); +} diff --git a/store/search.ts b/store/search.ts new file mode 100644 index 0000000..62ef8b5 --- /dev/null +++ b/store/search.ts @@ -0,0 +1,47 @@ +// Copyright (C) 2022-present Daniel31x13 +// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3. +// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// You should have received a copy of the GNU General Public License along with this program. If not, see . + +import { SearchSettings } from "@/types/global"; +import { create } from "zustand"; + +type SearchSettingsState = { + searchSettings: SearchSettings; + setSearchSettings: (searchSettings: SearchSettings) => void; + toggleCheckbox: (name: keyof SearchSettings["filter"]) => void; + setSearchQuery: (query: string) => void; +}; + +const useSearchSettingsStore = create((set) => ({ + searchSettings: { + query: "", + filter: { + name: true, + url: true, + title: true, + collection: true, + tags: true, + }, + }, + setSearchSettings: (searchSettings) => set({ searchSettings }), + toggleCheckbox: (name) => + set((state) => ({ + searchSettings: { + ...state.searchSettings, + filter: { + ...state.searchSettings.filter, + [name]: !state.searchSettings.filter[name], + }, + }, + })), + setSearchQuery: (query) => + set((state) => ({ + searchSettings: { + ...state.searchSettings, + query, + }, + })), +})); + +export default useSearchSettingsStore; diff --git a/types/global.ts b/types/global.ts index 5da7f89..c9ec1ac 100644 --- a/types/global.ts +++ b/types/global.ts @@ -46,3 +46,14 @@ export interface ExtendedCollection extends Collection { }; }[]; } + +export type SearchSettings = { + query: string; + filter: { + name: boolean; + url: boolean; + title: boolean; + collection: boolean; + tags: boolean; + }; +};