Source

components/location/TripHistoryDetails/TripHistoryDetails.vue

<template lang="pug">
.last_trip_history
  b-spinner(
      v-if="loading"
      class="loader"
      variant="info"
      style="width: 3rem; height: 3rem; margin: 0 auto; display:block;"
  )
  div(v-if="!loading && items.length===0") 
    .row
        .col-12
            .alert.alert-info.p-2 {{$t('location_module.no_results')}}
  .card.mb-2(style="border:0px" v-if="!loading && items.length>0")
    .card-header()
      .item.row(v-for="(item,index) in items" :key="item.id")
        .col-12
          .row.m-0
            .col-8.p-0.title
              | {{item.title}}
            .col-4.p-0.text-right()
              em.fas.fa-chevron-down(v-show="item.collapsed" @click="onToggle(item)")
              em.fas.fa-chevron-up(v-show="!item.collapsed" @click="onToggle(item)")
        .col-12
          .row.m-0
            .col-6.p-0
              p.label {{$t('common.Vitesse')}}: 
                span.value {{item.averageSpeed}} Km/h
            .col-6.p-0
              p.label {{$t('common.Distance')}}: 
                span.value {{item.tronconDistance | distanceMetersToKm}} Km
        .col-12.mt-2.node_table_modes_toolbar()
          LocationHistoryVehicleShapeExportButton(fontSize="18px")
          LocationExportKMLSingleButton(fontSize="18px")
          TableMapButton(
            @click="switchToTablePlusMapMode({bottom:'TripHistoryTable',top:'TripHistoryTableMap'})"
            :title="$t('location.history_tab.table_map_button')"
            icon="table-map"
          )
        .col-12(v-show="!item.collapsed")
          .card-body
            .step_group(v-for="(stepGroup) in item.steps" :key="stepGroup.stepNumber"
            @click="clickStep(stepGroup)"
              :class="{active:activeStepNumber == stepGroup.stepNumber}"
            )
              
              .step
                .step_nodes_wrapper
                  .step_number
                    .node_union_alt
                    .step_number_text {{$t('location_module.trip_step')}} {{stepGroup.stepNumber  }}
                  .step_nodes
                    .node_wrapper(v-for="(node, nodeIndex) in stepGroup.nodes" 
                    :key="node.id"
                    )
                      .node_union(v-show="nodeIndex>0")
                      .node
                        .node_icon(:class="{node_first: nodeIndex===0}")
                          img(v-if="node.type && !(['contact_off']).includes(node.type)" :class="'icon_'+node.type" :src="require(`./assets/node_type_${node.type}.svg`)")
                          ContactIcon(v-if="node.type==='contact_off'" :color="'var(--color-coral-red)'")
                          .node_union(style="" v-if="!isLastItemOfObject(lastItemOfTrip, node) || nodeIndex !== stepGroup.nodes.length -1")
                        .node_content
                          .node_date {{node.date}}
                          .node_label(v-show="node.label" v-html="node.label")
                          .node_from(v-show="node.fromAddress")  {{node.fromAddress}}
                .zoom_action(@click="handleItemZoom($event,stepGroup.stepNumber)")
                  em.fas.fa-search

</template>
<script>
import Vue from 'vue'
import moment from 'moment'
import ContactIcon from './ContactIcon'
import TableMapButton from '@c/shared/TableMapButton.vue'
import locationLayoutModesMixin from '@c/location/mixins/location-layout-modes.js'
import { mapGetters } from 'vuex'
import LocationHistoryVehicleShapeExportButton from '@c/location/LocationHistoryVehicleShapeExportButton.vue'
import LocationExportKMLSingleButton from '@c/location/LocationExportKMLSingleButton.vue'

/**
 * Used by
 * Main search - History by vehicle/driver - trip history tab
 * Main search - Real-time by [all] - trip history tab (last trip history)
 */
