diff --git a/src/components/GeoSearch.vue b/src/components/GeoSearch.vue
new file mode 100644
index 0000000..84e4e07
--- /dev/null
+++ b/src/components/GeoSearch.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+ No results found
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/IconPicker.vue b/src/components/IconPicker.vue
new file mode 100644
index 0000000..848d5f9
--- /dev/null
+++ b/src/components/IconPicker.vue
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+ {{ scope.opt.name }}
+
+
+
+
+
+
+
+
+
+ {{ scope.opt.name }}
+
+
+
+
+
+
+
+
+
diff --git a/src/components/LayerFab.vue b/src/components/LayerFab.vue
new file mode 100644
index 0000000..03a9b54
--- /dev/null
+++ b/src/components/LayerFab.vue
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+ Layers
+
+
+
+
+
+ Marker
+
+
+
+
+
+ Favorites
+
+
+
+
+
+ Routing
+
+
+
+
+
+ FindMy
+
+
+
+
+
+ Simulation Queue
+
+
+
+
+
diff --git a/src/components/LeafletTest.vue b/src/components/LeafletTest.vue
deleted file mode 100644
index f69c418..0000000
--- a/src/components/LeafletTest.vue
+++ /dev/null
@@ -1,1002 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Find My Location
-
-
-
-
- Sim Location
-
-
-
-
-
-
-
-
- Route Waypoints to SimQ
-
-
-
-
- Route to SimQ
-
-
-
-
- clearRoute
-
-
-
-
-
-
-
-
-
-
-
- Queue: {{ toTitleCase(simulationState) }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Zoom
-
-
- Delete
-
-
- Go Now
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Add Location
-
-
-
-
-
-
-
- Set Route Start
-
-
-
-
-
-
-
- Set Route End
-
-
-
-
-
- Set Favorite
-
-
-
-
-
- Clear Favorite
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Add Location
-
-
-
-
-
-
-
- Set Route Start
-
-
-
-
-
- Set Route End
-
-
-
-
- {{ findMyTimePast }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/components/LocateControl.vue b/src/components/LocateControl.vue
new file mode 100644
index 0000000..eaf2370
--- /dev/null
+++ b/src/components/LocateControl.vue
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/LocationItem.vue b/src/components/LocationItem.vue
index 9b5e4a6..540dd3c 100644
--- a/src/components/LocationItem.vue
+++ b/src/components/LocationItem.vue
@@ -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(() => {
{
:active="active"
@click="itemClicked"
:class="itemClass"
- active-class="text-orange bg-dark"
+ active-class="text-orange"
>
{{ latitude }}, {{ longitude }}
+ {{ instruction }}
{{ latitude }}, {{ longitude }}
-
+
start: {{ humanReadableDateTime(start) }}
-
+
end: {{ humanReadableDateTime(end) }}
@@ -389,7 +434,7 @@ onUnmounted(() => {
-
+
{{ calculateDeltaTime }}
diff --git a/src/components/MenuBar.vue b/src/components/MenuBar.vue
index ba380ed..d68a609 100644
--- a/src/components/MenuBar.vue
+++ b/src/components/MenuBar.vue
@@ -1,15 +1,14 @@
-
-
diff --git a/src/components/SetLocationDialog.vue b/src/components/SetLocationDialog.vue
index d5a19a7..b2c0d46 100644
--- a/src/components/SetLocationDialog.vue
+++ b/src/components/SetLocationDialog.vue
@@ -52,6 +52,7 @@
@@ -62,13 +63,15 @@
+
diff --git a/src/components/StatusBarFab.vue b/src/components/StatusBarFab.vue
new file mode 100644
index 0000000..7ee3c87
--- /dev/null
+++ b/src/components/StatusBarFab.vue
@@ -0,0 +1,222 @@
+
+
+
+
+
diff --git a/src/components/iCloudCodeDialog.vue b/src/components/iCloudCodeDialog.vue
index 1a330fd..19608a4 100644
--- a/src/components/iCloudCodeDialog.vue
+++ b/src/components/iCloudCodeDialog.vue
@@ -14,7 +14,7 @@
@keyup.enter="onOkClick"
label="Delay (seconds)"
type="number"
- :rules="[(val) => val.length === 6 || 'Must be 6 digits']"
+ :rules="[(val: string) => val.length === 6 || 'Must be 6 digits']"
/>