From 8d839a33cbc212d917d5ed927810bd0895b071d6 Mon Sep 17 00:00:00 2001
From: mateusz-winiarczyk <mateusz.winiarczyk@appunite.com>
Date: Thu, 11 Jan 2024 10:31:27 +0100
Subject: [PATCH] feat(export): included compartment pathways and excluded
 compartment pathways

---
 .../Elements/Elements.component.tsx           |  20 ++-
 .../Elements/Elements.utils.test.ts           |  61 +++++++++
 .../ExportDrawer/Elements/Elements.utils.ts   |  42 ++++++
 ...udedCompartmentPathways.component.test.tsx | 116 ++++++++++++++++
 .../ExcludedCompartmentPathways.component.tsx |  24 ++++
 .../ExcludedCompartmentPathways/index.ts      |   1 +
 ...udedCompartmentPathways.component.test.tsx | 116 ++++++++++++++++
 .../IncludedCompartmentPathways.component.tsx |  25 ++++
 .../IncludedCompartmentPathways /index.ts     |   1 +
 src/models/compartmentPathwaySchema.ts        |  50 +++++++
 src/models/fixtures/compartmentPathways.ts    |  29 ++++
 src/redux/apiPath.ts                          |   5 +
 .../comparmentPathways.constants.ts           |   1 +
 .../compartmentPathways.mock.ts               |  64 +++++++++
 .../compartmentPathways.reducers.test.ts      | 122 +++++++++++++++++
 .../compartmentPathways.reducers.ts           |  20 +++
 .../compartmentPathways.selectors.ts          |  17 +++
 .../compartmentPathways.slice.ts              |  20 +++
 .../compartmentPathways.thunks.test.ts        | 126 ++++++++++++++++++
 .../compartmentPathways.thunks.ts             | 120 +++++++++++++++++
 .../compartmentPathways.types.ts              |   4 +
 src/redux/root/root.fixtures.ts               |   4 +-
 src/redux/store.ts                            |   2 +
 src/types/models.ts                           |   6 +
 24 files changed, 994 insertions(+), 2 deletions(-)
 create mode 100644 src/components/Map/Drawer/ExportDrawer/Elements/Elements.utils.test.ts
 create mode 100644 src/components/Map/Drawer/ExportDrawer/Elements/Elements.utils.ts
 create mode 100644 src/components/Map/Drawer/ExportDrawer/Elements/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.test.tsx
 create mode 100644 src/components/Map/Drawer/ExportDrawer/Elements/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.tsx
 create mode 100644 src/components/Map/Drawer/ExportDrawer/Elements/ExcludedCompartmentPathways/index.ts
 create mode 100644 src/components/Map/Drawer/ExportDrawer/Elements/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx
 create mode 100644 src/components/Map/Drawer/ExportDrawer/Elements/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx
 create mode 100644 src/components/Map/Drawer/ExportDrawer/Elements/IncludedCompartmentPathways /index.ts
 create mode 100644 src/models/compartmentPathwaySchema.ts
 create mode 100644 src/models/fixtures/compartmentPathways.ts
 create mode 100644 src/redux/compartmentPathways/comparmentPathways.constants.ts
 create mode 100644 src/redux/compartmentPathways/compartmentPathways.mock.ts
 create mode 100644 src/redux/compartmentPathways/compartmentPathways.reducers.test.ts
 create mode 100644 src/redux/compartmentPathways/compartmentPathways.reducers.ts
 create mode 100644 src/redux/compartmentPathways/compartmentPathways.selectors.ts
 create mode 100644 src/redux/compartmentPathways/compartmentPathways.slice.ts
 create mode 100644 src/redux/compartmentPathways/compartmentPathways.thunks.test.ts
 create mode 100644 src/redux/compartmentPathways/compartmentPathways.thunks.ts
 create mode 100644 src/redux/compartmentPathways/compartmentPathways.types.ts

diff --git a/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.tsx b/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.tsx
index c4d5d6f4..ffc3bf45 100644
--- a/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.tsx
+++ b/src/components/Map/Drawer/ExportDrawer/Elements/Elements.component.tsx
@@ -1,13 +1,31 @@
-import { Types } from './Types';
+import { useEffect } from 'react';
+import { useAppSelector } from '@/redux/hooks/useAppSelector';
+import { modelsDataSelector } from '@/redux/models/models.selectors';
+import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
+import { getCompartmentPathways } from '@/redux/compartmentPathways/compartmentPathways.thunks';
 import { Annotations } from '../Annotations';
+import { Types } from './Types';
+import { IncludedCompartmentPathways } from './IncludedCompartmentPathways ';
+import { ExcludedCompartmentPathways } from './ExcludedCompartmentPathways';
 import { Columns } from './Columns';
+import { getModelsIds } from './Elements.utils';
 
 export const Elements = (): React.ReactNode => {
+  const models = useAppSelector(modelsDataSelector);
+  const dispatch = useAppDispatch();
+
+  useEffect(() => {
+    const modelsIds = getModelsIds(models);
+    dispatch(getCompartmentPathways(modelsIds));
+  }, [dispatch, models]);
+
   return (
     <div data-testid="elements-tab">
       <Types />
       <Columns />
       <Annotations />
+      <IncludedCompartmentPathways />
+      <ExcludedCompartmentPathways />
     </div>
   );
 };
