diff --git a/.gitignore b/.gitignore index c589c424..02a2cb1a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ pnpm-lock.yaml private past-* output +dist diff --git a/web/components/routes/search/wrapper.tsx b/web/components/routes/search/wrapper.tsx index 25d3f13e..68da0b46 100644 --- a/web/components/routes/search/wrapper.tsx +++ b/web/components/routes/search/wrapper.tsx @@ -1,138 +1,131 @@ "use client" import { useState } from "react" -// import { useAccount } from "@/lib/providers/jazz-provider" -import { IoSearch, IoCloseOutline, IoChevronForward } from "react-icons/io5" +import { useCoState } from "@/lib/providers/jazz-provider" +import { LaIcon } from "@/components/custom/la-icon" import AiSearch from "../../custom/ai-search" +import { Topic } from "@/lib/schema" +import { PublicGlobalGroup } from "@/lib/schema/master/public-group" +import { ID } from "jazz-tools" +import Link from "next/link" -interface ProfileTopicsProps { - topic: string -} - -const ProfileTopics: React.FC = ({ topic }) => { - return ( -
-

{topic}

- -
- ) -} - -interface ProfileLinksProps { - linklabel: string - link: string - topic: string -} - -interface ProfileTitleProps { +interface SearchTitleProps { + topics: string[] topicTitle: string - spanNumber: number } -const ProfileTitle: React.FC = ({ topicTitle, spanNumber }) => { +const SearchTitle: React.FC = ({ topicTitle, topics }) => { return ( -

- {topicTitle} {spanNumber} -

- ) -} - -const ProfileLinks: React.FC = ({ linklabel, link, topic }) => { - return ( -
-
-

{linklabel}

-
-

{link}

-
-
-
- {topic} +
+

{topicTitle}

+
+
+ {topics.length}
) } export const SearchWrapper = () => { - // const account = useAccount() const [searchText, setSearchText] = useState("") - const [aiSearch, setAiSearch] = useState("") const [showAiSearch, setShowAiSearch] = useState(false) - const [showAiPlaceholder, setShowAiPlaceholder] = useState(false) + const [searchResults, setSearchResults] = useState([]) - const inputChange = (e: React.ChangeEvent) => { - setSearchText(e.target.value) - if (e.target.value.trim() !== "") { - setShowAiPlaceholder(false) - setTimeout(() => setShowAiPlaceholder(true), 1000) - } else { - setShowAiPlaceholder(false) - setShowAiSearch(false) + const globalGroup = useCoState( + PublicGlobalGroup, + process.env.NEXT_PUBLIC_JAZZ_GLOBAL_GROUP as ID, + { + root: { + topics: [] + } } + ) + const handleSearch = (e: React.ChangeEvent) => { + const value = e.target.value + setSearchText(value) + + const results = value + ? globalGroup?.root.topics.filter( + (topic): topic is Topic => topic !== null && topic.prettyName.toLowerCase().startsWith(value.toLowerCase()) + ) + : [] + setSearchResults(results) } const clearSearch = () => { setSearchText("") - setShowAiSearch(false) - setShowAiPlaceholder(false) - } - - const handleKeyDown = (e: React.KeyboardEvent) => { - if (e.key === "Enter" && searchText.trim() !== "") { - setShowAiSearch(true) - setAiSearch(searchText) - } + setSearchResults([]) } return (
-
+
-
- - - - {showAiPlaceholder && searchText && !showAiSearch && ( -
- press "Enter" for AI search -
- )} - {searchText && ( - +
+ + + + {searchText && ( + + )} +
+
+
+ {searchResults.length > 0 ? ( +
+ topic.prettyName)} /> + {searchResults.map((topic, index) => ( +
+ +
+ e.stopPropagation()} + className="hover:text-primary text-sm font-medium hover:opacity-70" + > + {topic.prettyName} + + {topic.latestGlobalGuide?.sections?.reduce( + (total, section) => total + (section?.links?.length || 0), + 0 + ) || 0}{" "} + links + + +
+
+ ))} +
+ ) : ( +
+ {searchText && searchResults.length === 0 && !showAiSearch && ( +
setShowAiSearch(true)} + > + ✨ Didn't find what you were looking for? Ask AI +
+ )} + {showAiSearch && } +
)}
-
✨ Ask AI
- {showAiSearch ? ( -
-
- -
-
- ) : ( - <> -
- - -
-
- - - - -
- - )}