import PropTypes, { string } from 'prop-types'; import moment from 'moment'; import { ThemeProvider } from 'styled-components'; import React, { useState, Fragment, useEffect } from 'react'; import { isEmpty } from 'lodash'; import { ORDER_TYPE } from './constants'; import { NestedListContainer, RowsContainer, BorderedContainer, RowContainer, Container, FixedRowContainer, FixedRowsContainer, PaginatorContainer, GlobalContainer, } from './styledComponents'; import HeaderRow from './components/HeaderRow/HeaderRow'; import EmptyState from './components/EmptyState'; import LoadingState from './components/LoadingState/LoadingStateDisplay'; import useInteractDataRowAndGraph from './customHook/useInteractDataRowAndGraph'; import Row from './components/Row/Row'; import { getTheme } from '../utils/theme'; import { Props } from './interface'; import Paginator from '../Paginator'; const NestedList = (props: Props): JSX.Element => { const { theme, headers, modalHeaders, data, fixedRowsData, isLoading, isExpandable, defaultOrderBy, defaultOrderType, customMultipleOrder, minWidth, customModalIcon, labelEmptyState, iconEmptyState, iconSizeEmptyState, modalTitle, labelModalEmptyState, graphEmptyStateLabel, languageCode, hasNestedData, hasPagination, maxPerPageOptions, hideAllPerPageOption, customSortProperty, customSortFunc, customNestedContentPadding, currentPage, setCurrentPage, maxPerPage, setMaxPerPage, customContentHeight, } = props; const updatedTheme = getTheme(theme); const [orderBy, setOrderBy] = useState(defaultOrderBy); const [multipleOrderBy, setMultipleOrderBy] = useState( customMultipleOrder.orderBy ); const [orderType, setOrderType] = useState<'asc' | 'desc'>(defaultOrderType); const [multipleOrderType, setMultipleOrderType] = useState( customMultipleOrder.orderType ); useEffect(() => { moment.locale(languageCode); }, [languageCode]); useEffect(() => { setOrderBy(defaultOrderBy); }, [defaultOrderBy]); useEffect(() => { if (!isEmpty(customMultipleOrder)) { setMultipleOrderBy(customMultipleOrder.orderBy); setMultipleOrderType(customMultipleOrder.orderType); } }, [customMultipleOrder]); const setOrderColumn = (headerPropertyKey) => { if (orderBy === headerPropertyKey) { const newOrderType = orderType === ORDER_TYPE.ASCENDING ? ORDER_TYPE.DESCENDING : ORDER_TYPE.ASCENDING; setOrderType(newOrderType); if (!isEmpty(customMultipleOrder)) { setMultipleOrderType([newOrderType, ...customMultipleOrder.orderType]); } return; } setOrderBy(headerPropertyKey); setOrderType(ORDER_TYPE.ASCENDING); if (!isEmpty(customMultipleOrder)) { setMultipleOrderBy([headerPropertyKey, ...customMultipleOrder.orderBy]); setMultipleOrderType([ ORDER_TYPE.ASCENDING, ...customMultipleOrder.orderType, ]); } }; const interactData = useInteractDataRowAndGraph({ data, headers, orderBy, orderType, maxPerPage, currentPage, hasPagination, customSortProperty, customSortFunc, multipleOrderBy, multipleOrderType, customMultipleOrder, }); const handleOpenRow = (item, rowIndex: number, isRowFixed: boolean): void => { if ( !isExpandable || isRowFixed || (!item.nestedContent && !item.graphContent && !item.nestedData) ) { return; } interactData.openRow(rowIndex, !!hasNestedData); }; const renderRow = (item, index, isFixed = false) => { return ( handleOpenRow(item, index, isFixed)} openModal={() => interactData.openModal(index, 'modalOpened')} customModalIcon={customModalIcon} modalTitle={modalTitle} modalHeaders={modalHeaders || []} labelModalEmptyState={labelModalEmptyState || ''} graphEmptyStateLabel={graphEmptyStateLabel} customNestedContentPadding={customNestedContentPadding} isBold={isFixed} hasNestedData={hasNestedData} /> ); }; if (isLoading) { return ( ); } if (!data.length) { return ( ; ); } return ( {/* Handle display of fix rows on top of the listing from fixedRowsData props (usually TOTAL lines or something else) */} {fixedRowsData.length > 0 && ( {fixedRowsData.map((item, index) => ( {renderRow(item, index, true)} ))} )} {/* Handle display of each element in the listing from data props */} {interactData.dataState.map((item, index) => ( {renderRow(item, index)} ))} {hasPagination && data.length > 0 && ( )} ); }; NestedList.propTypes = { minWidth: PropTypes.string, headers: PropTypes.arrayOf( PropTypes.shape({ name: PropTypes.string.isRequired, propertyKey: PropTypes.string.isRequired, isNumber: PropTypes.bool, unit: PropTypes.string, tooltipDisplay: PropTypes.string, isSortable: PropTypes.bool.isRequired, large: PropTypes.bool, narrow: PropTypes.bool, customModalRender: PropTypes.bool, }) ).isRequired, data: PropTypes.arrayOf(PropTypes.objectOf(PropTypes.any)).isRequired, fixedRowsData: PropTypes.arrayOf(PropTypes.objectOf(PropTypes.any)), isLoading: PropTypes.bool, isExpandable: PropTypes.bool, defaultOrderBy: PropTypes.string, defaultOrderType: PropTypes.string, customMultipleOrder: PropTypes.shape({ orderBy: PropTypes.arrayOf(string), orderType: PropTypes.arrayOf(string), customOrderByFunc: PropTypes.func, }), customModalIcon: PropTypes.string, labelEmptyState: PropTypes.string, // eslint-disable-next-line react/forbid-prop-types iconEmptyState: PropTypes.any, iconSizeEmptyState: PropTypes.string, labelModalEmptyState: PropTypes.string, modalTitle: PropTypes.string, modalHeaders: PropTypes.arrayOf( PropTypes.shape({ propertyKey: PropTypes.string.isRequired, }) ), // eslint-disable-next-line react/forbid-prop-types theme: PropTypes.objectOf(PropTypes.any), graphEmptyStateLabel: PropTypes.string, languageCode: PropTypes.string, hasNestedData: PropTypes.bool, hasPagination: PropTypes.bool, maxPerPageOptions: PropTypes.arrayOf(PropTypes.number), hideAllPerPageOption: PropTypes.bool, customSortProperty: PropTypes.string, customSortFunc: PropTypes.func, customNestedContentPadding: PropTypes.string, customContentHeight: PropTypes.string, }; NestedList.defaultProps = { minWidth: '1200px', isLoading: false, isExpandable: true, defaultOrderBy: undefined, defaultOrderType: ORDER_TYPE.ASCENDING, customMultipleOrder: {}, customModalIcon: null, theme: null, labelEmptyState: 'Aucun résultat ne correspond à votre recherche', iconEmptyState: null, iconSizeEmptyState: null, labelModalEmptyState: 'Aucune commande dans les 15 prochains jours pour cet ingrédient', modalTitle: null, modalHeaders: [], fixedRowsData: [], graphEmptyStateLabel: '', languageCode: 'fr', hasNestedData: false, hasPagination: false, maxPerPageOptions: [10, 20, 50, 100], hideAllPerPageOption: false, customSortProperty: null, customSortFunc: null, customNestedContentPadding: '', customContentHeight: '', }; export default NestedList;