Skip to content
Snippets Groups Projects
AuthorCard.js 7.9 KiB
Newer Older
import React, { Fragment } from 'react'
import { isNumber, get } from 'lodash'
import styled from 'styled-components'
import { th } from '@pubsweet/ui-toolkit'
import { required } from 'xpub-validators'
import { reduxForm, Field } from 'redux-form'
Sebastian Mihalache's avatar
Sebastian Mihalache committed
import {
  Menu,
  H3,
  ValidatedField,
  TextField,
  Checkbox,
  Spinner,
} from '@pubsweet/ui'
import {
  compose,
  withState,
  withProps,
  withHandlers,
  setDisplayName,
} from 'recompose'
Sebastian Mihalache's avatar
Sebastian Mihalache committed
import { withCountries } from 'pubsweet-component-faraday-ui'
import { Tag, Label, Row, Item, PersonInfo, IconButton, OpenModal } from './'
import { validators } from './helpers'
const Empty = () => <div />

// #region AuthorTitle
const AuthorTitle = ({
  editMode,
  listIndex,
  toggleEditMode,
  isCorresponding,
}) => (
  <Fragment>
    {!editMode ? (
        {!isSubmitting && (
          <OpenModal
            isFetching={isFetching}
            modalKey="deleteAuthor"
            onConfirm={deleteAuthor}
            subtitle={`${get(author, 'firstName', '')} ${get(
              author,
              'lastName',
              '',
            )}`}
            title="Delete author?"
          >
            {showModal => (
              <IconButton
                icon="trash-2"
                iconSize={2}
                onClick={showModal}
                right={48}
                top={15}
              />
            )}
          </OpenModal>
        )}
          icon="edit-2"
          iconSize={2}
          onClick={toggleEditMode}
          right={8}
          top={15}
        />
      </Fragment>
    ) : (
      <Fragment>
        <IconButton
Daniel Sandu's avatar
Daniel Sandu committed
          data-test-id="author-card-cancel"
          onClick={toggleEditMode}
          right={48}
        {isFetching ? (
          <StyledSpinner>
            <Spinner />
          </StyledSpinner>
        ) : (
          <IconButton
Daniel Sandu's avatar
Daniel Sandu committed
            data-test-id="author-card-save"
            disabled={formSubmitting}
            icon="check-circle"
            iconSize={2}
            onClick={saveChanges}
            right={8}
            top={15}
          />
        )}
      </Fragment>
    )}
    <Row alignItems="center" justify="flex-start">
      <H3>{isNumber(listIndex) ? `#${listIndex + 1} Author` : 'Author'}</H3>
      {!editMode ? (
        <AuthorTags>
          {isSubmitting && <Tag mr={1}>SUBMITTING</Tag>}
          {isCorresponding && <Tag mr={1}>CORRESPONDING</Tag>}
        </AuthorTags>
      ) : (
        <ValidatedField
          component={({ value, onChange }) => (
            <Checkbox
              checked={value}
              onChange={onChange}
              value={value}
            />
          )}
          name="isCorresponding"
        />
      )}
    </Row>
  </Fragment>
)
// #endregion

// #region AuthorEdit
const AuthorEdit = ({
Sebastian Mihalache's avatar
Sebastian Mihalache committed
  countries,
  author,
  editMode,
  listIndex,
  handleSubmit,
  toggleEditMode,
    <AuthorTitle
      editMode={editMode}
      isAuthorsFetching={isAuthorsFetching}
      isCorresponding={author.isCorresponding}
      isSubmitting={author.isSubmitting}
      listIndex={listIndex}
      saveChanges={handleSubmit}
      toggleEditMode={toggleEditMode}
    />
      <Field component={Empty} name="id" />
      <Field component={Empty} name="isSubmitting" />
        <Label required>Email</Label>
        <ValidatedField
          component={TextField}
          data-test-id="author-card-email"
          validate={[required, validators.emailValidator]}
        <Label required>First name</Label>
        <ValidatedField
          component={TextField}
          data-test-id="author-card-firstname"
          name="firstName"
          validate={[required]}
        />
      </Item>
        <Label required>Last name</Label>
        <ValidatedField
          component={TextField}
          data-test-id="author-card-lastname"
          name="lastName"
          validate={[required]}
        />
      </Item>
Sebastian Mihalache's avatar
Sebastian Mihalache committed
      <Item mr={1} vertical>
        <Label required>Affiliation</Label>
        <ValidatedField
          component={TextField}
          data-test-id="author-card-affiliation"
          name="affiliation"
          validate={[required]}
        />
      </Item>
Sebastian Mihalache's avatar
Sebastian Mihalache committed
      <Item vertical>
        <Label required>Country</Label>
        <ValidatedField
          component={input => (
            <Menu {...input} options={countries} placeholder="Please select" />
          )}
          data-test-id="author-card-country"
Sebastian Mihalache's avatar
Sebastian Mihalache committed
          name="country"
        />
      </Item>
)
// #endregion

const EnhancedAuthorEdit = compose(
Sebastian Mihalache's avatar
Sebastian Mihalache committed
  withCountries,
  withProps(({ author }) => ({
  reduxForm({
    form: 'author-edit',
  }),
)(AuthorEdit)

  deleteAuthor,
  toggleEditMode,
  isAuthorsFetching,
}) => (
      author={author}
      deleteAuthor={deleteAuthor}
      isAuthorsFetching={isAuthorsFetching}
      isCorresponding={author.isCorresponding}
      isFetching={isFetching}
      isSubmitting={author.isSubmitting}
      listIndex={listIndex}
      toggleEditMode={toggleEditMode}
    />
    <PersonInfo person={author} />
  editExistingAuthor,
  authorEditorSubmit,
  <Root isDragging={isDragging} isOver={isOver}>
    {!editMode &&
      (typeof dragHandle === 'function' ? dragHandle() : dragHandle)}
    {editMode ? (
      <EnhancedAuthorEdit
        author={item}
        editExistingAuthor={editExistingAuthor}
        editMode={editMode}
        listIndex={index}
        onSubmit={authorEditorSubmit}
        saveNewAuthor={saveNewAuthor}
        toggleEditMode={toggleEdit(index)}
        deleteAuthor={deleteAuthor(item)}
        editMode={editMode}
        isAuthorsFetching={isAuthorsFetching}
        isFetching={isFetching}
        listIndex={index}
        toggleEditMode={toggleEdit(index)}
      />
    )}
  </Root>
)

export default compose(
  withState('editMode', 'setEditMode', ({ item }) => item.id === 'newAuthor'),
  withHandlers({
    toggleEdit: ({ editMode, setEditMode, onEdit }) => index => () => {
      onEdit(editMode ? null : index)
  setDisplayName('AuthorCard'),
)(AuthorCard)

// #region styles
const AuthorTags = styled.div`
  align-items: center;
  display: flex;
`

const AuthorContainer = styled.div`
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: calc(${th('gridUnit')} * 2);
const Root = styled.div`
  background-color: ${props =>
    props.isOver ? th('colorFurniture') : th('colorBackgroundHue')};
  border-radius: ${th('borderRadius')};
  box-shadow: ${th('boxShadow')};
  margin-bottom: ${th('gridUnit')};
  position: relative;

  ${Row} {
    margin-bottom: ${th('gridUnit')};
  }

  ${H3} {
    margin: 0;
    margin-right: ${th('gridUnit')};
    & + div div[role='alert'] {
      margin-top: 0;
    }

const StyledSpinner = styled.div`
  position: absolute;
  right: ${th('gridUnit')};
  top: calc(${th('gridUnit')} * 2);
`