milestones
This commit is contained in:
+136
-91
@@ -3,69 +3,42 @@ import { storeToRefs } from 'pinia';
|
||||
import { useSimulationStore } from 'stores/simulation';
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue';
|
||||
import type { NominatimResponse } from 'components/models';
|
||||
import { Icon, PinCirclePanel, PinStarPanel } from 'leaflet-extra-markers';
|
||||
import {
|
||||
Icon,
|
||||
PinCirclePanel,
|
||||
PinStarPanel,
|
||||
PointCircle,
|
||||
TackDiamondBorder,
|
||||
} from 'leaflet-extra-markers';
|
||||
|
||||
import FormattedAddress from 'components/FormattedAddress.vue';
|
||||
//import NestedKnob from 'components/NestedKnob.vue';
|
||||
|
||||
const simulationStore = useSimulationStore();
|
||||
const { currentLocation, locationQueueOrder, locationQueueData, simulationRunning } =
|
||||
storeToRefs(simulationStore);
|
||||
const {
|
||||
currentLocation,
|
||||
locationQueueOrder,
|
||||
locationQueueData,
|
||||
locationQueueDeletedItems,
|
||||
simulationRunning,
|
||||
} = storeToRefs(simulationStore);
|
||||
|
||||
const props = defineProps({
|
||||
address: {
|
||||
type: Object as () => NominatimResponse,
|
||||
required: false,
|
||||
},
|
||||
latitude: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
longitude: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'mdi-map-marker',
|
||||
},
|
||||
start: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
end: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
delay: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
active: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isCurrentDelay: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
loc_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isLast: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: 'queued',
|
||||
},
|
||||
});
|
||||
const props = defineProps<{
|
||||
address?: NominatimResponse | undefined;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
icon?: string;
|
||||
start: string;
|
||||
end?: string | undefined;
|
||||
delay: number;
|
||||
active: boolean;
|
||||
isCurrentDelay: boolean;
|
||||
loc_id: string;
|
||||
isLast: boolean;
|
||||
index: number;
|
||||
status?: string | undefined;
|
||||
type?: string | undefined;
|
||||
instruction?: string | undefined;
|
||||
}>();
|
||||
|
||||
// Define custom events that this component can emit
|
||||
const emit = defineEmits(['item-clicked']);
|
||||
@@ -75,6 +48,14 @@ function itemClicked() {
|
||||
emit('item-clicked', param1);
|
||||
}
|
||||
|
||||
const myData = computed(() => {
|
||||
return simulationStore.getLocationData(props.loc_id);
|
||||
});
|
||||
|
||||
const isDeleted = computed(() => {
|
||||
return myData.value.status === 'deleted' ? true : false;
|
||||
});
|
||||
|
||||
const currentTime = ref(new Date());
|
||||
let timerId: number;
|
||||
|
||||
@@ -103,7 +84,24 @@ function formatInAgo(seconds: number) {
|
||||
const calculateDeltaTime = computed(() => {
|
||||
let delta;
|
||||
if (props.active) {
|
||||
delta = 'now';
|
||||
const startTime = new Date(props.start);
|
||||
const nowMs: number = currentTime.value.getTime();
|
||||
const pastMs: number = startTime.getTime();
|
||||
const diffMs: number = Math.abs(nowMs - pastMs);
|
||||
const seconds: number = Math.floor(diffMs / 1000);
|
||||
const minutes: number = Math.floor(seconds / 60);
|
||||
const remainderSeconds: number = seconds % 60;
|
||||
const hours: number = Math.floor(minutes / 60);
|
||||
const days: number = Math.floor(hours / 24);
|
||||
if (days > 0) {
|
||||
delta = `for ${days} d${days > 1 ? 's' : ''}`;
|
||||
} else if (hours > 0) {
|
||||
delta = `for ${hours} h${hours > 1 ? 's' : ''}`;
|
||||
} else if (minutes > 0) {
|
||||
delta = `for ${minutes}:${remainderSeconds}`;
|
||||
} else {
|
||||
delta = `for ${seconds} s${seconds > 1 ? 's' : ''}`;
|
||||
}
|
||||
} else if (props.end && props.end !== '') {
|
||||
const pastTime: Date = new Date(props.end);
|
||||
const nowMs: number = currentTime.value.getTime();
|
||||
@@ -124,7 +122,7 @@ const calculateDeltaTime = computed(() => {
|
||||
}
|
||||
} else {
|
||||
let startSlice;
|
||||
if (currentIndex.value > 0) {
|
||||
if (currentIndex.value && currentIndex.value > 0) {
|
||||
startSlice = currentIndex.value;
|
||||
} else {
|
||||
startSlice = 0;
|
||||
@@ -175,15 +173,26 @@ const humanReadableDateTime = (iso: string) => {
|
||||
};
|
||||
|
||||
const currentIndex = computed(() => {
|
||||
return currentLocation.value ? locationQueueOrder.value.indexOf(currentLocation.value.loc_id) : 0;
|
||||
return currentLocation.value.loc_id
|
||||
? locationQueueOrder.value.indexOf(currentLocation.value.loc_id)
|
||||
: null;
|
||||
});
|
||||
|
||||
const myIndex = computed(() => {
|
||||
return locationQueueOrder.value.indexOf(props.loc_id);
|
||||
if (isDeleted.value) {
|
||||
return locationQueueDeletedItems.value.indexOf(props.loc_id);
|
||||
} else {
|
||||
return locationQueueOrder.value.indexOf(props.loc_id);
|
||||
}
|
||||
});
|
||||
|
||||
const myUpdatedIndex = computed(() => {
|
||||
return myIndex.value - currentIndex.value;
|
||||
if (isDeleted.value) {
|
||||
return myIndex.value + 1;
|
||||
} else {
|
||||
if (currentIndex.value === null) return myIndex.value + 1;
|
||||
return myIndex.value - currentIndex.value;
|
||||
}
|
||||
});
|
||||
|
||||
const itemClass = computed(() => {
|
||||
@@ -193,33 +202,66 @@ const itemClass = computed(() => {
|
||||
});
|
||||
|
||||
const customIcon = computed(() => {
|
||||
if (myUpdatedIndex.value > 0) {
|
||||
return new Icon({
|
||||
color: 'blue',
|
||||
accentColor: 'firebrick',
|
||||
content: myUpdatedIndex.value.toString(),
|
||||
contentColor: 'white',
|
||||
scale: 1,
|
||||
svg: PinCirclePanel,
|
||||
});
|
||||
} else if (myUpdatedIndex.value < 0) {
|
||||
if (myData.value.status === 'deleted') {
|
||||
return new Icon({
|
||||
color: 'black',
|
||||
accentColor: 'grey',
|
||||
accentColor: 'black',
|
||||
content: myUpdatedIndex.value.toString(),
|
||||
contentColor: 'white',
|
||||
scale: 1,
|
||||
svg: PinCirclePanel,
|
||||
svg: TackDiamondBorder,
|
||||
});
|
||||
} else {
|
||||
return new Icon({
|
||||
color: 'pink',
|
||||
accentColor: 'black',
|
||||
content: '*',
|
||||
contentColor: 'black',
|
||||
scale: 1,
|
||||
svg: PinStarPanel,
|
||||
});
|
||||
if (myUpdatedIndex.value > 0) {
|
||||
if (props.type === 'coord') {
|
||||
return new Icon({
|
||||
color: 'blue',
|
||||
accentColor: 'firebrick',
|
||||
content: myUpdatedIndex.value.toString(),
|
||||
contentColor: 'white',
|
||||
scale: 0.25,
|
||||
svg: PointCircle,
|
||||
});
|
||||
} else {
|
||||
return new Icon({
|
||||
color: 'blue',
|
||||
accentColor: 'firebrick',
|
||||
content: myUpdatedIndex.value.toString(),
|
||||
contentColor: 'white',
|
||||
scale: 1,
|
||||
svg: PinCirclePanel,
|
||||
});
|
||||
}
|
||||
} else if (myUpdatedIndex.value < 0) {
|
||||
if (props.type === 'coord') {
|
||||
return new Icon({
|
||||
color: 'black',
|
||||
accentColor: 'grey',
|
||||
content: myUpdatedIndex.value.toString(),
|
||||
contentColor: 'white',
|
||||
scale: 0.25,
|
||||
svg: PointCircle,
|
||||
});
|
||||
} else {
|
||||
return new Icon({
|
||||
color: 'black',
|
||||
accentColor: 'grey',
|
||||
content: myUpdatedIndex.value.toString(),
|
||||
contentColor: 'white',
|
||||
scale: 1,
|
||||
svg: PinCirclePanel,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return new Icon({
|
||||
color: 'pink',
|
||||
accentColor: 'black',
|
||||
content: '*',
|
||||
contentColor: 'black',
|
||||
scale: 1,
|
||||
svg: PinStarPanel,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -310,14 +352,16 @@ const delayInputMask = computed(() => {
|
||||
*/
|
||||
|
||||
const displayDelay = computed(() => {
|
||||
if (currentIndex.value === null) return true;
|
||||
return props.index > currentIndex.value;
|
||||
});
|
||||
|
||||
const delayActive = computed(() => {
|
||||
return props.index === currentIndex.value + 1;
|
||||
return props.index === currentIndex.value;
|
||||
});
|
||||
|
||||
const canDrag = computed(() => {
|
||||
if (currentIndex.value === null) return true;
|
||||
return props.index > currentIndex.value + 1;
|
||||
});
|
||||
|
||||
@@ -330,8 +374,8 @@ onUnmounted(() => {
|
||||
<q-item
|
||||
v-if="displayDelay"
|
||||
:active="delayActive"
|
||||
:class="delayActive ? 'text-orange bg-dark' : ''"
|
||||
active-class="text-orange bg-dark"
|
||||
:class="delayActive ? 'text-orange' : ''"
|
||||
active-class="text-orange"
|
||||
>
|
||||
<q-item-section class="flex flex-center">
|
||||
<q-input
|
||||
@@ -368,18 +412,19 @@ onUnmounted(() => {
|
||||
:active="active"
|
||||
@click="itemClicked"
|
||||
:class="itemClass"
|
||||
active-class="text-orange bg-dark"
|
||||
active-class="text-orange"
|
||||
>
|
||||
<q-item-section style="width: 70%">
|
||||
<q-item-label v-if="address">
|
||||
<FormattedAddress :address="props.address" />
|
||||
<q-tooltip> {{ latitude }}, {{ longitude }} </q-tooltip>
|
||||
</q-item-label>
|
||||
<q-item-label v-else-if="instruction" lines="2">{{ instruction }}</q-item-label>
|
||||
<q-item-label v-else> {{ latitude }}, {{ longitude }} </q-item-label>
|
||||
<q-item-label caption lines="1" v-if="start && simulationRunning">
|
||||
<q-item-label caption lines="1" v-if="start && simulationRunning && !isDeleted">
|
||||
start: {{ humanReadableDateTime(start) }}
|
||||
</q-item-label>
|
||||
<q-item-label caption lines="1" v-if="end && simulationRunning">
|
||||
<q-item-label caption lines="1" v-if="end && simulationRunning && !isDeleted">
|
||||
end: {{ humanReadableDateTime(end) }}
|
||||
</q-item-label>
|
||||
<q-item-label caption lines="1" v-if="!active && !end">
|
||||
@@ -389,7 +434,7 @@ onUnmounted(() => {
|
||||
<q-item-section
|
||||
side
|
||||
style="
|
||||
padding: 30px 0 0 10px;
|
||||
padding: 30px 0 0 0;
|
||||
height: 100%;
|
||||
width: 35%;
|
||||
display: flex;
|
||||
@@ -398,7 +443,7 @@ onUnmounted(() => {
|
||||
"
|
||||
>
|
||||
<q-icon :class="{ 'drag-handle': canDrag }" v-html="iconElement.outerHTML" />
|
||||
<q-item-label caption lines="1" v-if="simulationRunning">
|
||||
<q-item-label caption lines="1" v-if="simulationRunning && !isDeleted">
|
||||
{{ calculateDeltaTime }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
|
||||
Reference in New Issue
Block a user