Set initial camera based on location in compliance
This commit is contained in:
parent
97acdb0e2c
commit
c48aebcb0b
6 changed files with 83 additions and 29 deletions
|
|
@ -177,7 +177,8 @@ interface Emits {
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue: Camera | null;
|
initialCamera?: Camera;
|
||||||
|
modelValue: Camera;
|
||||||
markers?: Marker[];
|
markers?: Marker[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,12 +226,7 @@ function deactivateMap() {
|
||||||
function initializeMap() {
|
function initializeMap() {
|
||||||
if (!mapContainer.value) return;
|
if (!mapContainer.value) return;
|
||||||
|
|
||||||
let bounds = boundsDefault();
|
|
||||||
if (props.markers.length > 0) {
|
|
||||||
bounds = boundsMarkers(props.markers);
|
|
||||||
}
|
|
||||||
const _map = new maplibregl.Map({
|
const _map = new maplibregl.Map({
|
||||||
bounds: bounds,
|
|
||||||
container: mapContainer.value,
|
container: mapContainer.value,
|
||||||
style: "https://tiles.stadiamaps.com/styles/alidade_smooth.json",
|
style: "https://tiles.stadiamaps.com/styles/alidade_smooth.json",
|
||||||
// Disable interactions by default
|
// Disable interactions by default
|
||||||
|
|
@ -239,6 +235,30 @@ function initializeMap() {
|
||||||
scrollZoom: false,
|
scrollZoom: false,
|
||||||
touchZoomRotate: false,
|
touchZoomRotate: false,
|
||||||
});
|
});
|
||||||
|
if (props.markers.length > 0) {
|
||||||
|
_map.fitBounds(boundsMarkers(props.markers));
|
||||||
|
} else if (props.initialCamera) {
|
||||||
|
_map.jumpTo({
|
||||||
|
center: [
|
||||||
|
props.initialCamera.location.longitude,
|
||||||
|
props.initialCamera.location.latitude,
|
||||||
|
],
|
||||||
|
zoom: props.initialCamera.zoom,
|
||||||
|
});
|
||||||
|
} else if (
|
||||||
|
props.modelValue.location.latitude != 0 ||
|
||||||
|
props.modelValue.location.longitude != 0
|
||||||
|
) {
|
||||||
|
_map.jumpTo({
|
||||||
|
center: [
|
||||||
|
props.modelValue.location.longitude,
|
||||||
|
props.modelValue.location.latitude,
|
||||||
|
],
|
||||||
|
zoom: props.modelValue.zoom,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
_map.fitBounds(boundsDefault());
|
||||||
|
}
|
||||||
_map.addControl(new maplibregl.NavigationControl(), "top-left");
|
_map.addControl(new maplibregl.NavigationControl(), "top-left");
|
||||||
map.value = _map;
|
map.value = _map;
|
||||||
_map.on("click", (e: maplibregl.MapLayerMouseEvent) => {
|
_map.on("click", (e: maplibregl.MapLayerMouseEvent) => {
|
||||||
|
|
|
||||||
|
|
@ -50,10 +50,11 @@
|
||||||
<label class="form-label fw-semibold">Location Preview</label>
|
<label class="form-label fw-semibold">Location Preview</label>
|
||||||
<div class="map-container">
|
<div class="map-container">
|
||||||
<MapLocator
|
<MapLocator
|
||||||
v-model="currentCamera"
|
:initialCamera="initialCamera"
|
||||||
:markers="markers"
|
:markers="markers"
|
||||||
@click="doMapClick"
|
@click="doMapClick"
|
||||||
@marker-drag-end="doMapMarkerDragEnd"
|
@marker-drag-end="doMapMarkerDragEnd"
|
||||||
|
v-model="currentCamera"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -64,17 +65,18 @@ import AddressSuggestion from "@/components/AddressSuggestion.vue";
|
||||||
import MapLocator from "@/components/MapLocator.vue";
|
import MapLocator from "@/components/MapLocator.vue";
|
||||||
import type { Address, Geocode, GeocodeSuggestion, Location } from "@/type/api";
|
import type { Address, Geocode, GeocodeSuggestion, Location } from "@/type/api";
|
||||||
import { useGeocodeStore } from "@/store/geocode";
|
import { useGeocodeStore } from "@/store/geocode";
|
||||||
import type { Camera, Locator } from "@/type/map";
|
import { Camera, Locator } from "@/type/map";
|
||||||
import type { Marker } from "@/types";
|
import type { Marker } from "@/types";
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: "update:modelValue", value: Locator): void;
|
(e: "update:modelValue", value: Locator): void;
|
||||||
}
|
}
|
||||||
interface Props {
|
interface Props {
|
||||||
|
initialCamera?: Camera;
|
||||||
modelValue: Locator;
|
modelValue: Locator;
|
||||||
}
|
}
|
||||||
const address = ref<string>("");
|
const address = ref<string>("");
|
||||||
const currentCamera = ref<Camera | null>(null);
|
const currentCamera = ref<Camera>(new Camera());
|
||||||
const emit = defineEmits<Emits>();
|
const emit = defineEmits<Emits>();
|
||||||
const geocode = useGeocodeStore();
|
const geocode = useGeocodeStore();
|
||||||
const markers = computed((): Marker[] => {
|
const markers = computed((): Marker[] => {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,10 @@
|
||||||
Please enter the address so we can match your response with our records.
|
Please enter the address so we can match your response with our records.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<AddressAndMapLocator v-model="modelValue.locator" />
|
<AddressAndMapLocator
|
||||||
|
:initialCamera="initialCamera"
|
||||||
|
v-model="modelValue.locator"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="d-flex gap-2 mt-4">
|
<div class="d-flex gap-2 mt-4">
|
||||||
<RouterLink class="btn btn-outline-secondary" to="../compliance">
|
<RouterLink class="btn btn-outline-secondary" to="../compliance">
|
||||||
|
|
@ -24,7 +27,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from "vue";
|
import { computed, ref } from "vue";
|
||||||
|
|
||||||
import { router } from "@/rmo/router";
|
import { router } from "@/rmo/router";
|
||||||
import type { District } from "@/type/api";
|
import type { District } from "@/type/api";
|
||||||
|
|
@ -32,7 +35,7 @@ import HeaderCompliance from "@/rmo/components/HeaderCompliance.vue";
|
||||||
import ProgressBarCompliance from "@/rmo/components/ProgressBarCompliance.vue";
|
import ProgressBarCompliance from "@/rmo/components/ProgressBarCompliance.vue";
|
||||||
import AddressAndMapLocator from "@/rmo/components/AddressAndMapLocator.vue";
|
import AddressAndMapLocator from "@/rmo/components/AddressAndMapLocator.vue";
|
||||||
import { Compliance } from "@/rmo/view/Compliance.vue";
|
import { Compliance } from "@/rmo/view/Compliance.vue";
|
||||||
import { Locator } from "@/type/map";
|
import { Camera, Locator } from "@/type/map";
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: "doLocator"): void;
|
(e: "doLocator"): void;
|
||||||
|
|
@ -45,6 +48,15 @@ interface Props {
|
||||||
const emit = defineEmits<Emits>();
|
const emit = defineEmits<Emits>();
|
||||||
const error = ref<string>("");
|
const error = ref<string>("");
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
|
const initialCamera = computed((): Camera | undefined => {
|
||||||
|
if (props.modelValue.location) {
|
||||||
|
return {
|
||||||
|
location: props.modelValue.location,
|
||||||
|
zoom: 15,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
function doContinue() {
|
function doContinue() {
|
||||||
emit("update:modelValue", props.modelValue);
|
emit("update:modelValue", props.modelValue);
|
||||||
emit("doLocator");
|
emit("doLocator");
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,8 @@ import { useStoreDistrict } from "@/rmo/store/district";
|
||||||
import { useStoreLocal } from "@/store/local";
|
import { useStoreLocal } from "@/store/local";
|
||||||
import { useStoreLocation } from "@/store/location";
|
import { useStoreLocation } from "@/store/location";
|
||||||
import Intro from "@/rmo/content/compliance/Intro.vue";
|
import Intro from "@/rmo/content/compliance/Intro.vue";
|
||||||
import { type District, PermissionAccess, type PublicReport } from "@/type/api";
|
import type { District, Location, PublicReport } from "@/type/api";
|
||||||
|
import { PermissionAccess } from "@/type/api";
|
||||||
import { Locator } from "@/type/map";
|
import { Locator } from "@/type/map";
|
||||||
import { type Contact } from "@/rmo/content/compliance/Contact.vue";
|
import { type Contact } from "@/rmo/content/compliance/Contact.vue";
|
||||||
import { type Permission } from "@/rmo/content/compliance/Permission.vue";
|
import { type Permission } from "@/rmo/content/compliance/Permission.vue";
|
||||||
|
|
@ -51,6 +52,7 @@ import { type Permission } from "@/rmo/content/compliance/Permission.vue";
|
||||||
export interface Compliance {
|
export interface Compliance {
|
||||||
comments: string;
|
comments: string;
|
||||||
contact: Contact;
|
contact: Contact;
|
||||||
|
location: Location;
|
||||||
locator: Locator;
|
locator: Locator;
|
||||||
images: Image[];
|
images: Image[];
|
||||||
permission: Permission;
|
permission: Permission;
|
||||||
|
|
@ -70,6 +72,10 @@ const compliance = ref<Compliance>({
|
||||||
email: "",
|
email: "",
|
||||||
},
|
},
|
||||||
images: [],
|
images: [],
|
||||||
|
location: {
|
||||||
|
latitude: 0,
|
||||||
|
longitude: 0,
|
||||||
|
},
|
||||||
locator: {
|
locator: {
|
||||||
address: {
|
address: {
|
||||||
country: "",
|
country: "",
|
||||||
|
|
@ -134,6 +140,7 @@ onMounted(() => {
|
||||||
storeLocation
|
storeLocation
|
||||||
.get()
|
.get()
|
||||||
.then((loc: GeolocationPosition) => {
|
.then((loc: GeolocationPosition) => {
|
||||||
|
compliance.value.location = loc.coords;
|
||||||
createReport(session_id, loc);
|
createReport(session_id, loc);
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,18 @@ export enum PermissionAccess {
|
||||||
UNSELECTED = "unselected",
|
UNSELECTED = "unselected",
|
||||||
WITH_OWNER = "with-owner",
|
WITH_OWNER = "with-owner",
|
||||||
}
|
}
|
||||||
export interface Address {
|
export class Address {
|
||||||
country: string;
|
constructor(
|
||||||
gid: string;
|
public country: string,
|
||||||
locality: string;
|
public gid: string,
|
||||||
number: string;
|
public locality: string,
|
||||||
postal_code: string;
|
public number: string,
|
||||||
raw: string;
|
public postal_code: string,
|
||||||
region: string;
|
public raw: string,
|
||||||
street: string;
|
public region: string,
|
||||||
unit: string;
|
public street: string,
|
||||||
|
public unit: string,
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
export interface Bounds {
|
export interface Bounds {
|
||||||
min: Location;
|
min: Location;
|
||||||
|
|
@ -32,10 +34,15 @@ export interface District {
|
||||||
url_logo: string;
|
url_logo: string;
|
||||||
url_website: string;
|
url_website: string;
|
||||||
}
|
}
|
||||||
export interface Location {
|
export class Location {
|
||||||
accuracy?: number;
|
accuracy?: number;
|
||||||
latitude: number;
|
latitude: number;
|
||||||
longitude: number;
|
longitude: number;
|
||||||
|
constructor(latitude: number = 0, longitude: number = 0, accuracy?: number) {
|
||||||
|
this.accuracy = accuracy;
|
||||||
|
this.latitude = latitude;
|
||||||
|
this.longitude = longitude;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export interface GeocodeSuggestion {
|
export interface GeocodeSuggestion {
|
||||||
detail: string;
|
detail: string;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,19 @@
|
||||||
import maplibregl from "maplibre-gl";
|
import maplibregl from "maplibre-gl";
|
||||||
import type { Address, Location } from "@/type/api";
|
import { Address, Location } from "@/type/api";
|
||||||
|
|
||||||
export interface Camera {
|
export class Camera {
|
||||||
location: Location;
|
location: Location;
|
||||||
zoom: number;
|
zoom: number;
|
||||||
|
constructor(location: Location = new Location(), zoom: number = 0) {
|
||||||
|
this.location = location;
|
||||||
|
this.zoom = zoom;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export interface Locator {
|
export class Locator {
|
||||||
address: Address;
|
constructor(
|
||||||
location: Location;
|
public address: Address,
|
||||||
|
public location: Location,
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
export type MoveEndEventInternal = maplibregl.MapLibreEvent<
|
export type MoveEndEventInternal = maplibregl.MapLibreEvent<
|
||||||
| maplibregl.MapMouseEvent
|
| maplibregl.MapMouseEvent
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue