blob: cdd58c552959f6b90a099686b9b4827b430d9269 [file] [log] [blame]
gio5f2f1002025-03-20 18:38:48 +04001import { Button } from "@/components/ui/button";
gio90a265b2025-06-26 09:16:58 +00002import { Input } from "@/components/ui/input";
gio5f2f1002025-03-20 18:38:48 +04003import { v4 as uuidv4 } from "uuid";
gio90a265b2025-06-26 09:16:58 +00004import { useCallback, useState, useMemo } from "react";
gio5f2f1002025-03-20 18:38:48 +04005import { Accordion, AccordionTrigger } from "./ui/accordion";
6import { AccordionContent, AccordionItem } from "@radix-ui/react-accordion";
gio69148322025-06-19 23:16:12 +04007import { AppState, useCategories, useMode, useProjectId, useStateStore } from "@/lib/state";
gio5f2f1002025-03-20 18:38:48 +04008import { CategoryItem } from "@/lib/categories";
9import { Icon } from "./icon";
gio69148322025-06-19 23:16:12 +040010import { AppNode, NodeType } from "config";
gio5f2f1002025-03-20 18:38:48 +040011
gio818da4e2025-05-12 14:45:35 +000012function addResource(i: CategoryItem<NodeType>, store: AppState) {
gioaf8db832025-05-13 14:43:05 +000013 const deselected = store.nodes.map((n) => ({
gio818da4e2025-05-12 14:45:35 +000014 ...n,
15 selected: false,
16 }));
gioaf8db832025-05-13 14:43:05 +000017 store.setNodes(deselected);
18 store.addNode({
19 id: uuidv4(),
20 type: i.type,
21 data: i.init,
22 selected: true,
23 connectable: true,
24 } as any); // eslint-disable-line @typescript-eslint/no-explicit-any
gio5f2f1002025-03-20 18:38:48 +040025}
26
27export function Resources() {
gio818da4e2025-05-12 14:45:35 +000028 const store = useStateStore();
giod0026612025-05-08 13:00:36 +000029 const categories = useCategories();
gio33046722025-05-16 14:49:55 +000030 const projectId = useProjectId();
31 const mode = useMode();
giod0026612025-05-08 13:00:36 +000032 const onResourceAdd = useCallback(
33 (item: CategoryItem<NodeType>) => {
gio818da4e2025-05-12 14:45:35 +000034 return () => addResource(item, store);
giod0026612025-05-08 13:00:36 +000035 },
gio818da4e2025-05-12 14:45:35 +000036 [store],
giod0026612025-05-08 13:00:36 +000037 );
gioaf8db832025-05-13 14:43:05 +000038
giod0026612025-05-08 13:00:36 +000039 const [open, setOpen] = useState<string[]>(categories.map((c) => c.title));
gio90a265b2025-06-26 09:16:58 +000040 const [searchValue, setSearchValue] = useState<string>("");
41
42 // Filter categories based on search value
43 const filteredCategories = useMemo(() => {
44 if (!searchValue.trim()) {
45 return categories;
46 }
47
48 const searchLower = searchValue.toLowerCase();
49 return categories
50 .map((category) => ({
51 ...category,
52 items: category.items.filter((item) => item.title.toLowerCase().includes(searchLower)),
53 }))
54 .filter((category) => category.items.length > 0); // Remove empty categories
55 }, [categories, searchValue]);
gioaf8db832025-05-13 14:43:05 +000056
giod0026612025-05-08 13:00:36 +000057 return (
58 <>
gio90a265b2025-06-26 09:16:58 +000059 <div className="px-3 pb-3 mt-2">
60 <Input
61 type="text"
62 placeholder="Search resources..."
63 value={searchValue}
64 onChange={(e) => setSearchValue(e.target.value)}
65 className="w-full"
66 />
67 </div>
giod0026612025-05-08 13:00:36 +000068 <Accordion type="multiple" value={open} onValueChange={(v) => setOpen(v)}>
gio90a265b2025-06-26 09:16:58 +000069 {filteredCategories.map((c) => (
giod0026612025-05-08 13:00:36 +000070 <AccordionItem key={c.title} value={c.title} className={"px-3" + (c.active ? " bg-amber-100" : "")}>
71 <AccordionTrigger>{c.title}</AccordionTrigger>
72 <AccordionContent>
73 <div className="flex flex-col space-y-1">
gio818da4e2025-05-12 14:45:35 +000074 {c.items.map((item: CategoryItem<NodeType>) => (
giod0026612025-05-08 13:00:36 +000075 <Button
76 key={item.title}
77 onClick={onResourceAdd(item)}
78 style={{ justifyContent: "flex-start" }}
gio33046722025-05-16 14:49:55 +000079 disabled={projectId == null || mode !== "edit"}
giod0026612025-05-08 13:00:36 +000080 >
gio69148322025-06-19 23:16:12 +040081 <Icon node={{ type: item.type, data: item.init } as AppNode} />
giod0026612025-05-08 13:00:36 +000082 {item.title}
83 </Button>
84 ))}
85 </div>
86 </AccordionContent>
87 </AccordionItem>
88 ))}
89 </Accordion>
90 </>
91 );
gio5f2f1002025-03-20 18:38:48 +040092}