aboutsummaryrefslogtreecommitdiff
path: root/apps/web/app
diff options
context:
space:
mode:
authorDhravya <[email protected]>2024-06-01 21:21:52 -0500
committerDhravya <[email protected]>2024-06-01 21:21:52 -0500
commitf105a2fd92c25a75668c3615cd8328fa875050d8 (patch)
treedb5c8cd657623016029143b4123878ac6b025f2a /apps/web/app
parentstarted implmeneting filter (diff)
downloadsupermemory-f105a2fd92c25a75668c3615cd8328fa875050d8.tar.xz
supermemory-f105a2fd92c25a75668c3615cd8328fa875050d8.zip
commented the backend code with it's limitations + optimised and removed a bunch of unnecessary queries
Diffstat (limited to 'apps/web/app')
-rw-r--r--apps/web/app/chat/page.tsx23
-rw-r--r--apps/web/app/globals.css48
-rw-r--r--apps/web/app/helpers/lib/searchParams.ts7
-rw-r--r--apps/web/app/home/actions.ts6
-rw-r--r--apps/web/app/home/page.tsx1
-rw-r--r--apps/web/app/home/queryinput.tsx152
-rw-r--r--apps/web/app/layout.tsx1
7 files changed, 108 insertions, 130 deletions
diff --git a/apps/web/app/chat/page.tsx b/apps/web/app/chat/page.tsx
index fce4bfd1..bfe0c362 100644
--- a/apps/web/app/chat/page.tsx
+++ b/apps/web/app/chat/page.tsx
@@ -1,7 +1,24 @@
-import React from "react";
+import { chatSearchParamsCache } from "../helpers/lib/searchParams";
+import Menu from "../home/menu";
+import Header from "../home/header";
+import ChatWindow from "./chatWindow";
-function Page() {
- return <div>Page</div>;
+function Page({
+ searchParams,
+}: {
+ searchParams: Record<string, string | string[] | undefined>;
+}) {
+ const { firstTime, q, spaces } = chatSearchParamsCache.parse(searchParams);
+
+ return (
+ <main className="h-screen flex flex-col p-4 relative">
+ <Menu />
+
+ <Header />
+
+ <ChatWindow q={q} spaces={spaces ?? []} />
+ </main>
+ );
}
export default Page;
diff --git a/apps/web/app/globals.css b/apps/web/app/globals.css
deleted file mode 100644
index b1902464..00000000
--- a/apps/web/app/globals.css
+++ /dev/null
@@ -1,48 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-/* :root {
- --foreground-rgb: 0, 0, 0;
- --background-start-rgb: 214, 219, 220;
- --background-end-rgb: 255, 255, 255;
-} */
-
-@media (prefers-color-scheme: dark) {
- :root {
- --foreground: rgba(179, 188, 197, 1);
- --foreground-menu: rgba(106, 115, 125, 1);
- --background: rgba(23, 27, 31, 1);
- --secondary: rgba(31, 36, 40, 1);
- --primary: rgba(54, 157, 253, 1);
- --border: rgba(51, 57, 67, 1);
- }
-}
-
-body {
- color: var(--foreground);
- background: var(--background);
- font-size: 14px;
-}
-
-@layer base {
- .all-center {
- display: flex;
- align-items: center;
- justify-content: center;
- }
-}
-
-@layer utilities {
- .text-balance {
- text-wrap: balance;
- }
-}
-
-.gradient-background {
- background: linear-gradient(
- 150deg,
- rgba(255, 255, 255, 0.1) 0%,
- rgba(255, 255, 255, 0)
- );
-}
diff --git a/apps/web/app/helpers/lib/searchParams.ts b/apps/web/app/helpers/lib/searchParams.ts
index a43a28fe..2e02aa3e 100644
--- a/apps/web/app/helpers/lib/searchParams.ts
+++ b/apps/web/app/helpers/lib/searchParams.ts
@@ -3,8 +3,15 @@ import {
parseAsInteger,
parseAsString,
parseAsBoolean,
+ parseAsArrayOf,
} from "nuqs/server";
export const homeSearchParamsCache = createSearchParamsCache({
firstTime: parseAsBoolean.withDefault(false),
});
+
+export const chatSearchParamsCache = createSearchParamsCache({
+ firstTime: parseAsBoolean.withDefault(false),
+ q: parseAsString.withDefault(""),
+ spaces: parseAsArrayOf(parseAsInteger, ","),
+});
diff --git a/apps/web/app/home/actions.ts b/apps/web/app/home/actions.ts
index 0bb2d051..908fe79e 100644
--- a/apps/web/app/home/actions.ts
+++ b/apps/web/app/home/actions.ts
@@ -1,7 +1 @@
"use server";
-
-import { redirect } from "next/navigation";
-
-export async function navigate(q: string) {
- redirect(`/chat?q=${q}`);
-}
diff --git a/apps/web/app/home/page.tsx b/apps/web/app/home/page.tsx
index d9025a9d..9908c017 100644
--- a/apps/web/app/home/page.tsx
+++ b/apps/web/app/home/page.tsx
@@ -9,6 +9,7 @@ function Page({
}: {
searchParams: Record<string, string | string[] | undefined>;
}) {
+ // TODO: use this to show a welcome page/modal
const { firstTime } = homeSearchParamsCache.parse(searchParams);
return (
diff --git a/apps/web/app/home/queryinput.tsx b/apps/web/app/home/queryinput.tsx
index c394d9c6..a0e25d83 100644
--- a/apps/web/app/home/queryinput.tsx
+++ b/apps/web/app/home/queryinput.tsx
@@ -1,88 +1,96 @@
"use client";
-import { ArrowRightIcon, MemoriesIcon, SelectIcon } from "@repo/ui/icons";
+import { ArrowRightIcon } from "@repo/ui/icons";
import Image from "next/image";
-import React from "react";
+import React, { useCallback, useState } from "react";
import Divider from "@repo/ui/shadcn/divider";
-import { redirect } from "next/navigation";
-import { navigate } from "./actions";
-import { FilterSpaces } from "@repo/ui/components/filterSpaces";
+import { MultipleSelector, Option } from "@repo/ui/shadcn/combobox";
+import { AnimatePresence } from "framer-motion";
+import { useRouter } from "next/navigation";
-function QueryInput() {
- const [q, setQ] = React.useState("");
+const OPTIONS: Option[] = [
+ { label: "nextjs", value: "0" },
+ { label: "React", value: "1" },
+ { label: "Remix", value: "2" },
+ { label: "Vite", value: "3" },
+ { label: "Nuxt", value: "4" },
+ { label: "Vue", value: "5" },
+ { label: "Svelte", value: "6" },
+ { label: "Angular", value: "7" },
+ { label: "Ember", value: "8" },
+ { label: "Gatsby", value: "9" },
+];
- const parseQ = React.useCallback(() => {
- const newQ = q.replace(/\n/g, "\\n");
- return newQ;
- }, [q]);
+function QueryInput({
+ initialQuery = "",
+ initialSpaces = [],
+ disabled = false,
+}: {
+ initialQuery?: string;
+ initialSpaces?: number[];
+ disabled?: boolean;
+}) {
+ const [q, setQ] = useState(initialQuery);
- const [selectedSpaces, setSelectedSpaces] = React.useState<number[]>([]);
+ const [selectedSpaces, setSelectedSpaces] = useState<number[]>(initialSpaces);
- return (
- <div className="bg-secondary rounded-[24px] w-full mt-40">
- {/* input and action button */}
- <form action={async () => navigate(parseQ())} className="flex gap-4 p-3">
- <textarea
- name="q"
- cols={30}
- rows={4}
- className="bg-transparent pt-2.5 text-base text-[#989EA4] focus:text-foreground duration-200 tracking-[3%] outline-none resize-none w-full p-4"
- placeholder="Ask your second brain..."
- onKeyDown={(e) => {
- if (e.key === "Enter") {
- e.preventDefault();
- if (!e.shiftKey) navigate(parseQ());
- }
- }}
- onChange={(e) => setQ(e.target.value)}
- value={q}
- />
+ const { push } = useRouter();
- <button
- type="submit"
- className="h-12 w-12 rounded-[14px] bg-[#21303D] all-center shrink-0 hover:brightness-125 duration-200 outline-none focus:outline focus:outline-primary active:scale-90"
- >
- <Image src={ArrowRightIcon} alt="Right arrow icon" />
- </button>
- </form>
+ const parseQ = () => {
+ const newQ =
+ "/chat?q=" +
+ encodeURI(q) +
+ (selectedSpaces ? "&spaces=" + selectedSpaces.join(",") : "");
- <Divider />
+ return newQ;
+ };
+ return (
+ <div>
+ <div className="bg-secondary rounded-t-[24px] w-full mt-40">
+ {/* input and action button */}
+ <form action={async () => push(parseQ())} className="flex gap-4 p-3">
+ <textarea
+ name="q"
+ cols={30}
+ rows={4}
+ className="bg-transparent pt-2.5 text-base text-[#989EA4] focus:text-foreground duration-200 tracking-[3%] outline-none resize-none w-full p-4"
+ placeholder="Ask your second brain..."
+ onKeyDown={(e) => {
+ if (e.key === "Enter") {
+ e.preventDefault();
+ if (!e.shiftKey) push(parseQ());
+ }
+ }}
+ onChange={(e) => setQ(e.target.value)}
+ value={q}
+ disabled={disabled}
+ />
+
+ <button
+ type="submit"
+ disabled={disabled}
+ className="h-12 w-12 rounded-[14px] bg-[#21303D] all-center shrink-0 hover:brightness-125 duration-200 outline-none focus:outline focus:outline-primary active:scale-90"
+ >
+ <Image src={ArrowRightIcon} alt="Right arrow icon" />
+ </button>
+ </form>
+
+ <Divider />
+ </div>
{/* selected sources */}
- <div className="flex items-center gap-6 p-2">
- {/* <button className="bg-[#2B3237] h-9 p-2 px-3 flex items-center gap-2 rounded-full">
- <Image src={MemoriesIcon} alt="Memories icon" className="w-5" />
- <span className="pr-3">Filters</span>
- <Image src={SelectIcon} alt="Select icon" className="w-4" />
- </button> */}
- <FilterSpaces
- name="Filters"
- selectedSpaces={selectedSpaces}
- setSelectedSpaces={setSelectedSpaces}
- // side="top"
- // align="start"
- // className="mr-auto bg-[#252525] md:hidden"
- spaces={[
- {
- name: "Nvidia",
- id: 2,
- },
- {
- name: "Open-source",
- id: 3,
- },
- {
- name: "Artificial Intelligence",
- id: 4,
- },
- ]}
+ <div className="flex items-center gap-6 p-2 h-auto bg-secondary rounded-b-[24px]">
+ <MultipleSelector
+ disabled={disabled}
+ defaultOptions={OPTIONS}
+ onChange={(e) => setSelectedSpaces(e.map((x) => parseInt(x.value)))}
+ placeholder="Focus on specific spaces..."
+ emptyIndicator={
+ <p className="text-center text-lg leading-10 text-gray-600 dark:text-gray-400">
+ no results found.
+ </p>
+ }
/>
-
- <div className="flex gap-6 brightness-75">
- <p>Nvidia</p>
- <p>Open-source</p>
- <p>Artificial Intelligence</p>
- </div>
</div>
</div>
);
diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx
index 37541f04..8d7cd5ea 100644
--- a/apps/web/app/layout.tsx
+++ b/apps/web/app/layout.tsx
@@ -1,4 +1,3 @@
-// import "./globals.css";
import "@repo/tailwind-config/globals.css";
import type { Metadata } from "next";