From a2b8527d918dc70e017d3066af5cd78ce321d2f1 Mon Sep 17 00:00:00 2001
From: Eli Ribble
Date: Mon, 27 Apr 2026 19:40:24 +0000
Subject: [PATCH] Track user location with map and address data
This is useful because everywhere that we use the AddressAndMapLocator
component we also want to use the user's location and we want to zoom
the map based on their location. Instead of tracking this externally in
3 places we just pull it into the component.
---
ts/rmo/components/AddressAndMapLocator.vue | 70 +++++++++++++++-------
ts/rmo/content/Nuisance.vue | 57 +++++-------------
ts/rmo/content/Water.vue | 37 ++++++------
ts/rmo/content/compliance/Address.vue | 16 +++--
ts/store/geocode.ts | 12 +++-
ts/type/map.ts | 11 ++++
6 files changed, 113 insertions(+), 90 deletions(-)
diff --git a/ts/rmo/components/AddressAndMapLocator.vue b/ts/rmo/components/AddressAndMapLocator.vue
index 8f8a91f2..0fd964f3 100644
--- a/ts/rmo/components/AddressAndMapLocator.vue
+++ b/ts/rmo/components/AddressAndMapLocator.vue
@@ -38,7 +38,7 @@
diff --git a/ts/rmo/content/Nuisance.vue b/ts/rmo/content/Nuisance.vue
index 91ec13b5..acf0c5e7 100644
--- a/ts/rmo/content/Nuisance.vue
+++ b/ts/rmo/content/Nuisance.vue
@@ -125,7 +125,7 @@ select.tall {
You can also click on the map to mark the location precisely
-
+
(new Address());
const currentCamera = ref(null);
const currentLocation = ref(null);
const errorMessage = ref("");
@@ -611,6 +609,7 @@ const formElement = ref(null);
const geocode = useStoreGeocode();
const images = ref([]);
const isSubmitting = ref(false);
+const locator = ref(new Locator());
const marker = ref(null);
const markers = computed((): Marker[] => {
if (marker.value) {
@@ -633,31 +632,29 @@ async function doSubmit() {
const client_id = storeLocal.getClientID();
const formData = new FormData(formElement.value);
formData.append("client_id", client_id);
- if (address.value) {
- formData.append("address.gid", address.value.gid);
- formData.append("address.raw", address.value.raw);
- if (address.value.location) {
- formData.append(
- "address.location.latitude",
- address.value.location.latitude.toString(),
- );
- formData.append(
- "address.location.longitude",
- address.value.location.longitude.toString(),
- );
- }
+ formData.append("address.gid", locator.value.address.gid);
+ formData.append("address.raw", locator.value.address.raw);
+ if (locator.value.address.location) {
+ formData.append(
+ "address.location.latitude",
+ locator.value.address.location.latitude.toString(),
+ );
+ formData.append(
+ "address.location.longitude",
+ locator.value.address.location.longitude.toString(),
+ );
}
formData.append(
"location.accuracy",
- currentLocation.value?.accuracy?.toString() ?? "0",
+ locator.value.location?.accuracy?.toString() ?? "0",
);
formData.append(
"location.latitude",
- currentLocation.value?.latitude.toString() ?? "0",
+ locator.value.location?.latitude?.toString() ?? "0",
);
formData.append(
"location.longitude",
- currentLocation.value?.longitude.toString() ?? "0",
+ locator.value.location?.longitude?.toString() ?? "0",
);
images.value.forEach((image, index) => {
formData.append(`image[${index}]`, image.file, image.name);
diff --git a/ts/rmo/content/compliance/Address.vue b/ts/rmo/content/compliance/Address.vue
index 643d93c5..45a39661 100644
--- a/ts/rmo/content/compliance/Address.vue
+++ b/ts/rmo/content/compliance/Address.vue
@@ -10,10 +10,7 @@
Please enter the address so we can match your response with our records.
-
+
diff --git a/ts/store/geocode.ts b/ts/store/geocode.ts
index 65372185..a8bb60a5 100644
--- a/ts/store/geocode.ts
+++ b/ts/store/geocode.ts
@@ -7,14 +7,12 @@ export const useStoreGeocode = defineStore("geocode", () => {
const loading = ref(false);
const error = ref(null);
- // Actions
- async function reverse(location: Location): Promise {
+ async function doReverse(url: string, location: Location): Promise {
loading.value = true;
error.value = null;
try {
//const url = `https://api.stadiamaps.com/geocoding/v2/reverse?point.lat=${location.lat}&point.lon=${location.lng}`;
- const url = "/api/geocode/reverse";
const response = await fetch(url, {
body: JSON.stringify(location),
method: "POST",
@@ -29,9 +27,17 @@ export const useStoreGeocode = defineStore("geocode", () => {
throw err;
}
}
+ // Actions
+ async function reverse(location: Location): Promise {
+ return doReverse("/api/geocode/reverse", location);
+ }
+ async function reverseClosest(location: Location): Promise {
+ return doReverse("/api/geocode/reverse/closest", location);
+ }
return {
// Actions
reverse,
+ reverseClosest,
};
});
diff --git a/ts/type/map.ts b/ts/type/map.ts
index 4f458b6a..d11d38df 100644
--- a/ts/type/map.ts
+++ b/ts/type/map.ts
@@ -9,6 +9,17 @@ export class Camera {
this.zoom = zoom;
}
}
+export class Locator {
+ address: Address;
+ location: Location;
+ constructor(
+ address: Address = new Address(),
+ location: Location = new Location(),
+ ) {
+ this.address = address;
+ this.location = location;
+ }
+}
export type MoveEndEventInternal = maplibregl.MapLibreEvent<
| maplibregl.MapMouseEvent
| maplibregl.MapTouchEvent