ministryofjustice/Claim-for-Crown-Court-Defence

View on GitHub
app/webpack/javascripts/modules/external_users/claims/DuplicateExpenseCtrl.js

Summary

Maintainability
A
0 mins
Test Coverage
moj.Modules.DuplicateExpenseCtrl = {
  el: '.mod-expenses',
  init: function () {
    this.$el = $(this.el)

    if (this.$el.length) {
      this.bindEvents()
    }
  },

  bindEvents: function () {
    const self = this

    this.$el.on('click', '.fx-duplicate-expense', function () {
      self.step1()
      // return false to stop the href;
      return false
    })

    $.subscribe('/step1/complete/', function (e, data) {
      self.step2(data)
    })
  },
  /**
   * Step 1 will scrape the DOM for the
   * models, format it into an object and
   * publish the data for use
   * @return {[type]} [description]
   */
  step1: function () {
    this.mapFormData().then(function (data) {
      $.publish('/step1/complete/', data)
    })
    return this
  },

  /**
   * Step 2 will click the add button and
   * fill in the models
   * @param  {Object} data Models for the new section
   * @return {[type]}      [description]
   */
  step2: function (data) {
    this.$el.find('.add_fields').trigger('click')
    this.populateNewItem(data)
    return this
  },

  /**
   * Here the new dom nodes are given their
   * values and the change events are fired
   * @param  {Object} data The model for the new section
   */
  populateNewItem: function (data) {
    const $el = $('.expense-group:last')
    // expense type & travel reasons + other & milage rates
    this.setSelectValue($el, '.fx-travel-expense-type select', data.expense_type_id)
    this.setSelectValue($el, '.fx-travel-reason select', data.reason_id, data.location_type)
    this.setSelectValue($el, '.fx-travel-reason-other input', data.reason_text)

    // amounts
    this.setInputValue($el, '.fx-travel-vat-amount input', data.vat_amount)
    this.setInputValue($el, '.fx-travel-net-amount input', data.amount)

    // Hours & distance
    this.setInputValue($el, '.fx-travel-hours', data.hours)
    this.setInputValue($el, '.fx-travel-distance input', data.distance)
    this.setInputValue($el, '.fx-travel-calculated-distance', data.calculated_distance)

    this.setInputValue($el, '.fx-travel-location input', data.location)

    // select the option by the data.location value
    $el.find('.fx-establishment-select select option').filter(function (idx, el) { // eslint-disable-line
      if ($(el).text() === data.location) {
        $(el).prop('selected', true)
      }
    })

    this.setRadioValue($el, '.fx-travel-mileage input', data.mileage_rate_id)

    // set focus state on '.remove_fields' within the new section
    $el.find('.remove_fields:last').trigger('focus')

    // trigger the side bar to recalculate all totals
    $('#claim-form').trigger('recalculate')
  },

  setRadioValue: function ($el, selector, val) {
    if (val) {
      $el.find(selector + '[id$=mileage_rate_id_' + val + ']').prop('checked', true).trigger('click')
    }
  },

  setSelectValue: function ($el, selector, val, locationType) {
    if (locationType) {
      $el.find(selector + ' option[data-location-type=' + locationType + ']').prop('selected', true)
      $el.find(selector).trigger('change')
      return
    }

    if (val) {
      $el.find(selector).val(val).trigger('change')
    }
  },

  setInputValue: function ($el, selector, val) {
    if (val) {
      $el.find(selector).val(val)
    }
  },

  /**
   * Get all the `input` & `select` elements and
   * serialise them into an array
   * @return {Array} Serialised form elements
   */
  getFormData: function () {
    return $('.expense-group:last').find('input,select').serializeArray()
  },

  /**
   * The format of the input is important
   * Here we break up the input name attr
   * and use the last value at the key
   * `<input name="this[is-the][0][modelname]" ../>`
   * @return {String}     the model name
   */
  getKeyName: function (obj) {
    if (obj.name.indexOf('][') === -1) {
      return obj.name
    }
    const str = obj.name.split('][').slice(2)[0]
    return str.substring(0, str.length - 1)
  },

  /**
   * Map the serialised data into an obj
   * @return {Object}   Key/Value pairs to
   * populate the duplicated expenses
   */
  mapFormData: function () {
    const deferred = $.Deferred()
    const self = this
    const data = {}
    $.map(this.getFormData(), function (obj, idx) {
      const str = self.getKeyName(obj)
      if (obj.value) {
        data[str] = obj.value
      }
    })
    deferred.resolve(data)
    return deferred.promise()
  }
};

(function ($) {
  $.fn.serializeFormJSON = function () {
    const o = {}
    const a = this.serializeArray()
    $.each(a, function () {
      if (o[this.name]) {
        if (!o[this.name].push) {
          o[this.name] = [o[this.name]]
        }
        o[this.name].push(this.value || '')
      } else {
        o[this.name] = this.value || ''
      }
    })
    return o
  }
})(jQuery)