efcsydney/efcsydney-roster

View on GitHub
client/src/modules/admin/users/Container.js

Summary

Maintainability
C
7 hrs
Test Coverage
import _ from 'lodash';
import React, { Component } from 'react';
import { PropTypes } from 'prop-types';
import { Route } from 'react-router-dom';
import styled from 'styled-components';
import { Button, Cell, Grid, HeaderCell, Row } from 'components';
import { Link } from 'react-router-dom';
import IconPencil from 'react-icons/lib/fa/pencil';
import IconPlus from 'react-icons/lib/fa/plus';
import Popup from './Popup';
import { createApiActions, withResource } from 'resource';
import { media } from 'styled';
import Title from '../Title';

const { modifyUsers, createUsers } = createApiActions('users');

const mapResourceToProps = (resource, state, ownProps) => {
  const isLoading = _.get(resource, 'status.retrieve.isLoading', false);

  return {
    data: resource.data,
    isLoading,
    ...ownProps
  };
};

export default withResource('users', mapResourceToProps)(
  class UserIndex extends Component {
    static propTypes = {
      data: PropTypes.object,
      selectedId: PropTypes.number
    };
    static defaultProps = {
      data: {},
      selectedId: null
    };
    constructor(props) {
      super(props);
      this.rootPath = '/admin/users';
    }
    handlePopupClose = () => {
      const { history } = this.props;
      history.push(this.rootPath);
    };
    handlePopupSave = mode => data => {
      const { dispatch, data: originUsers } = this.props;
      const { id, ...body } = data;

      const otherEmails = _.reduce(
        originUsers,
        (result, user) => {
          if (user.id !== id) result.push(user.email);
          return result;
        },
        []
      );

      if (_.includes(otherEmails, data.email)) {
        alert(
          `The user email "${
            data.email
          }" has been used. Please use other email.`
        );
        return;
      }
      if (mode === 'new') {
        dispatch(createUsers({ ...body }));
      } else {
        dispatch(modifyUsers({ id, ...body }));
      }
    };
    render() {
      const { data, isLoading } = this.props;

      return (
        <Wrapper>
          <HeadRow>
            <Title>Users Management</Title>
            <Link to={`${this.rootPath}/new`}>
              <Button kind="green" theme="solid">
                <StyledIconPlus />
                Create New User
              </Button>
            </Link>
          </HeadRow>
          <Grid>
            <thead>
              <Row>
                <HeaderCell>Primary Name</HeaderCell>
                <HeaderCell>Secondary Name</HeaderCell>
                <HeaderCell>Email</HeaderCell>
                <HeaderCell>Actions</HeaderCell>
              </Row>
            </thead>
            <tbody>
              {_.map(data, ({ id, primaryName, secondaryName, email }) => (
                <Row key={id}>
                  <Cell>{primaryName}</Cell>
                  <Cell>{secondaryName}</Cell>
                  <Cell>{email}</Cell>
                  <ActionsCell>
                    <Link to={`${this.rootPath}/edit/${id}`}>
                      <StyledButton kind="blue">
                        <IconEdit />
                        Edit
                      </StyledButton>
                    </Link>
                  </ActionsCell>
                </Row>
              ))}
            </tbody>
          </Grid>
          <Route
            exact
            path="/admin/users/:mode(new|edit)/:id?"
            render={({ match: { params: { mode, id } } }) => (
              <Popup
                mode={mode}
                data={data[id]}
                isLoading={isLoading && mode === 'edit'}
                onSave={this.handlePopupSave(mode)}
                onClose={this.handlePopupClose}
              />
            )}
          />
        </Wrapper>
      );
    }
  }
);

const Wrapper = styled.div`
  overflow-x: auto;
`;
const HeadRow = styled.div`
  display: flex;
  margin: 10px 0;
  justify-content: space-between;
  ${media.mobile`
    justify-content: center;
  `};
`;
const ActionsCell = styled(Cell)`
  display: flex;
  justify-content: center;
`;
const StyledButton = styled(Button)`
  margin-left: 4px;
`;
const StyledIconPlus = styled(IconPlus)`
  margin-right: 4px;
`;
const IconEdit = styled(IconPencil)`
  margin-right: 4px;
`;