Skip to content
Snippets Groups Projects
LayerTextFactoryModal.component.tsx 4.15 KiB
Newer Older
/* eslint-disable no-magic-numbers */
import React, { useState } from 'react';
import './LayerTextFactoryModal.styles.css';
import { LayerTextForm } from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextForm.component';
import { LoadingIndicator } from '@/shared/LoadingIndicator';
import { Button } from '@/shared/Button';
import {
  DEFAULT_HORIZONTAL_ALIGNMENT,
  DEFAULT_TEXT_FONT_SIZE,
  DEFAULT_VERTICAL_ALIGNMENT,
} from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactory.constants';
import { LayerTextFactoryForm } from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactory.types';
import { Color } from '@/types/models';
import { useAppSelector } from '@/redux/hooks/useAppSelector';
import { layerTextFactoryStateSelector } from '@/redux/modal/modal.selector';
import { highestZIndexSelector, layersActiveLayerSelector } from '@/redux/layers/layers.selectors';
import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import { currentModelIdSelector } from '@/redux/models/models.selectors';
import { showToast } from '@/utils/showToast';
import { closeModal } from '@/redux/modal/modal.slice';
import { SerializedError } from '@reduxjs/toolkit';
import { addLayerText } from '@/redux/layers/layers.thunks';
import { layerAddText } from '@/redux/layers/layers.slice';
import drawElementOnLayer from '@/components/Map/MapViewer/utils/shapes/layer/utils/drawElementOnLayer';
import { useMapInstance } from '@/utils/context/mapInstanceContext';
import { BLACK_COLOR } from '@/components/Map/MapViewer/MapViewer.constants';
export const LayerTextFactoryModal: React.FC = () => {
  const activeLayer = useAppSelector(layersActiveLayerSelector);
  const currentModelId = useAppSelector(currentModelIdSelector);
  const layerTextFactoryState = useAppSelector(layerTextFactoryStateSelector);
  const dispatch = useAppDispatch();
  const highestZIndex = useAppSelector(highestZIndexSelector);
  const { mapInstance } = useMapInstance();

  const [isSending, setIsSending] = useState<boolean>(false);
  const [data, setData] = useState<LayerTextFactoryForm>({
    notes: '',
    fontSize: DEFAULT_TEXT_FONT_SIZE,
    horizontalAlign: DEFAULT_HORIZONTAL_ALIGNMENT,
    verticalAlign: DEFAULT_VERTICAL_ALIGNMENT,
    color: BLACK_COLOR,
  });

  const handleSubmit = async (): Promise<void> => {
    if (!layerTextFactoryState || !activeLayer) {
      return;
    }
    try {
      const textData = await dispatch(
        addLayerText({
          modelId: currentModelId,
          layerId: activeLayer,
          boundingBox: layerTextFactoryState,
          textData: data,
          z: highestZIndex + 1,
        }),
      ).unwrap();
      if (!textData) {
        showToast({
          type: 'error',
          message: 'Error while adding the text',
        });
        return;
      }
      dispatch(
        layerAddText({ modelId: currentModelId, layerId: activeLayer, layerText: textData }),
      );
      drawElementOnLayer({
        mapInstance,
        activeLayer,
        object: textData,
        drawFunctionKey: 'drawText',
      });
      showToast({
        type: 'success',
        message: 'A new text has been successfully added',
      });
      dispatch(closeModal());
    } catch (error) {
      const typedError = error as SerializedError;
      showToast({
        type: 'error',
        message: typedError.message || 'An error occurred while adding a new text',
      });
    } finally {
      setIsSending(false);
    }
  };

  const changeValues = (value: string | number | Color, key: string): void => {
    setData(prevData => ({ ...prevData, [key]: value }));
  };

  return (
    <div className="relative w-[900px] border border-t-[#E1E0E6] bg-white p-[24px]">
      {isSending && (
        <div className="c-layer-text-factory-modal-loader">
          <LoadingIndicator width={44} height={44} />
        </div>
      )}
      <LayerTextForm onChange={changeValues} data={data} />
      <hr className="py-2" />
      <Button
        type="button"
        onClick={handleSubmit}
        className="justify-center self-end justify-self-end text-base font-medium"
      >
        Submit
      </Button>
    </div>
  );
};