diff --git a/components/core/Search/index.js b/components/core/Search/index.js new file mode 100644 index 00000000..7484dc93 --- /dev/null +++ b/components/core/Search/index.js @@ -0,0 +1,231 @@ +import * as React from "react"; +import * as SVG from "~/common/svg"; +import * as Styles from "~/common/styles"; + +import { css } from "@emotion/react"; +import { Input as InputPrimitive } from "~/components/system/components/Input"; +import { useSearchStore } from "~/components/core/Search/store"; +import { LoaderSpinner } from "~/components/system/components/Loaders"; +import { FileTypeGroup } from "~/components/core/FileTypeIcon"; +import { Link } from "~/components/core/Link"; + +import DataView from "~/components/core/DataView"; +import CollectionPreviewBlock from "~/components/core/CollectionPreviewBlock"; +import EmptyState from "~/components/core/EmptyState"; +import omit from "lodash.omit"; + +/* ------------------------------------------------------------------------------------------------- + * Input + * -----------------------------------------------------------------------------------------------*/ + +const STYLES_SEARCH_COMPONENT = (theme) => css` + background-color: transparent; + box-shadow: none; + height: 100%; + input { + height: 100%; + padding: 0px 4px; + border-radius: 0px; + } + &::placeholder { + color: ${theme.semantic.textGray}; + } +`; + +const useSearchViaParams = ({ params, handleSearch }) => { + const { setQuery, clearSearch } = useSearchStore(); + + React.useEffect(() => { + if (params?.s) { + setQuery(params.s); + handleSearch(params.s); + } + }, []); + + // NOTE(amine): if we change + React.useEffect(() => { + if (!params.s) clearSearch(); + }, [params.s]); +}; + +const useDebouncedSearch = ({ handleSearch }) => { + const { query } = useSearchStore(); + + const timeRef = React.useRef(); + React.useEffect(() => { + timeRef.current = setTimeout(() => handleSearch(query), 300); + return () => clearTimeout(timeRef.current); + }, [query]); +}; + +function Input({ viewer, data, page, onAction }) { + const { search, query, isFetchingResults, setQuery } = useSearchStore(); + + const handleSearch = async (query) => { + // NOTE(amine): update params with search query + onAction({ + type: "UPDATE_PARAMS", + params: query?.length > 0 ? { s: query } : omit(page.params, ["s"]), + }); + + if (!query) return; + + // NOTE(amine): searching on your own tag. + if (page.id === "NAV_SLATE" && data?.ownerId === viewer?.id) { + search({ + types: ["FILE"], + tagIds: [data.id], + query, + }); + return; + } + + //NOTE(amine): searching on another user's tag + if (page.id === "NAV_SLATE" && data?.ownerId !== viewer?.id) { + search({ + types: ["FILE"], + tagIds: [data.id], + query, + globalSearch: true, + }); + return; + } + + //NOTE(amine): searching on another user's profile + if (page.id === "NAV_PROFILE" && data?.id !== viewer?.id) { + console.log(data?.id, page.id, page.id === "NAV_PROFILE", data?.id !== viewer?.id); + search({ + types: ["SLATE", "FILE"], + userId: data.id, + query, + globalSearch: true, + grouped: true, + }); + return; + } + + //NOTE(amine): searching on library + if (viewer) { + search({ + types: ["FILE", "SLATE"], + query, + grouped: true, + }); + return; + } + + // NOTE(amine): global search + search({ + types: ["FILE", "SLATE", "USER"], + globalSearch: true, + query: query, + grouped: true, + }); + }; + + useSearchViaParams({ params: page.params, onAction, handleSearch }); + + useDebouncedSearch({ handleSearch }); + + return ( +