Weekly display of headers with react-table

Viewed 1057

I am trying to implement a table to display shifts of employees with react-table. I would like to find a way to display every day of the week (Monday to Sunday) for each column in the table, and having a feature where I can navigate through the next/past weeks. I am trying every way but I am struggling to find a proper solution for this.

This is my table:

 <table
        {...getTableProps()}
        className="min-w-full divide-y divide-gray-200"
      >
        <thead className="bg-gray-50">
          {headerGroups.map((headerGroup) => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map((column) => (
                <th
                  {...column.getHeaderProps()}
                  scope="col"
                  className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
                >
                  {column.render("Header")}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {page.map((row) => {
            prepareRow(row);
            return (
              <tr {...row.getRowProps()} className="bg-white rt-tr-group">
                {row.cells.map((cell) => {
                  return (
                    <td
                      {...cell.getCellProps}
                      className="px-6 py-4 whitespace-nowrap text-sm text-gray-500"
                    >
                      {cell.render("Cell")}
                    </td>
                  );
                })}
              </tr>
            );
          })}
        </tbody>
      </table>

And those are my columns:

import moment from "moment";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faClock } from "@fortawesome/free-solid-svg-icons";

const today = new Date();
const tomorrow = new Date(today);

const renderStateOfShift = (shift: any) => {
  if (shift.arrived) {
    return (
      <span className="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
        In
      </span>
    );
  } else {
    return (
      <span className="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">
        Late
      </span>
    );
  }
};

const returnShifts = (
  data: { cell: { row: { original: { shifts: any[] } } } },
  formattedDay: string
) => {
  return (
    <div className="flex flex-col justify-center">
      {data.cell.row.original.shifts.map((shift: any) =>
        formattedDay === shift.start.split("T")[0] ? (
          <div>
            <div className="bg-white px-4 py-4 flex-1 my-2 rounded-lg shadow flex flex-col justify-center">
              <td>{shift.job_id}</td>
              <div className="flex flex-row">
                <td>
                  <FontAwesomeIcon icon={faClock} size="sm" />
                </td>

                <td>{shift.start.split("T")[1].substring(0, 5)}</td>
                <td>-</td>
                <td>{shift.end.split("T")[1].substring(0, 5)}</td>
                <td>{renderStateOfShift(shift)}</td>
              </div>
            </div>
          </div>
        ) : null
      )}
    </div>
  );
};

export const COLUMNS = [
  {
    Header: "EMPLOYEE",
    accessor: "worker_id",
    Cell: (data) => {
      const employeeName = data.cell.row.original.worker_name;
      const employeeRole = data.cell.row.original.worker_role;
      return (
        <div className="flex flex-row">
          <img
            className="inline-block  h-10 w-10 rounded-full"
            src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixqx=azIRqR0jgc&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
            alt=""
          />

          <div className="flex flex-col justify-center">
            <td>{employeeName}</td>
            <td>{employeeRole}</td>
          </div>
        </div>
      );
    },
  },
  {
    Header: moment(today).format("ll"),
    accessor: "monday",
    //@ts-ignore
    Cell: (data) => {
      const formattedDay = today.toISOString().split("T")[0];
      return returnShifts(data, formattedDay);
    },
  },
  {
    Header: moment(tomorrow.setDate(tomorrow.getDate() + 1)).format("ll"),
    accessor: "tuesday",
    Cell: (data: any) => {
      const formattedDay = moment(today)
        .add(1, "day")
        .toISOString()
        .split("T")[0];
      return returnShifts(data, formattedDay);
    },
  },
  {
    Header: moment(tomorrow.setDate(tomorrow.getDate() + 1)).format("ll"),
    accessor: "thursday",
    Cell: (data: any) => {
      const formattedDay = moment(today)
        .add(2, "day")
        .toISOString()
        .split("T")[0];
      return returnShifts(data, formattedDay);
    },
  },
  {
    Header: moment(tomorrow.setDate(tomorrow.getDate() + 1)).format("ll"),
    accessor: "wednesday",
    Cell: (data: any) => {
      const formattedDay = moment(today)
        .add(3, "day")
        .toISOString()
        .split("T")[0];
      return returnShifts(data, formattedDay);
    },
  },
  {
    Header: moment(tomorrow.setDate(tomorrow.getDate() + 1)).format("ll"),
    accessor: "friday",
    Cell: (data: any) => {
      const formattedDay = moment(today)
        .add(4, "day")
        .toISOString()
        .split("T")[0];
      return returnShifts(data, formattedDay);
    },
  },
  {
    Header: moment(tomorrow.setDate(tomorrow.getDate() + 1)).format("ll"),
    accessor: "saturday",
    Cell: (data: any) => {
      const formattedDay = moment(today)
        .add(5, "day")
        .toISOString()
        .split("T")[0];
      return returnShifts(data, formattedDay);
    },
  },
  {
    Header: moment(tomorrow.setDate(tomorrow.getDate() + 1)).format("ll"),
    accessor: "sunday",
    Cell: (data: any) => {
      const formattedDay = moment(today)
        .add(6, "day")
        .toISOString()
        .split("T")[0];
      return returnShifts(data, formattedDay);
    },
  },
  {
    Header: "DETAILS",
    accessor: "delivery",
  },
];

This is how the table looks like so far: enter image description here

Can someone help me out?

1 Answers

React-Table exposes pageIndex as part of its usePagination hook, and moment.js supports adding days. The Header object that is part of columns exposes the table's state if you pass it a JSX callback. You could probably, instead of having your headers be based on today, base them on today + [pageIndex * (7 + offset)]; for example, the header for the current date could look like:

    Header: ({ state }) => moment(today).add(7 * state.pageIndex, "days").format("ll"),
Related