From 78170f75535aeeac24552f726bea1f01bbc00693 Mon Sep 17 00:00:00 2001
From: pmoharana-cmd <pmoharana032474@gmail.com>
Date: Sat, 4 Jan 2025 13:16:23 -0500
Subject: [PATCH] Implement local state editting when creating new element

---
 compass/components/Drawer/CreateDrawer.tsx | 30 ++++++-
 compass/components/Table/Table.tsx         | 93 ++++++++++++++--------
 compass/components/TagsInput/Index.tsx     | 19 +++--
 3 files changed, 100 insertions(+), 42 deletions(-)

diff --git a/compass/components/Drawer/CreateDrawer.tsx b/compass/components/Drawer/CreateDrawer.tsx
index 97203be..1554b6b 100644
--- a/compass/components/Drawer/CreateDrawer.tsx
+++ b/compass/components/Drawer/CreateDrawer.tsx
@@ -10,7 +10,7 @@ import { Details } from "./Drawer";
 
 type CreateDrawerProps = {
     details: Details[];
-    onCreate: (newItem: any) => void;
+    onCreate: (newItem: any) => boolean;
 };
 
 const CreateDrawer: FunctionComponent<CreateDrawerProps> = ({
@@ -31,10 +31,20 @@ const CreateDrawer: FunctionComponent<CreateDrawerProps> = ({
         }));
     };
 
