aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorcodetorso <[email protected]>2024-07-18 18:18:01 +0530
committercodetorso <[email protected]>2024-07-18 18:18:01 +0530
commitd7491e0dbcb11f267d79dee3376fed8f63157149 (patch)
tree2021e13c7ad65fa9ac1afc350d40bc3e4b11ed73 /apps
parentig I need to commit lockfile (diff)
downloadsupermemory-d7491e0dbcb11f267d79dee3376fed8f63157149.tar.xz
supermemory-d7491e0dbcb11f267d79dee3376fed8f63157149.zip
Refactor and add beutiful spacefilter
Diffstat (limited to 'apps')
-rw-r--r--apps/web/app/(dash)/home/filterSpaces.tsx89
-rw-r--r--apps/web/app/(dash)/home/page.tsx1
-rw-r--r--apps/web/app/(dash)/home/queryinput.tsx132
3 files changed, 112 insertions, 110 deletions
diff --git a/apps/web/app/(dash)/home/filterSpaces.tsx b/apps/web/app/(dash)/home/filterSpaces.tsx
new file mode 100644
index 00000000..6a8ad9ec
--- /dev/null
+++ b/apps/web/app/(dash)/home/filterSpaces.tsx
@@ -0,0 +1,89 @@
+import { ChevronUpDownIcon } from "@heroicons/react/24/outline";
+import {
+ Command,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+} from "@repo/ui/shadcn/command";
+import { Check } from "lucide-react";
+import React, { useState } from "react";
+
+type space = {
+ id: number;
+ name: string;
+};
+
+export function FilterSpaces({
+ initialSpaces,
+ selectedSpaces,
+ setSelectedSpaces
+}: {
+ initialSpaces: space[];
+ selectedSpaces: space[];
+ setSelectedSpaces: React.Dispatch<React.SetStateAction<space[]>>
+}) {
+ const [input, setInput] = useState<string>("");
+
+ const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
+ if (e.key === "Backspace" && input === "") {
+ setSelectedSpaces((prevValue) => prevValue.slice(0, -1));
+ }
+ };
+
+ const handleSelect = (selectedSpace: space) => {
+ setSelectedSpaces((current) =>
+ current.some((space) => space.id === selectedSpace.id)
+ ? current.filter((space) => space.id !== selectedSpace.id)
+ : [...current, selectedSpace]
+ );
+ };
+
+ return (
+ <div className={`flex rounded-md overflow-hidden ${selectedSpaces.length ? "bg-[#2C3338]" : ""}`}>
+ <div className="flex rounded-lg items-center">
+ {selectedSpaces.map((v) => (
+ <button
+ key={v.id}
+ onClick={() => handleSelect(v)}
+ className="bg-[#3a4248] max-w-32 truncate-wor truncate whitespace-nowrap py-1 rounded-md px-2 mx-1 aria-selected:outline"
+ >
+ {v.name}
+ </button>
+ ))}
+ </div>
+ <Command className={`group border-0 bg-[rgb(44,51,56)] text-white outline-0 ${selectedSpaces.length ? "w-full" : "w-44"}`}>
+ <div className="relative">
+ <CommandInput
+ placeholder={selectedSpaces.length ? "" : "Search in Spaces"}
+ onKeyDown={handleKeyDown}
+ className="text-white peer placeholder:text-white"
+ // @ts-ignore - trust me bro it works
+ onChange={(e) => setInput(e.currentTarget.value)}
+ value={input}
+ />
+ <ChevronUpDownIcon
+ className={`h-6 w-6 text-[#858B92] absolute top-1/2 right-4 -translate-y-1/2 ${selectedSpaces.length && "opacity-0"}`}
+ />
+ </div>
+ <CommandList className="z-10 translate-y-12 translate-x-5 opacity-0 absolute group-focus-within:opacity-100 transition-opacity p-2 rounded-b-xl max-w-64 bg-[#2C3338]">
+ <CommandGroup className="hidden group-focus-within:block">
+ {initialSpaces.map((space) => (
+ <CommandItem
+ className="text-[#eaeaea] data-[disabled]:opacity-90"
+ value={space.name}
+ key={space.id}
+ onSelect={() => handleSelect(space)}
+ >
+ <Check
+ className={`mr-2 h-4 w-4 ${selectedSpaces.some((v) => v.id === space.id) ? "opacity-100" : "opacity-0"}`}
+ />
+ {space.name}
+ </CommandItem>
+ ))}
+ </CommandGroup>
+ </CommandList>
+ </Command>
+ </div>
+ );
+}
diff --git a/apps/web/app/(dash)/home/page.tsx b/apps/web/app/(dash)/home/page.tsx
index 68a14d53..43a4faa1 100644
--- a/apps/web/app/(dash)/home/page.tsx
+++ b/apps/web/app/(dash)/home/page.tsx
@@ -83,7 +83,6 @@ function Page({
);
}}
initialSpaces={spaces}
- setInitialSpaces={setSpaces}
/>
</div>
</div>
diff --git a/apps/web/app/(dash)/home/queryinput.tsx b/apps/web/app/(dash)/home/queryinput.tsx
index c7267298..f402b11b 100644
--- a/apps/web/app/(dash)/home/queryinput.tsx
+++ b/apps/web/app/(dash)/home/queryinput.tsx
@@ -2,23 +2,17 @@
import { ArrowRightIcon } from "@repo/ui/icons";
import Image from "next/image";
-import React, { useEffect, useMemo, useState } from "react";
+import React, { useState } from "react";
import Divider from "@repo/ui/shadcn/divider";
-import { useRouter } from "next/navigation";
-import { getSpaces } from "@/app/actions/fetchers";
-import Combobox from "@repo/ui/shadcn/combobox";
-import { MinusIcon } from "lucide-react";
-import { toast } from "sonner";
-import { createSpace } from "@/app/actions/doers";
+import { FilterSpaces } from "./filterSpaces";
function QueryInput({
+ initialSpaces,
initialQuery = "",
- initialSpaces = [],
disabled = false,
className,
mini = false,
handleSubmit,
- setInitialSpaces,
}: {
initialQuery?: string;
initialSpaces?: {
@@ -29,45 +23,25 @@ function QueryInput({
className?: string;
mini?: boolean;
handleSubmit: (q: string, spaces: { id: number; name: string }[]) => void;
- setInitialSpaces?: React.Dispatch<
- React.SetStateAction<{ id: number; name: string }[]>
- >;
}) {
const [q, setQ] = useState(initialQuery);
- const [selectedSpaces, setSelectedSpaces] = useState<number[]>([]);
-
- const options = useMemo(
- () =>
- initialSpaces.map((x) => ({
- label: x.name,
- value: x.id.toString(),
- })),
- [initialSpaces],
- );
-
- const preparedSpaces = useMemo(
- () =>
- initialSpaces
- .filter((x) => selectedSpaces.includes(x.id))
- .map((x) => {
- return {
- id: x.id,
- name: x.name,
- };
- }),
- [selectedSpaces, initialSpaces],
- );
+ const [selectedSpaces, setSelectedSpaces] = useState<
+ { id: number; name: string }[]
+ >([]);
return (
<div className={`${className}`}>
<div
- className={`bg-secondary border-2 border-b-0 border-border ${!mini ? "rounded-t-3xl" : "rounded-3xl"}`}
+ className={`bg-[#1F2428] overflow-hidden border-2 border-gray-700/50 shadow-md shadow-[#1d1d1dc7] rounded-3xl`}
>
{/* input and action button */}
<form
action={async () => {
- handleSubmit(q, preparedSpaces);
+ if (q.trim().length === 0) {
+ return;
+ }
+ handleSubmit(q, selectedSpaces);
setQ("");
}}
className="flex gap-4 p-3"
@@ -85,7 +59,7 @@ function QueryInput({
if (q.trim().length === 0) {
return;
}
- handleSubmit(q, preparedSpaces);
+ handleSubmit(q, selectedSpaces);
setQ("");
}
}}
@@ -96,84 +70,24 @@ function QueryInput({
<button
type="submit"
- onClick={(e) => {
- e.preventDefault();
- if (q.trim().length === 0) {
- return;
- }
- handleSubmit(q, preparedSpaces);
- }}
disabled={disabled}
className="h-12 w-12 rounded-[14px] bg-border 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>
+ </form>{" "}
+ {!mini && (
+ <>
+ <Divider />
+ <FilterSpaces
+ selectedSpaces={selectedSpaces}
+ setSelectedSpaces={setSelectedSpaces}
+ initialSpaces={initialSpaces || []}
+ />
+ </>
+ )}
</div>
{/* selected sources */}
- {!mini && (
- <>
- <Divider />
- <div className="flex justify-between items-center gap-6 h-auto bg-secondary rounded-b-3xl border-2 border-border">
- <Combobox
- options={options}
- className="rounded-bl-3xl bg-[#3C464D] w-44"
- onSelect={(v) =>
- setSelectedSpaces((prev) => {
- if (v === "") {
- return [];
- }
- return [...prev, parseInt(v)];
- })
- }
- onSubmit={async (spaceName) => {
- const space = options.find((x) => x.label === spaceName);
- toast.info("Creating space...");
-
- if (space) {
- toast.error("A space with that name already exists.");
- }
-
- const creationTask = await createSpace(spaceName);
- if (creationTask.success && creationTask.data) {
- toast.success("Space created " + creationTask.data);
- setInitialSpaces?.((prev) => [
- ...prev,
- {
- name: spaceName,
- id: creationTask.data!,
- },
- ]);
- setSelectedSpaces((prev) => [...prev, creationTask.data!]);
- } else {
- toast.error(
- "Space creation failed: " + creationTask.error ??
- "Unknown error",
- );
- }
- }}
- placeholder="Chat with a space..."
- />
-
- <div className="flex flex-row gap-0.5 h-full">
- {preparedSpaces.map((x, idx) => (
- <button
- key={x.id}
- onClick={() =>
- setSelectedSpaces((prev) => prev.filter((y) => y !== x.id))
- }
- className={`relative group p-2 py-3 bg-[#3C464D] max-w-32 ${idx === preparedSpaces.length - 1 ? "rounded-br-xl" : ""}`}
- >
- <p className="line-clamp-1">{x.name}</p>
- <div className="absolute h-full right-0 top-0 p-1 opacity-0 group-hover:opacity-100 items-center">
- <MinusIcon className="w-6 h-6 rounded-full bg-secondary" />
- </div>
- </button>
- ))}
- </div>
- </div>
- </>
- )}
</div>
);
}