From 8562f14aad1b4fa167182a3561cb205a61c3a62e Mon Sep 17 00:00:00 2001
From: Samed <sbalcioglu@graphpolaris.com>
Date: Tue, 24 Sep 2024 12:15:13 +0200
Subject: [PATCH] feat: insight sharing implementation

---
 libs/shared/lib/components/buttons/Button.tsx |   6 +-
 .../components/buttons/buttons.module.scss    |   6 +
 .../buttons/buttons.module.scss.d.ts          |   1 +
 .../lib/components/textEditor/TextEditor.tsx  | 133 +++++++++++++--
 .../textEditor/plugins/ToolbarPlugin.tsx      |   8 +-
 .../data-access/store/alertTemplateSlice.ts   |  38 +++++
 libs/shared/lib/data-access/store/hooks.ts    |   4 +
 .../data-access/store/reportTemplateSlice.ts  |  60 +++++++
 libs/shared/lib/data-access/store/store.ts    |   4 +
 .../lib/insight-sharing/InsightDialog.tsx     |  45 ++++-
 .../lib/insight-sharing/SettingsPanel.tsx     | 115 +++++++++----
 .../insight-sharing/alerting/AlertingForm.tsx |  40 ++++-
 .../insight-sharing/components/AddItem.tsx    |  25 ++-
 .../insight-sharing/components/Sidebar.tsx    |  27 +--
 .../reporting/ReportingForm.tsx               | 161 +++++++++++++-----
 15 files changed, 545 insertions(+), 128 deletions(-)
 create mode 100644 libs/shared/lib/data-access/store/alertTemplateSlice.ts
 create mode 100644 libs/shared/lib/data-access/store/reportTemplateSlice.ts

diff --git a/libs/shared/lib/components/buttons/Button.tsx b/libs/shared/lib/components/buttons/Button.tsx
index 79422a12d..bd697b9f7 100644
--- a/libs/shared/lib/components/buttons/Button.tsx
+++ b/libs/shared/lib/components/buttons/Button.tsx
@@ -21,6 +21,7 @@ type ButtonProps = {
   className?: string;
   style?: React.CSSProperties;
   tooltip?: string;
+  active?: boolean;
   onMouseUp?: (e: any) => void;
   onMouseDown?: (e: any) => void;
   onMouseEnter?: (e: any) => void;
@@ -54,6 +55,7 @@ export const Button = React.forwardRef<HTMLButtonElement | HTMLAnchorElement | H
       className,
       children,
       tooltip,
+      active,
       ...props
     },
     forwardedRef,
@@ -139,6 +141,8 @@ export const Button = React.forwardRef<HTMLButtonElement | HTMLAnchorElement | H
       [iconComponent, label, children],
     );
 
+    const activeClass = useMemo(() => (active ? styles['btn-active'] : ''), [active, styles]);
+
     const ButtonComponent = as;
 
     const isAnchor = as === 'a';
@@ -148,7 +152,7 @@ export const Button = React.forwardRef<HTMLButtonElement | HTMLAnchorElement | H
         {tooltip && <TooltipContent>{tooltip}</TooltipContent>}
         <TooltipTrigger>
           <ButtonComponent
-            className={`${styles.btn} ${typeClass} ${variantClass} ${sizeClass} ${blockClass} ${roundedClass} ${iconOnlyClass} ${className ? className : ''}`}
+            className={`${styles.btn} ${typeClass} ${variantClass} ${sizeClass} ${blockClass} ${roundedClass} ${iconOnlyClass} ${activeClass} ${className ? className : ''}`}
             onClick={onClick}
             disabled={disabled}
             aria-label={ariaLabel}
diff --git a/libs/shared/lib/components/buttons/buttons.module.scss b/libs/shared/lib/components/buttons/buttons.module.scss
index a348a6e10..54af8185c 100644
--- a/libs/shared/lib/components/buttons/buttons.module.scss
+++ b/libs/shared/lib/components/buttons/buttons.module.scss
@@ -144,3 +144,9 @@
 .btn-rounded {
   @apply rounded-full;
 }
+
+.btn-active {
+  background-color: #e0e0e0; 
+  border: 1px solid #b0b0b0; 
+  color: #000; 
+}
\ No newline at end of file
diff --git a/libs/shared/lib/components/buttons/buttons.module.scss.d.ts b/libs/shared/lib/components/buttons/buttons.module.scss.d.ts
index ac3cb0637..927d89a44 100644
--- a/libs/shared/lib/components/buttons/buttons.module.scss.d.ts
+++ b/libs/shared/lib/components/buttons/buttons.module.scss.d.ts
@@ -16,5 +16,6 @@ declare const classNames: {
   readonly 'btn-ghost': 'btn-ghost';
   readonly 'btn-block': 'btn-block';
   readonly 'btn-rounded': 'btn-rounded';
+  readonly 'btn-active': 'btn-active';
 };
 export = classNames;
