Untitled

src\modules\main\components\table\page-table.component.tsx
mail@pastecode.io avatar
unknown
plain_text
a year ago
3.7 kB
2
Indexable
Never
import { SettingsCustomColumns } from '@/modules/shared/hooks/table/settings/settingsCustomColumns.hook';
import { useTranslate } from '@/modules/shared/hooks/translate.hook';
import { ActionCreatorWithPayload, AsyncThunk, CombinedState } from '@reduxjs/toolkit';
import { Key, ReactElement, ReactNode, useCallback, useEffect } from 'react';
import { FormProvider, UseFormReturn } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { StoreType } from '../../../../store';
import { useAppSelector } from '../../../../store/hooks';
import { EDIT_PAGE, NEW_PAGE } from '../../consts/pageRouter';
import SettingsTable from '../../pages/settings/components/settingsTable';
import { EntityState } from '../../pages/settings/redux/entity-state.type';
import { IdentifiableEntity, IdType } from '../../pages/settings/redux/thunks';
import { useTableData } from './hooks/table.hook';
import { useEntityDeleteModal } from './hooks/useEntityDeleteModal';
import './table.scss';

export type TableProps<Entity, EntityMapped, SingleEntity> = {
  ns: string;
  columnsOrder: (keyof EntityMapped)[];
  filterThunk: ActionCreatorWithPayload<string, string>;
  readThunk: AsyncThunk<Entity[], IdType, Record<string, unknown>>;
  deleteThunk: AsyncThunk<IdType, IdType, Record<string, unknown>>;
  stateSelector: (state: CombinedState<StoreType>) => EntityState<Entity, SingleEntity>;
  mapEntityToUiData: (entity: Entity) => EntityMapped;
  getName: (entity: EntityMapped) => string;
  customColumns?: Partial<Record<keyof Entity & { status: number }, (value: any) => ReactNode>>;
  shouldFilterByStatus?: boolean;
  onSelectionChange?: (newSelectedRowKeys?: Key[]) => void;
  selectedRowKeys?: Key[];
  updateStatus?: (status: number) => void;
  additionalSearch?: (
    form: UseFormReturn<{ search: string; status: number | string | undefined }, any>,
  ) => void;
};

const PageTable = <Entity, EntityMapped extends IdentifiableEntity, SingleEntity>({
  ns,
  columnsOrder,
  deleteThunk,
  getName,
  onSelectionChange,
  selectedRowKeys,
  updateStatus,
  customColumns = {},
  additionalSearch = undefined,
  ...props
}: TableProps<Entity, EntityMapped, SingleEntity>): ReactElement => {
  const { stateSelector } = props;
  const state = useAppSelector(stateSelector);
  const { loading, uiData, form } = useTableData(props);
  const { translate } = useTranslate({ ns: ns });
  const navigate = useNavigate();

  const showMaintain = useCallback(
    (value?: EntityMapped): void => {
      navigate(!value ? NEW_PAGE : EDIT_PAGE.replace(':id', `${value.id}`));
    },
    [navigate],
  );
  const { modal, onDelete } = useEntityDeleteModal({ ns, deleteThunk, getName, state });

  const disableButton = useCallback((obj: EntityMapped) => {
    return obj.status === undefined ? obj.isActive : obj.status !== 3;
  }, []);

  if (additionalSearch) {
    additionalSearch(form);
  }

  return (
    <FormProvider {...form}>
      <div data-testid='table' className='table-container'>
        <SettingsTable
          isLoading={loading!}
          filteredData={uiData}
          translateNs={ns}
          columnsOrder={columnsOrder}
          onNew={showMaintain}
          onEdit={showMaintain}
          onDelete={onDelete}
          onUpdateStatus={updateStatus}
          customColumns={{ ...SettingsCustomColumns<EntityMapped>(translate), ...customColumns }}
          disableDeleteButtonCondition={disableButton}
          // rowSelection={rowSelection}
        />
      </div>
      {modal}
    </FormProvider>
  );
};

export default PageTable;