diff --git a/src/components/Map/Drawer/ExportDrawer/Elements/Elements.utils.test.ts b/src/components/Map/Drawer/ExportDrawer/Elements/Elements.utils.test.ts
new file mode 100644
index 00000000..76d37442
--- /dev/null
+++ b/src/components/Map/Drawer/ExportDrawer/Elements/Elements.utils.test.ts
@@ -0,0 +1,61 @@
+/* eslint-disable no-magic-numbers */
+import { CompartmentPathwayDetails } from '@/types/models';
+import { modelsFixture } from '@/models/fixtures/modelsFixture';
+import { getCompartmentPathwaysCheckboxElements, getModelsIds } from './Elements.utils';
+
+describe('getCompartmentPathwaysCheckboxElements', () => {
+  it('should return an empty array when given an empty items array', () => {
+    const items: CompartmentPathwayDetails[] = [];
+    const result = getCompartmentPathwaysCheckboxElements(items);
+    expect(result).toEqual([]);
+  });
+
+  it('should correctly extract unique names and corresponding ids from items', () => {
+    const items = [
+      { id: 1, name: 'Compartment A' },
+      { id: 2, name: 'Compartment B' },
+      { id: 3, name: 'Compartment A' },
+      { id: 4, name: 'Compartment C' },
+    ] as CompartmentPathwayDetails[];
+
+    const result = getCompartmentPathwaysCheckboxElements(items);
+
+    expect(result).toEqual([
+      { id: '1', label: 'Compartment A' },
+      { id: '2', label: 'Compartment B' },
+      { id: '4', label: 'Compartment C' },
+    ]);
+  });
+  it('should correctly extract unique names and corresponding ids from items and sorts them alphabetically', () => {
+    const items = [
+      { id: 1, name: 'Compartment C' },
+      { id: 2, name: 'Compartment A' },
+      { id: 3, name: 'Compartment B' },
+      { id: 4, name: 'Compartment A' },
+      { id: 5, name: 'Compartment D' },
+    ] as CompartmentPathwayDetails[];
+
+    const result = getCompartmentPathwaysCheckboxElements(items);
+
+    expect(result).toEqual([
+      { id: '2', label: 'Compartment A' },
+      { id: '3', label: 'Compartment B' },
+      { id: '1', label: 'Compartment C' },
+      { id: '5', label: 'Compartment D' },
+    ]);
+  });
+});
+
+const MODELS_IDS = modelsFixture.map(item => item.idObject);
+
+describe('getModelsIds', () => {
+  it('should return an empty array if models are not provided', () => {
+    const result = getModelsIds(undefined);
+    expect(result).toEqual([]);
+  });
+
+  it('should return an array of model IDs', () => {
+    const result = getModelsIds(modelsFixture);
+    expect(result).toEqual(MODELS_IDS);
+  });
+});
diff --git a/src/components/Map/Drawer/ExportDrawer/Elements/Elements.utils.ts b/src/components/Map/Drawer/ExportDrawer/Elements/Elements.utils.ts
new file mode 100644
index 00000000..25c68180
--- /dev/null
+++ b/src/components/Map/Drawer/ExportDrawer/Elements/Elements.utils.ts
@@ -0,0 +1,42 @@
+/* eslint-disable no-magic-numbers */
+import { CompartmentPathwayDetails, MapModel } from '@/types/models';
+
+type AddedNames = { [key: string]: number };
+
+type CheckboxElement = { id: string; label: string };
+
+type CheckboxElements = CheckboxElement[];
+
+export const getCompartmentPathwaysCheckboxElements = (
+  items: CompartmentPathwayDetails[],
+): CheckboxElements => {
+  const addedNames: AddedNames = {};
+
+  const setNameToIdIfUndefined = (item: CompartmentPathwayDetails): void => {
+    if (addedNames[item.name] === undefined) {
+      addedNames[item.name] = item.id;
+    }
+  };
+
+  items.forEach(setNameToIdIfUndefined);
+
+  const parseIdAndLabel = ([name, id]: [name: string, id: number]): CheckboxElement => ({
+    id: id.toString(),
+    label: name,
+  });
+
+  const sortByLabel = (a: CheckboxElement, b: CheckboxElement): number => {
+    if (a.label > b.label) return 1;
+    return -1;
+  };
+
+  const elements = Object.entries(addedNames).map(parseIdAndLabel).sort(sortByLabel);
+
+  return elements;
+};
+
+export const getModelsIds = (models: MapModel[] | undefined): number[] => {
+  if (!models) return [];
+
+  return models.map(model => model.idObject);
+};
diff --git a/src/components/Map/Drawer/ExportDrawer/Elements/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.test.tsx b/src/components/Map/Drawer/ExportDrawer/Elements/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.test.tsx
new file mode 100644
index 00000000..ded8e680
--- /dev/null
+++ b/src/components/Map/Drawer/ExportDrawer/Elements/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.test.tsx
@@ -0,0 +1,116 @@
+/* eslint-disable no-magic-numbers */
+import { render, screen, waitFor } from '@testing-library/react';
+import {
+  InitialStoreState,
+  getReduxWrapperWithStore,
+} from '@/utils/testing/getReduxWrapperWithStore';
+import { StoreType } from '@/redux/store';
+import { act } from 'react-dom/test-utils';
+import { compartmentPathwaysDetailsFixture } from '@/models/fixtures/compartmentPathways';
+import { ExcludedCompartmentPathways } from './ExcludedCompartmentPathways.component';
+
+const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
+  const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
+
+  return (
+    render(
+      <Wrapper>
+        <ExcludedCompartmentPathways />
+      </Wrapper>,
+    ),
+    {
+      store,
+    }
+  );
+};
+
+const CHECKBOX_ELEMENT_NAME = compartmentPathwaysDetailsFixture[0].name;
+
+describe('ExcludedCompartmentPathways - component', () => {
+  it('should display compartment / pathways checkboxes when fetching data is successful', async () => {
+    renderComponent({
+      compartmentPathways: {
+        data: compartmentPathwaysDetailsFixture,
+        loading: 'succeeded',
+        error: {
+          message: '',
+          name: '',
+        },
+      },
+    });
+
+    expect(screen.queryByTestId('checkbox-filter')).not.toBeVisible();
+
+    const navigationButton = screen.getByTestId('accordion-item-button');
+
+    act(() => {
+      navigationButton.click();
+    });
+
+    expect(screen.getByText('Select excluded compartment / pathways')).toBeInTheDocument();
+
+    await waitFor(() => {
+      expect(screen.getByTestId('checkbox-filter')).toBeInTheDocument();
+      expect(screen.getByLabelText('search-input')).toBeInTheDocument();
+      expect(screen.getByLabelText(CHECKBOX_ELEMENT_NAME)).toBeInTheDocument();
+    });
+  });
+  it('should not display compartment / pathways checkboxes when fetching data fails', async () => {
+    renderComponent({
+      compartmentPathways: {
+        data: [],
+        loading: 'failed',
+        error: {
+          message: '',
+          name: '',
+        },
+      },
+    });
+    expect(screen.getByText('Select excluded compartment / pathways')).toBeInTheDocument();
+    const navigationButton = screen.getByTestId('accordion-item-button');
+    act(() => {
+      navigationButton.click();
+    });
+
+    expect(screen.queryByTestId('checkbox-filter')).not.toBeInTheDocument();
+  });
+  it('should not display compartment / pathways checkboxes when fetched data is empty', async () => {
+    renderComponent({
+      compartmentPathways: {
+        data: [],
+        loading: 'succeeded',
+        error: {
+          message: '',
+          name: '',
+        },
+      },
+    });
+    expect(screen.getByText('Select excluded compartment / pathways')).toBeInTheDocument();
+    const navigationButton = screen.getByTestId('accordion-item-button');
+    act(() => {
+      navigationButton.click();
+    });
+
+    expect(screen.queryByTestId('checkbox-filter')).not.toBeInTheDocument();
+  });
+
+  it('should display loading message when fetching data is pending', async () => {
+    renderComponent({
+      compartmentPathways: {
+        data: [],
+        loading: 'pending',
+        error: {
+          message: '',
+          name: '',
+        },
+      },
+    });
+    expect(screen.getByText('Select excluded compartment / pathways')).toBeInTheDocument();
+    const navigationButton = screen.getByTestId('accordion-item-button');
+    act(() => {
+      navigationButton.click();
+    });
+
+    expect(screen.getByText('Loading...')).toBeInTheDocument();
+  });
+});
diff --git a/src/components/Map/Drawer/ExportDrawer/Elements/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.tsx b/src/components/Map/Drawer/ExportDrawer/Elements/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.tsx
new file mode 100644
index 00000000..73e95759
--- /dev/null
+++ b/src/components/Map/Drawer/ExportDrawer/Elements/ExcludedCompartmentPathways/ExcludedCompartmentPathways.component.tsx
@@ -0,0 +1,24 @@
+/* eslint-disable no-magic-numbers */
+import { useAppSelector } from '@/redux/hooks/useAppSelector';
+import {
+  compartmentPathwaysDataSelector,
+  loadingCompartmentPathwaysSelector,
+} from '@/redux/compartmentPathways/compartmentPathways.selectors';
+import { CheckboxFilter } from '../../CheckboxFilter';
+import { CollapsibleSection } from '../../CollapsibleSection';
+import { getCompartmentPathwaysCheckboxElements } from '../Elements.utils';
+
+export const ExcludedCompartmentPathways = (): React.ReactNode => {
+  const loadingCompartmentPathways = useAppSelector(loadingCompartmentPathwaysSelector);
+  const isPending = loadingCompartmentPathways === 'pending';
+  const compartmentPathways = useAppSelector(compartmentPathwaysDataSelector);
+  const checkboxElements = getCompartmentPathwaysCheckboxElements(compartmentPathways);
+  const isCheckboxFilterVisible = !isPending && checkboxElements && checkboxElements.length > 0;
+
+  return (
+    <CollapsibleSection title="Select excluded compartment / pathways">
+      {isPending && <p>Loading...</p>}
+      {isCheckboxFilterVisible && <CheckboxFilter options={checkboxElements} />}
+    </CollapsibleSection>
+  );
+};
diff --git a/src/components/Map/Drawer/ExportDrawer/Elements/ExcludedCompartmentPathways/index.ts b/src/components/Map/Drawer/ExportDrawer/Elements/ExcludedCompartmentPathways/index.ts
new file mode 100644
index 00000000..d1e759c9
--- /dev/null
+++ b/src/components/Map/Drawer/ExportDrawer/Elements/ExcludedCompartmentPathways/index.ts
@@ -0,0 +1 @@
+export { ExcludedCompartmentPathways } from './ExcludedCompartmentPathways.component';
diff --git a/src/components/Map/Drawer/ExportDrawer/Elements/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx b/src/components/Map/Drawer/ExportDrawer/Elements/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx
new file mode 100644
index 00000000..59a59c99
--- /dev/null
+++ b/src/components/Map/Drawer/ExportDrawer/Elements/IncludedCompartmentPathways /IncludedCompartmentPathways.component.test.tsx	
@@ -0,0 +1,116 @@
+/* eslint-disable no-magic-numbers */
+import { render, screen, waitFor } from '@testing-library/react';
+import {
+  InitialStoreState,
+  getReduxWrapperWithStore,
+} from '@/utils/testing/getReduxWrapperWithStore';
+import { StoreType } from '@/redux/store';
+import { act } from 'react-dom/test-utils';
+import { compartmentPathwaysDetailsFixture } from '@/models/fixtures/compartmentPathways';
+import { IncludedCompartmentPathways } from './IncludedCompartmentPathways.component';
+
+const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
+  const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
+
+  return (
+    render(
+      <Wrapper>
+        <IncludedCompartmentPathways />
+      </Wrapper>,
+    ),
+    {
+      store,
+    }
+  );
+};
+
+const CHECKBOX_ELEMENT_NAME = compartmentPathwaysDetailsFixture[0].name;
+
+describe('IncludedCompartmentPathways - component', () => {
+  it('should display compartment / pathways checkboxes when fetching data is successful', async () => {
+    renderComponent({
+      compartmentPathways: {
+        data: compartmentPathwaysDetailsFixture,
+        loading: 'succeeded',
+        error: {
+          message: '',
+          name: '',
+        },
+      },
+    });
+
+    expect(screen.queryByTestId('checkbox-filter')).not.toBeVisible();
+
+    const navigationButton = screen.getByTestId('accordion-item-button');
+
+    act(() => {
+      navigationButton.click();
+    });
+
+    expect(screen.getByText('Select included compartment / pathways')).toBeInTheDocument();
+
+    await waitFor(() => {
+      expect(screen.getByTestId('checkbox-filter')).toBeInTheDocument();
+      expect(screen.getByLabelText('search-input')).toBeInTheDocument();
+      expect(screen.getByLabelText(CHECKBOX_ELEMENT_NAME)).toBeInTheDocument();
+    });
+  });
+  it('should not display compartment / pathways checkboxes when fetching data fails', async () => {
+    renderComponent({
+      compartmentPathways: {
+        data: [],
+        loading: 'failed',
+        error: {
+          message: '',
+          name: '',
+        },
+      },
+    });
+    expect(screen.getByText('Select included compartment / pathways')).toBeInTheDocument();
+    const navigationButton = screen.getByTestId('accordion-item-button');
+    act(() => {
+      navigationButton.click();
+    });
+
+    expect(screen.queryByTestId('checkbox-filter')).not.toBeInTheDocument();
+  });
+  it('should not display compartment / pathways checkboxes when fetched data is empty', async () => {
+    renderComponent({
+      compartmentPathways: {
+        data: [],
+        loading: 'succeeded',
+        error: {
+          message: '',
+          name: '',
+        },
+      },
+    });
+    expect(screen.getByText('Select included compartment / pathways')).toBeInTheDocument();
+    const navigationButton = screen.getByTestId('accordion-item-button');
+    act(() => {
+      navigationButton.click();
+    });
+
+    expect(screen.queryByTestId('checkbox-filter')).not.toBeInTheDocument();
+  });
+
+  it('should display loading message when fetching data is pending', async () => {
+    renderComponent({
+      compartmentPathways: {
+        data: [],
+        loading: 'pending',
+        error: {
+          message: '',
+          name: '',
+        },
+      },
+    });
+    expect(screen.getByText('Select included compartment / pathways')).toBeInTheDocument();
+    const navigationButton = screen.getByTestId('accordion-item-button');
+    act(() => {
+      navigationButton.click();
+    });
+
+    expect(screen.getByText('Loading...')).toBeInTheDocument();
+  });
+});
diff --git a/src/components/Map/Drawer/ExportDrawer/Elements/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx b/src/components/Map/Drawer/ExportDrawer/Elements/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx
new file mode 100644
index 00000000..77a64aed
--- /dev/null
+++ b/src/components/Map/Drawer/ExportDrawer/Elements/IncludedCompartmentPathways /IncludedCompartmentPathways.component.tsx	
@@ -0,0 +1,25 @@
+/* eslint-disable no-magic-numbers */
+import {
+  compartmentPathwaysDataSelector,
+  loadingCompartmentPathwaysSelector,
+} from '@/redux/compartmentPathways/compartmentPathways.selectors';
+import { useAppSelector } from '@/redux/hooks/useAppSelector';
+import { CheckboxFilter } from '../../CheckboxFilter';
+import { CollapsibleSection } from '../../CollapsibleSection';
+import { getCompartmentPathwaysCheckboxElements } from '../Elements.utils';
+
+export const IncludedCompartmentPathways = (): React.ReactNode => {
+  const loadingCompartmentPathways = useAppSelector(loadingCompartmentPathwaysSelector);
+  const isPending = loadingCompartmentPathways === 'pending';
+  const compartmentPathways = useAppSelector(compartmentPathwaysDataSelector);
+  const checkboxElements = getCompartmentPathwaysCheckboxElements(compartmentPathways);
+
+  return (
+    <CollapsibleSection title="Select included compartment / pathways">
+      {isPending && <p>Loading...</p>}
+      {!isPending && checkboxElements && checkboxElements.length > 0 && (
+        <CheckboxFilter options={checkboxElements} />
+      )}
+    </CollapsibleSection>
+  );
+};
diff --git a/src/components/Map/Drawer/ExportDrawer/Elements/IncludedCompartmentPathways /index.ts b/src/components/Map/Drawer/ExportDrawer/Elements/IncludedCompartmentPathways /index.ts
new file mode 100644
index 00000000..56b78aea
--- /dev/null
+++ b/src/components/Map/Drawer/ExportDrawer/Elements/IncludedCompartmentPathways /index.ts	
@@ -0,0 +1 @@
+export { IncludedCompartmentPathways } from './IncludedCompartmentPathways.component';
diff --git a/src/models/compartmentPathwaySchema.ts b/src/models/compartmentPathwaySchema.ts
new file mode 100644
index 00000000..b7f3cdc4
--- /dev/null
+++ b/src/models/compartmentPathwaySchema.ts
@@ -0,0 +1,50 @@
+import { z } from 'zod';
+
+export const compartmentPathwaySchema = z.object({
+  id: z.number(),
+});
+
+export const boundsSchema = z.object({
+  height: z.number(),
+  width: z.number(),
+  x: z.number(),
+  y: z.number(),
+  z: z.number(),
+});
+
+export const otherSchema = z.object({
+  modifications: z.array(z.unknown()),
+  structuralState: z.null(),
+  structures: z.object({}),
+});
+
+export const compartmentPathwayDetailsSchema = z.object({
+  abbreviation: z.null(),
+  activity: z.null(),
+  boundaryCondition: z.null(),
+  bounds: boundsSchema,
+  compartmentId: z.number().nullable(),
+  complexId: z.null(),
+  constant: z.null(),
+  elementId: z.string(),
+  formerSymbols: z.array(z.unknown()),
+  formula: z.null(),
+  fullName: z.string().nullable(),
+  glyph: z.any(),
+  hierarchyVisibilityLevel: z.string(),
+  homomultimer: z.null(),
+  hypothetical: z.null(),
+  id: z.number(),
+  initialAmount: z.null(),
+  initialConcentration: z.null(),
+  linkedSubmodel: z.null(),
+  modelId: z.number(),
+  name: z.string(),
+  notes: z.string(),
+  other: otherSchema,
+  references: z.array(z.unknown()),
+  symbol: z.null(),
+  synonyms: z.array(z.unknown()),
+  transparencyLevel: z.string(),
+  type: z.string(),
+});
diff --git a/src/models/fixtures/compartmentPathways.ts b/src/models/fixtures/compartmentPathways.ts
new file mode 100644
index 00000000..c93b4dc0
--- /dev/null
+++ b/src/models/fixtures/compartmentPathways.ts
@@ -0,0 +1,29 @@
+import { ZOD_SEED } from '@/constants';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { createFixture } from 'zod-fixture';
+import { z } from 'zod';
+import {
+  compartmentPathwayDetailsSchema,
+  compartmentPathwaySchema,
+} from '../compartmentPathwaySchema';
+
+export const compartmentPathwaysFixture = createFixture(z.array(compartmentPathwaySchema), {
+  seed: ZOD_SEED,
+  array: { min: 3, max: 3 },
+});
+
+export const compartmentPathwaysOverLimitFixture = createFixture(
+  z.array(compartmentPathwaySchema),
+  {
+    seed: ZOD_SEED,
+    array: { min: 101, max: 101 },
+  },
+);
+
+export const compartmentPathwaysDetailsFixture = createFixture(
+  z.array(compartmentPathwayDetailsSchema),
+  {
+    seed: ZOD_SEED,
+    array: { min: 3, max: 3 },
+  },
+);
diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts
index 433b6c49..c417dbca 100644
--- a/src/redux/apiPath.ts
+++ b/src/redux/apiPath.ts
@@ -39,4 +39,9 @@ export const apiPath = {
   createOverlayFile: (): string => `files/`,
   uploadOverlayFileContent: (fileId: number): string => `files/${fileId}:uploadContent`,
   getStatisticsById: (projectId: string): string => `projects/${projectId}/statistics/`,
+  getCompartmentPathwaysIds: (objectId: number): string =>
+    `projects/${PROJECT_ID}/models/${objectId}/bioEntities/elements/?columns=id&type=Compartment,Pathway`,
+  getCompartmentPathwayDetails: (ids: number[]): string =>
+    `projects/${PROJECT_ID}/models/*/bioEntities/elements/?id=${ids.join(',')}`,
+  sendCompartmentPathwaysIds: (): string => `projects/${PROJECT_ID}/models/*/bioEntities/elements/`,
 };
