<template lang="pug">
.circuit-execution-details(:class="{loading:loading}")
b-spinner(
v-if="loading"
class="loader"
variant="info"
style="width: 3rem; height: 3rem; margin: 0 auto; display:block;"
)
div(v-if="!loading && (!headInfos || !stepsInfos)")
.row
.col-12
.alert.alert-info.p-2 {{$t('location_module.no_results')}}
div(v-if="!loading && !!headInfos&&!!stepsInfos")
.head_infos(v-if="['circuit','driver'].includes(item.type)" style="justify-content: flex-start;")
.info_item
label.info_item_label Vehicle:
.info_item_value {{item.vehicleName}}
.info_item
//@TODO: If no active circuit, print the circuit name here
.head_infos(v-if="!!headInfos && headInfos.sameDay")
.info_item(v-show="headInfos.circuitName")
label.info_item_label {{$t('common.Circuit')}}:
.info_item_value {{headInfos.circuitName}}
.info_item()
label.info_item_label {{$t('common.date')}}:
.info_item_value {{headInfos.dateFrom}}
.info_item
label.info_item_label {{$t('common.debut')}}:
.info_item_value {{headInfos.timeFrom}}
.info_item()
label.info_item_label {{$t('common.fin')}}:
.info_item_value {{headInfos.timeTo}}
.head_infos(v-if="!!headInfos && !headInfos.sameDay")
.info_item
label.info_item_label {{$t('common.debut')}}:
.info_item_value {{headInfos.dateFrom}} {{headInfos.timeFrom}}
.info_item()
label.info_item_label {{$t('common.fin')}}:
.info_item_value {{headInfos.dateTo}} {{headInfos.timeTo}}
.head_infos(v-if="!!headInfos")
.info_item
label.info_item_label {{$t('common.distance')}}:
.info_item_value {{headInfos.distance}}Km
.info_item
label.info_item_label {{$t('common.Réalisation')}}:
.info_item_value {{headInfos.donePercentage}}%
.info_item
.steps_filter_wrapper()
CircuitExecutionStepsFilter(v-model="stepsFilter")
VerticalChart(v-if="!!stepsInfos" :nodes="stepsInfos"
@nodeclick="nodeclick"
@nodeclickright="nodeclickright"
:activeNodeId="activeNodeId"
)
template(v-slot:node_icon="slotProps")
NodeIcon(:color="slotProps.node.color")
template(v-slot:node_content="slotProps")
span(v-if="slotProps.node.date") {{slotProps.node.date}}
.row.m-0
.col-6.p-0
.label {{$t('location.details.circuit_tab.label_step_number')}} {{slotProps.node.id}}
.col-6.p-0
.label {{$t('location.details.circuit_tab.label_distance')}}:
span.value {{(slotProps.node.distance_theorique*1000).toFixed(2)}}m
.row.m-0
.col-12.p-0
.label {{$t('location.details.circuit_tab.label_action')}}:
span.value {{slotProps.node.activite_nom}}
.row.m-0
.col-6.p-0()
.label {{$t('location.details.circuit_tab.label_duration')}}:
span.value {{slotProps.node.duration}}
.col-6.p-0
.label {{$t('location.details.circuit_tab.label_done_perc')}}:
em.fa.fa-check(v-show="slotProps.node.realise" style="color:var(--color-silver-tree)")
em.fa.fa-times(v-show="!slotProps.node.realise" style="color:var(--color-coral-red)")
</template>
<script>
import Vue from 'vue'
import moment from 'moment'
import VerticalChart from '@c/shared/SearchResults/Submenu/VerticalChart.vue'
import NodeIcon from '@c/shared/SearchResults/Submenu/CircuitExecutionStepIcon.vue'
import TableButton from '@c/shared/TableButton.vue'
import MapIcon from '@c/shared/TableModesToolbar/MapIcon.vue'
import { formatSeconds } from '@/utils/dates.js'
import CircuitExecutionStepsFilter from '@c/shared/CircuitExecutionStepsFilter.vue'
import { createCircuitExecutionStepsFilter } from '@c/location/mixins/circuit-execution-mixin.js'
import { APIV2RequestDatetimeFormat } from '@/config/simpliciti-apis.js'
function getFormattedTimeFromApiDate(date) {
let m = moment(date, APIV2RequestDatetimeFormat)
return (m.isValid() && Vue.$date.formatTimeWithSeconds(m)) || '...'
}
/**
* Used by Circuit reference feature to render circuit execution details (List mode)
*
* Main search - history by circuit - circuit tab
* Main search - realtime by [all] - circuit tab (last circuit)
* @namespace components
* @category components
* @subcategory reference-circuit
* @module CircuitExecutionDetails
**/
export default {
name: 'CircuitExecutionDetails',
components: {
CircuitExecutionStepsFilter,
VerticalChart,
NodeIcon,
TableButton,
MapIcon,
},
props: {
/**
* selected item (From real-time/history search)
*/
item: {
type: Object,
default: () => ({}),
},
/**
* Used by: Location - History - Circuit tab - (Multiple circuit executions for the same vehicle)
*/
circuitDetailsFromAPI: {
type: Object,
default: () => null,
},
/**
* Used by: Location - History - Circuit tab - (Multiple circuit executions for the same vehicle)
*/
circuitExecutionStepsFromAPI: {
type: Object,
default: () => null,
},
loading: {
type: Boolean,
default: false,
},
},
data() {
return {
activeNodeId: null,
stepsFilter: 'EXECUTION',
}
},
computed: {
bottomProps() {
return {
circuitExecutionSteps: this.circuitExecutionSteps,
circuitDetails: this.circuitDetails,
}
},
circuitDetails() {
return this.circuitDetailsFromAPI
},
circuitExecutionSteps() {
return this.circuitExecutionStepsFromAPI
},
headInfos() {
const item = this.circuitDetails
return (
(item &&
!!item.circuit_id &&
Object.keys(item).length > 0 && {
circuitName: item.circuit_nom_court || '',
dateFrom: this.$date.formatDate(item.dateFrom),
timeFrom: getFormattedTimeFromApiDate(item.dateFrom),
dateTo: this.$date.formatDate(item.dateTo),
timeTo: getFormattedTimeFromApiDate(item.dateTo),
sameDay: moment(item.dateFrom).isSame(moment(item.dateTo), 'day'),
distance: item.lg_realisee_circuit || '...',
donePercentage: item.taux_realisation_circuit || '...',
}) ||
null
)
},
unfilteredStepsInfos() {
return (this.circuitExecutionSteps.troncons || []).map((t) =>
Object.freeze({
...t,
date: this.$date.formatTime(t.dateheure_debut, {
fallbackValue: '...',
}),
duration: formatSeconds(t.duree_sec),
color: t.realise ? t.activite_couleur || '#70BD95' : '#FF4545',
})
)
},
stepsInfos() {
return (
(this.unfilteredStepsInfos || []).filter(
createCircuitExecutionStepsFilter(this.stepsFilter)
) || []
)
},
},
destroyed() {
this.$store.dispatch(
'simpliciti_map/highlightCircuitExecPolylineSection',
null
)
},
methods: {
nodeclick(node) {
if (this.activeNodeId) {
this.activeNodeId = null
this.$emit('onUnhighlight')
return
}
this.$emit('onHighlight', {
stepNumber: node.id,
})
this.activeNodeId = node.id
},
nodeclickright({ event, node }) {
event.stopPropagation()
this.activeNodeId = node.id
this.$emit('onHighlightAndFlyToBounds', {
stepNumber: node.id,
})
},
},
}
</script>
<style lang="scss" scoped>
.circuit-execution-details {
max-height: 560px;
overflow: auto;
padding-bottom: 50px;
&.loading {
min-width: 230px;
display: flex;
justify-content: center;
align-items: center;
}
}
.info_item_value {
text-align: left;
font: normal normal normal 12px/18px Open Sans;
letter-spacing: 0px;
color: var(--color-tundora);
}
.info_item_label {
text-align: left;
font: normal normal normal 11px/18px Open Sans;
letter-spacing: 0px;
color: var(--color-metal-rock);
margin-right: 5px;
}
.info_item {
display: flex;
flex-grow: 1;
min-width: 41px;
}
.head_infos {
display: flex;
justify-content: flex-start;
column-gap: 5px;
margin: 0px 5px;
flex-wrap: wrap;
}
.toolbar {
display: flex;
justify-content: flex-end;
column-gap: 5px;
}
.node,
.node_content {
display: flex;
justify-content: flex-start;
align-items: center;
}
.node_content {
flex-direction: column;
}
.node_union {
width: 4px;
background-color: var(--color-dark-blue);
height: 1px;
margin-left: 10px;
}
.steps_filter_wrapper {
display: flex;
align-items: center;
}
</style>
Source