import { formatDisplayedData } from '../../utils/processing/formatDisplayedData/formatDisplayedData';
import styleSheet from './TableRow.styleSheet';
import globalStyleSheet from '../../utils/style/globalStyle.styleSheet';
import { cx } from '../../utils/style/emotion';
import { useContext } from 'react';
import { store } from '../../store/store';
import { DataElementInterface } from '../../utils/types/types';
/**
* @namespace TableRow
*/
interface TableRowProps {
item: DataElementInterface;
isLastRow?: boolean;
isOddRow: boolean;
}
/**
* The TableRow component, displays the data within the TableBody. One TableRow composent per Data item.
* Displays all the cells no matter what value has the displayedColumns state value, but put the sr-only class to the cell which should not be displayed.
* this not displayed cells are put within an additional info row with aria-hidden attribute (this row doesn't exist if no data to put into).
* Uses the state moreInfoOpenList to know if the additionnal info row should be displayed or collapsed.
* Adds classes to manage the background color of cells depending on parity and current sort.
* @param {object} item - the data item from the displayed data array.
* @param {boolean} isOddRow - a bool depending on the row parity.
* @param {boolean} isLastRow - a boll depending on the index of data related to data.length, used to correctly display the body border-bottom.
* @memberof TableRow
* @function
* @return {React.ReactElement} jsx to be injected in the html.
*/
export const TableRow = ({
item,
isLastRow,
isOddRow,
}: TableRowProps): React.ReactElement => {
const {
headings,
currentSort,
moreInfoOpenList,
displayedColumns,
style,
dispatch,
} = useContext(store);
const hasMoreInfo: boolean = displayedColumns !== headings.length;
const isMoreInfoOpen: boolean = moreInfoOpenList.includes(
JSON.stringify(item)
);
/**
* Dispatch the action to update the displayed status of the clicked row.
* @memberof TableRow
* @function
*/
const toggleMoreInfoDisplay = (): void => {
dispatch({ type: 'setMoreInfoOpenList', payload: JSON.stringify(item) });
};
/**
* An object containing the classnames generated from the stylesheet made with emotion and using the style state of the store
* @memberof TableRow
*/
const classNames: { [Class: string]: string } = styleSheet(style);
return (
<>
<tr
className={classNames.tableRow}
data-oddrow={isOddRow ? true : undefined}
data-clickable={hasMoreInfo ? true : undefined}
data-hideborderbottom={!isMoreInfoOpen && isLastRow ? true : undefined}
onClick={hasMoreInfo ? toggleMoreInfoDisplay : undefined}
>
{headings.map((heading, index) => (
<td
key={heading.key}
className={cx(
classNames.cell,
index >= displayedColumns && globalStyleSheet.srOnly
)}
data-sortedcolumn={
heading.key === currentSort.key ? true : undefined
}
>
{item[heading.key]
? formatDisplayedData(item[heading.key], heading.format)
: ''}
</td>
))}
</tr>
{hasMoreInfo ? (
<tr
className={classNames.moreInfo}
data-hidden={isMoreInfoOpen ? undefined : true}
aria-hidden
onClick={toggleMoreInfoDisplay}
>
<td colSpan={displayedColumns}>
<table className={classNames.moreInfoTable}>
<tbody>
{headings.map((heading, index) =>
index < displayedColumns ? null : (
<tr className={classNames.moreInfoRow} key={heading.key}>
<th className={classNames.moreInfoHeadCell}>
{heading.label}
</th>
<td className={classNames.moreInfoBodyCell}>
{item[heading.key]}
</td>
</tr>
)
)}
</tbody>
</table>
</td>
</tr>
) : null}
</>
);
};
Source