diff --git a/src/components/FunctionalArea/ContextMenu/ContextMenu.component.tsx b/src/components/FunctionalArea/ContextMenu/ContextMenu.component.tsx
index a6811e654b1c3cb140eced363877b627cdb4ea6d..59bb7f07e6d101242a35b68793a472901c532eb1 100644
--- a/src/components/FunctionalArea/ContextMenu/ContextMenu.component.tsx
+++ b/src/components/FunctionalArea/ContextMenu/ContextMenu.component.tsx
@@ -3,7 +3,7 @@ import { contextMenuSelector } from '@/redux/contextMenu/contextMenu.selector';
 import { closeContextMenu } from '@/redux/contextMenu/contextMenu.slice';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
-import { openMolArtModalById } from '@/redux/modal/modal.slice';
+import { openAddCommentModal, openMolArtModalById } from '@/redux/modal/modal.slice';
 import React from 'react';
 import { twMerge } from 'tailwind-merge';
 
@@ -27,6 +27,11 @@ export const ContextMenu = (): React.ReactNode => {
     }
   };
 
+  const handleAddCommentClick = (): void => {
+    dispatch(closeContextMenu());
+    dispatch(openAddCommentModal());
+  };
+
   return (
     <div
       className={twMerge(
@@ -50,6 +55,15 @@ export const ContextMenu = (): React.ReactNode => {
       >
         Open MolArt ({getUnitProtId()})
       </button>
+      <hr />
+      <button
+        className={twMerge('cursor-pointer text-xs font-normal')}
+        onClick={handleAddCommentClick}
+        type="button"
+        data-testid="add-comment"
+      >
+        Add comment
+      </button>
     </div>
   );
 };
diff --git a/src/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component.test.tsx b/src/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component.test.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..0ba098a130cab5a0631547aa7414526ed2a7d0fa
--- /dev/null
+++ b/src/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component.test.tsx
@@ -0,0 +1,87 @@
+import { StoreType } from '@/redux/store';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
+import {
+  InitialStoreState,
+  getReduxWrapperWithStore,
+} from '@/utils/testing/getReduxWrapperWithStore';
+import { act } from 'react-dom/test-utils';
+import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
+import { MODAL_INITIAL_STATE_MOCK } from '@/redux/modal/modal.mock';
+import { AddCommentModal } from '@/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component';
+import { apiPath } from '@/redux/apiPath';
+import { HttpStatusCode } from 'axios';
+import { ZERO } from '@/constants/common';
+import { commentFixture } from '@/models/fixtures/commentFixture';
+import { commentsFixture } from '@/models/fixtures/commentsFixture';
+
+const mockedAxiosClient = mockNetworkResponse();
+
+const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
+  const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
+
+  return (
+    render(
+      <Wrapper>
+        <AddCommentModal />
+      </Wrapper>,
+    ),
+    {
+      store,
+    }
+  );
+};
+
+describe('AddCommentModal - component', () => {
+  test('renders AddCommentModal component', () => {
+    renderComponent();
+
+    const emailInput = screen.getByLabelText(/email/i);
+    const contentInput = screen.getByLabelText(/content/i);
+    expect(emailInput).toBeInTheDocument();
+    expect(contentInput).toBeInTheDocument();
+  });
+
+  test('handles input change correctly', () => {
+    renderComponent();
+
+    const emailInput: HTMLInputElement = screen.getByLabelText(/email/i);
+    const contentInput: HTMLInputElement = screen.getByLabelText(/content/i);
+
+    fireEvent.change(emailInput, { target: { value: 'test@email.pl' } });
+    fireEvent.change(contentInput, { target: { value: 'test content' } });
+
+    expect(emailInput.value).toBe('test@email.pl');
+    expect(contentInput.value).toBe('test content');
+  });
+
+  test('submits form', async () => {
+    mockedAxiosClient
+      .onPost(apiPath.addComment(ZERO, ZERO, ZERO))
+      .reply(HttpStatusCode.Ok, commentFixture);
+    mockedAxiosClient.onGet(apiPath.getComments()).reply(HttpStatusCode.Ok, commentsFixture);
+
+    const { store } = renderComponent({
+      modal: {
+        ...MODAL_INITIAL_STATE_MOCK,
+        isOpen: true,
+        modalName: 'add-comment',
+      },
+    });
+
+    const emailInput: HTMLInputElement = screen.getByLabelText(/email/i);
+    const contentInput: HTMLInputElement = screen.getByLabelText(/content/i);
+    const submitButton = screen.getByText(/submit/i);
+
+    fireEvent.change(emailInput, { target: { value: 'test@email.pl' } });
+    fireEvent.change(contentInput, { target: { value: 'test content' } });
+    act(() => {
+      submitButton.click();
+    });
+
+    await waitFor(() => {
+      const modalState = store.getState().modal;
+      expect(modalState.modalName).toBe('none');
+      expect(modalState.isOpen).toBeFalsy();
+    });
+  });
+});
diff --git a/src/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component.tsx b/src/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..9c4fde54b754948a099b53bbaf8626b78f2bbb2c
--- /dev/null
+++ b/src/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component.tsx
@@ -0,0 +1,68 @@
+import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
+import { Button } from '@/shared/Button';
+import { Input } from '@/shared/Input';
+import React from 'react';
+
+import { addComment } from '@/redux/comment/thunks/addComment';
+import { useAppSelector } from '@/redux/hooks/useAppSelector';
+import { lastRightClickSelector } from '@/redux/models/models.selectors';
+import { closeModal } from '@/redux/modal/modal.slice';
+import { getComments } from '@/redux/comment/thunks/getComments';
+
+export const AddCommentModal: React.FC = () => {
+  const dispatch = useAppDispatch();
+  const lastClick = useAppSelector(lastRightClickSelector);
+
+  const [data, setData] = React.useState({
+    email: '',
+    content: '',
+    modelId: lastClick.modelId,
+    position: lastClick.position,
+  });
+
+  const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
+    const { name, value } = e.target;
+    setData(prevData => ({ ...prevData, [name]: value }));
+  };
+
+  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>): Promise<void> => {
+    e.preventDefault();
+    await dispatch(addComment(data));
+    dispatch(closeModal());
+    dispatch(getComments());
+  };
+
+  return (
+    <div className="w-[400px] border border-t-[#E1E0E6] bg-white p-[24px]">
+      <form onSubmit={handleSubmit}>
+        <label className="mb-5 block text-sm font-semibold" htmlFor="email">
+          Email (visible only to moderators):
+          <Input
+            type="text"
+            name="email"
+            id="email"
+            placeholder="Your email here..."
+            value={data.email}
+            onChange={handleChange}
+            className="mt-2.5 text-sm font-medium text-font-400"
+          />
+        </label>
+        <label className="text-sm font-semibold" htmlFor="content">
+          Content:
+          <Input
+            type="textarea"
+            name="content"
+            id="content"
+            placeholder="Message here..."
+            value={data.content}
+            onChange={handleChange}
+            className="mt-2.5 text-sm font-medium text-font-400"
+          />
+        </label>
+        <Button type="submit" className="w-full justify-center text-base font-medium">
+          Submit
+        </Button>
+      </form>
+    </div>
+  );
+};
diff --git a/src/components/FunctionalArea/Modal/Modal.component.tsx b/src/components/FunctionalArea/Modal/Modal.component.tsx
index 44005fcd0cd9fafe6b29b870f0137613faa35e21..8e2a02b528cf172eebb868fd183008da565dde12 100644
--- a/src/components/FunctionalArea/Modal/Modal.component.tsx
+++ b/src/components/FunctionalArea/Modal/Modal.component.tsx
@@ -2,6 +2,7 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import { modalSelector } from '@/redux/modal/modal.selector';
 import dynamic from 'next/dynamic';
 import { AccessDeniedModal } from '@/components/FunctionalArea/Modal/AccessDeniedModal/AccessDeniedModal.component';