diff --git a/src/redux/compartmentPathways/comparmentPathways.constants.ts b/src/redux/compartmentPathways/comparmentPathways.constants.ts
new file mode 100644
index 00000000..2bf4d519
--- /dev/null
+++ b/src/redux/compartmentPathways/comparmentPathways.constants.ts
@@ -0,0 +1 @@
+export const MAX_NUMBER_OF_IDS_IN_GET_QUERY = 100;
diff --git a/src/redux/compartmentPathways/compartmentPathways.mock.ts b/src/redux/compartmentPathways/compartmentPathways.mock.ts
new file mode 100644
index 00000000..6d62817d
--- /dev/null
+++ b/src/redux/compartmentPathways/compartmentPathways.mock.ts
@@ -0,0 +1,64 @@
+import { MapModel } from '@/types/models';
+import { CompartmentPathwaysState } from './compartmentPathways.types';
+
+export const COMPARTMENT_PATHWAYS_INITIAL_STATE_MOCK: CompartmentPathwaysState = {
+  loading: 'idle',
+  data: [],
+  error: { name: '', message: '' },
+};
+export const MODELS_MOCK: MapModel[] = [
+  {
+    idObject: 5053,
+    width: 26779.25,
+    height: 13503.0,
+    defaultCenterX: null,
+    defaultCenterY: null,
+    description: '',
+    name: 'Core PD map',
+    defaultZoomLevel: null,
+    tileSize: 256,
+    references: [],
+    authors: [],
+    creationDate: null,
+    modificationDates: [],
+    minZoom: 2,
+    maxZoom: 9,
+  },
+  {
+    idObject: 5054,
+    width: 26779.25,
+    height: 13503.0,
+    defaultCenterX: null,
+    defaultCenterY: null,
+    description: '',
+    name: 'Core PD map',
+    defaultZoomLevel: null,
+    tileSize: 256,
+    references: [],
+    authors: [],
+    creationDate: null,
+    modificationDates: [],
+    minZoom: 2,
+    maxZoom: 9,
+  },
+];
+
+export const MODELS_MOCK_SHORT: MapModel[] = [
+  {
+    idObject: 5050,
+    width: 26779.25,
+    height: 13503.0,
+    defaultCenterX: null,
+    defaultCenterY: null,
+    description: '',
+    name: 'Core PD map',
+    defaultZoomLevel: null,
+    tileSize: 256,
+    references: [],
+    authors: [],
+    creationDate: null,
+    modificationDates: [],
+    minZoom: 2,
+    maxZoom: 9,
+  },
+];
diff --git a/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts b/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts
new file mode 100644
index 00000000..2c263903
--- /dev/null
+++ b/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts
@@ -0,0 +1,122 @@
+/* eslint-disable no-magic-numbers */
+import {
+  ToolkitStoreWithSingleSlice,
+  createStoreInstanceUsingSliceReducer,
+} from '@/utils/createStoreInstanceUsingSliceReducer';
+import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
+import { HttpStatusCode } from 'axios';
+import {
+  compartmentPathwaysDetailsFixture,
+  compartmentPathwaysFixture,
+  compartmentPathwaysOverLimitFixture,
+} from '@/models/fixtures/compartmentPathways';
+import { getModelsIds } from '@/components/Map/Drawer/ExportDrawer/Elements/Elements.utils';
+import { apiPath } from '../apiPath';
+import compartmentPathwaysReducer from './compartmentPathways.slice';
+import { CompartmentPathwaysState } from './compartmentPathways.types';
+import { getCompartmentPathways } from './compartmentPathways.thunks';
+import { MODELS_MOCK } from './compartmentPathways.mock';
+
+const mockedAxiosClient = mockNetworkResponse();
+const MODELS_MOCK_IDS = getModelsIds(MODELS_MOCK);
+const INITIAL_STATE: CompartmentPathwaysState = {
+  loading: 'idle',
+  error: { name: '', message: '' },
+  data: [],
+};
+
+describe('compartmentPathways reducer', () => {
+  let store = {} as ToolkitStoreWithSingleSlice<CompartmentPathwaysState>;
+  beforeEach(() => {
+    store = createStoreInstanceUsingSliceReducer('compartmentPathways', compartmentPathwaysReducer);
+  });
+
+  it('should match initial state', () => {
+    const action = { type: 'unknown' };
+    expect(compartmentPathwaysReducer(undefined, action)).toEqual(INITIAL_STATE);
+  });
+  it('should update store on loading getCompartmentPathways query', async () => {
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwaysIds(52))
+      .reply(HttpStatusCode.Ok, compartmentPathwaysFixture);
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwayDetails([1, 2, 3]))
+      .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture);
+    mockedAxiosClient
+      .onPost(apiPath.sendCompartmentPathwaysIds())
+      .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture);
+
+    const { loading, data } = store.getState().compartmentPathways;
+
+    expect(loading).toEqual('idle');
+    expect(data).toEqual([]);
+
+    store.dispatch(getCompartmentPathways());
+
+    const { loading: loadingPending, data: dataPending } = store.getState().compartmentPathways;
+
+    expect(loadingPending).toEqual('pending');
+    expect(dataPending).toEqual([]);
+  });
+
+  it('should update store after succesful getCompartmentPathways query', async () => {
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwaysIds(5053))
+      .reply(HttpStatusCode.Ok, compartmentPathwaysFixture);
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwaysIds(5054))
+      .reply(HttpStatusCode.Ok, compartmentPathwaysOverLimitFixture);
+
+    const ids = compartmentPathwaysFixture.map(el => el.id);
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwayDetails(ids))
+      .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture);
+    mockedAxiosClient
+      .onPost(apiPath.sendCompartmentPathwaysIds())
+      .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture);
+
+    const compartmentPathwaysPromise = store.dispatch(getCompartmentPathways(MODELS_MOCK_IDS));
+
+    const { loading, data } = store.getState().compartmentPathways;
+
+    expect(loading).toEqual('pending');
+    expect(data).toEqual([]);
+
+    const { type } = await compartmentPathwaysPromise;
+
+    expect(type).toBe('compartmentPathways/getCompartmentPathways/fulfilled');
+
+    const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways;
+
+    expect(dataFulfilled).toEqual([
+      ...compartmentPathwaysDetailsFixture,
+      ...compartmentPathwaysDetailsFixture,
+    ]);
+    expect(promiseFulfilled).toEqual('succeeded');
+  });
+
+  it('should update store after failed getCompartmentPathways query', async () => {
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwaysIds(5053))
+      .reply(HttpStatusCode.NotFound, []);
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwayDetails([]))
+      .reply(HttpStatusCode.NotFound, []);
+    mockedAxiosClient
+      .onPost(apiPath.sendCompartmentPathwaysIds())
+      .reply(HttpStatusCode.NotFound, []);
+
+    const compartmentPathwaysPromise = store.dispatch(getCompartmentPathways(MODELS_MOCK_IDS));
+
+    const { loading, data } = store.getState().compartmentPathways;
+    expect(loading).toEqual('pending');
+    expect(data).toEqual([]);
+
+    await compartmentPathwaysPromise;
+
+    const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways;
+
+    expect(promiseFulfilled).toEqual('failed');
+    expect(dataFulfilled).toEqual([]);
+  });
+});
diff --git a/src/redux/compartmentPathways/compartmentPathways.reducers.ts b/src/redux/compartmentPathways/compartmentPathways.reducers.ts
new file mode 100644
index 00000000..8010fbc0
--- /dev/null
+++ b/src/redux/compartmentPathways/compartmentPathways.reducers.ts
@@ -0,0 +1,20 @@
+import { ActionReducerMapBuilder } from '@reduxjs/toolkit';
+import { getCompartmentPathways } from './compartmentPathways.thunks';
+import { CompartmentPathwaysState } from './compartmentPathways.types';
+
+export const getCompartmentPathwaysReducer = (
+  builder: ActionReducerMapBuilder<CompartmentPathwaysState>,
+): void => {
+  builder
+    .addCase(getCompartmentPathways.pending, state => {
+      state.loading = 'pending';
+    })
+    .addCase(getCompartmentPathways.fulfilled, (state, action) => {
+      state.data = action.payload;
+      state.loading = 'succeeded';
+    })
+    .addCase(getCompartmentPathways.rejected, state => {
+      state.loading = 'failed';
+      // TODO: error management to be discussed in the team
+    });
+};
diff --git a/src/redux/compartmentPathways/compartmentPathways.selectors.ts b/src/redux/compartmentPathways/compartmentPathways.selectors.ts
new file mode 100644
index 00000000..d6c82942
--- /dev/null
+++ b/src/redux/compartmentPathways/compartmentPathways.selectors.ts
@@ -0,0 +1,17 @@
+import { rootSelector } from '@/redux/root/root.selectors';
+import { createSelector } from '@reduxjs/toolkit';
+
+export const compartmentPathwaysSelector = createSelector(
+  rootSelector,
+  state => state.compartmentPathways,
+);
+
+export const compartmentPathwaysDataSelector = createSelector(
+  compartmentPathwaysSelector,
+  state => state.data,
+);
+
+export const loadingCompartmentPathwaysSelector = createSelector(
+  compartmentPathwaysSelector,
+  state => state.loading,
+);
diff --git a/src/redux/compartmentPathways/compartmentPathways.slice.ts b/src/redux/compartmentPathways/compartmentPathways.slice.ts
new file mode 100644
index 00000000..3cc1b375
--- /dev/null
+++ b/src/redux/compartmentPathways/compartmentPathways.slice.ts
@@ -0,0 +1,20 @@
+import { createSlice } from '@reduxjs/toolkit';
+import { CompartmentPathwaysState } from './compartmentPathways.types';
+import { getCompartmentPathwaysReducer } from './compartmentPathways.reducers';
+
+export const initialState: CompartmentPathwaysState = {
+  loading: 'idle',
+  error: { name: '', message: '' },
+  data: [],
+};
+
+export const compartmentPathwaysSlice = createSlice({
+  name: 'compartmentPathways',
+  initialState,
+  reducers: {},
+  extraReducers: builder => {
+    getCompartmentPathwaysReducer(builder);
+  },
+});
+
+export default compartmentPathwaysSlice.reducer;
diff --git a/src/redux/compartmentPathways/compartmentPathways.thunks.test.ts b/src/redux/compartmentPathways/compartmentPathways.thunks.test.ts
new file mode 100644
index 00000000..b2d801e3
--- /dev/null
+++ b/src/redux/compartmentPathways/compartmentPathways.thunks.test.ts
@@ -0,0 +1,126 @@
+/* eslint-disable no-magic-numbers */
+import {
+  ToolkitStoreWithSingleSlice,
+  createStoreInstanceUsingSliceReducer,
+} from '@/utils/createStoreInstanceUsingSliceReducer';
+import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
+import { HttpStatusCode } from 'axios';
+import {
+  compartmentPathwaysDetailsFixture,
+  compartmentPathwaysFixture,
+  compartmentPathwaysOverLimitFixture,
+} from '@/models/fixtures/compartmentPathways';
+import { getModelsIds } from '@/components/Map/Drawer/ExportDrawer/Elements/Elements.utils';
+import { apiPath } from '../apiPath';
+import compartmentPathwaysReducer from './compartmentPathways.slice';
+import { CompartmentPathwaysState } from './compartmentPathways.types';
+import { getCompartmentPathways } from './compartmentPathways.thunks';
+import { MODELS_MOCK, MODELS_MOCK_SHORT } from './compartmentPathways.mock';
+
+const mockedAxiosClient = mockNetworkResponse();
+const MODELS_MOCK_IDS = getModelsIds(MODELS_MOCK);
+
+describe('compartmentPathways thunk', () => {
+  let store = {} as ToolkitStoreWithSingleSlice<CompartmentPathwaysState>;
+  beforeEach(() => {
+    store = createStoreInstanceUsingSliceReducer('compartmentPathways', compartmentPathwaysReducer);
+  });
+
+  it('should handle query getCompartmentPathways properly when models are undefined', async () => {
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwaysIds(52))
+      .reply(HttpStatusCode.Ok, compartmentPathwaysFixture);
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwayDetails([1, 2, 3]))
+      .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture);
+    mockedAxiosClient
+      .onPost(apiPath.sendCompartmentPathwaysIds())
+      .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture);
+
+    const { loading, data } = store.getState().compartmentPathways;
+
+    expect(loading).toEqual('idle');
+    expect(data).toEqual([]);
+
+    const comparmentPathwaysPromise = store.dispatch(getCompartmentPathways());
+
+    const { loading: loadingPending, data: dataPending } = store.getState().compartmentPathways;
+
+    expect(loadingPending).toEqual('pending');
+    expect(dataPending).toEqual([]);
+
+    await comparmentPathwaysPromise;
+    const { loading: loadingFulfilled, data: dataFulfilled } = store.getState().compartmentPathways;
+
+    expect(loadingFulfilled).toEqual('succeeded');
+    expect(dataFulfilled).toEqual([]);
+  });
+  it('should handle sendCompartmentPathwaysIds request properly if it is more than 100 ids', async () => {
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwaysIds(5053))
+      .reply(HttpStatusCode.Ok, compartmentPathwaysFixture);
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwaysIds(5054))
+      .reply(HttpStatusCode.Ok, compartmentPathwaysOverLimitFixture);
+
+    const ids = compartmentPathwaysFixture.map(el => el.id);
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwayDetails(ids))
+      .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture);
+    mockedAxiosClient
+      .onPost(apiPath.sendCompartmentPathwaysIds())
+      .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture);
+
+    const compartmentPathwaysPromise = store.dispatch(getCompartmentPathways(MODELS_MOCK_IDS));
+
+    const { loading, data } = store.getState().compartmentPathways;
+
+    expect(loading).toEqual('pending');
+    expect(data).toEqual([]);
+
+    const { type } = await compartmentPathwaysPromise;
+
+    expect(type).toBe('compartmentPathways/getCompartmentPathways/fulfilled');
+
+    const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways;
+
+    expect(dataFulfilled).toEqual([
+      ...compartmentPathwaysDetailsFixture,
+      ...compartmentPathwaysDetailsFixture,
+    ]);
+    expect(promiseFulfilled).toEqual('succeeded');
+  });
+
+  it('should not do a network request sendCompartmentPathwaysIds if it is less than 100 ids', async () => {
+    const ONE_MODEL = MODELS_MOCK_SHORT[0];
+    const ID = ONE_MODEL.idObject;
+
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwaysIds(ID))
+      .reply(HttpStatusCode.Ok, compartmentPathwaysFixture);
+
+    const ids = compartmentPathwaysFixture.map(el => el.id);
+    mockedAxiosClient
+      .onGet(apiPath.getCompartmentPathwayDetails(ids))
+      .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture);
+    mockedAxiosClient
+      .onPost(apiPath.sendCompartmentPathwaysIds())
+      .reply(HttpStatusCode.Ok, compartmentPathwaysDetailsFixture);
+
+    const compartmentPathwaysPromise = store.dispatch(getCompartmentPathways([ONE_MODEL.idObject]));
+
+    const { loading, data } = store.getState().compartmentPathways;
+
+    expect(loading).toEqual('pending');
+    expect(data).toEqual([]);
+
+    const { type } = await compartmentPathwaysPromise;
+
+    expect(type).toBe('compartmentPathways/getCompartmentPathways/fulfilled');
+
+    const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways;
+
+    expect(dataFulfilled).toEqual(compartmentPathwaysDetailsFixture);
+    expect(promiseFulfilled).toEqual('succeeded');
+  });
+});
diff --git a/src/redux/compartmentPathways/compartmentPathways.thunks.ts b/src/redux/compartmentPathways/compartmentPathways.thunks.ts
new file mode 100644
index 00000000..e0d69617
--- /dev/null
+++ b/src/redux/compartmentPathways/compartmentPathways.thunks.ts
@@ -0,0 +1,120 @@
+/* eslint-disable no-restricted-syntax */
+import { axiosInstance } from '@/services/api/utils/axiosInstance';
+import { createAsyncThunk } from '@reduxjs/toolkit';
+import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
+import { CompartmentPathway, CompartmentPathwayDetails } from '@/types/models';
+import {
+  compartmentPathwayDetailsSchema,
+  compartmentPathwaySchema,
+} from '@/models/compartmentPathwaySchema';
+import { z } from 'zod';
+import { MAX_NUMBER_OF_IDS_IN_GET_QUERY } from './comparmentPathways.constants';
+import { apiPath } from '../apiPath';
+
+/** UTILS */
+
+const fetchCompartmentPathwaysIds = async (
+  modelsIds: number[] | undefined,
+): Promise<number[][]> => {
+  if (!modelsIds) return [];
+
+  const compartmentIds = [];
+
+  for (const modelId of modelsIds) {
+    /* eslint-disable no-await-in-loop */
+    const response = await axiosInstance<CompartmentPathway[]>(
+      apiPath.getCompartmentPathwaysIds(modelId),
+    );
+
+    const isDataValid = validateDataUsingZodSchema(
+      response.data,
+      z.array(compartmentPathwaySchema),
+    );
+
+    if (isDataValid) {
+      const result = response.data;
+      const ids: number[] = [];
+
+      result.forEach(item => {
+        ids.push(item.id);
+      });
+
+      compartmentIds.push(ids);
+    }
+  }
+
+  return compartmentIds;
+};
+
+const fetchCompartmentPathwayDetailsByPost = async (
+  compartmentPathwayIds: number[],
+): Promise<CompartmentPathwayDetails[]> => {
+  const params = {
+    id: compartmentPathwayIds.join(','),
+  };
+  const body = new URLSearchParams(params);
+
+  const response = await axiosInstance.post<CompartmentPathwayDetails[]>(
+    apiPath.sendCompartmentPathwaysIds(),
+    body,
+  );
+
+  return response.data;
+};
+
+const fetchCompartmentPathwayDetailsByGet = async (
+  compartmentPathwayIds: number[],
+): Promise<CompartmentPathwayDetails[]> => {
+  const response = await axiosInstance.get<CompartmentPathwayDetails[]>(
+    apiPath.getCompartmentPathwayDetails(compartmentPathwayIds),
+  );
+
+  return response.data;
+};
+
+const fetchCompartmentPathwayDetails = async (
+  compartmentPathwayIds: number[],
+): Promise<CompartmentPathwayDetails[]> => {
+  if (compartmentPathwayIds.length) {
+    let compartmentPathwayDetails;
+    if (compartmentPathwayIds.length > MAX_NUMBER_OF_IDS_IN_GET_QUERY) {
+      compartmentPathwayDetails = await fetchCompartmentPathwayDetailsByPost(compartmentPathwayIds);
+    } else {
+      compartmentPathwayDetails = await fetchCompartmentPathwayDetailsByGet(compartmentPathwayIds);
+    }
+
+    const isDataValid = validateDataUsingZodSchema(
+      compartmentPathwayDetails,
+      z.array(compartmentPathwayDetailsSchema),
+    );
+
+    if (isDataValid) return compartmentPathwayDetails;
+  }
+  return [];
+};
+
+export const fetchCompartmentPathways = async (
+  compartmentPathwaysData: number[][],
+): Promise<CompartmentPathwayDetails[]> => {
+  const compartments = [];
+
+  /* eslint-disable no-await-in-loop */
+  for (const compartmentPathwayIds of compartmentPathwaysData) {
+    const compartmentPathwayDetails = await fetchCompartmentPathwayDetails(compartmentPathwayIds);
+
+    if (compartmentPathwayDetails) compartments.push(...compartmentPathwayDetails);
+  }
+
+  return compartments;
+};
+
+/** UTILS */
+
+export const getCompartmentPathways = createAsyncThunk(
+  'compartmentPathways/getCompartmentPathways',
+  async (modelsIds: number[] | undefined) => {
+    const compartmentIds = await fetchCompartmentPathwaysIds(modelsIds);
+    const comparmentPathways = await fetchCompartmentPathways(compartmentIds);
+    return comparmentPathways;
+  },
+);
diff --git a/src/redux/compartmentPathways/compartmentPathways.types.ts b/src/redux/compartmentPathways/compartmentPathways.types.ts
new file mode 100644
index 00000000..76718b54
--- /dev/null
+++ b/src/redux/compartmentPathways/compartmentPathways.types.ts
@@ -0,0 +1,4 @@
+import { FetchDataState } from '@/types/fetchDataState';
+import { CompartmentPathwayDetails } from '@/types/models';
+
+export type CompartmentPathwaysState = FetchDataState<CompartmentPathwayDetails[], []>;
diff --git a/src/redux/root/root.fixtures.ts b/src/redux/root/root.fixtures.ts
index aaca59eb..a8494c46 100644
--- a/src/redux/root/root.fixtures.ts
+++ b/src/redux/root/root.fixtures.ts
@@ -15,9 +15,10 @@ import { OVERLAYS_INITIAL_STATE_MOCK } from '../overlays/overlays.mock';
 import { PROJECT_STATE_INITIAL_MOCK } from '../project/project.mock';
 import { REACTIONS_STATE_INITIAL_MOCK } from '../reactions/reactions.mock';
 import { SEARCH_STATE_INITIAL_MOCK } from '../search/search.mock';
