Untitled
raw download clone
JAVASCRIPT
views 31
,
size 43455 b
{% extends "base.html" %}
{% load crispy_forms_tags compress widget_tweaks static %}

{% block title %}Add new expense{% endblock title %}

{% block head %}
<link href="{% static 'css/maps/leaflet.css' %}" rel="stylesheet" type="text/css">
<link href="{% static 'css/maps/style.css' %}" rel="stylesheet" type="text/css">
{% endblock %}

{% block content %}

<!-- /page header -->
<!-- Page header -->
<div class="page-header">
  <div class="breadcrumb-line"><a class="breadcrumb-elements-toggle">
      <ul class="breadcrumb">
        <li>
          <a href="/">
            <i class="icon-home2 position-left"></i> Dashboard
          </a>
        </li>
        <li class="active">Add new expense</li>
      </ul>

      <ul class="breadcrumb-elements">
        <li>
          <a href="mailto:support@reimbi.com" class="legitRipple">
            <i class="icon-comment-discussion position-left"></i> Support
          </a>
        </li>
      </ul>
  </div>
</div>
<!-- /page header -->

<div class="panel panel-flat col-md-12">
  <div class="panel-heading">
    <div class="heading-elements">
      <ul class="icons-list">
        <li><a data-action="collapse"></a></li>
      </ul>
    </div>
  </div>

  <div class="panel-body col-md-12">
    {% if form.errors %}
    {% for field in form %}
    {% for error in field.errors %}
    <div class="alert alert-danger">
      <strong>{{ field.name }} {{ error|escape }}</strong>
    </div>
    {% endfor %}
    {% endfor %}
    {% for error in form.non_field_errors %}
    <div class="alert alert-danger">
      <strong>{{ field.name }} {{ error|escape }}</strong>
    </div>
    {% endfor %}
    {% endif %}

    <form ref="update" v-cloak id="create-expense-form" class="form-horizontal col-md-5" method="post" enctype="multipart/form-data">
      {% csrf_token %}
      <fieldset>
        <div id="div_id_expense_type" class="form-group {% if form.expense_type.errors %}has-error{% endif %}">
          <label for="id_expense_type" class="control-label  requiredField">
            Expense type<span class="asteriskField">*</span>
          </label>
          <div class="controls">
            <select id="id_expense_type" v-model="expense_type" name="expense_type" class="form-control" required>
              <option value="">----------</option>
              {% for expense_type in expense_types %}
              <option value="{{ expense_type.expense_type }}"
                {% if form.data.expense_type == expense_type.expense_type %}selected="selected" {% endif %}>
                {{ expense_type.get_expense_type_display }}
              </option>
              {% endfor %}
            </select>
            {% if form.expense_type.errors %}
            <span id="error_1_{{ form.expense_type.auto_id }}"
              class="help-block"><strong>{{ form.expense_type.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

        <div id="div_id_from" v-show="milage" class="form-group {% if form.from.errors %}has-error{% endif %}">
          <label for="from" class="control-label ">
            From<span class="asteriskField">*</span>
          </label>
          <div class="controls ">
            <input autocomplete="off" type="text" :value="displayText(from)" id="from" name="from"
              {% comment %} value="{% if form.data.from %}{{ form.data.from }}{% endif %}" {% endcomment %}
              class="typeahead textinput textInput form-control {% if form.from.errors %}form-control-danger{% endif %}"
              :required="milage">
            {% if form.from.errors %}
            <span id="error_1_{{ form.from.auto_id }}"
              class="help-block"><strong>{{ form.from.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

        <div class="form-group form-group-float" v-show="milage && showVia1">
          <div class="form-group-feedback form-group-feedback-right">
            <input autocomplete="off" type="text" :value="displayText(via1)" id="via1" name="via1"
              {% comment %} value="{% if form.data.from %}{{ form.data.from }}{% endif %}" {% endcomment %}
              class="typeahead textinput textInput form-control" placeholder="Via">
            <div class="form-control-feedback pointer-events" @click="removeViaPoint('showVia1')">
              <i class="icon-cancel-circle2 mouse-pointer"></i>
            </div>
          </div>
        </div>

        <div class="form-group form-group-float" v-show="milage && showVia2">
          <div class="form-group-feedback form-group-feedback-right">
            <input autocomplete="off" type="text" :value="displayText(via2)" id="via2" name="via2"
              {% comment %} value="{% if form.data.from %}{{ form.data.from }}{% endif %}" {% endcomment %}
              class="typeahead textinput textInput form-control" placeholder="Via">
            <div class="form-control-feedback pointer-events" @click="removeViaPoint('showVia2')">
              <i class="icon-cancel-circle2 mouse-pointer"></i>
            </div>
          </div>
        </div>

        <div class="form-group form-group-float" v-show="milage && showVia3">
          <div class="form-group-feedback form-group-feedback-right">
            <input autocomplete="off" type="text" v-model="displayText(via3)" id="via3" name="via3"
              value="{% if form.data.from %}{{ form.data.from }}{% endif %}"
              class="typeahead textinput textInput form-control" placeholder="Via">
            <div class="form-control-feedback pointer-events" @click="removeViaPoint('showVia3')">
              <i class="icon-cancel-circle2 mouse-pointer"></i>
            </div>
          </div>
        </div>

        <div class="form-group form-group-float" v-show="milage && showVia4">
          <div class="form-group-feedback form-group-feedback-right">
            <input autocomplete="off" type="text" :value="displayText(via4)" id="via4" name="via4"
              {% comment %} value="{% if form.data.from %}{{ form.data.from }}{% endif %}" {% endcomment %}
              class="typeahead textinput textInput form-control" placeholder="Via">
            <div class="form-control-feedback pointer-events" @click="removeViaPoint('showVia4')">
              <i class="icon-cancel-circle2 mouse-pointer"></i>
            </div>
          </div>
        </div>

        <div id="div_id_destination" v-show="milage"
          class="form-group {% if form.destination.errors %}has-error{% endif %}">
          <label for="destination" class="control-label ">
            Destination<span class="asteriskField">*</span>
          </label>
          <div class="controls ">
            <input autocomplete="off" type="text" :value="displayText(destination)" id="destination" name="destination"
              {% comment %} value="{% if form.data.destination %}{{ form.data.destination }}{% endif %}" {% endcomment %}
              class="typeahead textinput textInput form-control {% if form.destination.errors %}form-control-danger{% endif %}"
              :required="milage">
            {% if form.destination.errors %}
            <span id="error_1_{{ form.destination.auto_id }}"
              class="help-block"><strong>{{ form.destination.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

        <div class="form-group" v-if="milage && viaNumber < 4">
          <button type="button" class="btn btn-primary" @click="addViaPoint">
            <i class="icon-plus-circle2 mr-2"></i> Add point
          </button>
        </div>

        <div class="form-group" v-show="milage">
          <div id="routing-map" style="cursor: default; height:400px; width: 100%;"></div>
        </div>

        <div id="div_id_miles" class="form-group {% if form.miles.errors %}has-error{% endif %}"
          v-show="decideToHide('miles')">
          <label for="id_miles" class="control-label ">
            Miles
          </label>
          <div class="controls ">
            <input type="text" v-model="sRoundTrip(metersToMiles(miles))" id="id_miles" name="miles"
              value="{% if form.data.miles %}{{ form.data.miles }}{% endif %}"
              class="form-control {% if form.miles.errors %}form-control-danger{% endif %}" readonly>
            {% if form.miles.errors %}
            <span id="error_1_{{ form.miles.auto_id }}"
              class="help-block"><strong>{{ form.miles.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

         <div id="div_id_miles" class="form-group {% if form.miles_rate.errors %}has-error{% endif %}"
          v-show="decideToHide('miles_rate')">
          <label for="id_miles" class="control-label ">
            Miles rate ([[policy_default_currency]])
          </label>
          <div class="controls ">
            <input type="text" v-model="miles_rate" id="miles_rate" name="miles_rate"
              value="{% if form.data.miles_rate %}{{ form.data.mildes_rate }}{% endif %}"
              class="form-control {% if form.miles_rate.errors %}form-control-danger{% endif %}" readonly>
            {% if form.miles_rate.errors %}
            <span id="error_1_{{ form.miles_rate.auto_id }}"
              class="help-block"><strong>{{ form.miles_rate.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

        <div id="div_id_miles" class="form-group {% if form.miles.errors %}has-error{% endif %}"
          v-show="decideToHide('kilometers')">
          <label for="id_miles" class="control-label ">
            Kilometers
          </label>
          <div class="controls ">
            <input type="text" v-model="isRoundTrip(metersToKilometers(kilometers))" id="kilometers" name="kilometers"
              value="{% if form.data.kilometers %}{{ form.data.kilometers }}{% endif %}"
              class="form-control {% if form.kilometers.errors %}form-control-danger{% endif %}" readonly>
            {% if form.kilometers.errors %}
            <span id="error_1_{{ form.kilometers.auto_id }}"
              class="help-block"><strong>{{ form.kilometers.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

         <div id="div_id_miles" class="form-group {% if form.kilometers_rate.errors %}has-error{% endif %}"
          v-show="decideToHide('kilometers_rate')">
          <label for="id_miles" class="control-label ">
            Kilometers rate ([[policy_default_currency]])
          </label>
          <div class="controls ">
            <input type="text" v-model="kilometers_rate" id="kilometers_rate" name="kilometers_rate"
              value="{% if form.data.kilometers_rate %}{{ form.data.mildes_rate }}{% endif %}"
              class="form-control {% if form.kilometers_rate.errors %}form-control-danger{% endif %}" readonly>
            {% if form.miles_rate.errors %}
            <span id="error_1_{{ form.kilometers_rate.auto_id }}"
              class="help-block"><strong>{{ form.kilometers_rate.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

        <input type="hidden" name="geocoordinates" id="id_geocoordinates" :value="hiddenInputData"/>

        <div id="div_round_trip" class="form-group {% if form.round_trip.errors %}has-error{% endif %}"
          v-show="decideToHide('round_trip')">
          <div class="row">
            <div class="col-md-6">
              <div class="controls">
                <div class="">
                  <input type="checkbox" v-model="round_trip" id="id_round_trip" name="round_trip"

                    class="{% if form.round_trip.errors %}form-control-danger{% endif %}">
                  <label for="round_trip">Round trip</label>
                </div>

                {% if form.round_trip.errors %}
                  <span id="error_1_{{ form.round_trip.auto_id }}" class="help-block"><strong>{{ form.round_trip.errors.0 }}</strong></span>
                {% endif %}
              </div>
            </div>
          </div>
        </div>

        <div id="div_id_meal_subtype" class="form-group {% if form.meal_subtype.errors %}has-error{% endif %}"
          v-if="decideToHideMealSubtype('meal_subtype')">
          <label for="id_meal_subtype" class="control-label ">
            Meal type
          </label>
          <div class="controls ">
            <select id="id_meal_subtype" name="meal_subtype" v-model="meal_subtypes" class="form-control">
              {% for subtype in meal_subtypes %}
              <option value="{{ subtype.0 }}" {% if form.data.meal_subtype == subtype.0 %}selected="selected"
                {% endif %}>
                {{ subtype.1 }}
              </option>
              {% endfor %}
            </select>
            {% if form.meal_subtype.errors %}
            <span id="error_1_{{ form.meal_subtype.auto_id }}"
              class="help-block"><strong>{{ form.meal_subtype.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

        <div id="div_id_nights" class="form-group {% if form.nights.errors %}has-error{% endif %}"
          v-if="decideToHide('nights')">
          <label for="id_nights" class="control-label ">
            # of nights
          </label>
          <div class="controls ">
            <input type="text" v-model="nights" id="id_nights" name="nights"
              value="{% if form.data.nights %}{{ form.data.nights }}{% endif %}"
              class="form-control {% if form.nights.errors %}form-control-danger{% endif %}" :required="!decideToHide('nights')">
            {% if form.nights.errors %}
            <span id="error_1_{{ form.nights.auto_id }}"
              class="help-block"><strong>{{ form.nights.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

        <div id="div_id_expense_date" class="form-group {% if form.expense_date.errors %}has-error{% endif %}">
          <label for="id_expense_date" class="control-label  requiredField">
            Expense Date<span class="asteriskField">*</span>
          </label>
          <div class="controls ">
            <input ref="pickadate" type="text" v-model="expense_date" id="id_expense_date" name="expense_date"
              value="{% if form.data.expense_date %}{{ form.data.expense_date }}{% endif %}"
              class="pickadate form-control {% if form.expense_date.errors %}form-control-danger{% endif %}" required>
            {% if form.expense_date.errors %}
            <span id="error_1_{{ form.expense_date.auto_id }}"
              class="help-block"><strong>{{ form.expense_date.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

        <div id="div_id_city_of_purchase" v-show="decideToShow('city_of_purchase')" class="form-group {% if form.city_of_purchase.errors %}has-error{% endif %}">
          <label for="city_of_purchase" class="control-label ">
            City of purchase*
          </label>
          <div class="controls ">
            <input autocomplete="off" type="text" v-model="city_of_purchase" id="city_of_purchase"
              name="city_of_purchase"
              value="{% if form.data.city_of_purchase %}{{ form.data.city_of_purchase }}{% endif %}"
              class="textinput textInput form-control {% if form.city_of_purchase.errors %}form-control-danger{% endif %}"
              :required="decideToShow('city_of_purchase')">
            {% if form.city_of_purchase.errors %}
            <span id="error_1_{{ form.city_of_purchase.auto_id }}"
              class="help-block"><strong>{{ form.city_of_purchase.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

        <div class="row">
          <div class="col-xs-7">
            <div id="div_id_amount" class="form-group {% if form.amount.errors %}has-error{% endif %}"
              :class="{ 'has-warning': warning }">
              <label for="id_amount" class="control-label  requiredField">
                Expense Amount<span class="asteriskField">*</span>
              </label>
              <div class="controls ">
                <input type="number" v-model="amount" @input="handleAmountChange" id="id_amount" name="amount"
                  value="{% if form.data.amount %}{{ form.data.amount }}{% endif %}"
                  class="form-control {% if form.amount.errors %}form-control-danger{% endif %}" required :readonly="milage">

                {% if form.amount.errors %}
                <span id="error_1_{{ form.amount.auto_id }}"
                  class="help-block"><strong>{{ form.amount.errors.0 }}</strong></span>
                {% endif %}
              </div>
            </div>
            <div class="form-text text-warning" v-if="warning">
              This expense exceeds the policy limit. Please ensure to explain the expense in the description for
              approval.
            </div>
          </div>

          <div class="col-xs-5">
            <div id="div_id_currency" class="form-group {% if form.currency.errors %}has-error{% endif %}">
              <label for="id_currency" class="control-label  requiredField">
                Currency<span class="asteriskField">*</span>
              </label>
              <div class="controls ">
                <select id="id_currency" name="currency" v-model="selected_currency" class="form-control" required :disabled="milage">
                  {% for currency in currencies %}
                  <option value="{{ currency.0 }}" {% if form.data.currency == currency.0 %}selected="selected"
                    {% endif %}>
                    {{ currency.0 }}
                  </option>
                  {% endfor %}
                </select>
                <input type="hidden" id="id_currency" name="currency" v-model="selected_currency"/>
                {% if form.currency.errors %}
                <span id="error_1_{{ form.currency.auto_id }}"
                  class="help-block"><strong>{{ form.currency.errors.0 }}</strong></span>
                {% endif %}
              </div>
            </div>
          </div>
        </div>

        <div id="div_id_description" class="form-group {% if form.description.errors %}has-error{% endif %}">
          <label for="id_description" class="control-label ">
            Description
          </label>
          <div class="controls ">
            <textarea value="{% if form.data.description %}{{ form.data.description }}{% endif %}" v-model="description" name="description" cols="40" rows="3" maxlength="200" class="textarea form-control {% if form.description.errors %}form-control-danger{% endif %}" id="id_description" spellcheck="false"></textarea>
            {% if form.description.errors %}
            <span id="error_1_{{ form.description.auto_id }}"
              class="help-block"><strong>{{ form.description.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

        <div id="div_id_vendor" v-show="decideToShow('vendor')" class="form-group {% if form.vendor.errors %}has-error{% endif %}">
          <label for="id_vendor" class="control-label ">
            Vendor*
          </label>
          <div class="controls">
            <input type="text" v-model="vendor" id="id_vendor" name="vendor"
              value="{% if form.data.vendor %}{{ form.data.vendor }}{% endif %}"
              class="form-control {% if form.vendor.errors %}form-control-danger{% endif %}" :required="decideToShow('vendor')">
            {% if form.vendor.errors %}
            <span id="error_1_{{ form.vendor.auto_id }}"
              class="help-block"><strong>{{ form.vendor.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>

        <div id="div_id_receipt" v-show="decideToShow('receipt')" class="form-group {% if form.receipt.errors %}has-error{% endif %}">
          <label for="id_receipt" class="control-label ">
            Receipt
          </label>
          <div class="controls ">
            <input type="file" id="id_receipt" name="receipt"
              value="{% if form.data.receipt %}{{ form.data.receipt }}{% endif %}"
              class="form-control {% if form.receipt.errors %}form-control-danger{% endif %}">
            {% if form.receipt.errors %}
            <span id="error_1_{{ form.receipt.auto_id }}"
              class="help-block"><strong>{{ form.receipt.errors.0 }}</strong></span>
            {% endif %}
          </div>
        </div>
      </fieldset>

      <div class="buttonHolder">
        <input :disabled="submitButtonDisabled" @submit.prevent="onSubmit" @click="submit" type="button" name="save" value="Save" class="btn btn-primary btn btn-primary" id="submit-id-save" />
        <input :disabled="submitButtonDisabled" @submit.prevent="onSubmit" @click="submit" type="button" name="save_and_add_another" value="Save and add another"
          class="btn btn-primary btn border-slate text-slate-800 btn-flat legitRipple"
          id="submit-id-save_and_add_another" />
          <input v-model="receipt_source" type="hidden" id="id_receipt_source" name="receipt_source"/>
      </div>
    </form>
  </div>
</div>
{% endblock %}

{% block extra_scripts %}
{% compress js %}

<script src="{% static 'js/maps/leaflet.js' %}"></script>
<script src="{% static 'js/maps/bouncemarker.js' %}"></script>
<script src="{% static 'js/maps/togeojson.js' %}"></script>
<script src="{% static 'js/maps/graphhopper-client.js' %}"></script>
<script src="{% static 'js/maps/leaflet-image.js' %}"></script>
<script src="{% static 'js/maps/easy_print.js' %}"></script>

<script>
  const meal_subtype_enabled = "{{ meal_subtype_enabled }}";
  const requester_type_policy_currency = "{{requester_type_policy_currency}}";
  const meal_amount_warning_limit = "{{ meal_amount_warning_limit }}";
  const meal_breakfast_amount_warning_limit = "{{ meal_breakfast_amount_warning_limit }}";
  const meal_lunch_amount_warning_limit = " {{ meal_lunch_amount_warning_limit }}";
  const meal_dinner_amount_warning_limit = " {{ meal_dinner_amount_warning_limit }}";
  const lodging_warning_limit = "{{ lodging_warning_limit }}";
  const requester_default_currency = "{{ form.data.currency }}" != "" ? "{{ form.data.currency }}" : "{{request.user.default_currency}}";
  const policy_default_currency = "{{requester_type_policy_currency}}";
  const expense_type = "{{ form.data.expense_type }}" != "" ? "{{ form.data.expense_type }}" : "{{ form.expense_type.initial|default_if_none:'' }}";
  const expense_date = "{{ form.data.expense_date }}" != "" ? "{{ form.data.expense_date }}" : "{{ form.expense_date.initial|date:'Y-m-d' }}";
  const amount = "{{ form.data.amount }}" != "" ? "{{ form.data.amount }}" : "{{ form.amount.initial|default_if_none:'' }}";
  const meal_subtypes = "{{ form.data.meal_subtype }}" != "" ? "{{ form.data.meal_subtype }}" : "{{ form.meal_subtype.initial|default_if_none:'' }}";
  const city_of_purchase = "{{ form.data.city_of_purchase }}" != "" ? "{{ form.data.city_of_purchase }}" : "{{ form.city_of_purchase.initial|default_if_none:'' }}";
  const vendor = "{{ form.data.vendor }}" != "" ? "{{ form.data.vendor }}" : "{{ form.vendor.initial|default_if_none:'' }}";
  const description = "{{ form.data.description }}" != "" ? "{{ form.data.description }}" : "{{ form.description.initial|default_if_none:'' }}";
  const nights = "{{ form.data.nights }}" != "" ? "{{ form.data.nights }}" : "{{ form.nights.initial|default_if_none:'' }}";
  const receipt = "{{ form.data.receipt }}";
  const miles_rate = "{{ mileage_rate }}";
  const kilometers_rate = "{{ mileage_kilometers }}";

  new Vue({
    delimiters: ['[[', ']]'],
    el: '#create-expense-form',
    data: function () {
      return {
        expense_type: expense_type,
        from: {},
        destination: {},
        viaNumber: 0,
        showVia1: false,
        via1: {},
        showVia2: false,
        via2: {},
        showVia3: false,
        via3: {},
        showVia4: false,
        via4: {},
        miles: null,
        kilometers: null,
        distance: null,
        routingLayer: null,
        routingMap: null,
        ghRouting: null,
        printPlugin: null,
        amount: amount,
        meal_subtypes: meal_subtypes,
        selected_currency: requester_default_currency,
        expense_date: expense_date,
        city_of_purchase: city_of_purchase,
        nights: nights,
        vendor: vendor,
        description: description,
        receipt: receipt,
        receipt_source: "",
        meal_subtype_enabled: meal_subtype_enabled,
        policy_default_currency: policy_default_currency,
        miles_rate: miles_rate,
        kilometers_rate: kilometers_rate,
        round_trip: false,
        warning: false,
        mapSizeChanged: false,
        submitButtonDisabled: false,
        tableOfTruth: {
          'meal_subtype': ['meals'],
          'nights': ['lodging'],
          'city_of_purchase': ['mileage', 'mileage_kilometers'],
          'receipt': ['mileage', 'mileage_kilometers'],
          'vendor': ['mileage', 'mileage_kilometers'],
          'miles': ['mileage'],
          'miles_rate': ['mileage'],
          'kilometers': ['mileage_kilometers'],
          'kilometers_rate': ['mileage_kilometers'],
          'round_trip': ['mileage', 'mileage_kilometers'],
        }
      }
    },
    computed: {
      hiddenInputData() {
        var data =
          {"from": JSON.parse(JSON.stringify(this.from)), "via1": JSON.parse(JSON.stringify(this.via1)), "via2": JSON.parse(JSON.stringify(this.via2)), "via3": JSON.parse(JSON.stringify(this.via3)), "via4": JSON.parse(JSON.stringify(this.via4)), "destination": JSON.parse(JSON.stringify(this.destination))};
        return JSON.stringify(data);
      },
      viaFields() {
        this.via1;
        this.via2;
        this.via3;
        this.via4;
        return Date.now();
      },
      milage() {
        return this.expense_type === 'mileage' || this.expense_type === 'mileage_kilometers';
      },
      allGeoCoordinates: function () {
        data = {
          'from': this.from,
          'destination': this.destination,
          'via1': this.via1,
          'via2': this.via2,
          'via3': this.via3,
          'via4': this.via4
        }
        return data
      },
    },
    mounted: function () {
      // maps
      var host; // = "http://localhost:9000/api/1";
      var defaultKey = '86890f06-716b-4809-a196-f2d65108f934';
      var profile = 'car';

      // create a routing client to fetch real routes, elevation.true is only supported for vehicle bike or foot
      this.ghRouting = new GraphHopper.Routing({ key: defaultKey, host: host, vehicle: profile, elevation: false });
      var ghGeocoding = new GraphHopper.Geocoding({
        key: defaultKey,
        host: host,
        limit: 8,
        locale: 'en'
      });

      var osmAttr = '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>';
      var omniscale = L.tileLayer.wms('https://maps.omniscale.net/v1/ghexamples-3646a190/tile', {
        layers: 'osm',
        attribution: osmAttr + ', &copy; <a href="http://maps.omniscale.com/">Omniscale</a>'
      });
      var osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: osmAttr
      });

      this.routingMap = L.map('routing-map', { layers: [ osm ], preferCanvas: true, zoomControl: false, scrollWheelZoom: false, doubleClickZoom: false});
      this.routingMap.setView([ 42.361145, -71.057083 ], 12);
      this.routingMap.invalidateSize(false);
      this.routingLayer = L.geoJson().addTo(this.routingMap);
      this.routingLayer.options = {
        style: { color: '#00cc33', weight: 5, opacity: 0.6 }
      };

      this.routingMap.invalidateSize(false);

      this.printPlugin = L.easyPrint({
        hidden: true,
        sizeModes: ['A4Portrait'],
        outputMode: 'event',
        filename: 'Miles 1400',
      }).addTo(this.routingMap);

      //jquery
      const self = this;

      $('.pickadate').pickadate({
        max: Date.now(),
        format: "yyyy-mm-dd",
        onSet: function () {
          self.expense_date = this.get('select', 'yyyy-mm-dd')
        }
      });

      $(".typeahead").typeahead({
        minLength: 3,
        highlight: true,
        source: function (query, process) {
          return $.get({
            url: '/api/place-autocomplete',
            rateLimitBy: 80,
            data: {
              'q': query
            }
          }, function (data) {
            return process(data.hits);
          });
        },
        matcher: function(item){
            return true;
        },
        displayText: function (item) {
          function insComma(textA, textB) {
            if (textA.length > 0)
                return textA + ", " + textB;
            return textB;
          }
          var text = "";
          if (item.name && text.indexOf(item.name) < 0) {
              text += item.name;
          }

          if (item.postcode)
              text = insComma(text, item.postcode);

          // make sure name won't be duplicated
          if (item.city && text.indexOf(item.city) < 0)
              text = insComma(text, item.city);

          if (item.state && text.indexOf(item.state) < 0)
              text = insComma(text, item.state);

          // if (item.country && text.indexOf(item.country) < 0)
          //     text = insComma(text, item.country);
          return text;
        },
        updater: function (item) {
          self[this.$element.context.id] = item
        },
      });

      $("#city_of_purchase").typeahead({
        source: function (query, process) {
          return $.get({
            url: '/expenses/~cities',
            data: {
              'q': query
            }
          }, function (data) {
            return process(data);
          });
        },
        updater: function (item) {
          self.city_of_purchase = item.name
        },
      });
    },
    methods: {
      setupRoutingAPI(map, ghRouting, points, routingLayer) {
        self = this;
        ghRouting.clearPoints();
        routingLayer.clearLayers();
        var points = points;

        if (Object.keys(points).length != 0) {
          if (points.from && points.from.point && points.from.point.lat && points.from.point.lng) {

            startPointMarker = L.marker(points.from.point, {bindTooltip: "Icon"}).addTo(routingLayer);
            ghRouting.addPoint(new GHInput(points.from.point.lat, points.from.point.lng));
          }

          if (points.via1 && points.via1.point && points.via1.point.lat && points.via1.point.lng) {
            L.marker(points.via1.point, {bindTooltip: "Icon"}).bindTooltip(self.displayText(points.via1),
            {
              permanent: true,
              direction: 'right'
            }).addTo(routingLayer);
            ghRouting.addPoint(new GHInput(points.via1.point.lat, points.via1.point.lng));
          }

          if (points.via2 && points.via2.point && points.via2.point.lat && points.via2.point.lng) {
            L.marker(points.via2.point, {bindTooltip: "Icon"}).bindTooltip(self.displayText(points.via2),
            {
              permanent: true,
              direction: 'right'
            }).addTo(routingLayer);
            ghRouting.addPoint(new GHInput(points.via2.point.lat, points.via2.point.lng));
          }

          if (points.via3 && points.via3.point && points.via3.point.lat && points.via3.point.lng) {
            L.marker(points.via3.point, {bindTooltip: "Icon"}).bindTooltip(self.displayText(points.via3),
            {
              permanent: true,
              direction: 'right'
            }).addTo(routingLayer);
            ghRouting.addPoint(new GHInput(points.via3.point.lat, points.via3.point.lng));
          }

          if (points.via4 && points.via4.point && points.via4.point.lat && points.via4.point.lng) {
            L.marker(points.via4.point, {bindTooltip: "Icon"}).bindTooltip(self.displayText(points.via4),
            {
              permanent: true,
              direction: 'right'
            }).addTo(routingLayer);
            ghRouting.addPoint(new GHInput(points.via4.point.lat, points.via4.point.lng));
          }

          if (points.destination && points.destination.point && points.destination.point.lat && points.destination.point.lng) {
            L.marker(points.destination.point, {bindTooltip: "Icon"}).bindTooltip(self.displayText(points.destination),
            {
              permanent: true,
              direction: 'right'
            }).addTo(routingLayer);
            ghRouting.addPoint(new GHInput(points.destination.point.lat, points.destination.point.lng));
          }
        }
        // routing request
        ghRouting
          .doRequest()
          .then(function(json) {
            var path = json.paths[0];
            routingLayer.addData({
              type: 'Feature',
              geometry: path.points
            });
            self.miles = path.distance;
            self.kilometers = path.distance;

            if (path.bbox) {
              var minLon = path.bbox[0];
              var minLat = path.bbox[1];
              var maxLon = path.bbox[2];
              var maxLat = path.bbox[3];
              var tmpB = new L.LatLngBounds(new L.LatLng(minLat, minLon), new L.LatLng(maxLat, maxLon));
              map.fitBounds(tmpB);

              // update start point marker
              current_kilometers = self.kilometers;
              current_miles = self.miles;
              if (self.expense_type == "mileage") {
                var totalDistance = self.metersToMiles(current_miles) + " miles"
              } else {
                var totalDistance = self.metersToKilometers(current_kilometers) + " kilometers"
              }
              tooltipText = "<b>Start point:</b> " + self.displayText(points.from) + "<br><b>Total distance:</b>" + " " + totalDistance;
                startPointMarker.bindTooltip(tooltipText,
                  {
                    permanent: true,
                    direction: 'right'
                })
                self.saveMapAsReceipt();
            }
          })
          .catch(function(err) {
            var str = 'An error occured: ' + err.message;
            $('#routing-response').text(str);
          });
      },
      insComma: function(textA, textB) {
          if (textA.length > 0)
              return textA + ", " + textB;
          return textB;
      },
      displayText: function (item) {
          var text = "";
          if (item.name && text.indexOf(item.name) < 0) {
              text += item.name;
          }

          if (item.postcode)
              text = this.insComma(text, item.postcode);

          // make sure name won't be duplicated
          if (item.city && text.indexOf(item.city) < 0)
              text = this.insComma(text, item.city);

          if (item.state && text.indexOf(item.state) < 0)
              text = this.insComma(text, item.state);

          // if (item.country && text.indexOf(item.country) < 0)
          //     text = insComma(text, item.country);
          return text;
      },
      saveMapAsReceipt() {
        this.printPlugin.printMap('A4Portrait page', 'Miles');
        self = this;
        this.routingMap.on('easyPrint-finished', e => {
            var reader = new window.FileReader();
            reader.readAsDataURL(e.event);
            reader.onloadend = function () {
                 base64data = reader.result;
                 self.receipt_source = base64data;
            }
        });
      },
      submit() {
          this.submitButtonDisabled = true;
          this.$refs.update.submit();
      },
      addViaPoint(viaPoint) {
        this[`showVia${this.viaNumber+1}`] = true;
        this.viaNumber++;
      },
      removeViaPoint(viaPoint) {
        this[viaPoint] = false;
        this.viaNumber--;
        this[`${viaPoint.slice(4,8).toLowerCase()}`] = {};
      },
      getCurrencyByCountryName(country_name) {
        if (country_name == 'United States') {
          return 'USD'
        } else if (country_name == 'Poland') {
          return 'PLN'
        } else if (country_name == 'Canada') {
          return 'CAD'
        } else if (country_name == 'China') {
          return 'CNY'
        } else if (country_name == 'Germany' || country_name == 'France') {
          return 'EUR'
        } else if (country_name == 'United Kingdom') {
          return 'GBP'
        } else if (country_name == 'Switzerland') {
          return 'CHF'
        } else if (country_name == 'Japan') {
          return 'JPY'
        } else if (country_name == 'Mexico') {
          return 'MXN'
        }
        return false
      },
      decideToHide(value) {
        return this.expense_type && this.tableOfTruth[value].includes(this.expense_type);
      },
      decideToHideMealSubtype(value) {
        return this.decideToHide(value) && meal_subtype_enabled === '1';
      },
      decideToShow(value) {
        return !this.decideToHide(value);
      },
      handleWarning(res, meal_type) {
        return res.then(resp => {
          const converted_amount = resp.data['converted_amount'];
          if (parseInt(converted_amount) > parseInt(meal_type) && parseInt(meal_type) !== 0) {
            this.warning = true;
          } else {
            this.warning = false;
          }
        });
      },
      handleAmountChange() {
        const req = `/expenses/~convert-warning-amount/?selected_currency=${this.selected_currency}&amount=${this.amount}&date=${this.expense_date}&limit_currency=${requester_type_policy_currency}`
        const res = this.$http.get(req);

        if (this.expense_type === 'meals' && meal_subtype_enabled === '0') {
          this.handleWarning(res, meal_amount_warning_limit)
        } else if (this.meal_subtypes === 'breakfast' && meal_subtype_enabled === '1') {
          this.handleWarning(res, meal_breakfast_amount_warning_limit)
        } else if (this.meal_subtypes === 'lunch' && meal_subtype_enabled === '1') {
          this.handleWarning(res, meal_lunch_amount_warning_limit)
        } else if (this.meal_subtypes === 'dinner' && meal_subtype_enabled === '1') {
          this.handleWarning(res, meal_dinner_amount_warning_limit)
        } else if (this.expense_type === 'lodging') {
          res.then(resp => {
            const converted_amount = resp.data['converted_amount'];
            const amount_limit = parseInt(lodging_warning_limit) * parseInt(this.nights);

            if (parseInt(converted_amount) > parseInt(amount_limit)) {
              this.warning = true;
            } else {
              this.warning = false;
            }
          });
        } else {
          this.warning = false;
        }
      },
      metersToMiles(val) {
        if (val) {
          return Math.round(val * 0.000621371192);
        } else {
          return ""
        }
      },
      metersToKilometers(val) {
        if (val) {
          return Math.round(val * 0.001);
        } else {
          return ""
        }
      },
      isRoundTrip(val) {
        if (this.round_trip) {
          return val * 2
        } else {
          return val
        }
      },
      clearAllFormFields() {
        this.distance = null;
        this.amount = null;
        this.nights = null;
        this.description = null;
      },
      calculateExpenseAmount: function() {
        var distance;
        var result;

        if (this.expense_type === 'mileage') {
          distance = this.metersToMiles(this.miles);
          result = distance * this.miles_rate;
        } else if (this.expense_type === 'mileage_kilometers') {
          distance = this.metersToKilometers(this.kilometers);
          result = distance * this.kilometers_rate;
        }

        if (this.round_trip) {
          result = result * 2;
        }

        var expense_date = this.expense_date;

        if (expense_date == null) {
          var today = new Date();
          var expense_date = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate();
        }
        const req = `/expenses/~convert-warning-amount/?selected_currency=${requester_type_policy_currency}&amount=${result}&date=${expense_date}&limit_currency=${requester_default_currency}`
        const res = this.$http.get(req);
        res.then(resp => {
          this.amount = resp.data['converted_amount'];
        });
      },
      setDateAndCalculateExpense: function() {
        this.setupRoutingAPI(this.routingMap, this.ghRouting, this.allGeoCoordinates, this.routingLayer);
        if (!this.expense_date) {
          var today = new Date();
          var dd = String(today.getDate()).padStart(2, '0');
          var mm = String(today.getMonth() + 1).padStart(2, '0');
          var yyyy = today.getFullYear();

          this.expense_date = yyyy + '-' + mm + '-' + dd;
        }
        this.calculateExpenseAmount();
      }
    },
    watch: {
      expense_type: function(val) {
        if (val === 'mileage' || val === 'mileage_kilometers') {
          if (!this.mapSizeChanged) {
            this.routingMap._onResize();
          }
          this.mapSizeChanged = true;
        }
        this.clearAllFormFields();
      },
      city_of_purchase: function (val) {
        const country = val.split(", ").pop();
        const currency = this.getCurrencyByCountryName(country);
        if (currency) {
          this.selected_currency = currency;
        }
      },
      from: function (val) {
        if (val && this.destination && this.destination.name) {
          this.setDateAndCalculateExpense();
          this.calculateExpenseAmount();
        }
      },
      destination: function (val) {
        if (val && this.from && this.from.name) {
          this.setDateAndCalculateExpense();
          this.calculateExpenseAmount();
        }
      },
      viaFields: function() {
        if (this.destination && this.from) {
          this.setDateAndCalculateExpense();
          this.calculateExpenseAmount();
        }
      },
      expense_date: function() {
        this.calculateExpenseAmount();
      },
      round_trip: function() {
        this.calculateExpenseAmount();
      },
      kilometers: function() {
        this.calculateExpenseAmount();
      },
      miles: function() {
        this.calculateExpenseAmount();
      }
    },
  });
</script>
{% endcompress %}
{% endblock extra_scripts %}
close fullscreen
Login or Register to edit or fork this paste. It's free.