+import { AddCommentModal } from '@/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component';
 import { EditOverlayModal } from './EditOverlayModal';
 import { LoginModal } from './LoginModal';
 import { ErrorReportModal } from './ErrorReportModal';
@@ -56,6 +57,11 @@ export const Modal = (): React.ReactNode => {
           <AccessDeniedModal />
         </ModalLayout>
       )}
+      {isOpen && modalName === 'add-comment' && (
+        <ModalLayout>
+          <AddCommentModal />
+        </ModalLayout>
+      )}
     </>
   );
 };
diff --git a/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx b/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx
index b2630c627897de41145ede1fe6c00a52df95bc10..3afcf1f8cfc442b64f8ced8934545a33337b4d2c 100644
--- a/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx
+++ b/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx
@@ -29,6 +29,7 @@ export const ModalLayout = ({ children }: ModalLayoutProps): JSX.Element => {
             'flex h-5/6 w-10/12	flex-col	overflow-hidden rounded-lg',
             modalName === 'login' && 'h-auto w-[400px]',
             modalName === 'access-denied' && 'h-auto w-[400px]',
+            modalName === 'add-comment' && 'h-auto w-[400px]',
             modalName === 'error-report' && 'h-auto w-[800px]',
             ['edit-overlay', 'logged-in-menu'].includes(modalName) && 'h-auto w-[432px]',
           )}