-import { STATISTICS_STATE_INITIAL_MOCK } from '../statistics/statistics.mock';
 import { RootState } from '../store';
 import { USER_INITIAL_STATE_MOCK } from '../user/user.mock';
+import { STATISTICS_STATE_INITIAL_MOCK } from '../statistics/statistics.mock';
+import { COMPARTMENT_PATHWAYS_INITIAL_STATE_MOCK } from '../compartmentPathways/compartmentPathways.mock';
 
 export const INITIAL_STORE_STATE_MOCK: RootState = {
   search: SEARCH_STATE_INITIAL_MOCK,
@@ -39,4 +40,5 @@ export const INITIAL_STORE_STATE_MOCK: RootState = {
   user: USER_INITIAL_STATE_MOCK,
   legend: LEGEND_INITIAL_STATE_MOCK,
   statistics: STATISTICS_STATE_INITIAL_MOCK,
+  compartmentPathways: COMPARTMENT_PATHWAYS_INITIAL_STATE_MOCK,
 };
diff --git a/src/redux/store.ts b/src/redux/store.ts
index b79cf2b2..944288e8 100644
--- a/src/redux/store.ts
+++ b/src/redux/store.ts
@@ -25,6 +25,7 @@ import {
 import legendReducer from './legend/legend.slice';
 import { mapListenerMiddleware } from './map/middleware/map.middleware';
 import statisticsReducer from './statistics/statistics.slice';
+import compartmentPathwaysReducer from './compartmentPathways/compartmentPathways.slice';
 
 export const reducers = {
   search: searchReducer,
@@ -46,6 +47,7 @@ export const reducers = {
   overlayBioEntity: overlayBioEntityReducer,
   legend: legendReducer,
   statistics: statisticsReducer,
+  compartmentPathways: compartmentPathwaysReducer,
 };
 
 export const middlewares = [mapListenerMiddleware.middleware];
diff --git a/src/types/models.ts b/src/types/models.ts
index 8f4582e5..23d350f7 100644
--- a/src/types/models.ts
+++ b/src/types/models.ts
@@ -3,6 +3,10 @@ import { bioEntityResponseSchema } from '@/models/bioEntityResponseSchema';
 import { bioEntitySchema } from '@/models/bioEntitySchema';
 import { chemicalSchema } from '@/models/chemicalSchema';
 import { colorSchema } from '@/models/colorSchema';
+import {
+  compartmentPathwayDetailsSchema,
+  compartmentPathwaySchema,
+} from '@/models/compartmentPathwaySchema';
 import { configurationOptionSchema } from '@/models/configurationOptionSchema';
 import { configurationSchema } from '@/models/configurationSchema';
 import { disease } from '@/models/disease';
@@ -65,3 +69,5 @@ export type UploadedOverlayFileContent = z.infer<typeof uploadedOverlayFileConte
 export type CreatedOverlay = z.infer<typeof createdOverlaySchema>;
 export type Color = z.infer<typeof colorSchema>;
 export type Statistics = z.infer<typeof statisticsSchema>;
+export type CompartmentPathway = z.infer<typeof compartmentPathwaySchema>;
+export type CompartmentPathwayDetails = z.infer<typeof compartmentPathwayDetailsSchema>;
-- 
GitLab