Untitled
unknown
plain_text
3 years ago
37 kB
4
Indexable
import React, { Component } from 'react'; import { withRouter } from 'react-router-dom'; import { connect } from 'react-redux'; import Cookie from 'isomorphic-cookie'; import Card from '@material-ui/core/Card'; import isEmpty from 'lodash/isEmpty'; import get from 'lodash/get'; import uniq from 'lodash/uniq'; import cloneDeep from 'lodash/cloneDeep'; import uniqBy from 'lodash/uniqBy'; import startCase from 'lodash/startCase'; import { FORM_DATA_SCHEMA, VALIDATION_TYPE, ALERT_TYPE, OPTION_RELATION_OPERATORS, OPTION_TIME_FRAME, OPTION_PAX_TYPE, OPTION_CABIN_CLASS, DEFAULT_USERLANG, OPTION_REFUND_TYPE, OPTION_REFUND_METHOD } from '../../core/constants'; import { setData, url as urlHelper } from '../../helpers'; import { setAlert, actionSetLoading } from '../../redux/actions'; import { getAllSupplier } from '../../models/supplier'; import { getAllAirlines } from '../../models/airlines'; import { getAllAirports } from '../../models/airport'; import { getAllCountries } from '../../models/country'; import { getAllReason, getRefundDetailByReasonId } from '../../models/refundReason'; import { getRefundMatrixById, addRefundMatrix, editRefundMatrix, validateFormula } from '../../models/refundMatrix'; import { Head, Submit } from './../../components/Form'; import Validator from '../../components/Validator'; import TixField from '../../components/TixField'; import { Wrapper, WrapperContent } from '../../components/Wrapper/index.js'; import Select from '../../components/Select'; import InputTag from '../../components/InputTag'; import MatrixCalculator from '../../components/MatrixCalculator'; import { TixDatePicker } from '../../components/Picker'; import { select as selectHelper } from '../../helpers'; import { getAmadeusCredentialById } from '../../models/amadeusCredential'; export class Form extends Component { constructor(props) { super(props); this.state = { formData: { supplierCode: { [FORM_DATA_SCHEMA.value]: '', [VALIDATION_TYPE.required]: true }, supplierType: { [FORM_DATA_SCHEMA.value]: '', [VALIDATION_TYPE.required]: true }, supplierName: { [FORM_DATA_SCHEMA.value]: '', [VALIDATION_TYPE.required]: true }, currency: { [FORM_DATA_SCHEMA.value]: '', [VALIDATION_TYPE.required]: true }, username: { [FORM_DATA_SCHEMA.value]: '', [VALIDATION_TYPE.required]: true }, password: { [FORM_DATA_SCHEMA.value]: '', [VALIDATION_TYPE.required]: true }, wsap: { [FORM_DATA_SCHEMA.value]: '', [VALIDATION_TYPE.required]: true }, dutyCode: { [FORM_DATA_SCHEMA.value]: '', [VALIDATION_TYPE.required]: true }, officeId: { [FORM_DATA_SCHEMA.value]: '', [VALIDATION_TYPE.required]: true }, promoCodes: { [FORM_DATA_SCHEMA.value]: '', [VALIDATION_TYPE.required]: false }, airlineCodes: { [FORM_DATA_SCHEMA.value]: '', [VALIDATION_TYPE.required]: true }, additionalData: {} }, url: '/amadeus-credential', dataAllAirlines: [] }; } componentDidMount() { this.handleFetches(); } handleFetches = () => { const arr = [getAllAirlines()]; this.props.actionSetLoading(true); const paramsId = this.props.match.params.id; /* istanbul ignore else */ if (paramsId) { arr.push(getAmadeusCredentialById(paramsId)); } Promise.all(arr) .then(values => { const { url, currentPage } = this.state; let dataAllAirlines = []; const [resAllAirlines] = values; // Airlines if (resAllAirlines.code === 'SUCCESS') { dataAllAirlines = selectHelper.setOptions({ data: resAllAirlines.data, labelBy: 'name', valueBy: 'code' }); dataAllAirlines.push({ label: '*', value: '*' }); } else { urlHelper.redirectPage( this, resAllAirlines, ALERT_TYPE.error, `${url}?page=${currentPage}` ); } // Get By Id /* istanbul ignore else */ if (paramsId) { const resFormData = get(values, '[1]', {}); if (resFormData.code === 'SUCCESS') { this.setFormData(resFormData.data); } else { urlHelper.redirectPage( this, resFormData, ALERT_TYPE.error, `${url}?page=${currentPage}` ); } } this.setState({ dataAllAirlines }); }) .catch(err => { this.props.setAlert({ message: err.message, alertType: ALERT_TYPE.error }); }) .finally(() => { this.props.actionSetLoading(false); }); }; handlePopulateReasonDetail = async (reasonId, handleChange, e) => { const { tempReasonId } = this.state; let selectedReason = []; // Set loading to false this.setState({ reasonLoading: false }); if (!reasonId.includes('*')) { selectedReason = reasonId; this.setState({ dataReasonId: tempReasonId }); } else { selectedReason = ['*']; this.setState({ dataReasonId: [{ label: '*', value: '*' }] }); } if (handleChange && e) { if (!isEmpty(e.target.value)) this.setState({ reasonLoading: true }); handleChange(e); } try { const responses = await Promise.all( selectedReason.map(reasonId => { return getRefundDetailByReasonId(reasonId); }) ); const reducer = (acc, curr) => { if (curr.code === 'SUCCESS') { curr.data .filter(row => row.lang === this.state.lang) .map(row => { acc.push(startCase(row.content)); }); } return acc; }; const result = uniq(responses.reduce(reducer, [])); this.setState({ reasonLoading: false, dataReasonDetail: result }); } catch (e) { console.error(e.message); } }; handleFetchReason = (airlineCode, resReasonId) => { this.props.actionSetLoading(true); getAllReason(airlineCode) .then(res => { let dataReasonId = []; if (res.code === 'SUCCESS') { const dataReasonIdTemp = selectHelper .setOptions({ data: res.data, customLabel: this.customLabelReason, valueBy: 'reasonId' }) .filter(item => item.lang === this.state.lang) || []; dataReasonId = uniqBy(dataReasonIdTemp, 'reasonId'); dataReasonId.push({ label: '*', value: '*' }); } else { this.props.setAlert({ message: res.message || res.code, alertType: ALERT_TYPE.error }); } this.setState( { tempReasonId: dataReasonId, dataReasonId }, () => { // Populate after fetch reason Id if (resReasonId) this.handlePopulateReasonDetail(resReasonId); } ); }) .catch(err => { this.props.setAlert({ message: err.message, alertType: ALERT_TYPE.error }); }) .finally(() => { this.props.actionSetLoading(false); }); }; customLabelReason = data => { return `${data.content} v${data.reasonVersion}`; }; handleChangeDate = (e, setError, dateFrom, dateTo) => { this.setState( { [`${e.target.name}Temp`]: e.target.value }, () => { this.validationDate(setError, dateFrom, dateTo); } ); }; validationDate = (setError, dateFrom, dateTo) => { const dateFromTemp = this.state[`${dateFrom}Temp`]; const dateToTemp = this.state[`${dateTo}Temp`]; const errorDate = this.state.errorDate; if ((!dateFromTemp && dateToTemp) || (dateFromTemp && !dateToTemp)) { setError(dateFrom, errorDate); setError(dateTo, errorDate); } else { setError(dateFrom, ''); setError(dateTo, ''); } }; handleSubmit = ({ isError, data }) => { /* istanbul ignore else */ if (!isError) { const { url } = this.state; this.props.actionSetLoading(true); addRefundMatrix(data) .then(res => { if (res.code === 'SUCCESS') { urlHelper.redirectPage(this, res, ALERT_TYPE.success, url); } else { this.props.setAlert({ message: res.message || res.code, alertType: ALERT_TYPE.error }); } }) .catch(err => { this.props.setAlert({ message: err.message, alertType: ALERT_TYPE.error }); }) .finally(() => { this.props.actionSetLoading(false); }); } }; handleEdit = ({ isError, data }) => { /* istanbul ignore else */ if (!isError) { const paramData = { ...data }; delete paramData.reasonContent; delete paramData.reasonDetailContent; const { url, currentPage } = this.state; this.props.actionSetLoading(true); editRefundMatrix(this.props.match.params.id, paramData) .then(res => { if (res.code === 'SUCCESS') { urlHelper.redirectPage( this, res, ALERT_TYPE.success, `${url}?page=${currentPage}` ); } else { this.props.setAlert({ message: res.message || res.code, alertType: ALERT_TYPE.error }); } }) .catch(err => { this.props.setAlert({ message: err.message, alertType: ALERT_TYPE.error }); }) .finally(() => { this.props.actionSetLoading(false); }); } }; setFormData = data => { const formData = setData(data, this.state.formData); this.setState({ formData }); }; handleFormulaChange = (value, key, onFormulaChange) => { onFormulaChange({ target: { name: `penaltyMatrices[${key}].formula`, value } }); }; handleValidateFormula = (value, key) => { const { errorFormulas } = this.state; // Reset the errors errorFormulas[key] = null; this.setState({ errorFormulas }); return new Promise((resolve, reject) => { // HIT API validateFormula(value) .then(res => { if (res.code === 'SUCCESS') { // Check formula validation resolve(true); errorFormulas[key] = null; } else { reject(false); errorFormulas[key] = 'Formula tidak valid.'; } }) .catch(() => { reject(false); errorFormulas[key] = 'Something bad happened. Contact developer.'; }) .finally(() => { this.setState({ errorFormulas }); }); }); }; render() { const { formData, dataAllSupplier, dataAllAirlines, dataAllAirports, dataAllCountries, dataReasonId, dataReasonDetail, penaltyMatricTemplate, errorFormulas, reasonLoading } = this.state; const isAdd = this.props.match.params.id === undefined; const _cloneData = cloneDeep(formData); return ( <Validator initialValue={_cloneData} onSubmit={isAdd ? this.handleSubmit : this.handleEdit} > {({ values, errors, handleChange, handleSubmit, handleAddItem, handleRemoveItem, setError }) => { return ( <Card className="ov--visible"> <form onSubmit={handleSubmit}> <Head title={`${isAdd ? 'Add' : 'Edit'} Refund Matrix`} /> <div className="row"> <div className="col-xs-4"> <Select placeholder="Airline Code" name="airlineCode" options={dataAllAirlines} value={get( values, `airlineCode.${FORM_DATA_SCHEMA.value}`, '' )} onChange={e => { this.handleFetchReason(e.target.value); handleChange(e); }} error={!isEmpty(errors.airlineCode)} helperText={errors.airlineCode ? errors.airlineCode : ''} /> </div> <div className="col-xs-4"> <Select placeholder="Origin" name="origin" options={dataAllAirports} value={get( values, `origin.${FORM_DATA_SCHEMA.value}`, '' )} onChange={handleChange} error={!isEmpty(errors.origin)} helperText={errors.origin ? errors.origin : ''} /> </div> <div className="col-xs-4"> <Select placeholder="Destination" name="destination" options={dataAllAirports} value={get( values, `destination.${FORM_DATA_SCHEMA.value}`, '' )} onChange={handleChange} error={!isEmpty(errors.destination)} helperText={errors.destination ? errors.destination : ''} /> </div> </div> <div className="row"> <div className="col-xs-4"> <Select placeholder="Origin Country" name="originCountry" options={dataAllCountries} value={get( values, `originCountry.${FORM_DATA_SCHEMA.value}`, '' )} onChange={handleChange} error={!isEmpty(errors.originCountry)} helperText={ errors.originCountry ? errors.originCountry : '' } /> </div> <div className="col-xs-4"> <Select placeholder="Destination Country" name="destinationCountry" options={dataAllCountries} value={get( values, `destinationCountry.${FORM_DATA_SCHEMA.value}`, '' )} onChange={handleChange} error={!isEmpty(errors.destinationCountry)} helperText={ errors.destinationCountry ? errors.destinationCountry : '' } /> </div> <div className="col-xs-4"> <Select placeholder="Supplier Code" name="supplierCode" options={dataAllSupplier} value={get( values, `supplierCode.${FORM_DATA_SCHEMA.value}`, [] )} onChange={handleChange} error={!isEmpty(errors.supplierCode)} helperText={ errors.supplierCode ? errors.supplierCode : '' } /> </div> </div> <div className="row"> <div className="col-xs-4"> <Select placeholder="Pax Types" name="paxTypes" options={OPTION_PAX_TYPE} value={get( values, `paxTypes.${FORM_DATA_SCHEMA.value}`, [] )} onChange={handleChange} multi error={!isEmpty(errors.paxTypes)} helperText={errors.paxTypes ? errors.paxTypes : ''} /> </div> <div className="col-xs-4"> <Select placeholder="Cabin Classes" name="cabinClasses" options={OPTION_CABIN_CLASS} value={get( values, `cabinClasses.${FORM_DATA_SCHEMA.value}`, [] )} onChange={handleChange} multi error={!isEmpty(errors.cabinClasses)} helperText={ errors.cabinClasses ? errors.cabinClasses : '' } /> </div> <div className="col-xs-4"> <TixField error={!isEmpty(errors.description)} id="description" name="description" label="Description" helperText={errors.description ? errors.description : ''} margin="normal" onChange={handleChange} value={get( values, `description.${FORM_DATA_SCHEMA.value}`, '' )} variant="outlined" multiline row="5" /> </div> </div> <div className="row"> <div className="col-xs-4"> <InputTag id="fareClasses" options={ formData.fareClasses[FORM_DATA_SCHEMA.value].length > 0 ? formData.fareClasses[FORM_DATA_SCHEMA.value] : [] } onChange={values => { const target = { value: values, name: 'fareClasses' }; handleChange({ target }); }} values={ values.fareClasses[FORM_DATA_SCHEMA.value].length > 0 ? values.fareClasses[FORM_DATA_SCHEMA.value] : [] } label="Fare Classes" placeholder="Enter multiple Fare Class here" error={!isEmpty(errors.fareClasses)} helperText={errors.fareClasses} info="* Use Tab to separate Fare Classes" /> </div> <div className="col-xs-4"> <InputTag id="fareBasisCodes" options={ formData.fareBasisCodes[FORM_DATA_SCHEMA.value].length > 0 ? formData.fareBasisCodes[FORM_DATA_SCHEMA.value] : [] } onChange={values => { const target = { value: values, name: 'fareBasisCodes' }; handleChange({ target }); }} values={ values.fareBasisCodes[FORM_DATA_SCHEMA.value].length > 0 ? values.fareBasisCodes[FORM_DATA_SCHEMA.value] : [] } label="Fare Basis" placeholder="Enter multiple Fare Basis Code here" error={!isEmpty(errors.fareBasisCodes)} helperText={errors.fareBasisCodes} info="* Use Tab to separate Fare Basis Code" /> </div> <div className="col-xs-4"> <Select placeholder="Matrix Type" name="matrixType" options={OPTION_REFUND_TYPE} searchable={false} value={get( values, `matrixType.${FORM_DATA_SCHEMA.value}`, '' )} onChange={handleChange} error={!isEmpty(errors.matrixType)} helperText={errors.matrixType ? errors.matrixType : ''} /> </div> </div> <div className="row"> <div className="col-xs-4"> <Select placeholder="Refund Method" name="refundMethod" options={OPTION_REFUND_METHOD} searchable={false} value={get( values, `refundMethod.${FORM_DATA_SCHEMA.value}`, '' )} onChange={handleChange} error={!isEmpty(errors.refundMethod)} helperText={ errors.refundMethod ? errors.refundMethod : '' } /> </div> <div className="col-xs-4"> <Select placeholder="Reason Id" name="reasonId" multi options={dataReasonId} value={get( values, `reasonId.${FORM_DATA_SCHEMA.value}`, '' )} onChange={e => { const reasonId = e.target.value; this.handlePopulateReasonDetail( reasonId, handleChange, e ); }} error={!isEmpty(errors.reasonId)} helperText={errors.reasonId ? errors.reasonId : ''} disabled={dataReasonId.length === 0} /> </div> <div className="col-xs-4"> <div className="ReasonDetailId"> <div className={[ 'Container', reasonLoading || isEmpty(dataReasonDetail) ? 'disabled' : '' ].join(' ')} role="button" > <div className="Title">Reason Detail Id</div> <span className="Toggle Select-arrow" /> {isEmpty(dataReasonId) && ( <div className="EmptyReason"> Please choose <strong>Reason Id</strong> first </div> )} {reasonLoading && ( <div className="EmptyReason">Loading…</div> )} {!reasonLoading && !isEmpty(dataReasonDetail) && ( <ul className="Content"> {dataReasonDetail.map((row, idx) => ( <li key={`detail-${idx}`}> {idx + 1}. {row} </li> ))} </ul> )} </div> </div> </div> </div> <div className="row"> <div className="col-xs-6"> <TixDatePicker clearable value={this.state.dateOfIssuanceFromTemp} name="dateOfIssuanceFrom" label="Date of Issuance From" onChange={e => { handleChange(e); this.handleChangeDate( e, setError, 'dateOfIssuanceFrom', 'dateOfIssuanceTo' ); }} valueFormat="YYYY-MM-DD" helperText={errors.dateOfIssuanceFrom} disablePast={false} error={!isEmpty(errors.dateOfIssuanceFrom)} /> </div> <div className="col-xs-6"> <TixDatePicker clearable value={this.state.dateOfIssuanceToTemp} name="dateOfIssuanceTo" label="Date Of Issuance To" onChange={e => { handleChange(e); this.handleChangeDate( e, setError, 'dateOfIssuanceFrom', 'dateOfIssuanceTo' ); }} valueFormat="YYYY-MM-DD" helperText={errors.dateOfIssuanceTo} disablePast={false} minDate={ this.state.dateOfIssuanceFromTemp ? this.state.dateOfIssuanceFromTemp : '' } hasStartDate onError={errorMessage => { setError('dateOfIssuanceTo', errorMessage); }} error={!isEmpty(errors.dateOfIssuanceTo)} /> </div> </div> <div className="row"> <div className="col-xs-6"> <TixDatePicker clearable value={this.state.dateOfTravelFromTemp} name="dateOfTravelFrom" label="Date of Travel From" onChange={e => { handleChange(e); this.handleChangeDate( e, setError, 'dateOfTravelFrom', 'dateOfTravelTo' ); }} valueFormat="YYYY-MM-DD" helperText={errors.dateOfTravelFrom} disablePast={false} error={!isEmpty(errors.dateOfTravelFrom)} /> </div> <div className="col-xs-6"> <TixDatePicker clearable value={this.state.dateOfTravelToTemp} name="dateOfTravelTo" label="Date Of Travel To" onChange={e => { handleChange(e); this.handleChangeDate( e, setError, 'dateOfTravelFrom', 'dateOfTravelTo' ); }} valueFormat="YYYY-MM-DD" helperText={errors.dateOfTravelTo} disablePast={false} minDate={ this.state.dateOfTravelFromTemp ? this.state.dateOfTravelFromTemp : '' } hasStartDate onError={errorMessage => { setError('dateOfTravelTo', errorMessage); }} error={!isEmpty(errors.dateOfTravelTo)} /> </div> </div> <Head title="Penalty Matrices" TagHTML="h3" /> <Wrapper labelButton={'Matrices'} onClickAdd={() => { handleAddItem('penaltyMatrices', penaltyMatricTemplate); // Add error formulas this.setState({ errorFormulas: [...errorFormulas, null] }); }} > {values.penaltyMatrices.map((list, key) => { const errorRelationOperator = get( errors, `penaltyMatrices[${key}].relationOperator` ); const errorFormula = get( errors, `penaltyMatrices[${key}].formula` ); const errorCurrency = get( errors, `penaltyMatrices[${key}].currency` ); const errorTimeFrame = get( errors, `penaltyMatrices[${key}].timeFrame` ); const errorMinutes = get( errors, `penaltyMatrices[${key}].minutes` ); return ( <WrapperContent key={key} index={key} dataLength={values.penaltyMatrices.length} onClickRemove={() => { handleRemoveItem('penaltyMatrices', key); // Remove error formulas const errors = [...errorFormulas]; errors.splice(key, 1); this.setState({ errorFormulas: errors }); }} itemType="parent" isRemoveWrapper > <div className="row"> <div className="col-xs-1"> <div className="general-form__item--number"> {key + 1} </div> </div> <div className="col-xs-11"> <div className="row"> <div className="col-xs-4"> <Select placeholder="Relation Operator" name={`penaltyMatrices[${key}].relationOperator`} options={OPTION_RELATION_OPERATORS} value={get( list, `relationOperator.${FORM_DATA_SCHEMA.value}`, '' )} onChange={handleChange} error={!isEmpty(errorRelationOperator)} searchable={false} helperText={ errorRelationOperator ? errorRelationOperator : '' } /> <Select placeholder="Time Frame" name={`penaltyMatrices[${key}].timeFrame`} options={OPTION_TIME_FRAME} value={get( list, `timeFrame.${FORM_DATA_SCHEMA.value}`, '' )} onChange={handleChange} error={!isEmpty(errorTimeFrame)} helperText={ errorTimeFrame ? errorTimeFrame : '' } searchable={false} /> <TixField error={!isEmpty(errorCurrency)} id="currency" name={`penaltyMatrices[${key}].currency`} label="Currency" helperText={ errorCurrency ? errorCurrency : '' } margin="normal" onChange={handleChange} value={get( list, `currency.${FORM_DATA_SCHEMA.value}`, '' )} variant="outlined" /> <TixField type="number" error={!isEmpty(errorMinutes)} name={`penaltyMatrices[${key}].minutes`} id="minutes" label="Minutes" helperText={errorMinutes ? errorMinutes : ''} margin="normal" onChange={handleChange} value={get( list, `minutes.${FORM_DATA_SCHEMA.value}`, '' )} variant="outlined" /> </div> <div className="col-xs-8"> <MatrixCalculator style={{ marginTop: 16 }} error={errorFormula} formulaError={errorFormulas[key]} selected={get( list, `formula.${FORM_DATA_SCHEMA.value}`, '' )} onChange={value => this.handleFormulaChange( value, key, handleChange ) } onSubmit={value => this.handleValidateFormula(value, key) } /> </div> </div> </div> </div> </WrapperContent> ); })} </Wrapper> <Submit title="Submit" onSubmit={handleSubmit} /> </form> </Card> ); }} </Validator> ); } } export const mapStateToProps = () => ({}); const mapDispatchToProps = { setAlert, actionSetLoading }; export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Form));
Editor is loading...