diff --git a/eslint.config.js b/eslint.config.js index 8515d73..e924d18 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -39,6 +39,7 @@ export default defineConfigWithVueTs( files: ['**/*.ts', '**/*.vue'], rules: { '@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }], + 'vue/no-v-text-v-html-on-component': 'off' }, }, // https://github.com/vuejs/eslint-config-typescript diff --git a/package-lock.json b/package-lock.json index fe497d9..0a22d86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,8 @@ "hasInstallScript": true, "dependencies": { "@quasar/extras": "^1.16.4", + "@sentry/tracing": "^7.120.4", + "@sentry/vue": "^10.47.0", "@vue-leaflet/vue-leaflet": "^0.10.1", "axios": "^1.2.1", "leaflet": "^1.9.4", @@ -1961,6 +1963,212 @@ "win32" ] }, + "node_modules/@sentry-internal/browser-utils": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.47.0.tgz", + "integrity": "sha512-bVFRAeJWMBcBCvJKIFCMJ1/yQToL4vPGqfmlnDZeypcxkqUDKQ/Y3ziLHXoDL2sx0lagcgU2vH1QhCQ67Aujjw==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.47.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/browser-utils/node_modules/@sentry/core": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.47.0.tgz", + "integrity": "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.47.0.tgz", + "integrity": "sha512-pdvMmi4dQpX5S/vAAzrhHPIw3T3HjUgDNgUiCBrlp7N9/6zGO2gNPhUnNekP+CjgI/z0rvf49RLqlDenpNrMOg==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.47.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/feedback/node_modules/@sentry/core": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.47.0.tgz", + "integrity": "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.47.0.tgz", + "integrity": "sha512-ScdovxP7hJxgMt70+7hFvwT02GIaIUAxdEM/YPsayZBeCoAukPW8WiwztJfoKtsfPyKJ5A6f0H3PIxTPcA9Row==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "10.47.0", + "@sentry/core": "10.47.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.47.0.tgz", + "integrity": "sha512-A5OY8friSe6g8WAK4L8IeOPiEd9D3Ps40DzRH5j2f6SUja0t90mKMvHRcRf8zq0d4BkdB+JM7tjOkwxpuv8heA==", + "license": "MIT", + "dependencies": { + "@sentry-internal/replay": "10.47.0", + "@sentry/core": "10.47.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay-canvas/node_modules/@sentry/core": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.47.0.tgz", + "integrity": "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay/node_modules/@sentry/core": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.47.0.tgz", + "integrity": "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/tracing": { + "version": "7.120.4", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.120.4.tgz", + "integrity": "sha512-Fz5+4XCg3akeoFK+K7g+d7HqGMjmnLoY2eJlpONJmaeT9pXY7yfUyXKZMmMajdE2LxxKJgQ2YKvSCaGVamTjHw==", + "license": "MIT", + "dependencies": { + "@sentry/core": "7.120.4", + "@sentry/types": "7.120.4", + "@sentry/utils": "7.120.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/browser": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.47.0.tgz", + "integrity": "sha512-rC0agZdxKA5XWfL4VwPOr/rJMogXDqZgnVzr93YWpFn9DMZT/7LzxSJVPIJwRUjx3bFEby3PcTa3YaX7pxm1AA==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "10.47.0", + "@sentry-internal/feedback": "10.47.0", + "@sentry-internal/replay": "10.47.0", + "@sentry-internal/replay-canvas": "10.47.0", + "@sentry/core": "10.47.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/browser/node_modules/@sentry/core": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.47.0.tgz", + "integrity": "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/core": { + "version": "7.120.4", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.120.4.tgz", + "integrity": "sha512-TXu3Q5kKiq8db9OXGkWyXUbIxMMuttB5vJ031yolOl5T/B69JRyAoKuojLBjRv1XX583gS1rSSoX8YXX7ATFGA==", + "license": "MIT", + "dependencies": { + "@sentry/types": "7.120.4", + "@sentry/utils": "7.120.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/tracing": { + "version": "7.120.4", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.120.4.tgz", + "integrity": "sha512-cAtpLh23qW3hoqZJ6c36EvFki5NhFWUSK71ALHefqDXEocMlfDc9I+IGn3B/ola2D2TDEDamCy3x32vctKqOag==", + "license": "MIT", + "dependencies": { + "@sentry-internal/tracing": "7.120.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/types": { + "version": "7.120.4", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.120.4.tgz", + "integrity": "sha512-cUq2hSSe6/qrU6oZsEP4InMI5VVdD86aypE+ENrQ6eZEVLTCYm1w6XhW1NvIu3UuWh7gZec4a9J7AFpYxki88Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/utils": { + "version": "7.120.4", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.120.4.tgz", + "integrity": "sha512-zCKpyDIWKHwtervNK2ZlaK8mMV7gVUijAgFeJStH+CU/imcdquizV3pFLlSQYRswG+Lbyd6CT/LGRh3IbtkCFw==", + "license": "MIT", + "dependencies": { + "@sentry/types": "7.120.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/vue": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-10.47.0.tgz", + "integrity": "sha512-zIscc2e1d70yGK4qi4nqBy87TaQBKy0aXza+PtxI9qUWelF4bw0SJoVSglbISw+eOO4y0CBxZVRibLuj0Kv1pw==", + "license": "MIT", + "dependencies": { + "@sentry/browser": "10.47.0", + "@sentry/core": "10.47.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@tanstack/vue-router": "^1.64.0", + "pinia": "2.x || 3.x", + "vue": "2.x || 3.x" + }, + "peerDependenciesMeta": { + "@tanstack/vue-router": { + "optional": true + }, + "pinia": { + "optional": true + } + } + }, + "node_modules/@sentry/vue/node_modules/@sentry/core": { + "version": "10.47.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.47.0.tgz", + "integrity": "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", diff --git a/package.json b/package.json index 4217d43..ed199dd 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,8 @@ }, "dependencies": { "@quasar/extras": "^1.16.4", + "@sentry/tracing": "^7.120.4", + "@sentry/vue": "^10.47.0", "@vue-leaflet/vue-leaflet": "^0.10.1", "axios": "^1.2.1", "leaflet": "^1.9.4", diff --git a/quasar.config.ts b/quasar.config.ts index c77270e..1b22535 100644 --- a/quasar.config.ts +++ b/quasar.config.ts @@ -124,7 +124,7 @@ export default defineConfig((/* ctx */) => { '/api': { target: 'http://localhost:49151', changeOrigin: true, - rewrite: (path) => path.replace(/^\/api/, ''), + // rewrite: (path) => path.replace(/^\/api/, ''), }, '/socket.io': { target: 'http://localhost:49151', // Your backend WebSocket server @@ -134,24 +134,15 @@ export default defineConfig((/* ctx */) => { changeOrigin: true, // rewrite: (path) => path.replace(/^\/socket.io/, ''), }, - '/osm': { - target: 'https://nominatim.openstreetmap.org', - changeOrigin: true, - rewrite: (path) => path.replace(/^\/osm/, ''), - headers: { - Referer: 'https://nominatim.openstreetmap.org/', - 'User-Agent': 'map-sim-location/0.0.1 (iam@williambr.uno)', - }, - }, '/ors': { -// target: 'https://router.project-osrm.org', + // target: 'https://router.project-osrm.org', target: 'http://localhost:8080', changeOrigin: true, -// rewrite: (path) => path.replace(/^\/osrm/, ''), -// headers: { -// Referer: 'https://router.project-osrm.org/', -// 'User-Agent': 'map-sim-location/0.0.1 (iam@williambr.uno)', -// }, + // rewrite: (path) => path.replace(/^\/osrm/, ''), + // headers: { + // Referer: 'https://router.project-osrm.org/', + // 'User-Agent': 'map-sim-location/0.0.1 (iam@williambr.uno)', + // }, }, }, }, diff --git a/src/axios.ts b/src/axios.ts deleted file mode 100644 index 304110a..0000000 --- a/src/axios.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { defineBoot } from '#q-app/wrappers'; -import axios, { type AxiosInstance } from 'axios'; - -declare module 'vue' { - interface ComponentCustomProperties { - $axios: AxiosInstance; - $api: AxiosInstance; - } -} - -// Be careful when using SSR for cross-request state pollution -// due to creating a Singleton instance here; -// If any client changes this (global) instance, it might be a -// good idea to move this instance creation inside of the -// "export default () => {}" function below (which runs individually -// for each client) -const api = axios.create({ baseURL: 'http://localhost:5000/api' }); - -export default defineBoot(({ app }) => { - // for use inside Vue files (Options API) through this.$axios and this.$api - - app.config.globalProperties.$axios = axios; - // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form) - // so you won't necessarily have to import axios in each vue file - - app.config.globalProperties.$api = api; - // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form) - // so you can easily perform requests against your app's API -}); - -export { api }; diff --git a/src/boot/sentry.ts b/src/boot/sentry.ts new file mode 100644 index 0000000..132b62b --- /dev/null +++ b/src/boot/sentry.ts @@ -0,0 +1,18 @@ +import { defineBoot } from '#q-app/wrappers' +import * as Sentry from '@sentry/vue'; + +export default defineBoot(({ app }) => { + Sentry.init({ + app, + dsn: "https://c117cc7eee3a88df9d289edc77d57c60@o4511152447553536.ingest.us.sentry.io/4511152493559808", + sendDefaultPii: true, + enableLogs: true, + integrations: [ + Sentry.browserTracingIntegration(), + Sentry.replayIntegration() + ], + tracesSampleRate: 1.0, + replaysSessionSampleRate: 0.1, + replaysOnErrorSampleRate: 1.0, + }); +}) diff --git a/src/components/FormattedAddress.vue b/src/components/FormattedAddress.vue new file mode 100644 index 0000000..8603eab --- /dev/null +++ b/src/components/FormattedAddress.vue @@ -0,0 +1,102 @@ + + + diff --git a/src/components/L.Routing.OpenRouteServiceV2.ts b/src/components/L.Routing.OpenRouteServiceV2.ts index 780bbb7..119f0f4 100644 --- a/src/components/L.Routing.OpenRouteServiceV2.ts +++ b/src/components/L.Routing.OpenRouteServiceV2.ts @@ -245,7 +245,6 @@ export class OpenRouteServiceV2 extends L.Class { /** * Leaflet factory function (typed) - * Attach to L.Routing.openrouteserviceV2 so that it's callable as L.Routing.openrouteserviceV2 */ export function openrouteserviceV2( apiKeyOrOptions: string | ORSRequestOptions, @@ -264,15 +263,5 @@ export function openrouteserviceV2( ); } -type LeafletWithRouting = typeof L & { - Routing?: { - openrouteserviceV2?: typeof openrouteserviceV2; - [key: string]: unknown; - }; -}; - -const leafletWithRouting = L as LeafletWithRouting; -if (!leafletWithRouting.Routing) { - leafletWithRouting.Routing = {}; -} -leafletWithRouting.Routing.openrouteserviceV2 = openrouteserviceV2; +// Do not mutate the ESM namespace import (`import * as L`) because it is non-extensible +// in production bundles. Consumers should import and use `openrouteserviceV2` directly. diff --git a/src/components/LeafletTest.vue b/src/components/LeafletTest.vue index 948722d..4c57b56 100644 --- a/src/components/LeafletTest.vue +++ b/src/components/LeafletTest.vue @@ -108,18 +108,41 @@ :lat-lng="safeMarkerLatLng" @click="handleMarkerClick" > - - - - + + + + + + Add Location - - + + + + Set Route Start - - + + + + Set Route End @@ -186,7 +209,7 @@ import LRoutingMachine from 'components/LRoutingMachine.vue'; import LocationMark from 'components/LocationMark.vue'; import SetLocationDialog from 'components/SetLocationDialog.vue'; import { customRouter } from 'functions/serviceURL'; -import { reverseGeocodeRateLimited } from 'functions/reverseGeocode'; +//import { reverseGeocodeRateLimited } from 'functions/reverseGeocode'; import { useRoutingEvents } from '../composables/useRoutingEvents'; import { useMarkerContextMenu } from '../composables/useMarkerContextMenu'; import type { IRouter } from 'leaflet-routing-machine'; @@ -195,8 +218,7 @@ import type { IRouter } from 'leaflet-routing-machine'; import type { coords, SearchControlProps, - NominatimAddress, - routeSegments, + // NominatimAddress, } from 'components/models'; import type { LeafletMouseEvent, Map } from 'leaflet'; @@ -208,7 +230,7 @@ import { useLeafletStore } from 'stores/leaflet'; import { favorites } from 'constants/favorites'; const leafletStore = useLeafletStore(); -const { zoom, center, markerLatLng, qLocDrawer, routeSet, routeSegments } = +const { zoom, center, markerLatLng, qLocDrawer, routeSet, routeDirections } = storeToRefs(leafletStore); const socketStore = useSocketioStore(); @@ -226,7 +248,6 @@ const $q = useQuasar(); const mapRef = ref(); const responseMessage = ref(''); const miniState = ref(true); -const loading = ref(false); const safeCenter = computed<[number, number]>(() => { const lat = center.value?.[0]; const lng = center.value?.[1]; @@ -320,25 +341,54 @@ function updateMarker(event: LeafletMouseEvent) { center.value = [event.latlng.lat, event.latlng.lng]; } -function routeToQueue() { - console.log('routeToQueue'); - if (routeSet.value.start && routeSet.value.end && routeSegments.value) { - console.log('routeToQueue: start: ', routeSet.value.start); - setLocation({ lat: routeSet.value.start.lat, lng: routeSet.value.start.lng }, 0); - routeSegments.value.forEach((segment: routeSegments) => { - console.log('routeToQueue: segment: ', segment); - setLocation( - { lat: segment.toCoordinates.lat, lng: segment.toCoordinates.lng }, - segment.timeSeconds, - ); - }); - console.log('routeToQueue: end: ', routeSet.value.end); - setLocation({ lat: routeSet.value.end.lat, lng: routeSet.value.end.lng }, 0); +function closeAllPopups() { + if (mapRef.value) { + // Access the Leaflet map instance directly + mapRef.value.leafletObject.closePopup(); } } +const delay = (ms: number) => new Promise((res) => setTimeout(res, ms)); + +async function routeToQueue() { + if (routeSet.value.start && routeSet.value.end && routeDirections) { + if (routeDirections.value && routeDirections.value.length > 0) { + for (const direction of routeDirections.value) { + if (direction.coordinates) { + await setLocation( + { lat: Number(direction.coordinates.lat), lng: Number(direction.coordinates.lng) }, + direction.time, + ); + } + await delay(1000); + } + } + } +} +/* function routeToQueue() { + console.log('routeToQueue'); + if (routeSet.value.start && routeSet.value.end && routeSegments) { + console.log('routeToQueue: start: ', routeSet.value.start); + setLocation( + { lat: Number(routeSet.value.start.lat), lng: Number(routeSet.value.start.lng) }, + 0, + ); + if (routeSegments.value) { + routeSegments.value.forEach((segment: routeSegments) => { + console.log('routeToQueue: segment: ', segment); + setLocation( + { lat: Number(segment.toCoordinates.lat), lng: Number(segment.toCoordinates.lng) }, + segment.timeSeconds, + ); + }); + } + console.log('routeToQueue: end: ', routeSet.value.end); + setLocation({ lat: Number(routeSet.value.end.lat), lng: Number(routeSet.value.end.lng) }, 0); + } +} + */ function clearRoute() { - routeSegments.value = []; + void leafletStore.clearRouteSegments; routingOptions.waypoints = []; routeSet.value.start = { lat: null, lng: null }; routeSet.value.end = { lat: null, lng: null }; @@ -362,47 +412,49 @@ const updateRoute = () => { const { clickedLatLng, handleMarkerClick, setStartRoute, setEndRoute } = useMarkerContextMenu( routeSet, updateRoute, + closeAllPopups, ); function handleAddLocation() { if (clickedLatLng.value) { const latlng = clickedLatLng.value; + closeAllPopups(); $q.notify(`add location...${latlng.toString()}`); - reverseGeocode(latlng.lat, latlng.lng) - .then((data) => { - const NomAddress = data.address as unknown as NominatimAddress; - $q.dialog({ - component: SetLocationDialog, - componentProps: { - lat: Number(latlng.lat), - lng: Number(latlng.lng), - address: NomAddress, - }, - }) - .onOk((delay: number) => { - void setLocation({ lat: Number(latlng.lat), lng: Number(latlng.lng) }, delay); - console.log( - 'Confirmed location add: latitude: ' + - latlng.lat + - ', longitude: ' + - latlng.lng + - ', delay: ' + - delay, - ); - }) - .onCancel(() => { - console.log('Dialog cancelled'); - }) - .onDismiss(() => { - console.log('Dialog dismissed'); - }); + // reverseGeocode(latlng.lat, latlng.lng) + // .then((data) => { + // const NomAddress = data.address as unknown as NominatimAddress; + $q.dialog({ + component: SetLocationDialog, + componentProps: { + lat: Number(latlng.lat), + lng: Number(latlng.lng), + // address: NomAddress, + }, + }) + .onOk((delay: number) => { + void setLocation({ lat: Number(latlng.lat), lng: Number(latlng.lng) }, delay); + console.log( + 'Confirmed location add: latitude: ' + + latlng.lat + + ', longitude: ' + + latlng.lng + + ', delay: ' + + delay, + ); }) - .catch((error) => { - console.error('Error fetching reverse geocode:', error); + .onCancel(() => { + console.log('Dialog cancelled'); + }) + .onDismiss(() => { + console.log('Dialog dismissed'); }); + // }) + // .catch((error) => { + // console.error('Error fetching reverse geocode:', error); + // }); } } - +/* async function reverseGeocode(lat: number, lng: number) { loading.value = true; try { @@ -416,29 +468,36 @@ async function reverseGeocode(lat: number, lng: number) { loading.value = false; } } +*/ -function setLocation(coords: coords, delay: number) { - let notType: string = 'positive'; - try { - const setCmdRsp = socketStore.simulationControl('add', delay, coords.lat, coords.lng); - if (setCmdRsp.sts === 'error') { +async function setLocation(coords: coords, delay: number) { + return new Promise((resolve, reject) => { + let notType: string = 'positive'; + try { + const setCmdRsp = socketStore.simulationControl('add', delay, coords.lat, coords.lng); + if (setCmdRsp.msg) { + responseMessage.value = setCmdRsp.msg; + } + if (setCmdRsp.sts === 'error') { + notType = 'negative'; + reject(new Error(setCmdRsp.msg || 'Unknown error')); + } + resolve(setCmdRsp); + } catch (error: unknown) { notType = 'negative'; + if (error instanceof Error) { + console.error('Error setting location:', error.message); + responseMessage.value = `Failed to set location: ${error.message}`; + reject(error); + } else { + console.error('Error setting location:', error); + responseMessage.value = `Failed to set location: Unknown error`; + reject(new Error('Unknown error')); + } + } finally { + $q.notify({ type: notType, message: responseMessage.value }); } - if (setCmdRsp.msg) { - responseMessage.value = setCmdRsp.msg; - } - } catch (error: unknown) { - notType = 'negative'; - if (error instanceof Error) { - console.error('Error setting location:', error.message); - responseMessage.value = `Failed to set location: ${error.message}`; - } else { - console.error('Error setting location:', error); - responseMessage.value = `Failed to set location: Unknown error`; - } - } finally { - $q.notify({ type: notType, message: responseMessage.value }); - } + }); } function zoomToCoods(arg: string) { @@ -507,4 +566,9 @@ onMounted(() => { .leafletDrawer background-color: $dark color: $dark + +.marker-popup .leaflet-popup-content-wrapper, .marker-popup .leaflet-popup-tip + background-color: $dark +.marker-popup .leaflet-popup-content + margin: 13px 10px 13px 10px diff --git a/src/components/LocationMark.vue b/src/components/LocationMark.vue index 4b13990..bd8fa65 100644 --- a/src/components/LocationMark.vue +++ b/src/components/LocationMark.vue @@ -2,15 +2,18 @@ import { storeToRefs } from 'pinia'; import { useSocketioStore } from 'stores/socketio'; import { computed, onMounted, onUnmounted, ref } from 'vue'; +import type { NominatimResponse } from 'components/models'; import { Icon, PinCirclePanel } from 'leaflet-extra-markers'; +import FormattedAddress from 'components/FormattedAddress.vue'; + const socketStore = useSocketioStore(); const { currentLocation, locationQueueOrder, simulationRunning } = storeToRefs(socketStore); const props = defineProps({ address: { - type: String, + type: Object as () => NominatimResponse, required: true, }, latitude: { @@ -52,7 +55,7 @@ const props = defineProps({ index: { type: Number, default: 0, - } + }, }); // Define custom events that this component can emit @@ -133,7 +136,7 @@ const humanReadableDateTime = (iso: string) => { minute: '2-digit', }); }; - +/* const stateAbbrevMap: Record = { Alabama: 'AL', Alaska: 'AK', @@ -204,6 +207,7 @@ function formatAddress(input: string): string { return `${streetNumber} ${streetName}, ${city}, ${state} ${zip}`; } +*/ const currentIndex = computed(() => { return currentLocation.value ? locationQueueOrder.value.indexOf(currentLocation.value.loc_id) : 0; @@ -260,8 +264,8 @@ onUnmounted(() => {