diff --git a/src/components/Map/Drawer/BioEntityDrawer/Comments/CommentItem.component.tsx b/src/components/Map/Drawer/BioEntityDrawer/Comments/CommentItem.component.tsx
index 282ee447d17e2583ad08309f2f9407635debdbc9..f080077c6a0ff6873f14cbb0eabd70f9ea5a6f0e 100644
--- a/src/components/Map/Drawer/BioEntityDrawer/Comments/CommentItem.component.tsx
+++ b/src/components/Map/Drawer/BioEntityDrawer/Comments/CommentItem.component.tsx
@@ -7,13 +7,9 @@ interface CommentItemProps {
 
 export const CommentItem = (commentItemProps: CommentItemProps): JSX.Element => {
   const { comment } = commentItemProps;
-  let { owner } = comment;
-  if (!owner) {
-    owner = 'Anonymous';
-  }
   return (
     <div className="border border-slate-400">
-      <div className="p-4 font-bold"> {owner} </div>
+      <div className="p-4 font-bold"> #{comment.id} </div>
       <div className="p-4"> {comment.content} </div>
     </div>
   );
diff --git a/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.test.ts b/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.test.ts
index 2992cfaae4300662cfb1b64fdfe74295738a29cc..bead3d12015b534bd89e5f5cc0beff50f93caeae 100644
--- a/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.test.ts
+++ b/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.test.ts
@@ -8,7 +8,7 @@ import {
   ELEMENT_SEARCH_RESULT_MOCK_REACTION,
 } from '@/models/mocks/elementSearchResultMock';
 import { waitFor } from '@testing-library/react';
-import { FIRST_ARRAY_ELEMENT, SIZE_OF_EMPTY_ARRAY } from '@/constants/common';
+import { FIRST_ARRAY_ELEMENT, SECOND_ARRAY_ELEMENT, SIZE_OF_EMPTY_ARRAY } from '@/constants/common';
 import { onMapRightClick } from './onMapRightClick';
 import * as handleDataReset from '../mapSingleClick/handleDataReset';
 import * as handleSearchResultForRightClickAction from './handleSearchResultForRightClickAction';
@@ -58,7 +58,8 @@ describe('onMapRightClick - util', () => {
     it('should fire open context menu handler', async () => {
       const actions = store.getActions();
       expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY);
-      expect(actions[FIRST_ARRAY_ELEMENT].type).toEqual('contextMenu/openContextMenu');
+      expect(actions[FIRST_ARRAY_ELEMENT].type).toEqual('map/updateLastRightClick');
+      expect(actions[SECOND_ARRAY_ELEMENT].type).toEqual('contextMenu/openContextMenu');
     });
   });
 
diff --git a/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.ts b/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.ts
index 2288c0c6deb6bedef430c00b506fbd67ff5c7fe8..d5d284892aeb7aeff9b263df4d8db19e93d50dfb 100644
--- a/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.ts
+++ b/src/components/Map/MapViewer/utils/listeners/mapRightClick/onMapRightClick.ts
@@ -1,9 +1,12 @@
-import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common';
 import { openContextMenu } from '@/redux/contextMenu/contextMenu.slice';
+import { SIZE_OF_EMPTY_ARRAY } from '@/constants/common';
 import { MapSize } from '@/redux/map/map.types';
 import { AppDispatch } from '@/redux/store';
 import { Coordinate } from 'ol/coordinate';
 import { Pixel } from 'ol/pixel';
+import { updateLastRightClick } from '@/redux/map/map.slice';
+import { toLonLat } from 'ol/proj';
+import { latLngToPoint } from '@/utils/map/latLngToPoint';
 import { getSearchResults } from '../mapSingleClick/getSearchResults';
 import { handleDataReset } from '../mapSingleClick/handleDataReset';
 import { handleSearchResultForRightClickAction } from './handleSearchResultForRightClickAction';
@@ -11,6 +14,11 @@ import { handleSearchResultForRightClickAction } from './handleSearchResultForRi
 /* prettier-ignore */
 export const onMapRightClick =
   (mapSize: MapSize, modelId: number, dispatch: AppDispatch) => async (coordinate: Coordinate, pixel: Pixel): Promise<void> => {
+    const [lng, lat] = toLonLat(coordinate);
+    const point = latLngToPoint([lat, lng], mapSize);
+
+    dispatch(updateLastRightClick({coordinates:point, modelId}));
+
     dispatch(handleDataReset);
     dispatch(openContextMenu(pixel));
 
diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts
index cb09d0a5bccf2493ae96b6361ca3e5921ee8e9ef..e04f2880a546ad753225e2301de34487753f3c53 100644
--- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts
+++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/onMapSingleClick.ts
@@ -4,6 +4,9 @@ import { AppDispatch } from '@/redux/store';
 import { Map, MapBrowserEvent } from 'ol';
 import { FeatureLike } from 'ol/Feature';
 import { Comment } from '@/types/models';
+import { updateLastClick } from '@/redux/map/map.slice';
+import { toLonLat } from 'ol/proj';
+import { latLngToPoint } from '@/utils/map/latLngToPoint';
 import { getSearchResults } from './getSearchResults';
 import { handleDataReset } from './handleDataReset';
 import { handleFeaturesClick } from './handleFeaturesClick';
@@ -14,6 +17,11 @@ export const onMapSingleClick =
   (mapSize: MapSize, modelId: number, dispatch: AppDispatch, searchDistance: string | undefined, maxZoom: number, zoom: number, isResultDrawerOpen: boolean,
     comments: Comment[]) =>
     async ({ coordinate, pixel }: Pick<MapBrowserEvent<UIEvent>, 'coordinate' | 'pixel'>, mapInstance: Map): Promise<void> => {
+      const [lng, lat] = toLonLat(coordinate);
+      const point = latLngToPoint([lat, lng], mapSize);
+
+      dispatch(updateLastClick({coordinates:point, modelId}));
+
       const featuresAtPixel: FeatureLike[] = [];
       mapInstance.forEachFeatureAtPixel(pixel, (feature) => featuresAtPixel.push(feature));
       const { shouldBlockCoordSearch } = handleFeaturesClick(featuresAtPixel, dispatch, comments);
@@ -26,7 +34,7 @@ export const onMapSingleClick =
       // so we need to reset all the data before updating
       dispatch(handleDataReset);
 
-      const {searchResults, point} = await getSearchResults({ coordinate, mapSize, modelId });
+      const {searchResults} = await getSearchResults({ coordinate, mapSize, modelId });
       if (!searchResults || searchResults.length === SIZE_OF_EMPTY_ARRAY) {
         return;
       }
diff --git a/src/models/fixtures/commentFixture.ts b/src/models/fixtures/commentFixture.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a28e2618e273c2cdf736be26c231cfce0ba5a53a
--- /dev/null
+++ b/src/models/fixtures/commentFixture.ts
@@ -0,0 +1,8 @@
+import { ZOD_SEED } from '@/constants';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { createFixture } from 'zod-fixture';
+import { commentSchema } from '@/models/commentSchema';
+
+export const commentFixture = createFixture(commentSchema, {
+  seed: ZOD_SEED,
+});
diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts
index ffb7a308907de9364ea48fa05affdc5695de7005..22f16e77a7483b0fdd2f86ce20aaee85bc1f5c2f 100644
--- a/src/redux/apiPath.ts
+++ b/src/redux/apiPath.ts
@@ -103,4 +103,6 @@ export const apiPath = {
   submitError: (): string => `minervanet/submitError`,
   userPrivileges: (login: string): string => `users/${login}?columns=privileges`,
   getComments: (): string => `projects/${PROJECT_ID}/comments/models/*/`,
+  addComment: (modelId: number, x: number, y: number): string =>
+    `projects/${PROJECT_ID}/comments/models/${modelId}/points/${x},${y}/`,
 };
diff --git a/src/redux/comment/comment.types.ts b/src/redux/comment/comment.types.ts
index 581da6e4959f40728d402d1dcf51750c731cb15b..8cb0e4b59872fc53a0ddeb147b506628abf4f1af 100644
--- a/src/redux/comment/comment.types.ts
+++ b/src/redux/comment/comment.types.ts
@@ -1,6 +1,7 @@
 import { FetchDataState } from '@/types/fetchDataState';
 import { BioEntity, Comment, Reaction } from '@/types/models';
 import { PayloadAction } from '@reduxjs/toolkit';
+import { Point } from '@/types/map';
 
 export interface CommentsState extends FetchDataState<Comment[], []> {
   isOpen: boolean;
@@ -15,3 +16,10 @@ export type GetElementProps = {
   elementId: number;
   modelId: number;
 };
+
+export type AddCommentProps = {
+  email: string;
+  content: string;
+  modelId: number;
+  position: Point;
+};
diff --git a/src/redux/comment/thunks/addComment.ts b/src/redux/comment/thunks/addComment.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cbb3a4e177da924596b6e4068a05afea4f6d7d93
--- /dev/null
+++ b/src/redux/comment/thunks/addComment.ts
@@ -0,0 +1,28 @@
+import { commentSchema } from '@/models/commentSchema';
+import { apiPath } from '@/redux/apiPath';
+import { axiosInstance } from '@/services/api/utils/axiosInstance';
+import { ThunkConfig } from '@/types/store';
+import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
+import { createAsyncThunk } from '@reduxjs/toolkit';
+import { Comment } from '@/types/models';
+import { AddCommentProps } from '@/redux/comment/comment.types';
+import { getError } from '@/utils/error-report/getError';
+
+export const addComment = createAsyncThunk<Comment | null, AddCommentProps, ThunkConfig>(
+  'project/addComment',
+  async ({ email, content, modelId, position }) => {
+    try {
+      const payload = new URLSearchParams({ email, content });
+      const response = await axiosInstance.post<Comment>(
+        apiPath.addComment(modelId, Math.trunc(position.x), Math.trunc(position.y)),
+        payload,
+      );
+
+      const isDataValid = validateDataUsingZodSchema(response.data, commentSchema);
+
+      return isDataValid ? response.data : null;
+    } catch (error) {
+      return Promise.reject(getError({ error }));
+    }
+  },
+);
diff --git a/src/redux/comment/thunks/getComments.ts b/src/redux/comment/thunks/getComments.ts
index 7f526700e26f80c3120427bf573ec881ce81b3e2..05156ede750d4f74c8f43fce95d44ef4690f13f5 100644
--- a/src/redux/comment/thunks/getComments.ts
+++ b/src/redux/comment/thunks/getComments.ts
@@ -10,6 +10,7 @@ import { bioEntitySchema } from '@/models/bioEntitySchema';
 import { GetElementProps } from '@/redux/comment/comment.types';
 import { reactionSchema } from '@/models/reaction';
 import { ZERO } from '@/constants/common';
+import { getError } from '@/utils/error-report/getError';
 
 export const getComments = createAsyncThunk<Comment[], void, ThunkConfig>(
   'project/getComments',
@@ -21,7 +22,7 @@ export const getComments = createAsyncThunk<Comment[], void, ThunkConfig>(
 
       return isDataValid ? response.data : [];
     } catch (error) {
-      return Promise.reject(error);
+      return Promise.reject(getError({ error }));
     }
   },
 );
@@ -38,7 +39,7 @@ export const getCommentElement = createAsyncThunk<BioEntity | null, GetElementPr
 
       return isDataValid ? response.data : null;
     } catch (error) {
-      return Promise.reject(error);
+      return Promise.reject(getError({ error }));
     }
   },
 );
