Created
April 28, 2020 08:33
-
-
Save brandonsueur/94c855f421a6c8e2751f47a0c2fab4a3 to your computer and use it in GitHub Desktop.
managefixation.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import { connect } from 'react-redux' | |
import { withTranslation } from 'react-i18next' | |
import { Modal, Form, DatePicker, Select, Button, Row, Col, Alert } from 'antd' | |
import { Formik, Field as FormikField } from 'formik' | |
import { ExclamationCircleOutlined } from '@ant-design/icons' | |
import { | |
fixations, | |
getFixations, | |
changeFixations, | |
hasFixationsSuccess, | |
} from '../../store/ducks/contract' | |
import { SelectPeriods } from '../SelectPeriods' | |
import Fixations from '../Tables/Fixations' | |
import FormatPeriodDate from '../FormatPeriodDate' | |
import { uuid, Error } from '../../utils' | |
import { getSelects } from '../../utils/fixations' | |
import moment from 'moment' | |
import { ModalUpdateOptimization } from './index' | |
const FormItem = Form.Item | |
const { Option } = Select | |
const { confirm } = Modal | |
class ModalManageFixations extends React.Component { | |
constructor(props) { | |
super(props) | |
this.state = { | |
edited: false, | |
periods: null, | |
currentPeriod: null, | |
amountFixed: null, | |
amountRemaining: null, | |
} | |
} | |
/** | |
* Calculates the already fixed and the remaining to fix. | |
* @param {Object} period | |
*/ | |
calculateTotal(period) { | |
const { maxFixation } = this.state | |
const countAmountFixed = period.fixations.reduce( | |
(result, { amount }) => result + amount, | |
0, | |
) | |
this.setState({ | |
currentPeriod: period, | |
amountFixed: countAmountFixed, | |
amountRemaining: maxFixation - countAmountFixed, | |
}) | |
} | |
/** | |
* Initializes the value of state currentPeriod. | |
* @param {Number} id Get the ID of the selected period. | |
*/ | |
handleChangeSelectPeriod(id) { | |
const period = this.state.periods.filter(period => period.id === id)[0] | |
this.setState({ currentPeriod: period }) | |
this.calculateTotal(period) | |
} | |
handleChangeSelectAmount(fixation) { | |
this.setState({ | |
edited: true, | |
currentPeriod: this.state.currentPeriod.fixations.map(f => { | |
if (f.id === fixation.id) f.amount = fixation.value | |
return f | |
}), | |
}) | |
this.calculateTotal(this.state.currentPeriod) | |
} | |
handleDeleteFixation(fixation) { | |
const currentPeriod = this.state.currentPeriod | |
currentPeriod.fixations = currentPeriod.fixations.filter( | |
fix => fix.id !== fixation.id, | |
) | |
this.setState({ | |
edited: true, | |
currentPeriod: currentPeriod, | |
}) | |
this.calculateTotal(this.state.currentPeriod) | |
} | |
/** | |
* Add an fixation in the table. | |
* @param {*} fixation | |
*/ | |
handleAddFixation(fixation) { | |
const currentPeriod = this.state.currentPeriod | |
const sortedFixations = [...currentPeriod.fixations, fixation].sort( | |
(a, b) => new Date(a.date) - new Date(b.date), | |
) | |
currentPeriod.fixations = sortedFixations | |
this.setState({ | |
edited: true, | |
currentPeriod: currentPeriod, | |
}) | |
} | |
componentDidMount() { | |
this.props.getFixations(this.props.contract.id) | |
} | |
UNSAFE_componentWillReceiveProps(nextProps) { | |
if (!nextProps.fixations) return | |
this.setState({ | |
maxFixation: nextProps.fixations.contract.maxFixation, | |
periods: nextProps.fixations.periods, | |
}) | |
} | |
render() { | |
const { | |
t, | |
contract, | |
fixations, | |
toggleModal, | |
hasChangeFixationsSuccess, | |
} = this.props | |
const { | |
periods, | |
currentPeriod, | |
amountFixed, | |
amountRemaining, | |
maxFixation, | |
} = this.state | |
return ( | |
<Modal | |
title={t('modal.manage_fixations.title')} | |
centered | |
visible={true} | |
cancelText={t('global.cancel')} | |
okText={t('global.save')} | |
onOk={() => { | |
if (!this.state.edited) return | |
this.setState({ | |
modalWaiting: true, | |
}) | |
this.props.changeFixations(this.props.contract.id, { | |
contract: this.props.contract, | |
periods: this.state.periods, | |
}) | |
}} | |
onCancel={() => { | |
if (this.state.edited) { | |
return confirm({ | |
title: t('modal.manage_fixations.cancelled.title'), | |
icon: <ExclamationCircleOutlined />, | |
content: t('modal.manage_fixations.cancelled.description'), | |
okText: t('global.yes'), | |
onOk() { | |
toggleModal() | |
}, | |
}) | |
} else { | |
toggleModal() | |
} | |
}} | |
maskClosable={false} | |
width={'700px'} | |
> | |
<h2>{contract.name}</h2> | |
<p>{t('modal.manage_fixations.description')}</p> | |
{this.state.modalWaiting && <ModalUpdateOptimization />} | |
<SelectPeriods | |
granularity={fixations && fixations.contract.fixationGranularity} | |
periods={periods} | |
data={this.handleChangeSelectPeriod.bind(this)} | |
/> | |
{currentPeriod && ( | |
<div className="page-createfixation" style={{ marginTop: '20px' }}> | |
<h2> | |
Fixations for{' '} | |
<FormatPeriodDate | |
granularity={ | |
fixations && fixations.contract.fixationGranularity | |
} | |
date={currentPeriod} | |
/> | |
</h2> | |
<div | |
style={{ | |
marginBottom: '10px', | |
display: 'flex', | |
justifyContent: 'space-between', | |
}} | |
> | |
<div> | |
Already fixed: <b>{amountFixed}%</b> | |
</div> | |
<div> | |
Remaining to fix : <b>{amountRemaining}%</b> | |
</div> | |
</div> | |
<Fixations | |
fixations={[ | |
...currentPeriod.fixations.filter(f => f.type === 'initial'), | |
...currentPeriod.fixations.filter(f => f.type !== 'initial'), | |
]} | |
granularity={fixations && fixations.contract.fixationGranularity} | |
maxFixation={maxFixation} | |
amountFixed={amountFixed} | |
data={this.handleChangeSelectAmount.bind(this)} | |
deleteFixation={this.handleDeleteFixation.bind(this)} | |
/> | |
<h2>Add a fixation</h2> | |
{amountFixed === fixations.contract.maxFixation && ( | |
<Alert | |
message={t('form.add_fixation.rate.error.maxRate')} | |
type="warning" | |
style={{ marginBottom: '1em' }} | |
showIcon | |
/> | |
)} | |
<Formik | |
initialValues={{ | |
fixation_date: '', | |
fixation_rate: '', | |
}} | |
onSubmit={(values, actions) => { | |
const data = { | |
id: uuid(), | |
type: 'external', | |
date: moment(values.fixation_date).format('YYYY-MM-DD'), | |
amount: values.fixation_rate, | |
} | |
this.handleAddFixation(data) | |
this.calculateTotal(currentPeriod) | |
actions.resetForm({}) | |
actions.setSubmitting(false) | |
}} | |
> | |
{props => { | |
const { | |
submitForm, | |
setFieldValue, | |
values, | |
validateForm, | |
} = props | |
const getNumbersSelect = getSelects() | |
const maxDate = fixations.contract.end | |
const validateFixationDate = value => { | |
let error | |
if (!value) error = t('form.add_fixation.date.error.required') | |
return error | |
} | |
const validateFixationRate = value => { | |
let error | |
if (!value) error = t('form.add_fixation.rate.error.required') | |
if (value < 5) | |
error = t('form.add_fixation.rate.error.limitFive') | |
return error | |
} | |
return ( | |
<div> | |
<Row style={{ alignItems: 'center' }}> | |
<Col xs={7} lg={7}> | |
<FormItem label={t('form.add_fixation.date.label')}> | |
<FormikField | |
name="fixation_date" | |
validate={validateFixationDate} | |
> | |
{({ field }) => ( | |
<DatePicker | |
{...field} | |
onChange={value => { | |
setFieldValue('fixation_date', value) | |
}} | |
size={'large'} | |
disabled={ | |
amountFixed === fixations.contract.maxFixation | |
} | |
format="dddd D MMMM YYYY" | |
label={t('form.add_fixation.date.placeholder')} | |
disabledDate={d => | |
!d || d.isSameOrAfter(maxDate) | |
} | |
/> | |
)} | |
</FormikField> | |
<Error name="fixation_date" /> | |
</FormItem> | |
</Col> | |
<Col xs={15} lg={7}> | |
<FormItem | |
label={t('form.add_fixation.rate.label')} | |
style={{ | |
marginLeft: '3em', | |
}} | |
> | |
<FormikField | |
name="fixation_rate" | |
validate={validateFixationRate} | |
> | |
{({ field }) => ( | |
<Select | |
{...field} | |
onChange={value => | |
setFieldValue('fixation_rate', value) | |
} | |
value={values.fixation_rate} | |
disabled={ | |
amountFixed === fixations.contract.maxFixation | |
} | |
size={'middle'} | |
> | |
{getNumbersSelect.map((number, index) => ( | |
<Option | |
key={index} | |
value={number} | |
name="fixation_rate" | |
size={'large'} | |
disabled={ | |
number > | |
this.state.maxFixation - | |
this.state.amountFixed | |
} | |
> | |
{number}% | |
</Option> | |
))} | |
</Select> | |
)} | |
</FormikField> | |
<Error name="fixation_rate" /> | |
</FormItem> | |
</Col> | |
<Col xs={24} lg={7}> | |
<Button | |
className="btn btn-succes btn-outline" | |
disabled={ | |
amountFixed === fixations.contract.maxFixation | |
} | |
onClick={() => | |
validateForm().then(() => submitForm()) | |
} | |
> | |
{t('global.add')} | |
</Button> | |
</Col> | |
</Row> | |
</div> | |
) | |
}} | |
</Formik> | |
</div> | |
)} | |
</Modal> | |
) | |
} | |
} | |
const mapStateToProps = state => ({ | |
fixations: fixations(state), | |
hasFixationsSuccess: hasFixationsSuccess(state), | |
isChangeFixationsLoaded: state.contractReducer.loadingChangeStrategy, | |
}) | |
const mapDispatchToProps = dispatch => ({ | |
getFixations: contractId => dispatch(getFixations(contractId)), | |
changeFixations: (contractId, data) => | |
dispatch(changeFixations(contractId, data)), | |
}) | |
export default connect( | |
mapStateToProps, | |
mapDispatchToProps, | |
)(withTranslation()(ModalManageFixations)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment