GospelToolbox/Labs

View on GitHub
app/javascript/apps/teamschedule/TeamScheduleTable.jsx

Summary

Maintainability
A
1 hr
Test Coverage
import React from 'react';
import moment from 'moment';

import TeamPersonBadge from './TeamPersonBadge';

function TeamScheduleTable(props) {
  const {
    schedule
  } = props;

  if (schedule == null) {
    return null;
  }

  return (
    <div style={{ overflow: 'scroll', height: '100%', width: '100%' }}>
      <table className="table serve-team-table">
        <thead>
          <tr>
            <th>Serve Area</th>
            <th>Team</th>
            <th>Position</th>
            {schedule.schedule_dates.map(date => (<th style={{ whiteSpace: 'nowrap' }} key={date}>{moment(date).format('MMM D')}</th>))}
          </tr>
        </thead>
        <tbody>
          {renderScheduleRows(schedule)}
        </tbody>
      </table>
    </div>
  );
}

/**
 *  
 * @param {*} schedule 
 */
function renderScheduleRows(schedule) {
  const serviceTypeIds = Object.keys(schedule.service_types);
  const serviceTypeRowCells = serviceTypeIds.map(serviceTypeId => {
    const serviceTypeContext = {
      schedule,
      serviceTypeId
    };

    return generateServiceTypeRowCells(serviceTypeContext);
  });

  // Merge all of the service type rows together
  return [].concat.apply([], serviceTypeRowCells);
}

/**
 * Render the service type and all of the teams
 * @param {*} context 
 */
function generateServiceTypeRowCells(context) {
  const {
    schedule,
    serviceTypeId
  } = context;

  const serviceTeams = schedule.service_type_teams[serviceTypeId];
  const teamRows = serviceTeams.map(teamId => {
    const teamContext = {
      schedule,
      serviceTypeId,
      teamId
    };

    return generateTeamRowCells(teamContext);
  });
  // Merge all of the team rows together
  const serviceTypeRows = [].concat.apply([], teamRows);

  // Add the service type column to the first row
  if(serviceTypeRows.length > 0) {
    const serviceTypeName = schedule.service_types[serviceTypeId];
    const serviceTypeCell = (
      <td className="service-type-name" rowSpan={serviceTypeRows.length}>
        {serviceTypeName}
      </td>);
      

    serviceTypeRows[0] = <tr key={key(serviceTypeId, serviceTeams[0], 'first' )} className="team-first">{[serviceTypeCell, ...serviceTypeRows[0].props.children]}</tr>;
  }

  return serviceTypeRows;
}

/**
 * Render the service team and all of the team positions
 * @param {*} context 
 */
function generateTeamRowCells(context) {
  const {
    schedule,
    serviceTypeId,
    teamId
  } = context;

  const teamPositions = schedule.team_positions[teamId];
  const teamRows = teamPositions.map(position => {
    const teamPositionContext = {
      schedule,
      serviceTypeId,
      teamId,
      position
    };

    return generateTeamPositionRowCells(teamPositionContext);
  });

  // Add the team name column to the first row
  if(teamRows.length > 0) {
    const teamName = schedule.team_names[teamId]
    const serviceTypeCell = (
      <td key={key(serviceTypeId, teamId, 'name')} className="team-name" rowSpan={teamRows.length}>
        {teamName}
      </td>);

    teamRows[0] = <tr key={key(serviceTypeId,teamId)} className="team-position-first">{[serviceTypeCell, ...teamRows[0].props.children]}</tr>;
  }

  return teamRows;
}

/**
 * Render the current team position and all of the
 * people schedule for the given dates
 * @param {*} context 
 */
function generateTeamPositionRowCells(context) {
  const {
    schedule,
    serviceTypeId,
    teamId,
    position
  } = context;

  // Add cells for each plan date we have
  const dateCells = schedule.schedule_dates.map(date => {
    const dateContext = {
      schedule,
      serviceTypeId,
      teamId,
      position,
      date
    };       

    let people = schedule.records[serviceTypeId][teamId][position][date];
    return (
      <td key={key(serviceTypeId, teamId, position, date)} className="position-date">
        {people && people.map(person => <TeamPersonBadge key={person.name} person={person}></TeamPersonBadge>) }
      </td>
    );
  });

  const nameCell = (
    <td key={key(serviceTypeId, teamId, position, 'name')} className="team-position-name">
      {position}
    </td>
  );

  return <tr key={[serviceTypeId, teamId, position].join('-')}>{[nameCell, ...dateCells]}</tr>;
}

export default TeamScheduleTable;

function key(...args) {
  return args.map(a => a.toString()).join('-');
}