diff --git a/libs/shared/lib/components/textEditor/TextEditor.tsx b/libs/shared/lib/components/textEditor/TextEditor.tsx
index 8a95a8042..af1957d07 100644
--- a/libs/shared/lib/components/textEditor/TextEditor.tsx
+++ b/libs/shared/lib/components/textEditor/TextEditor.tsx
@@ -1,43 +1,148 @@
-import React from 'react';
+import React, { useState, useEffect } from 'react';
 import { LexicalComposer } from '@lexical/react/LexicalComposer';
 import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
 import { ContentEditable } from '@lexical/react/LexicalContentEditable';
+import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
 import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
-import { EditorState } from 'lexical';
-import { MyOnChangePlugin } from './plugins/StateChangePlugin';
-import { ToolbarPlugin } from './plugins/ToolbarPlugin';
+import { $getRoot, $getSelection, $isRangeSelection, TextFormatType } from 'lexical';
+import { $generateHtmlFromNodes, $generateNodesFromDOM } from '@lexical/html';
 import { ErrorHandler } from './ErrorHandler';
 import { Placeholder } from './Placeholder';
+import { Button } from '../buttons/Button';
 
 type TextEditorProps = {
-  editorState: EditorState | undefined;
-  setEditorState: (value: EditorState) => void;
+  initialContent?: string;
+  onContentChange?: (content: string) => void;
   showToolbar: boolean;
   placeholder?: string;
 };
 
-export function TextEditor({ editorState, setEditorState, showToolbar, placeholder }: TextEditorProps) {
-  function onChange(editorState: EditorState) {
-    setEditorState(editorState);
-  }
+function ToolbarPlugin() {
+  const [editor] = useLexicalComposerContext();
+  const [activeStyles, setActiveStyles] = useState<Set<string>>(new Set());
+
+  React.useEffect(() => {
+    return editor.registerUpdateListener(({ editorState }) => {
+      editorState.read(() => {
+        const selection = $getSelection();
+        if ($isRangeSelection(selection)) {
+          const newActiveStyles = new Set<string>();
+          if (selection.hasFormat('bold')) newActiveStyles.add('bold');
+          if (selection.hasFormat('italic')) newActiveStyles.add('italic');
+          if (selection.hasFormat('underline')) newActiveStyles.add('underline');
+          setActiveStyles(newActiveStyles);
+        }
+      });
+    });
+  }, [editor]);
+
+  const toggleStyle = (style: TextFormatType) => {
+    editor.update(() => {
+      const selection = $getSelection();
+      if ($isRangeSelection(selection)) {
+        selection.formatText(style);
+      }
+    });
+  };
+
+  return (
+    <div className="flex bg-secondary-50 rounded mt-4 p-2 space-x-2">
+      <Button
+        variantType="secondary"
+        variant="ghost"
+        size="xs"
+        iconComponent="icon-[ic--baseline-format-bold]"
+        onClick={() => toggleStyle('bold')}
+        active={activeStyles.has('bold')}
+      />
+      <Button
+        variantType="secondary"
+        variant="ghost"
+        size="xs"
+        iconComponent="icon-[ic--baseline-format-italic]"
+        onClick={() => toggleStyle('italic')}
+        active={activeStyles.has('italic')}
+      />
+      <Button
+        variantType="secondary"
+        variant="ghost"
+        size="xs"
+        iconComponent="icon-[ic--baseline-format-underlined]"
+        onClick={() => toggleStyle('underline')}
+        active={activeStyles.has('underline')}
+      />
+    </div>
+  );
+}
+
+function ContentSetterPlugin({ initialContent }: { initialContent: string }) {
+  const [editor] = useLexicalComposerContext();
+
+  useEffect(() => {
+    if (initialContent) {
+      editor.update(() => {
+        const parser = new DOMParser();
+        const dom = parser.parseFromString(initialContent, 'text/html');
+        const nodes = $generateNodesFromDOM(editor, dom);
+        const root = $getRoot();
+        root.clear();
+        root.append(...nodes);
+      });
+    }
+  }, [editor, initialContent]);
+
+  return null;
+}
+
+function OnChangePlugin({ onContentChange }: { onContentChange?: (content: string) => void }) {
+  const [editor] = useLexicalComposerContext();
+
+  useEffect(() => {
+    if (!onContentChange) return;
+
+    return editor.registerUpdateListener(() => {
+      editor.getEditorState().read(() => {
+        const htmlString = $generateHtmlFromNodes(editor, null);
+        onContentChange(htmlString);
+      });
+    });
+  }, [editor, onContentChange]);
+
+  return null;
+}
+
+export function TextEditor({
+  initialContent = '',
+  onContentChange,
+  showToolbar,
+  placeholder,
+}: TextEditorProps) {
+  const theme = {
+    text: {
+      bold: 'font-bold',
+      italic: 'italic',
+      underline: 'underline',
+    },
+  };
 
   const initialConfig = {
     namespace: 'MyEditor',
-    editorState: editorState,
+    theme,
     onError: ErrorHandler,
   };
 
   return (
     <LexicalComposer initialConfig={initialConfig}>
       {showToolbar && <ToolbarPlugin />}
-      <div className="relative">
+      <div className="relative border rounded">
         <RichTextPlugin
-          contentEditable={<ContentEditable className="border min-h-24" />}
+          contentEditable={<ContentEditable className="min-h-24 p-2" />}
           placeholder={<Placeholder placeholder={placeholder} />}
           ErrorBoundary={LexicalErrorBoundary}
         />
       </div>
-      <MyOnChangePlugin onChange={onChange} />
+      <ContentSetterPlugin initialContent={initialContent} />
+      <OnChangePlugin onContentChange={onContentChange} />
     </LexicalComposer>
   );
 }
diff --git a/libs/shared/lib/components/textEditor/plugins/ToolbarPlugin.tsx b/libs/shared/lib/components/textEditor/plugins/ToolbarPlugin.tsx
index 93c56d75c..65a9d02ae 100644
--- a/libs/shared/lib/components/textEditor/plugins/ToolbarPlugin.tsx
+++ b/libs/shared/lib/components/textEditor/plugins/ToolbarPlugin.tsx
@@ -22,13 +22,7 @@ export function ToolbarPlugin() {
     <div className="flex bg-secondary-50 rounded mt-4 p-2 space-x-2">
       <Button variantType="secondary" variant="ghost" size="xs" iconComponent="icon-[ic--baseline-format-bold]" onClick={formatBold} />
       <Button variantType="secondary" variant="ghost" size="xs" iconComponent="icon-[ic--baseline-format-italic]" onClick={formatItalic} />
-      <Button
-        variantType="secondary"
-        variant="ghost"
-        size="xs"
-        iconComponent="icon-[ic--baseline-format-underlined]"
-        onClick={formatItalic}
-      />
+      <Button variantType="secondary" variant="ghost" size="xs" iconComponent="icon-[ic--baseline-format-underlined]"onClick={formatUnderline}/>
     </div>
   );
 }