export default {
  name: 'TripHistoryDetails',
  components: {
    ContactIcon,
    TableMapButton,
    LocationHistoryVehicleShapeExportButton,
    LocationExportKMLSingleButton,
  },
  filters: {
    distanceMetersToKm: function (value) {
      return (value && (value / 1000).toFixed(2)) || ''
    },
  },
  mixins: [locationLayoutModesMixin],
  props: {
    item: {
      type: Object,
      default: () => ({}),
    },
  },
  data() {
    return {
      activeStepNumber: -1,
      loading: false,
      items: [],
    }
  },
  computed: {
    ...mapGetters({
      layout: 'app/layout',
      tripHistory: 'location_module/currentTripHistory',
    }),
    tripLength() {
      return (this.tripHistory || []).length
    },
    lastItemOfTrip() {
      return this.tripHistory[this.tripLength - 1]
    },
  },
  watch: {
    item: {
      async handler() {
        this.update()
      },
      deep: true,
    },
  },

  async mounted() {
    this.update()
  },
  destroyed() {
    this.$store.dispatch(
      'simpliciti_map/highlightTripHistoryPolylineSection',
      null
    )
  },
  methods: {
    handleItemZoom(e, stepNumber) {
      e.stopPropagation()

      this.$mitt.emit('SIMPLICITI_MAP__FLY_TO_POLYLINE', {
        stepNumber,
      })
    },
    isLastItemOfObject(obj, item) {
      if (!obj) {
        return false
      }
      let main = JSON.stringify(obj.number)
      let elem = JSON.stringify(item.step)
      return main === elem
    },
    clickStep(stepGroup) {
      if (this.activeStepNumber == stepGroup.stepNumber) {
        this.activeStepNumber = -1
        this.$store.dispatch(
          'simpliciti_map/highlightTripHistoryPolylineSection',
          null
        )
      } else {
        this.activeStepNumber = stepGroup.stepNumber

        this.$store.dispatch(
          'simpliciti_map/highlightTripHistoryPolylineSection',
          stepGroup.stepNumber
        )
      }
    },
    onToggle(item) {
      this.$set(item, 'collapsed', !item.collapsed)
    },
    async update() {
      if (this.item.id) {
        this.loading = true
        this.switchToListMode({
          mapComponent: 'TripHistoryMap',
        })
        this.items = await this.$store.dispatch(
          'location_module/getChartTripHistoryFromVehicleId',
          {
            id: this.item.id,
            date: this.item.date,
          }
        )
        this.$nextTick(() => (this.loading = false))
        this.$emit('onUpdate')
      }
    },
  },
}
</script>
<style lang="scss" scoped>
.node_table_modes_toolbar {
  display: flex;
  justify-content: flex-end;
  column-gap: 10px;
  align-items: center;
}
.title {
  font-size: 13px;
  font-weight: bold;
  color: var(--color-tundora);
}
.card-header {
  background: white;
  border-bottom: 0;
}
.item,
.item * {
  -webkit-user-select: none; /* Safari */
  -moz-user-select: none; /* Firefox */
  -ms-user-select: none; /* IE10+/Edge */
  user-select: none; /* Standard */
}
.card-body {
  padding: 0px;
}

.label {
  margin: 0px;
  color: var(--color-metal-rock);
}
.value {
  color: var(--color-tundora);
}
.label,
.value {
  font: normal normal normal 12px/18px Open Sans;
  letter-spacing: 0px;
}

.node,
.node_content {
  display: flex;
  justify-content: flex-start;
  align-items: center;
}
.node_content {
  flex-direction: column;
}
.node_date {
  width: -webkit-fill-available;
  color: #727272;
}
.node_icon {
  align-self: stretch;
  background: transparent;
}
.node_icon.node_first {
  align-self: stretch;
}
.node_content {
  color: var(--color-tundora);
  font: normal normal normal 12px/18px Open Sans;
  letter-spacing: 0px;
  margin-left: 10px;
}
.node_union {
  width: 4px;
  background-color: var(--color-dark-blue);
  height: calc(100% - 25px);
  margin-left: 10px;
}
.node_union_alt {
  width: 4px;
  background-color: var(--color-dark-blue);
  margin-left: 10px;
}
.icon_play,
.icon_flag {
  border: 2px solid var(--color-denim);
  border-radius: 50px;
  padding: 5px;
  height: 25px;
  width: 25px;
}
.fa-chevron-down,
.fa-chevron-up {
  cursor: pointer;
}
.step_group:hover,
.step_group.active {
  background: var(--color-wild-sand);
  cursor: pointer;
}
.zoom_action {
  opacity: 0;
}
.step_group:hover .zoom_action {
  opacity: 1;
}

.step {
  display: flex;
  align-items: center;
}
.step_nodes {
  display: flex;
  flex-direction: column;
}
.step_number {
  position: relative;
  display: flex;
}
.step_number_text {
  width: 100%;
  font-size: 13px;
  font-weight: bold;
  color: var(--color-tundora);
  text-align: center;
}
.step_group:not(:first-child) .step_number_text {
  margin-top: 20px;
}
</style>