huridocs/uwazi

View on GitHub
app/react/V2/Routes/Settings/RelationshipTypes/RelationshipTypes.tsx

Summary

Maintainability
B
4 hrs
Test Coverage
/* eslint-disable max-statements */
/* eslint-disable react/jsx-props-no-spreading */
import React, { useEffect, useState } from 'react';
import { IncomingHttpHeaders } from 'http';
import { LoaderFunction, useLoaderData, useRevalidator } from 'react-router-dom';
import { Row } from '@tanstack/react-table';
import { useSetAtom, useAtomValue } from 'jotai';
import { Translate } from 'app/I18N';
import * as relationshipTypesAPI from 'app/V2/api/relationshiptypes';
import { ClientRelationshipType, Template } from 'app/apiResponseTypes';
import { notificationAtom, templatesAtom } from 'app/V2/atoms';
import { relationshipTypesAtom } from 'app/V2/atoms/relationshipTypes';
import { Button, Table, Sidepanel, ConfirmationModal } from 'app/V2/Components/UI';
import { SettingsContent } from 'app/V2/Components/Layouts/SettingsContent';
import { columns, TableRelationshipType } from './components/TableComponents';
import { Form } from './components/Form';

const relationshipTypesLoader =
  (headers?: IncomingHttpHeaders): LoaderFunction =>
  async () =>
    relationshipTypesAPI.get(headers);

const RelationshipTypes = () => {
  const relationshipTypes = useLoaderData() as ClientRelationshipType[];
  const revalidator = useRevalidator();

  const [isSidepanelOpen, setIsSidepanelOpen] = useState(false);
  const [showConfirmationModal, setShowConfirmationModal] = useState(false);
  const setNotifications = useSetAtom(notificationAtom);
  const setRelationshipTypes = useSetAtom(relationshipTypesAtom);
  const templates = useAtomValue(templatesAtom);

  interface formType extends Omit<ClientRelationshipType, '_id'> {
    _id?: string;
  }
  const [formValues, setFormValues] = useState<formType>({} as ClientRelationshipType);

  const [selectedItems, setSelectedItems] = useState<Row<TableRelationshipType>[]>([]);
  const [tableRelationshipTypes, setTableRelationshipTypes] = useState<TableRelationshipType[]>([]);

  useEffect(() => {
    setTableRelationshipTypes(
      relationshipTypes.map(relationshipType => {
        const templatesUsingIt = templates
          .map(t => {
            const usingIt = t.properties?.some(
              property => property.relationType === relationshipType._id
            );
            return usingIt ? t : null;
          })
          .filter(t => t) as Template[];

        return {
          ...relationshipType,
          templates: templatesUsingIt,
          disableRowSelection: Boolean(templatesUsingIt.length),
        };
      })
    );
  }, [relationshipTypes, templates]);

  const edit = (row: Row<ClientRelationshipType>) => {
    setFormValues(row.original);
    setIsSidepanelOpen(true);
  };

  const add = () => {
    setFormValues({ name: '' });
    setIsSidepanelOpen(true);
  };

  const submit = async (submitedData: ClientRelationshipType) => {
    try {
      await relationshipTypesAPI.save(submitedData);
      setNotifications({
        type: 'success',
        text: <Translate>Updated</Translate>,
      });
      setIsSidepanelOpen(false);
    } catch (error) {
      setNotifications({
        type: 'error',
        text: <Translate>An error occurred</Translate>,
        details: error.error,
      });
      setIsSidepanelOpen(false);
    }
    revalidator.revalidate();
    setRelationshipTypes(relationshipTypes);
  };

  const deleteSelected = async () => {
    try {
      await relationshipTypesAPI.deleteRelationtypes(selectedItems.map(item => item.original._id));
      setNotifications({
        type: 'success',
        text: <Translate>Updated</Translate>,
      });
      setShowConfirmationModal(false);
    } catch (error) {
      setNotifications({
        type: 'error',
        text: <Translate>An error occurred</Translate>,
        details: error.error,
      });
      setShowConfirmationModal(false);
    }
    revalidator.revalidate();
    setRelationshipTypes(relationshipTypes);
  };

  return (
    <div className="tw-content" style={{ width: '100%', overflowY: 'auto' }}>
      <SettingsContent>
        <SettingsContent.Header title="Relationship types" />
        <SettingsContent.Body>
          <Table<TableRelationshipType>
            enableSelection
            columns={columns({ edit })}
            data={tableRelationshipTypes}
            title={<Translate>Relationship types</Translate>}
            onSelection={setSelectedItems}
          />
        </SettingsContent.Body>
        <SettingsContent.Footer className={selectedItems.length ? 'bg-primary-50' : ''}>
          {selectedItems.length > 0 && (
            <div className="flex gap-2 items-center">
              <Button
                type="button"
                onClick={() => setShowConfirmationModal(true)}
                color="error"
                data-testid="relationship-types-delete"
              >
                <Translate>Delete</Translate>
              </Button>
              <Translate>Selected</Translate> {selectedItems.length} <Translate>of</Translate>
              {relationshipTypes.length}
            </div>
          )}
          {selectedItems.length === 0 && (
            <div className="flex justify-between w-full">
              <div className="flex gap-2">
                <Button type="button" onClick={add} data-testid="relationship-types-add">
                  <Translate>Add relationship type</Translate>
                </Button>
              </div>
            </div>
          )}
        </SettingsContent.Footer>
      </SettingsContent>
      <Sidepanel
        title={
          <Translate className="uppercase">
            {`${formValues?.name === '' ? 'Add' : 'Edit'} relationship type`}
          </Translate>
        }
        isOpen={isSidepanelOpen}
        closeSidepanelFunction={() => setIsSidepanelOpen(false)}
        size="medium"
        withOverlay
      >
        <Form
          relationtype={formValues as ClientRelationshipType}
          closePanel={() => setIsSidepanelOpen(false)}
          currentTypes={relationshipTypes}
          submit={submit}
        />
      </Sidepanel>
      {showConfirmationModal && (
        <ConfirmationModal
          size="lg"
          header={<Translate>Delete</Translate>}
          warningText={<Translate>Do you want to delete the following items?</Translate>}
          body={
            <ul className="flex flex-wrap gap-8 max-w-md list-disc list-inside">
              {selectedItems.map(item => (
                <li key={item.original.name}>{item.original.name}</li>
              ))}
            </ul>
          }
          onAcceptClick={deleteSelected}
          onCancelClick={() => setShowConfirmationModal(false)}
          dangerStyle
        />
      )}
    </div>
  );
};

export { RelationshipTypes, relationshipTypesLoader };