diff --git a/libs/shared/lib/data-access/store/alertTemplateSlice.ts b/libs/shared/lib/data-access/store/alertTemplateSlice.ts
new file mode 100644
index 000000000..f49d4d64c
--- /dev/null
+++ b/libs/shared/lib/data-access/store/alertTemplateSlice.ts
@@ -0,0 +1,38 @@
+import { createSlice, PayloadAction } from '@reduxjs/toolkit';
+import type { RootState } from './store';
+
+export interface Alert {
+  id: string;
+  name: string;
+  recipients: string[];
+  template: string;
+  frequency: string;
+}
+
+export interface AlertsState {
+  alerts: Alert[];
+}
+
+const initialAlertsState: AlertsState = {
+  alerts: [],
+};
+
+const alertsSlice = createSlice({
+  name: 'alerts',
+  initialState: initialAlertsState,
+  reducers: {
+    setAlerts: (state: AlertsState, action: PayloadAction<Alert[]>) => {
+      state.alerts = action.payload;
+    },
+    addAlert: (state: AlertsState, action: PayloadAction<Alert>) => {
+      state.alerts.push(action.payload);
+    },
+    removeAlert: (state: AlertsState, action: PayloadAction<string>) => {
+      state.alerts = state.alerts.filter(alert => alert.name !== action.payload);
+    },
+  },
+});
+
+export const { setAlerts, addAlert, removeAlert } = alertsSlice.actions;
+export const selectAlerts = (state: RootState) => state.alerts.alerts;
+export default alertsSlice.reducer;
diff --git a/libs/shared/lib/data-access/store/hooks.ts b/libs/shared/lib/data-access/store/hooks.ts
index 9680186ed..55917d5d1 100644
--- a/libs/shared/lib/data-access/store/hooks.ts
+++ b/libs/shared/lib/data-access/store/hooks.ts
@@ -40,6 +40,7 @@ import { SelectionStateI, FocusStateI, focusState, selectionState } from './inte
 import { VisualizationSettingsType } from '../../vis/common';
 import { PolicyUsersState, selectPolicyState } from './authorizationUsersSlice';
 import { PolicyResourcesState, selectResourcesPolicyState } from './authorizationResourcesSlice';
+import { ReportTemplate } from './reportTemplateSlice';
 
 // Use throughout your app instead of plain `useDispatch` and `useSelector`
 export const useAppDispatch: () => AppDispatch = useDispatch;