@@ -55,7 +56,7 @@ export const getCommentReaction = createAsyncThunk<Reaction | null, GetElementPr
 
       return isDataValid && response.data.length > ZERO ? response.data[ZERO] : null;
     } catch (error) {
-      return Promise.reject(error);
+      return Promise.reject(getError({ error }));
     }
   },
 );
diff --git a/src/redux/map/map.constants.ts b/src/redux/map/map.constants.ts
index 70126c71e6dbd43d510b1662096b9178d20452f1..3b9e9e530e5ee7b93e2c5e7141b7d79b74ab72fc 100644
--- a/src/redux/map/map.constants.ts
+++ b/src/redux/map/map.constants.ts
@@ -39,6 +39,20 @@ export const MAP_DATA_INITIAL_STATE: MapData = {
     minZoom: DEFAULT_MIN_ZOOM,
     maxZoom: DEFAULT_MAX_ZOOM,
   },
+  lastClick: {
+    modelId: MODEL_ID_DEFAULT,
+    position: {
+      x: 0,
+      y: 0,
+    },
+  },
+  lastRightClick: {
+    modelId: MODEL_ID_DEFAULT,
+    position: {
+      x: 0,
+      y: 0,
+    },
+  },
 };
 export const DEFAULT_POSITION: Point = { x: 0, y: 0, z: 0 };
 
