1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
import React, { useState } from "react";
import { ArrowLeftIcon, Cog6ToothIcon } from "@heroicons/react/16/solid";
import Link from "next/link";
import Card from "./sidepanelcard";
import { sourcesZod } from "@repo/shared-types";
import { toast } from "sonner";
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
type card = {
title: string;
type: string;
source: string;
content: string;
numChunks: string;
};
function Sidepanel() {
const [content, setContent] = useState<card[]>([]);
return (
<div className="h-[98vh] bg-[#1f2428] rounded-xl overflow-hidden">
<div className="flex bg-[#2C3439] items-center py-2 px-4 mb-2 text-lg">
<Link
href="/thinkpad"
className="p-2 px-4 transition-colors rounded-lg hover:bg-[#334044] flex items-center gap-2"
>
<ArrowLeftIcon className="h-5 w-5" />
Back
</Link>
</div>
<div className="h-full px-2">
<div className=" p-2 h-full">
<Search setContent={setContent} />
<div className="py-5 space-y-4">
{content.map((v, i) => (
<Card {...v} />
))}
</div>
</div>
</div>
</div>
);
}
function Search({ setContent }: { setContent: (e: any) => void }) {
return (
<form
className="flex justify-between items-center rounded-md bg-[#121718]"
action={async (FormData) => {
const search = FormData.get("search") as string;
const sourcesFetch = await fetch("/api/canvasai", {
method: "POST",
body: JSON.stringify({ query: search }),
});
const sources = await sourcesFetch.json();
console.log(sources);
const sourcesParsed = sourcesZod.safeParse(sources);
if (!sourcesParsed.success) {
console.error(sourcesParsed.error);
toast.error("Something went wrong while getting the sources");
return;
}
const filteredSourceUrls = new Set(
sourcesParsed.data.metadata.map((source) => source.url),
);
const uniqueSources = sourcesParsed.data.metadata.filter((source) => {
if (filteredSourceUrls.has(source.url)) {
filteredSourceUrls.delete(source.url);
return true;
}
return false;
});
setContent(
uniqueSources.map((source) => ({
title: source.title ?? "Untitled",
type: source.type ?? "page",
source: source.url ?? "https://supermemory.ai",
content: source.description ?? "No content available",
numChunks: sourcesParsed.data.metadata.filter(
(f) => f.url === source.url,
).length,
})),
);
}}
>
<input
name="search"
placeholder="search memories..."
className="w-full bg-transparent p-3 text-lg outline-none flex-grow"
type="text"
/>
<button type="submit" className=" border-l-2 border-gray-600 h-full p-3">
<MagnifyingGlassIcon className=" h-5 text-[#fff]" />
</button>
</form>
);
}
export default Sidepanel;
|