aboutsummaryrefslogtreecommitdiff
path: root/apps/web/app/(dash)/home
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/app/(dash)/home')
-rw-r--r--apps/web/app/(dash)/home/history.tsx106
-rw-r--r--apps/web/app/(dash)/home/page.tsx61
-rw-r--r--apps/web/app/(dash)/home/queryinput.tsx60
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>