Skip to content
Snippets Groups Projects
Table.tsx 2.53 KiB
Newer Older
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
// import './Table.css'
import { ChangeEvent, MouseEvent } from "react";
export interface Column {
  id: string
  name?: string,
export interface Value {
  columnId: string,
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
  value: any
}

  columns: Column[];
  data: Value[][];
  selectable?: boolean;
  selectedRows?: Set<number>;
  onClick?: (element: MouseEvent<HTMLTableRowElement>, index: number) => void
  onSelect?: (element: ChangeEvent<HTMLInputElement>, index: number) => void
export const Table = (props: TableParams) => {
  const {
    columns,
    data,
    selectable = false,
    selectedRows,
    onClick,
    onSelect
  } = props;

Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
  const thClassName = "border-b font-medium p-4 first:pl-8 last:pr-8 pt-0 pb-3 \
    text-left text-slate-800";
  const Header = () => {
    return (
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
      <thead>
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
          {selectable ? <th></th> : null}
          {columns.map(column =>
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
            <th
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
              className={thClassName}
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
              {column.name}
            </th>)}
        </tr>
      </thead>
    );
  };

  const Body = () => {
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
    const rows = data.map(row => {
      return row.reduce((acc: any, item) => {
        acc[item.columnId] = item.value;
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
        return acc;
      }, new Map());
    })

    const columnIds = columns.map(col => col.id);

    return (
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
      <tbody className="bg-white">
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
          rows.map((row, rowIndex) => {
            return <tr
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
              className="hover:bg-slate-200 text-slate-500
               hover:text-slate-800 hover:cursor-pointer"
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
              onClick={(el) => onClick?.(el, rowIndex)}
              key={rowIndex}>
              {
                selectable ?
                  <th className="pl-4">
                    <input
                      type="checkbox"
                      onChange={(el) => (onSelect && onSelect(el, rowIndex))}
                      checked={selectedRows && selectedRows.has(rowIndex)}
                    >
                    </input>
                  </th> : null
              }
              {columnIds.map((colId, index) => {
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
                return <td
                  className="border-b border-slate-100 
                  p-4 first:pl-8 last:pr-8 text-left"
                  key={index}>
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
                </td>
  return (
Jacopo Gasparetto's avatar
Jacopo Gasparetto committed
    <div className="w-full bg-slate-100 shadow-lg rounded-xl">
      <table className={"table-auto w-full text-sm mt-8 mb-6"}>
        <Header />
        <Body />
      </table>
    </div>