Coursemology/coursemology2

View on GitHub
client/app/bundles/course/group/pages/GroupShow/index.jsx

Summary

Maintainability
A
35 mins
Test Coverage
import { useCallback, useEffect } from 'react';
import { defineMessages, FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
import { useParams } from 'react-router-dom';
import PropTypes from 'prop-types';

import ErrorCard from 'lib/components/core/ErrorCard';
import LoadingIndicator from 'lib/components/core/LoadingIndicator';
import Note from 'lib/components/core/Note';

import { fetchCourseUsers, fetchGroupData } from '../../actions';
import actionTypes from '../../constants';
import { categoryShape, groupShape } from '../../propTypes';

import CategoryCard from './CategoryCard';
import GroupManager from './GroupManager';
import GroupTableCard from './GroupTableCard';

const translations = defineMessages({
  fetchFailure: {
    id: 'course.group.GroupShow.fetchFailure',
    defaultMessage: 'Failed to fetch group data! Please reload and try again.',
  },
  noCategory: {
    id: 'course.group.GroupShow.noCategory',
    defaultMessage: "You don't have a group category created! Create one now!",
  },
  noGroups: {
    id: 'course.group.GroupShow.noGroups',
    defaultMessage:
      "You don't have any groups under this category! Manage groups now to get started!",
  },
});

const Category = ({
  dispatch,
  groupCategory,
  groups,
  isFetching,
  isManagingGroups,
  hasFetchError,
  canManageCategory,
  canManageGroups,
}) => {
  const { groupCategoryId } = useParams();
  const handleGroupSelect = useCallback(
    (groupId) => {
      dispatch({ type: actionTypes.MANAGE_GROUPS_START });
      dispatch({
        type: actionTypes.SET_SELECTED_GROUP_ID,
        selectedGroupId: groupId,
      });
    },
    [dispatch],
  );

  useEffect(() => {
    if (groupCategoryId) {
      dispatch(fetchGroupData(groupCategoryId));
    }
  }, [groupCategoryId]);

  // This is done as a separate call since it shouldn't slow down the render
  useEffect(() => {
    if (groupCategoryId) {
      dispatch(fetchCourseUsers(groupCategoryId));
    }
  }, [groupCategoryId]);

  if (isFetching) {
    return <LoadingIndicator />;
  }
  if (hasFetchError) {
    return (
      <ErrorCard
        message={<FormattedMessage {...translations.fetchFailure} />}
      />
    );
  }

  // This shouldn't happen, but just in case. Handles both null and undefined
  if (groupCategory == null) {
    return <Note message={<FormattedMessage {...translations.noCategory} />} />;
  }

  return (
    <div className="mt-8">
      {canManageGroups && isManagingGroups ? (
        <GroupManager category={groupCategory} groups={groups} />
      ) : (
        <>
          <CategoryCard
            canManageCategory={canManageCategory}
            canManageGroups={canManageGroups}
            category={groupCategory}
            numGroups={groups.length}
            onManageGroups={() =>
              dispatch({ type: actionTypes.MANAGE_GROUPS_START })
            }
          />
          {groups.map((group) => (
            <GroupTableCard
              key={group.id}
              canManageCategory={canManageCategory}
              group={group}
              onManageGroup={() => handleGroupSelect(group.id)}
            />
          ))}
          {groups.length === 0 ? (
            <Note message={<FormattedMessage {...translations.noGroups} />} />
          ) : null}
        </>
      )}
    </div>
  );
};

Category.propTypes = {
  isFetching: PropTypes.bool.isRequired,
  isManagingGroups: PropTypes.bool.isRequired,
  canManageCategory: PropTypes.bool.isRequired,
  canManageGroups: PropTypes.bool.isRequired,
  hasFetchError: PropTypes.bool.isRequired,
  groupCategory: categoryShape,
  groups: PropTypes.arrayOf(groupShape).isRequired,
  dispatch: PropTypes.func.isRequired,
};

export default connect(({ groups }) => ({
  isFetching: groups.groupsFetch.isFetching,
  hasFetchError: groups.groupsFetch.hasFetchError,
  groupCategory: groups.groupsFetch.groupCategory,
  groups: groups.groupsFetch.groups,
  canManageCategory: groups.groupsFetch.canManageCategory,
  canManageGroups: groups.groupsFetch.canManageGroups,
  isManagingGroups: groups.groupsManage.isManagingGroups,
}))(Category);