diff --git a/src/redux/map/map.fixtures.ts b/src/redux/map/map.fixtures.ts
index be022b6972ad0c42f4ff1c7c9e2c95351f47af4e..049bdc645285fcfcaa89883d21fe85fd86f6884e 100644
--- a/src/redux/map/map.fixtures.ts
+++ b/src/redux/map/map.fixtures.ts
@@ -1,4 +1,5 @@
 import { DEFAULT_ERROR } from '@/constants/errors';
+import { MODEL_ID_DEFAULT } from '@/redux/map/map.constants';
 import { MapData, MapState, OppenedMap } from './map.types';
 
 export const openedMapsInitialValueFixture: OppenedMap[] = [
@@ -32,6 +33,20 @@ export const initialMapDataFixture: MapData = {
     minZoom: 2,
     maxZoom: 9,
   },
+  lastClick: {
+    modelId: MODEL_ID_DEFAULT,
+    position: {
+      x: 0,
+      y: 0,
+    },
+  },
+  lastRightClick: {
+    modelId: MODEL_ID_DEFAULT,
+    position: {
+      x: 0,
+      y: 0,
+    },
+  },
 };
 
 export const initialMapStateFixture: MapState = {
diff --git a/src/redux/map/map.reducers.ts b/src/redux/map/map.reducers.ts
index c65bfe9746acc4cd2197cab5200fc891066ba834..f193e7536e94936d2662d7bb69f102f2149f569c 100644
--- a/src/redux/map/map.reducers.ts
+++ b/src/redux/map/map.reducers.ts
@@ -15,6 +15,7 @@ import {
   OpenMapAndSetActiveAction,
   SetActiveMapAction,
   SetBackgroundAction,
+  SetLastClickPositionAction,
   SetLastPositionZoomAction,
   SetLastPositionZoomWithDeltaAction,
   SetMapDataAction,
@@ -100,6 +101,22 @@ export const setLastPositionZoomReducer = (
   state.data.position.initial.z = zoom;
 };
 
+export const updateLastClickReducer = (
+  state: MapState,
+  action: SetLastClickPositionAction,
+): void => {
+  state.data.lastClick.modelId = action.payload.modelId;
+  state.data.lastClick.position = action.payload.coordinates;
+};
+
+export const updateLastRightClickReducer = (
+  state: MapState,
+  action: SetLastClickPositionAction,
+): void => {
+  state.data.lastRightClick.modelId = action.payload.modelId;
+  state.data.lastRightClick.position = action.payload.coordinates;
+};
+
 const updateLastPositionOfCurrentlyActiveMap = (state: MapState): void => {
   const currentMapId = state.data.modelId;
   const currentOpenedMap = state.openedMaps.find(openedMap => openedMap.modelId === currentMapId);
diff --git a/src/redux/map/map.slice.ts b/src/redux/map/map.slice.ts
index 46f68b78379b43eea92e3897455d4ddd82f5668b..3106a118eaa14cdcc373ea0366b74c53e121dffb 100644
--- a/src/redux/map/map.slice.ts
+++ b/src/redux/map/map.slice.ts
@@ -14,6 +14,8 @@ import {
   setMapBackgroundReducer,
   setMapDataReducer,
   setMapPositionReducer,
+  updateLastClickReducer,
+  updateLastRightClickReducer,
   varyPositionZoomReducer,
 } from './map.reducers';
 
@@ -31,6 +33,8 @@ const mapSlice = createSlice({
     setMapBackground: setMapBackgroundReducer,
     openMapAndOrSetActiveIfSelected: openMapAndOrSetActiveIfSelectedReducer,
     setLastPositionZoom: setLastPositionZoomReducer,
+    updateLastClick: updateLastClickReducer,
+    updateLastRightClick: updateLastRightClickReducer,
   },
   extraReducers: builder => {
     initMapPositionReducers(builder);
@@ -51,6 +55,8 @@ export const {
   varyPositionZoom,
   openMapAndOrSetActiveIfSelected,
   setLastPositionZoom,
+  updateLastClick,
+  updateLastRightClick,
 } = mapSlice.actions;
 
 export default mapSlice.reducer;
diff --git a/src/redux/map/map.types.ts b/src/redux/map/map.types.ts
index 727df76f71b29da80f9690edcc3e9e86c9888d12..72b600dcf1a42cc08ea329d65d82144db088abaa 100644
--- a/src/redux/map/map.types.ts
+++ b/src/redux/map/map.types.ts
@@ -30,6 +30,14 @@ export type MapData = {
   overlaysIds: number[];
   size: MapSize;
   position: Position;
+  lastClick: {
+    position: Point;
+    modelId: number;
+  };
+  lastRightClick: {
+    position: Point;
+    modelId: number;
+  };
   show: {
     legend: boolean;
     comments: boolean;
@@ -101,6 +109,13 @@ export type SetLastPositionZoomActionPayload = {
 
 export type SetLastPositionZoomAction = PayloadAction<SetLastPositionZoomActionPayload>;
 
+export type SetLastClickPositionActionPayload = {
+  modelId: number;
+  coordinates: Point;
+};
+
+export type SetLastClickPositionAction = PayloadAction<SetLastClickPositionActionPayload>;
+
 export type InitMapDataActionPayload = {
   data: GetUpdatedMapDataResult | object;
   openedMaps: OppenedMap[];
diff --git a/src/redux/modal/modal.reducers.ts b/src/redux/modal/modal.reducers.ts
index a93e5fd119e12aac58667c6dc61dca3f442176ad..f9d88800610efc49275e3cdad86a19a2396a4d97 100644
--- a/src/redux/modal/modal.reducers.ts
+++ b/src/redux/modal/modal.reducers.ts
@@ -43,6 +43,12 @@ export const openLoginModalReducer = (state: ModalState): void => {
   state.modalTitle = 'You need to login';
 };
 
+export const openAddCommentModalReducer = (state: ModalState): void => {
+  state.isOpen = true;
+  state.modalName = 'add-comment';
+  state.modalTitle = 'Add comment';
+};
+
 export const openLoggedInMenuModalReducer = (state: ModalState): void => {
   state.isOpen = true;
   state.modalName = 'logged-in-menu';
diff --git a/src/redux/modal/modal.slice.ts b/src/redux/modal/modal.slice.ts
index b0b76cf56c66de2674305fb57b1f864de18d7f48..57d852cd19596f39ccb2476e0aae599d4927be4f 100644
--- a/src/redux/modal/modal.slice.ts
+++ b/src/redux/modal/modal.slice.ts
@@ -10,6 +10,7 @@ import {
   openPublicationsModalReducer,
   openEditOverlayModalReducer,
   openLoggedInMenuModalReducer,
+  openAddCommentModalReducer,
   openErrorReportModalReducer,
   openAccessDeniedModalReducer,
 } from './modal.reducers';
@@ -24,6 +25,7 @@ const modalSlice = createSlice({
     openMolArtModalById: openMolArtModalByIdReducer,
     setOverviewImageId: setOverviewImageIdReducer,
     openLoginModal: openLoginModalReducer,
+    openAddCommentModal: openAddCommentModalReducer,
     openPublicationsModal: openPublicationsModalReducer,
     openEditOverlayModal: openEditOverlayModalReducer,
     openLoggedInMenuModal: openLoggedInMenuModalReducer,
@@ -37,6 +39,7 @@ export const {
   closeModal,
   openOverviewImagesModalById,
   setOverviewImageId,
+  openAddCommentModal,
   openMolArtModalById,
   openLoginModal,
   openPublicationsModal,
diff --git a/src/redux/models/models.selectors.ts b/src/redux/models/models.selectors.ts
index 99d94b7648a22f1d07d77ac63cdf69592d55c0f9..406e1f3c28623f2cff51abac303dd841016fb30b 100644
--- a/src/redux/models/models.selectors.ts
+++ b/src/redux/models/models.selectors.ts
@@ -33,6 +33,12 @@ export const currentModelIdSelector = createSelector(
   model => model?.idObject || MODEL_ID_DEFAULT,
 );
 
+export const lastClickSelector = createSelector(mapDataSelector, mapData => mapData.lastClick);
+export const lastRightClickSelector = createSelector(
+  mapDataSelector,
+  mapData => mapData.lastRightClick,
+);
+
 export const currentModelNameSelector = createSelector(
   currentModelSelector,
   model => model?.name || '',
diff --git a/src/types/modal.ts b/src/types/modal.ts
index 499406998946f45b8b045ee95fae952b05594387..90e7c20d501aa6c7cb50642df1eea295c6406816 100644
--- a/src/types/modal.ts
+++ b/src/types/modal.ts
@@ -1,5 +1,6 @@
 export type ModalName =
   | 'none'
+  | 'add-comment'
   | 'overview-images'
   | 'mol-art'
   | 'login'
diff --git a/src/utils/error-report/getErrorStack.ts b/src/utils/error-report/getErrorStack.ts
index e148696f16214a786cb7a48ee1862fa3743bbbe2..d57851b3b3c04a3ab0d76af7ea297930e47a2c1a 100644
--- a/src/utils/error-report/getErrorStack.ts
+++ b/src/utils/error-report/getErrorStack.ts
@@ -5,7 +5,6 @@ export const getErrorStack = (error: unknown): string => {
   let stack = null;
   if (axios.isAxiosError(error)) {
     const url = getErrorUrl(error);
-
     stack = (url ? `(Request URL: ${url}) ` : '') + error.stack;
   } else if (error instanceof Error) {
     stack = error.stack;
diff --git a/src/utils/error-report/getErrorUrl.ts b/src/utils/error-report/getErrorUrl.ts
index 53ef46e9f4e5c4bf4bb9541f252594f357c8de8f..0edd3d69702b291cb8a7aa18c9feb53461520226 100644
--- a/src/utils/error-report/getErrorUrl.ts
+++ b/src/utils/error-report/getErrorUrl.ts
@@ -6,6 +6,10 @@ export const getErrorUrl = (error: unknown): string | null => {
       if (error.request.responseURL) {
         return error.request.responseURL;
       }
+    } else if (error.config) {
+      if (error.config.url) {
+        return error.config.url;
+      }
     }
   }
   return null;