Skip to content
Snippets Groups Projects
LayersDrawer.component.tsx 4.01 KiB
Newer Older
import { useAppSelector } from '@/redux/hooks/useAppSelector';
import { DrawerHeading } from '@/shared/DrawerHeading';
import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import {
  layersForCurrentModelSelector,
  layersVisibilityForCurrentModelSelector,
} from '@/redux/layers/layers.selectors';
import { setLayerVisibility } from '@/redux/layers/layers.slice';
import { currentModelIdSelector } from '@/redux/models/models.selectors';
import { Button } from '@/shared/Button';
import { openLayerFactoryModal } from '@/redux/modal/modal.slice';
import QuestionModal from '@/components/FunctionalArea/Modal/QuestionModal/QustionModal.component';
import { useState } from 'react';
import { getLayersForModel, removeLayer } from '@/redux/layers/layers.thunks';
import { showToast } from '@/utils/showToast';
import { SerializedError } from '@reduxjs/toolkit';
import { LayersDrawerLayerActions } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component';
import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors';

export const LayersDrawer = (): JSX.Element => {
  const layersForCurrentModel = useAppSelector(layersForCurrentModelSelector);
  const layersVisibilityForCurrentModel = useAppSelector(layersVisibilityForCurrentModelSelector);
  const currentModelId = useAppSelector(currentModelIdSelector);
  const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector);
  const dispatch = useAppDispatch();
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [layerId, setLayerId] = useState<number | null>(null);

  const addNewLayer = (): void => {
    dispatch(openLayerFactoryModal());
  };

  const editLayer = (layerIdToEdit: number): void => {
    dispatch(openLayerFactoryModal(layerIdToEdit));
  };

  const rejectRemove = (): void => {
    setIsModalOpen(false);
  };

  const confirmRemove = async (): Promise<void> => {
    if (!layerId) {
      return;
    }
    try {
      await dispatch(removeLayer({ modelId: currentModelId, layerId })).unwrap();
      showToast({
        type: 'success',
        message: 'The layer has been successfully removed',
      });
      setIsModalOpen(false);
      dispatch(getLayersForModel(currentModelId));
    } catch (error) {
      const typedError = error as SerializedError;
      showToast({
        type: 'error',
        message: typedError.message || 'An error occurred while removing the layer',
      });
    }
  };

  const onRemoveLayer = (layerIdToRemove: number): void => {
    setLayerId(layerIdToRemove);
    setIsModalOpen(true);
  };

  return (
    <div data-testid="layers-drawer" className="h-full max-h-full">
      <QuestionModal
        isOpen={isModalOpen}
        onClose={rejectRemove}
        onConfirm={confirmRemove}
        question="Are you sure you want to remove the layer?"
      />
      <DrawerHeading title="Layers" />
      <div className="flex h-[calc(100%-93px)] max-h-[calc(100%-93px)] flex-col overflow-y-auto px-6">
        {hasPrivilegeToWriteProject && (
          <div className="flex justify-start pt-2">
            <Button icon="plus" isIcon isFrontIcon onClick={addNewLayer}>
              Add new layer
            </Button>
          </div>
        )}
        {layersForCurrentModel.map(layer => (
          <div
            key={layer.details.id}
            className="flex items-center justify-between gap-3 border-b py-4"
          >
            <h1 className="truncate">{layer.details.name}</h1>
            <LayersDrawerLayerActions
              isChecked={layersVisibilityForCurrentModel[layer.details.id]}
              editLayer={() => editLayer(layer.details.id)}
              removeLayer={() => onRemoveLayer(layer.details.id)}
              toggleVisibility={value =>
                dispatch(
                  setLayerVisibility({
                    modelId: currentModelId,
                    visible: value,
                    layerId: layer.details.id,
                  }),
                )
              }
            />