diff options
Diffstat (limited to 'apps/web/app/(dash)/home')
| -rw-r--r-- | apps/web/app/(dash)/home/history.tsx | 106 | ||||
| -rw-r--r-- | apps/web/app/(dash)/home/page.tsx | 61 | ||||
| -rw-r--r-- | apps/web/app/(dash)/home/queryinput.tsx | 60 |
3 files changed, 118 insertions, 109 deletions
diff --git a/apps/web/app/(dash)/home/history.tsx b/apps/web/app/(dash)/home/history.tsx index 3d8d5a28..a4cd11d0 100644 --- a/apps/web/app/(dash)/home/history.tsx +++ b/apps/web/app/(dash)/home/history.tsx @@ -1,53 +1,65 @@ -import { getChatHistory } from '@repo/web/app/actions/fetchers'; -import { ArrowLongRightIcon } from '@heroicons/react/24/outline'; -import { Skeleton } from '@repo/ui/shadcn/skeleton'; -import Link from 'next/link'; -import { memo, useEffect, useState } from 'react'; -import { motion } from 'framer-motion'; -import { chatThreads } from '@/server/db/schema'; +import { ArrowLongRightIcon } from "@heroicons/react/24/outline"; +import { Skeleton } from "@repo/ui/shadcn/skeleton"; +import { memo, useEffect, useState } from "react"; +import { motion } from "framer-motion"; +import { getQuerySuggestions } from "@/app/actions/doers"; -const History = memo(() => { - const [chatThreads_, setChatThreads] = useState< - (typeof chatThreads.$inferSelect)[] | null - >(null); +const History = memo(({ setQuery }: { setQuery: (q: string) => void }) => { + const [suggestions, setSuggestions] = useState<string[] | null>(null); - useEffect(() => { - (async () => { - const chatThreads = await getChatHistory(); - if (!chatThreads.success || !chatThreads.data) { - console.error(chatThreads.error); - return; - } - setChatThreads(chatThreads.data.reverse().slice(0, 3)); - })(); - }, []); + useEffect(() => { + (async () => { + const suggestions = await getQuerySuggestions(); + if (!suggestions.success || !suggestions.data) { + console.error(suggestions.error); + setSuggestions([]); + return; + } + console.log(suggestions); + if (typeof suggestions.data === "string") { + const queries = suggestions.data.slice(1, -1).split(", "); + const parsedQueries = queries.map((query) => + query.replace(/^'|'$/g, ""), + ); + console.log(parsedQueries); + setSuggestions(parsedQueries); + return; + } + setSuggestions(suggestions.data.reverse().slice(0, 3)); + })(); + }, []); - if (!chatThreads) { - return ( - <> - <Skeleton className="w-[80%] h-4 bg-[#3b444b] "></Skeleton> - <Skeleton className="w-[40%] h-4 bg-[#3b444b] "></Skeleton> - <Skeleton className="w-[60%] h-4 bg-[#3b444b] "></Skeleton> - </> - ); - } - - return ( - <ul className="text-base list-none space-y-3 text-[#b9b9b9] mt-8"> - {chatThreads_?.map((thread) => ( - <motion.li - initial={{ opacity: 0, filter: 'blur(1px)' }} - animate={{ opacity: 1, filter: 'blur(0px)' }} - className="flex items-center gap-2 truncate" - > - <ArrowLongRightIcon className="h-5" />{' '} - <Link prefetch={false} href={`/chat/${thread.id}`}> - {thread.firstMessage} - </Link> - </motion.li> - ))} - </ul> - ); + return ( + <ul className="text-base list-none space-y-3 text-[#b9b9b9] mt-8"> + {!suggestions && ( + <> + <Skeleton + key="loader-1" + className="w-[80%] h-4 bg-[#3b444b] " + ></Skeleton> + <Skeleton + key="loader-2" + className="w-[40%] h-4 bg-[#3b444b] " + ></Skeleton> + <Skeleton + key="loader-3" + className="w-[60%] h-4 bg-[#3b444b] " + ></Skeleton> + </> + )} + {suggestions?.map((suggestion) => ( + <motion.li + initial={{ opacity: 0, filter: "blur(1px)" }} + animate={{ opacity: 1, filter: "blur(0px)" }} + className="flex items-center gap-2 truncate cursor-pointer" + key={suggestion} + onClick={() => setQuery(suggestion)} + > + <ArrowLongRightIcon className="h-5" /> {suggestion} + </motion.li> + ))} + </ul> + ); }); export default History; diff --git a/apps/web/app/(dash)/home/page.tsx b/apps/web/app/(dash)/home/page.tsx index cc1856b4..d192d07d 100644 --- a/apps/web/app/(dash)/home/page.tsx +++ b/apps/web/app/(dash)/home/page.tsx @@ -4,12 +4,15 @@ import React, { useEffect, useState } from "react"; import QueryInput from "./queryinput"; import { getSessionAuthToken, getSpaces } from "@/app/actions/fetchers"; import { redirect, useRouter } from "next/navigation"; -import { createChatThread, linkTelegramToUser } from "@/app/actions/doers"; +import { + createChatThread, + getQuerySuggestions, + linkTelegramToUser, +} from "@/app/actions/doers"; import { toast } from "sonner"; import { motion } from "framer-motion"; -import { ChromeIcon, GithubIcon, TwitterIcon } from "lucide-react"; +import { ChromeIcon, GithubIcon, MailIcon, TwitterIcon } from "lucide-react"; import Link from "next/link"; -import { homeSearchParamsCache } from "@/lib/searchParams"; import History from "./history"; const slap = { @@ -26,28 +29,14 @@ const slap = { }; function Page({ searchParams }: { searchParams: Record<string, string> }) { - // TODO: use this to show a welcome page/modal - const firstTime = searchParams.firstTime === "true"; + const telegramUser = searchParams.telegramUser; + const extensionInstalled = searchParams.extension; + const [query, setQuery] = useState(searchParams.q || ""); - const query = searchParams.q || ""; - - if (firstTime) { - redirect("/onboarding"); - } - - const [queryPresent, setQueryPresent] = useState<boolean>(false); - - const [telegramUser, setTelegramUser] = useState<string | undefined>( - searchParams.telegramUser as string, - ); - const [extensionInstalled, setExtensionInstalled] = useState< - string | undefined - >(searchParams.extension as string); + const [spaces, setSpaces] = useState<{ id: number; name: string }[]>([]); const { push } = useRouter(); - const [spaces, setSpaces] = useState<{ id: number; name: string }[]>([]); - useEffect(() => { if (telegramUser) { const linkTelegram = async () => { @@ -63,10 +52,6 @@ function Page({ searchParams }: { searchParams: Record<string, string> }) { linkTelegram(); } - if (extensionInstalled) { - toast.success("Extension installed successfully"); - } - getSpaces().then((res) => { if (res.success && res.data) { setSpaces(res.data); @@ -77,21 +62,21 @@ function Page({ searchParams }: { searchParams: Record<string, string> }) { getSessionAuthToken().then((token) => { if (typeof window === "undefined") return; + if (extensionInstalled) { + toast.success("Extension installed successfully"); + } window.postMessage({ token: token.data }, "*"); }); }, [telegramUser]); return ( <div className="max-w-3xl h-full justify-center flex mx-auto w-full flex-col px-2 md:px-0"> - {/* all content goes here */} - {/* <div className="">hi {firstTime ? 'first time' : ''}</div> */} - <motion.h1 {...{ ...slap, transition: { ...slap.transition, delay: 0.2 }, }} - className="text-center mx-auto bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)] bg-clip-text text-4xl tracking-tighter text-transparent md:text-5xl" + className="text-center mx-auto bg-[linear-gradient(180deg,_#FFF_0%,_rgba(255,_255,_255,_0.00)_202.08%)] bg-clip-text text-4xl tracking-tighter text-transparent md:text-5xl pb-2" > <span>Ask your</span>{" "} <span className="inline-flex items-center gap-2 bg-gradient-to-r to-blue-300 from-zinc-300 text-transparent bg-clip-text"> @@ -99,17 +84,16 @@ function Page({ searchParams }: { searchParams: Record<string, string> }) { </span> </motion.h1> - <div className="w-full pb-20 mt-12"> + <div className="w-full pb-20 mt-10"> <QueryInput - initialQuery={query} - setQueryPresent={setQueryPresent} - handleSubmit={async (q, spaces) => { + query={query} + setQuery={setQuery} + handleSubmit={async (q, spaces, proMode) => { if (q.length === 0) { toast.error("Query is required"); return; } - console.log("creating thread"); const threadid = await createChatThread(q); if (!threadid.success || !threadid.data) { @@ -117,15 +101,14 @@ function Page({ searchParams }: { searchParams: Record<string, string> }) { return; } - console.log("pushing to chat"); push( - `/chat/${threadid.data}?spaces=${JSON.stringify(spaces)}&q=${q}`, + `/chat/${threadid.data}?spaces=${JSON.stringify(spaces)}&q=${q}&proMode=${proMode}`, ); }} initialSpaces={spaces} /> - <History /> + <History setQuery={setQuery} /> </div> <div className="w-full fixed bottom-0 left-0 p-4"> @@ -140,12 +123,12 @@ function Page({ searchParams }: { searchParams: Record<string, string> }) { Install extension </Link> <Link - href="https://github.com/supermemoryai/supermemory/issues/new" + href="mailto:[email protected]" target="_blank" rel="noreferrer" className="flex items-center gap-2 text-muted-foreground hover:text-grey-50 duration-300" > - <GithubIcon className="w-4 h-4" /> + <MailIcon className="w-4 h-4" /> Bug report </Link> <Link diff --git a/apps/web/app/(dash)/home/queryinput.tsx b/apps/web/app/(dash)/home/queryinput.tsx index e49f06e0..82561438 100644 --- a/apps/web/app/(dash)/home/queryinput.tsx +++ b/apps/web/app/(dash)/home/queryinput.tsx @@ -1,26 +1,32 @@ "use client"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { FilterSpaces } from "./filterSpaces"; import { ArrowRightIcon } from "@repo/ui/icons"; import Image from "next/image"; +import { Switch } from "@repo/ui/shadcn/switch"; +import { Label } from "@repo/ui/shadcn/label"; function QueryInput({ - setQueryPresent, - initialQuery, initialSpaces, handleSubmit, + query, + setQuery, }: { - setQueryPresent: (t: boolean) => void; initialSpaces?: { id: number; name: string; }[]; - initialQuery?: string; mini?: boolean; - handleSubmit: (q: string, spaces: { id: number; name: string }[]) => void; + handleSubmit: ( + q: string, + spaces: { id: number; name: string }[], + proMode: boolean, + ) => void; + query: string; + setQuery: (q: string) => void; }) { - const [q, setQ] = useState(initialQuery || ""); + const [proMode, setProMode] = useState(false); const [selectedSpaces, setSelectedSpaces] = useState< { id: number; name: string }[] @@ -34,11 +40,11 @@ function QueryInput({ {/* input and action button */} <form action={async () => { - if (q.trim().length === 0) { + if (query.trim().length === 0) { return; } - handleSubmit(q, selectedSpaces); - setQ(""); + handleSubmit(query, selectedSpaces, proMode); + setQuery(""); }} > <textarea @@ -51,20 +57,15 @@ function QueryInput({ onKeyDown={(e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); - if (q.trim().length === 0) { + if (query.trim().length === 0) { return; } - handleSubmit(q, selectedSpaces); - setQ(""); + handleSubmit(query, selectedSpaces, proMode); + setQuery(""); } }} - onChange={(e) => - setQ((prev) => { - setQueryPresent(!!e.target.value.length); - return e.target.value; - }) - } - value={q} + onChange={(e) => setQuery(e.target.value)} + value={query} /> <div className="flex p-2 px-3 w-full items-center justify-between rounded-xl overflow-hidden"> <FilterSpaces @@ -72,9 +73,22 @@ function QueryInput({ setSelectedSpaces={setSelectedSpaces} initialSpaces={initialSpaces || []} /> - <button type="submit" className="rounded-lg bg-[#369DFD1A] p-3"> - <Image src={ArrowRightIcon} alt="Enter" /> - </button> + <div className="flex items-center gap-4"> + <div className="flex items-center gap-2"> + <Label htmlFor="pro-mode" className="text-sm text-[#9B9B9B]"> + Pro mode + </Label> + <Switch + value={proMode ? "on" : "off"} + onCheckedChange={(v) => setProMode(v)} + id="pro-mode" + about="Pro mode" + /> + </div> + <button type="submit" className="rounded-lg bg-[#369DFD1A] p-3"> + <Image src={ArrowRightIcon} alt="Enter" /> + </button> + </div> </div> </form> </div> |