+    const initializeSelectField = (key: string) => {
+        if (!newItemContent[key]) {
+            setNewItemContent((prev: any) => ({
+                ...prev,
+                [key]: [],
+            }));
+        }
+    };
+
     const handleCreate = () => {
-        onCreate(newItemContent);
-        setNewItemContent({});
-        setIsOpen(false);
+        if (onCreate(newItemContent)) {
+            setNewItemContent({});
+            setIsOpen(false);
+        }
     };
 
     const toggleDrawer = () => {
@@ -93,6 +103,7 @@ const CreateDrawer: FunctionComponent<CreateDrawerProps> = ({
                             switch (detail.inputType) {
                                 case "select-one":
                                 case "select-multiple":
+                                    initializeSelectField(detail.key);
                                     inputField = (
                                         <TagsInput
                                             presetValue={[]}
@@ -103,6 +114,17 @@ const CreateDrawer: FunctionComponent<CreateDrawerProps> = ({
                                                 detail.presetOptionsSetter ||
                                                 (() => {})
                                             }
+                                            onTagsChange={(
+                                                tags: Set<string>
+                                            ) => {
+                                                setNewItemContent(
+                                                    (prev: any) => ({
+                                                        ...prev,
+                                                        [detail.key]:
+                                                            Array.from(tags),
+                                                    })
+                                                );
+                                            }}
                                         />
                                     );
                                     break;
diff --git a/compass/components/Table/Table.tsx b/compass/components/Table/Table.tsx
index 1b84224..d4eefbb 100644
--- a/compass/components/Table/Table.tsx
+++ b/compass/components/Table/Table.tsx
@@ -29,6 +29,25 @@ type TableProps<T extends DataPoint> = {
     details: Details[];
 };
 
+/** Validates that all required fields in a new item have values */
+const validateNewItem = (newItem: any, details: Details[]): boolean => {
+    const hasEmptyFields = details.some((detail) => {
+        const value = newItem[detail.key];
+        return (
+            value === undefined ||
+            value === null ||
+            value === "" ||
+            (Array.isArray(value) && value.length === 0)
+        );
+    });
+
+    if (hasEmptyFields) {
+        alert("Please fill in all fields before creating a new item");
+        return false;
+    }
+    return true;
+};
+
 /** Fuzzy search function */
 const fuzzyFilter = (
     row: Row<any>,
@@ -60,39 +79,39 @@ export default function Table<T extends DataPoint>({
 }: TableProps<T>) {
     const columnHelper = createColumnHelper<T>();
 
-    /** Sorting function based on visibility */
-    const visibilitySort = (a: T, b: T) =>
-        a.visible === b.visible ? 0 : a.visible ? -1 : 1;
+    // /** Sorting function based on visibility */
+    // const visibilitySort = (a: T, b: T) =>
+    //     a.visible === b.visible ? 0 : a.visible ? -1 : 1;
 
-    // Sort data on load
-    useEffect(() => {
-        setData((prevData) => prevData.sort(visibilitySort));
-    }, [setData]);
+    // // Sort data on load
+    // useEffect(() => {
+    //     setData((prevData) => prevData.sort(visibilitySort));
+    // }, [setData]);
 
-    // Data manipulation methods
-    // TODO: Connect data manipulation methods to the database (deleteData, hideData, addData)
-    const deleteData = (dataId: number) => {
-        console.log(data);
-        setData((currentData) =>
-            currentData.filter((data) => data.id !== dataId)
-        );
-    };
+    // // Data manipulation methods
+    // // TODO: Connect data manipulation methods to the database (deleteData, hideData, addData)
+    // const deleteData = (dataId: number) => {
+    //     console.log(data);
+    //     setData((currentData) =>
+    //         currentData.filter((data) => data.id !== dataId)
+    //     );
+    // };
 
-    const hideData = (dataId: number) => {
-        console.log(`Toggling visibility for data with ID: ${dataId}`);
-        setData((currentData) => {
-            const newData = currentData
-                .map((data) =>
-                    data.id === dataId
-                        ? { ...data, visible: !data.visible }
-                        : data
-                )
-                .sort(visibilitySort);
+    // const hideData = (dataId: number) => {
+    //     console.log(`Toggling visibility for data with ID: ${dataId}`);
+    //     setData((currentData) => {
+    //         const newData = currentData
+    //             .map((data) =>
+    //                 data.id === dataId
+    //                     ? { ...data, visible: !data.visible }
+    //                     : data
+    //             )
+    //             .sort(visibilitySort);
 
-            console.log(newData);
-            return newData;
-        });
-    };
+    //         console.log(newData);
+    //         return newData;
+    //     });
+    // };
 
     const addData = () => {
         setData([...data]);
@@ -104,8 +123,10 @@ export default function Table<T extends DataPoint>({
             id: "options",
             cell: (props) => (
                 <RowOptionMenu
-                    onDelete={() => deleteData(props.row.original.id)}
-                    onHide={() => hideData(props.row.original.id)}
+                    onDelete={() => {}}
+                    onHide={() => {}}
+                    // onDelete={() => deleteData(props.row.original.id)}
+                    // onHide={() => hideData(props.row.original.id)}
                 />
             ),
         })
@@ -217,7 +238,15 @@ export default function Table<T extends DataPoint>({
                         >
                             <CreateDrawer
                                 details={details}
-                                onCreate={(newItem) => {}}
+                                onCreate={(newItem) => {
+                                    if (!validateNewItem(newItem, details)) {
+                                        return false;
+                                    }
+
+                                    newItem.visible = true;
+                                    setData((prev) => [...prev, newItem]);
+                                    return true;
+                                }}
                             />
                         </td>
                     </tr>
diff --git a/compass/components/TagsInput/Index.tsx b/compass/components/TagsInput/Index.tsx
index 132ddf8..6d7d96e 100644
--- a/compass/components/TagsInput/Index.tsx
+++ b/compass/components/TagsInput/Index.tsx
@@ -8,12 +8,14 @@ interface TagsInputProps {
     presetOptions: string[];
     presetValue: string[];
     setPresetOptions: Dispatch<SetStateAction<string[]>>;
+    onTagsChange?: (tags: Set<string>) => void;
 }
 
 const TagsInput: React.FC<TagsInputProps> = ({
     presetValue,
     presetOptions,
     setPresetOptions,
+    onTagsChange,
 }) => {
     const [inputValue, setInputValue] = useState("");
     const [cellSelected, setCellSelected] = useState(false);
@@ -70,23 +72,28 @@ const TagsInput: React.FC<TagsInputProps> = ({
     const addTag = (e?: React.KeyboardEvent<HTMLInputElement>) => {
         e?.stopPropagation();
 
+        const newTags = new Set(Array.from(tags).concat(inputValue));
         setOptions(new Set(Array.from(options).concat(inputValue)));
-        setTags(new Set(Array.from(tags).concat(inputValue)));
+        setTags(newTags);
         setFilteredOptions(new Set(Array.from(options).concat(inputValue)));
         setInputValue("");
+        onTagsChange?.(newTags);
     };
 
     const handleSelectTag = (tagToAdd: string) => {
-        console.log(tagToAdd);
-        console.log(tags);
-
         if (!tags.has(tagToAdd)) {
-            setTags(new Set(Array.from(tags).concat(tagToAdd)));
+            const newTags = new Set(Array.from(tags).concat(tagToAdd));
+            setTags(newTags);
+            onTagsChange?.(newTags);
         }
     };
 
     const handleDeleteTag = (tagToDelete: string) => {
-        setTags(new Set(Array.from(tags).filter((tag) => tag !== tagToDelete)));
+        const newTags = new Set(
+            Array.from(tags).filter((tag) => tag !== tagToDelete)
+        );
+        setTags(newTags);
+        onTagsChange?.(newTags);
     };
 
     const handleDeleteTagOption = (tagToDelete: string) => {