@@ -93,3 +94,6 @@ export const useUsersPolicy: () => PolicyUsersState = () => useAppSelector(selec
 
 // Authorization Resources Slice
 export const useResourcesPolicy: () => PolicyResourcesState = () => useAppSelector(selectResourcesPolicyState);
+
+// Reporting Template Slice
+export const useReportTemplates = (): ReportTemplate[] => useAppSelector((state: RootState) => state.reportTemplates.templates);
\ No newline at end of file
diff --git a/libs/shared/lib/data-access/store/reportTemplateSlice.ts b/libs/shared/lib/data-access/store/reportTemplateSlice.ts
new file mode 100644
index 000000000..d6b40db2f
--- /dev/null
+++ b/libs/shared/lib/data-access/store/reportTemplateSlice.ts
@@ -0,0 +1,60 @@
+import { createSlice, PayloadAction} from '@reduxjs/toolkit';
+import type { RootState } from './store';
+
+export interface ReportTemplate {
+  id: string;
+  name: string;
+  recipients: string[];
+  frequency: string | number;
+  template: string;
+}
+
+export interface ReportTemplatesState {
+  templates: ReportTemplate[];
+}
+
+
+const initialTemplates: ReportTemplate[] = [
+  {
+    id: 'template1',
+    name: 'Weekly Report',
+    recipients: ['test1@graphpolaris.com'],
+    frequency: 'Weekly',
+    template: '<p>This is a weekly report template.</p>',
+  },
+  {
+    id: 'template2',
+    name: 'Daily Report',
+    recipients: ['test2@graphpolaris.com'],
+    frequency: 'Daily',
+    template: '<p>This is a daily report template.</p>',
+  },
+];
+
+const initialState: ReportTemplatesState = {
+  templates: initialTemplates,
+};
+
+
+export const reportTemplatesSlice = createSlice({
+  name: 'reportTemplates',
+  initialState,
+  reducers: {
+    addTemplate: (state, action: PayloadAction<ReportTemplate>) => {
+      state.templates.push(action.payload);
+    },
+    updateTemplate: (state, action: PayloadAction<ReportTemplate>) => {
+      const index = state.templates.findIndex((template) => template.id === action.payload.id);
+      if (index !== -1) {
+        state.templates[index] = action.payload;
+      }
+    },
+    deleteTemplate: (state, action: PayloadAction<string>) => {
+      state.templates = state.templates.filter((template) => template.id !== action.payload);
+    },
+  },
+});
+
+export const { addTemplate, updateTemplate, deleteTemplate } = reportTemplatesSlice.actions;
+export const selectReportTemplates = (state: RootState) => state.reportTemplates.templates;
+export default reportTemplatesSlice.reducer;
\ No newline at end of file
diff --git a/libs/shared/lib/data-access/store/store.ts b/libs/shared/lib/data-access/store/store.ts
index c1aea4606..e881bbd78 100644
--- a/libs/shared/lib/data-access/store/store.ts
+++ b/libs/shared/lib/data-access/store/store.ts
@@ -11,6 +11,8 @@ import visualizationSlice from './visualizationSlice';
 import interactionSlice from './interactionSlice';
 import policyUsersSlice from './authorizationUsersSlice';
 import policyPermissionSlice from './authorizationResourcesSlice';
+import reportTemplateSlice from './reportTemplateSlice';
+import alertTemplateSlice from './alertTemplateSlice';
 
 export const store = configureStore({
   reducer: {
@@ -26,6 +28,8 @@ export const store = configureStore({
     visualize: visualizationSlice,
     policyUsers: policyUsersSlice,
     policyResources: policyPermissionSlice,
+    reportTemplates: reportTemplateSlice,
+    alerts: alertTemplateSlice,
   },
   middleware: (getDefaultMiddleware) =>
     getDefaultMiddleware({
diff --git a/libs/shared/lib/insight-sharing/InsightDialog.tsx b/libs/shared/lib/insight-sharing/InsightDialog.tsx
index 0af6191f2..26ca601bf 100644
--- a/libs/shared/lib/insight-sharing/InsightDialog.tsx
+++ b/libs/shared/lib/insight-sharing/InsightDialog.tsx
@@ -1,24 +1,54 @@
-import React, { useState } from 'react';
+import React, { useState, useEffect} from 'react';
+import { useSelector, useDispatch } from 'react-redux';
 import { Dialog, DialogContent } from '../components';
 import { SettingsPanel } from './SettingsPanel';
 import { MonitorType, Sidebar } from './components/Sidebar';
+import { RootState } from '../data-access';
+import { addTemplate, ReportTemplate, updateTemplate} from '../data-access/store/reportTemplateSlice';
+import { v4 as uuidv4 } from 'uuid';
+import { useReportTemplates } from '../data-access';
+import { useAppDispatch } from '../data-access';
+import { Alert } from '../data-access/store/alertTemplateSlice';
 
 type Props = {
   open: boolean;
   onClose: () => void;
 };
 
-const reports = ['Sequence 1', 'Sequence 2'];
-const alerts = ['Potential New Incident', 'Potential New Info'];
 
 export function InsightDialog(props: Props) {
+  const dispatch = useAppDispatch();
+  const reportTemplates = useReportTemplates();
+  const alerts: Alert[] = useSelector((state: RootState) => state.alerts.alerts || []);
   const [adding, setAdding] = useState<boolean>(false);
   const [active, setActive] = useState<string>('');
   const [activeCategory, setActiveCategory] = useState<MonitorType | undefined>(undefined);
 
-  const handleChangeActive = (category: MonitorType, name: string) => {
-    setActive(name);
+  const handleChangeActive = (category: MonitorType, id: string) => {
+    setActive(id);
     setActiveCategory(category);
+    setAdding(false)
+  };
+
+  const handleSaveTemplate = (templateData: Omit<ReportTemplate, 'id'>) => {
+    const existingTemplate = reportTemplates.find((t) => t.id === active);
+
+    if (existingTemplate) {
+      const updatedTemplate: ReportTemplate = {
+        ...existingTemplate,
+        ...templateData,
+      };
+      dispatch(updateTemplate(updatedTemplate));
+      setActive(updatedTemplate.id);
+    } else {
+      const newTemplate: ReportTemplate = {
+        ...templateData,
+        id: uuidv4(),
+      };
+      dispatch(addTemplate(newTemplate));
+      setActive(newTemplate.id);
+    }
+    setAdding(false);
   };
 
   return (
@@ -31,7 +61,7 @@ export function InsightDialog(props: Props) {
       <DialogContent className="w-5/6 h-5/6 rounded-none py-0 px-0">
         <div className="flex w-full h-full">
           <Sidebar
-            reports={reports}
+            reports={reportTemplates}
             alerts={alerts}
             changeActive={handleChangeActive}
             setAdding={setAdding}
@@ -43,6 +73,9 @@ export function InsightDialog(props: Props) {
             adding={adding}
             setAdding={setAdding}
             setActiveCategory={setActiveCategory}
+            setActive={setActive}
+            onSaveTemplate={handleSaveTemplate}
+            templates={reportTemplates}
           />
         </div>
       </DialogContent>
diff --git a/libs/shared/lib/insight-sharing/SettingsPanel.tsx b/libs/shared/lib/insight-sharing/SettingsPanel.tsx
index 9d0a7a676..84a51b0d1 100644
--- a/libs/shared/lib/insight-sharing/SettingsPanel.tsx
+++ b/libs/shared/lib/insight-sharing/SettingsPanel.tsx
@@ -1,10 +1,11 @@
-import React, { useEffect, useState } from 'react';
+import React from 'react';
 import { ReportingForm } from './reporting/ReportingForm';
 import { AlertingForm } from './alerting/AlertingForm';
-import { Button, Icon } from '../components';
 import { AddItem } from './components/AddItem';
 import { StartScreen } from './components/StartScreen';
 import { MonitorType } from './components/Sidebar';
+import { ReportTemplate } from '../data-access/store/reportTemplateSlice';
+import { v4 as uuidv4 } from 'uuid';
 
 type Props = {
   active: string;
@@ -12,42 +13,92 @@ type Props = {
   adding: boolean;
   setAdding: (val: boolean) => void;
   setActiveCategory: (val: MonitorType | undefined) => void;
+  setActive: (val: string) => void;
+  onSaveTemplate: (templateData: ReportTemplate) => void;
+  templates?: ReportTemplate[];
 };
 
 export function SettingsPanel(props: Props) {
-  const [contacts, setContacts] = useState<string[]>([]);
+  const {
+    active,
+    activeCategory,
+    adding,
+    setAdding,
+    setActiveCategory,
+    setActive,
+    onSaveTemplate,
+    templates = [],
+  } = props;
 
-  const getContacts = (): string[] => ['Jan', 'Piet'];
+  const activeTemplate = templates.find((template) => template.id === active);
 
-  useEffect(() => {
-    if (!contacts) {
-      const userContacts = getContacts();
-      setContacts(userContacts);
+  const handleAddItem = (name: string) => {
+    if (activeCategory === 'report') {
+      const newTemplate: ReportTemplate = {
+        id: uuidv4(),
+        name,
+        recipients: [],
+        frequency: 'Daily',
+        template: '',
+      };
+      onSaveTemplate(newTemplate);
+      setAdding(false);
+      setActive(newTemplate.id);
+      setActiveCategory('report')
     }
-  }, []);
-
-  return props.activeCategory ? (
-    <div className="w-3/4 p-4">
-      {props.adding ? (
-        <AddItem category={props.activeCategory} />
-      ) : (
-        props.active &&
-        props.activeCategory && (
-          <div>
-            {props.activeCategory === 'report' ? (
-              <ReportingForm activeTemplate={props.active} />
-            ) : (
-              <AlertingForm activeTemplate={props.active} />
-            )}
-          </div>
-        )
-      )}
-      <div className="flex justify-end mt-2">
-        <Button label="Delete" variantType="secondary" variant="outline" />
-        <Button label="Save" variantType="primary" className="ml-2" />
-      </div>
+  };
+
+  const handleSaveTemplate = (templateData: Omit<ReportTemplate, 'id'>) => {
+    const fullTemplateData: ReportTemplate = {
+      ...templateData,
+      id: activeTemplate?.id || '',
+    };
+    onSaveTemplate(fullTemplateData);
+  };
+
+  const renderContent = () => {
+    if (adding) {
+      return (
+        <AddItem
+          category={activeCategory as MonitorType}
+          onAdd={handleAddItem}
+        />
+      );
+    }
+
+    if (!activeCategory || !active) {
+      return (
+        <StartScreen
+          setAdding={setAdding}
+          setActiveCategory={setActiveCategory}
+        />
+      );
+    }
+
+    switch (activeCategory) {
+      case 'report':
+        return (
+          <ReportingForm
+            onSave={onSaveTemplate}
+            initialData={activeTemplate}
+          />
+        );
+      //case 'alert':
+       // return (
+         // <AlertingForm
+          //  initialData={activeAlert}
+          ///>
+       // );
+      default:
+        return null;
+    }
+  };
+
+  console.log('Templates in SettingsPanel:', templates);
+
+  return (
+    <div className="flex-1 p-4 overflow-auto">
+      {renderContent()}
     </div>
-  ) : (
-    <StartScreen setAdding={props.setAdding} setActiveCategory={props.setActiveCategory} />
   );
 }
diff --git a/libs/shared/lib/insight-sharing/alerting/AlertingForm.tsx b/libs/shared/lib/insight-sharing/alerting/AlertingForm.tsx
index 11ea8d907..f048be166 100644
--- a/libs/shared/lib/insight-sharing/alerting/AlertingForm.tsx
+++ b/libs/shared/lib/insight-sharing/alerting/AlertingForm.tsx
@@ -1,18 +1,33 @@
 import React, { useState } from 'react';
 import { Accordion, AccordionItem, AccordionHead, AccordionBody } from '../../components/accordion';
 import { TextEditor } from '../../components/textEditor';
-import { EditorState } from 'lexical';
+import { EditorState , createEditor} from 'lexical';
+import { Alert } from '../../data-access/store/alertTemplateSlice';
 
 type Props = {
-  activeTemplate: string;
+  initialData?: Alert;
+  onSave: (alertData: Alert) => void;
 };
 
-export function AlertingForm(props: Props) {
-  const [editorState, setEditorState] = useState<EditorState | undefined>(undefined);
+export function AlertingForm({ initialData, onSave }: Props) {
+  const [editorState, setEditorState] = useState<EditorState | undefined>(
+    initialData?.template ? createEditor().parseEditorState(initialData.template) : undefined
+  );
+  const [recipients, setRecipients] = useState<string>(initialData?.recipients.join(', ') || '');
+
+  const handleSave = () => {
+    const updatedAlert: Alert = {
+      ...initialData,
+      recipients: recipients.split(',').map(r => r.trim()),
+      template: JSON.stringify(editorState?.toJSON() ?? ''),
+      frequency: initialData?.frequency ?? 'Immediate',
+    };
+    onSave(updatedAlert);
+  };
 
   return (
     <div>
-      <span className="text-lg text-secondary-600 font-bold mb-4">Alert ID: {props.activeTemplate}</span>
+      <span className="text-lg text-secondary-600 font-bold mb-4">Alert ID: {initialData?.id || 'New Alert'}</span>
       <Accordion defaultOpenAll={true} className="border-t divide-y">
         <AccordionItem className="pt-2 pb-4">
           <AccordionHead showArrow={false}>
@@ -20,7 +35,12 @@ export function AlertingForm(props: Props) {
           </AccordionHead>
           <AccordionBody>
             <div>
-              <input className="border" />
+              <input 
+                className="border w-full p-2" 
+                value={recipients} 
+                onChange={(e) => setRecipients(e.target.value)}
+                placeholder="Enter recipients, separated by commas"
+              />
             </div>
           </AccordionBody>
         </AccordionItem>
@@ -38,6 +58,12 @@ export function AlertingForm(props: Props) {
           </AccordionBody>
         </AccordionItem>
       </Accordion>
+      <button 
+        className="mt-4 px-4 py-2 bg-blue-500 text-white rounded"
+        onClick={handleSave}
+      >
+        Save Alert
+      </button>
     </div>
   );
-}
+}
\ No newline at end of file
diff --git a/libs/shared/lib/insight-sharing/components/AddItem.tsx b/libs/shared/lib/insight-sharing/components/AddItem.tsx
index 771ab6bcc..5ec415d0b 100644
--- a/libs/shared/lib/insight-sharing/components/AddItem.tsx
+++ b/libs/shared/lib/insight-sharing/components/AddItem.tsx
@@ -1,18 +1,35 @@
 import React, { useState } from 'react';
-import { Input } from '../../components';
+import { Input, Button } from '../../components';
 import { MonitorType } from './Sidebar';
 
 type Props = {
-  category: MonitorType;
+  category: MonitorType; 
+  onAdd: (name: string) => void;
 };
 
 export function AddItem(props: Props) {
-  const [value, setValue] = useState<string>('');
+  const [name, setName] = useState<string>('');
+
+  const handleAdd = () => {
+    if (name.trim()) {
+      props.onAdd(name.trim());
+      setName('');
+    }
+  };
 
   return (
     <div>
       <span className="text-lg text-secondary-600 font-bold mb-4">Add a new {props.category}ing service</span>
-      <Input type="text" label="Name" value={value} onChange={setValue} />
+      <div className="mt-4 space-y-4">
+        <Input 
+          type="text" 
+          label="Name" 
+          value={name} 
+          onChange={(value: string) => setName(value)} 
+          placeholder={`Enter ${props.category} name`}
+        />
+        <Button onClick={handleAdd}>Add {props.category}</Button>
+      </div>
     </div>
   );
 }
diff --git a/libs/shared/lib/insight-sharing/components/Sidebar.tsx b/libs/shared/lib/insight-sharing/components/Sidebar.tsx
index d8ebcfe1c..6a40b3b8c 100644
--- a/libs/shared/lib/insight-sharing/components/Sidebar.tsx
+++ b/libs/shared/lib/insight-sharing/components/Sidebar.tsx
@@ -1,18 +1,25 @@
 import React from 'react';
 import { Button } from '../../components';
 import { Accordion, AccordionBody, AccordionHead, AccordionItem } from '../../components/accordion';
+import { ReportTemplate } from '../../data-access/store/reportTemplateSlice';
+import { Alert } from '../../data-access/store/alertTemplateSlice';
+
 
 export type MonitorType = 'report' | 'alert';
 
 type SidebarProps = {
-  reports: string[];
-  alerts: string[];
+  reports: ReportTemplate[];
+  alerts: Alert[];
   changeActive: (category: MonitorType, val: string) => void;
   setAdding: (val: boolean) => void;
   setActiveCategory: (val: MonitorType | undefined) => void;
 };
 
 export function Sidebar(props: SidebarProps) {
+  const reports = props.reports || [];
+  const alerts = props.alerts || [];
+  console.log('Reports in Sidebar:', props.reports);
+
   return (
     <div className="w-1/4 border-r overflow-auto flex flex-col h-full">
       <span className="text-lg text-secondary-700 font-semibold px-2 py-4">Insight Sharing</span>
@@ -41,16 +48,16 @@ export function Sidebar(props: SidebarProps) {
           </AccordionHead>
           <AccordionBody className="ml-0">
             <ul className="space-y-2">
-              {props.reports.map((name, index) => (
+              {props.reports.map((template) => (
                 <li
-                  key={index}
+                  key={template.id}
                   className="cursor-pointer p-2 hover:bg-secondary-50"
                   onClick={() => {
-                    props.changeActive('report', name);
+                    props.changeActive('report', template.id);
                     props.setAdding(false);
                   }}
                 >
-                  {name}
+                  {template.name}
                 </li>
               ))}
             </ul>
@@ -80,16 +87,16 @@ export function Sidebar(props: SidebarProps) {
           </AccordionHead>
           <AccordionBody className="ml-0">
             <ul className="space-y-2">
-              {props.alerts.map((name, index) => (
+              {props.alerts.map((alert) => (
                 <li
-                  key={index}
+                  key={alert.id}
                   className="cursor-pointer p-2 hover:bg-secondary-50"
                   onClick={() => {
-                    props.changeActive('alert', name);
+                    props.changeActive('alert', alert.id);
                     props.setAdding(false);
                   }}
                 >
-                  {name}
+                  {alert.name}
                 </li>
               ))}
             </ul>
diff --git a/libs/shared/lib/insight-sharing/reporting/ReportingForm.tsx b/libs/shared/lib/insight-sharing/reporting/ReportingForm.tsx
index 9b2645b91..1c4bf5326 100644
--- a/libs/shared/lib/insight-sharing/reporting/ReportingForm.tsx
+++ b/libs/shared/lib/insight-sharing/reporting/ReportingForm.tsx
@@ -1,57 +1,124 @@
-import React, { useState } from 'react';
-import { Input, LoadingSpinner } from '../../components';
+import React, { useState, useEffect} from 'react';
+import { Input, Button, LoadingSpinner, DropdownInput } from '../../components';
 import { Accordion, AccordionBody, AccordionHead, AccordionItem } from '../../components/accordion';
 import { TextEditor } from '../../components/textEditor';
 import { EditorState } from 'lexical';
+import { ReportTemplate } from '../../data-access/store/reportTemplateSlice';
+import { useAppDispatch } from '../../data-access';
+import { addWarning } from '../../data-access/store/configSlice';
+import { DropdownTrigger, DropdownContainer, DropdownItem, DropdownItemContainer } from '../../components/dropdowns';
+import { v4 as uuidv4 } from 'uuid';
+import { Icon } from '../../components';
 
-type Props = {
-  activeTemplate: string;
-};
+interface ReportingFormProps {
+  onSave: (data:ReportTemplate) => void;
+  initialData?: ReportTemplate;
+  activeTemplate?: string;
+}
 
-export function ReportingForm(props: Props) {
+export function ReportingForm({ onSave, initialData, activeTemplate }: ReportingFormProps) {
   const [loading, setLoading] = useState(false);
-  const [editorState, setEditorState] = useState<EditorState | undefined>(undefined);
+  const [name, setName] = useState(initialData?.name || '');
+  const [recipients, setRecipients] = useState(initialData?.recipients.join(', ') || '');
+  const [frequency, setFrequency] = useState<string>('Daily');
+  const [content, setContent] = useState(initialData?.template || '');
+  const [isCollapsed, setIsCollapsed] = useState(false);
+  
+  const dispatch = useAppDispatch();
+
+  useEffect(() => {
+    if (initialData) {
+      setName(initialData.name || '');
+      setRecipients(initialData.recipients.join(', ') || '');
+      setFrequency(initialData.frequency.toString() || 'Daily');
+    } else {
+      setName('');
+      setRecipients('');
+      setFrequency('Daily');
+    }
+  }, [initialData]);
 
-  return loading ? (
-    <LoadingSpinner />
-  ) : (
-    props.activeTemplate && (
-      <div>
-        <span className="text-lg text-secondary-600 font-bold mb-4">Report ID: {props.activeTemplate}</span>
-        <Accordion defaultOpenAll={true} className="border-t divide-y">
-          <AccordionItem className="pt-2 pb-4">
-            <AccordionHead showArrow={false}>
-              <span className="font-semibold">Recipient(s)</span>
-            </AccordionHead>
-            <AccordionBody>
+  const handleSave= () => {
+    if (!content || content.trim() === '') {
+      dispatch(addWarning('Template content cannot be empty.'));
+      return;
+    }
+  
+    if (!recipients.trim()) {
+      dispatch(addWarning('Please add at least one recipient.'));
+      return;
+    }
+  
+    const templateData: ReportTemplate = {
+      id: initialData?.id || uuidv4(),
+      name,
+      recipients: recipients.split(',').map((email) => email.trim()),
+      frequency,
+      template: content,
+    };
+    setLoading(true);
+    onSave(templateData);
+    setTimeout(() => setLoading(false), 1000);
+    };
+  
+  if (loading) return <LoadingSpinner />;
+
+  return (
+    <div>
+      <span className="text-lg text-secondary-600 font-bold mb-4">
+        {activeTemplate ? `Report ID: ${activeTemplate}` : 'New Report Template'}
+      </span>
+      <Accordion defaultOpenAll={true} className="border-t divide-y">
+        <AccordionItem className="pt-4 pb-4">
+          <AccordionHead showArrow={true}>
+            <span className="font-semibold">Report Template</span>
+          </AccordionHead>
+          <AccordionBody>
+            <div className="space-y-4">
+              <Input
+                type="text"
+                label="Template Name"
+                value={name}
+                onChange={(value: string) => setName(value)}
+                placeholder="Enter template name"
+              />
+              <Input
+                type="text"
+                label="Recipients"
+                value={recipients}
+                onChange={(value: string) => setRecipients(value)}
+                placeholder="Enter email addresses"
+              />
+              <div className="form-control w-full">
+                <label className="label p-0">
+                  <span className="text-sm font-medium text-secondary-700">Frequency</span>
+                </label>
+                <select
+                  className="select select-bordered w-full focus:outline-none focus:ring-0"
+                  value={frequency}
+                  onChange={(e) => setFrequency(e.target.value)}
+                >
+                  <option value="Daily">Daily</option>
+                  <option value="Weekly">Weekly</option>
+                  <option value="Monthly">Monthly</option>
+                </select>
+              </div>
               <div>
-                <input className="border" />
+                <label className="block text-sm font-medium text-gray-700 mb-1">
+                  Email Template
+                </label>
+                <TextEditor
+                  initialContent={initialData?.template || ''}
+                  onContentChange={setContent}
+                  showToolbar={true}
+                  placeholder="Start typing your report template..."
+                />
               </div>
-            </AccordionBody>
-          </AccordionItem>
-          <AccordionItem className="pt-2 pb-4">
-            <AccordionHead showArrow={false}>
-              <span className="font-semibold">Repeat</span>
-            </AccordionHead>
-            <AccordionBody>
-              <Input label="Frequency" type="dropdown" value={'Daily'} onChange={() => {}} options={['Daily', 'Weekly']} className="mb-1" />
-            </AccordionBody>
-          </AccordionItem>
-          <AccordionItem className="pt-2 pb-4">
-            <AccordionHead showArrow={false}>
-              <span className="font-semibold">Email template</span>
-            </AccordionHead>
-            <AccordionBody>
-              <TextEditor
-                editorState={editorState}
-                setEditorState={setEditorState}
-                showToolbar={true}
-                placeholder="Start typing your report template..."
-              />
-            </AccordionBody>
-          </AccordionItem>
-        </Accordion>
-      </div>
-    )
+              <Button onClick={handleSave}>Save Template</Button>
+            </div>
+          </AccordionBody>
+        </AccordionItem>
+      </Accordion>
+    </div>
   );
-}
+}
\ No newline at end of file
-- 
GitLab