import React, { Fragment } from 'react' import { debounce, isEqual } from 'lodash' import { connect } from 'react-redux' import { required } from 'xpub-validators' import styled, { css } from 'styled-components' import { th, Menu, ValidatedField, Icon, Button } from '@pubsweet/ui' import { compose, withHandlers, withProps } from 'recompose' import { reduxForm, isSubmitting, change as changeForm, getFormValues, } from 'redux-form' import AutosaveIndicator from 'pubsweet-component-wizard/src/components/AutosaveIndicator' import { autosaveRequest, autosaveSuccess, } from 'pubsweet-component-wizard/src/redux/autosave' import { ConfirmationModal, withModal2, } from 'pubsweet-component-modal/src/components' import { selectError, selectFetching, createRecommendation, updateRecommendation, getFragmentRecommendations, } from 'pubsweet-components-faraday/src/redux/recommendations' import { parseReviewResponseToForm, parseReviewRequest } from './utils' const guidelinesLink = 'https://about.hindawi.com/authors/peer-review-at-hindawi/' const options = [ { value: 'publish', label: 'Publish unaltered', }, { value: 'major', label: 'Consider after major revision', }, { value: 'minor', label: 'Consider after major revision', }, { value: 'reject', label: 'Reject', }, ] const onChange = ( values, dispatch, { project, version, createRecommendation, updateRecommendation }, ) => { dispatch(autosaveRequest()) if (values.id) { updateRecommendation(parseReviewRequest(values)) .then(console.log) .then(dispatch(autosaveSuccess(new Date()))) } else { createRecommendation(parseReviewRequest(values)) .then(console.log) .then(dispatch(autosaveSuccess(new Date()))) } } const ReviewerReportForm = ({ isSubmitting, changeField, handleSubmit, formValues = {}, }) => ( <Root> <Row> <Label>Recommendation*</Label> <ActionLink href={guidelinesLink} target="_blank"> Hindawi Reviewer Guidelines </ActionLink> </Row> <Row> <ValidatedField component={input => ( <Menu {...input} inline onChange={v => changeField('recommendation', v)} options={options} placeholder="Select" /> )} name="recommendation" validate={[required]} /> </Row> <Spacing /> <Row> <Label> Report <ActionText left={12}>Upload file</ActionText> </Label> </Row> <Row> <FullWidth> <ValidatedField component={input => ( <Textarea {...input} hasError={input.validationStatus === 'error'} onChange={e => changeField('public', e.target.value)} rows={6} /> )} name="public" validate={[required]} /> </FullWidth> </Row> {formValues.hasConfidential ? ( <Fragment> <Row> <Label> Note for the editorial team <i>Not shared with the author</i> </Label> <ActionTextIcon onClick={() => changeField('hasConfidential', false)}> <Icon primary size={3}> x </Icon> Remove </ActionTextIcon> </Row> <Row> <FullWidth> <ValidatedField component={input => ( <Textarea {...input} hasError={input.validationStatus === 'error'} onChange={e => changeField('confidential', e.target.value)} rows={6} /> )} name="confidential" validate={[required]} /> </FullWidth> </Row> </Fragment> ) : ( <Row> <ActionText onClick={() => changeField('hasConfidential', true)}> Add confidential note for the Editorial Team </ActionText> </Row> )} <Spacing /> <Row> <ActionButton onClick={handleSubmit}> Submit report </ActionButton> <AutosaveIndicator formName="reviewerReport" /> </Row> </Root> ) const ModalWrapper = compose( connect(state => ({ fetching: selectFetching(state), modalError: selectError(state), })), )(({ fetching, ...rest }) => ( <ConfirmationModal {...rest} isFetching={fetching} /> )) export default compose( connect( state => ({ formValues: getFormValues('reviewerReport')(state), isSubmitting: isSubmitting('reviewerReport')(state), }), { changeForm, getFormValues, getFragmentRecommendations, createRecommendation, updateRecommendation, }, ), withProps(({ recommendations = [] }) => ({ initialValues: parseReviewResponseToForm(recommendations[0]), })), withModal2(props => ({ modalComponent: ModalWrapper, })), withHandlers({ changeField: ({ changeForm }) => (field, value) => { changeForm('reviewerReport', field, value) }, }), reduxForm({ form: 'reviewerReport', onChange: debounce(onChange, 1000, { maxWait: 5000 }), onSubmit: ( values, dispatch, { isSubmitting, showModal, hideModal, project, version }, ) => { showModal({ title: 'Ready to Submit your Report?', subtitle: 'Once submitted, the report can`t be modified', confirmText: 'Submit report', onConfirm: () => { dispatch(autosaveRequest()) updateRecommendation(parseReviewRequest(values)) .then(console.log) .then(hideModal) .then(dispatch(autosaveSuccess(new Date()))) // sleep(1000) // .then(hideModal) // .then(() => { // // TODO: link to backend // const review = parseReviewRequest(values) // window.alert( // `You submitted:\n\n${JSON.stringify(review, null, 2)}`, // ) // }) }, onCancel: hideModal, }) }, }), )(ReviewerReportForm) // #region styled-components const defaultText = css` color: ${th('colorPrimary')}; font-family: ${th('fontReading')}; font-size: ${th('fontSizeBaseSmall')}; ` const Root = styled.div` display: flex; flex-direction: column; margin: auto; [role='listbox'] { min-width: 280px; } ` const Label = styled.div` ${defaultText}; text-transform: uppercase; i { text-transform: none; margin-left: ${th('gridUnit')}; } ` const ActionText = styled.span` ${defaultText}; text-decoration: underline; cursor: pointer; margin-left: ${({ left }) => left || 0}px; ` const ActionTextIcon = styled(ActionText)` display: flex; align-items: center; ` const ActionLink = styled.a` ${defaultText}; ` const Textarea = styled.textarea` width: 100%; padding: calc(${th('subGridUnit')}*2); font-size: ${th('fontSizeBaseSmall')}; font-family: ${th('fontWriting')}; border-color: ${({ hasError }) => hasError ? th('colorError') : th('colorPrimary')}; ` const Spacing = styled.div` margin-top: ${th('gridUnit')}; flex: 1; ` const FullWidth = styled.div` flex: 1; > div { flex: 1; } ` const Row = styled.div` display: flex; flex-direction: row; align-items: center; flex: 1; box-sizing: border-box; flex-wrap: wrap; justify-content: space-between; ` const ActionButton = styled(Button)` ${defaultText}; align-items: center; background-color: ${th('colorPrimary')}; color: ${th('colorTextReverse')}; display: flex; padding: 4px 8px; text-align: center; height: calc(${th('subGridUnit')}*5); text-transform: uppercase; ` // #endregion