Added geoloc button to filters
This commit is contained in:
@@ -1,21 +1,68 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useMap } from '@/stores/map'
|
import { useMap } from '@/stores/map'
|
||||||
|
import { PhMapPin, PhSpinner } from '@phosphor-icons/vue'
|
||||||
|
import { useGeolocation, usePermission } from '@vueuse/core'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
|
import { computed, ref, watch } from 'vue'
|
||||||
|
import ParkingSpaceRange from './filters/ParkingSpaceRange.vue'
|
||||||
import Checkbox from './forms/Checkbox.vue'
|
import Checkbox from './forms/Checkbox.vue'
|
||||||
import ParkingSpaceRange from './filters/ParkingSpaceRange.vue';
|
|
||||||
|
|
||||||
const { filterCovered, filterUncovered, filterKorrigo, filterCargoOnly, filterStdOnly } = storeToRefs(useMap())
|
const { userCoords, filterCovered, filterUncovered, filterKorrigo, filterCargoOnly, filterStdOnly } = storeToRefs(useMap())
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
nbUncovered?: number
|
nbUncovered?: number
|
||||||
nbCovered?: number
|
nbCovered?: number
|
||||||
nbKorrigo?: number
|
nbKorrigo?: number
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const { coords, error, resume, pause, locatedAt } = useGeolocation({ immediate: false })
|
||||||
|
|
||||||
|
const geolocationPermission = usePermission('geolocation')
|
||||||
|
|
||||||
|
const isRequesting = ref(false)
|
||||||
|
const hasLocation = computed(() => locatedAt.value !== null && !error.value)
|
||||||
|
|
||||||
|
// Auto-start if permission was already granted
|
||||||
|
watch(geolocationPermission, (permission) => {
|
||||||
|
if (permission === 'granted' && !hasLocation.value) {
|
||||||
|
resume()
|
||||||
|
}
|
||||||
|
}, { immediate: true })
|
||||||
|
|
||||||
|
function toggleGeolocation() {
|
||||||
|
if (hasLocation.value) {
|
||||||
|
pause()
|
||||||
|
isRequesting.value = false
|
||||||
|
} else {
|
||||||
|
isRequesting.value = true
|
||||||
|
resume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(locatedAt, () => { isRequesting.value = false })
|
||||||
|
watch(error, () => { isRequesting.value = false })
|
||||||
|
watch(coords, () => {
|
||||||
|
if (coords.value.latitude && coords.value.longitude) {
|
||||||
|
userCoords.value = coords.value
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<aside class="max-w-xs absolute top-5 left-5 z-10 p-2 bg-slate-50 text-slate-950 rounded-xs">
|
<div class="max-w-xs absolute top-5 left-5 z-10 grid gap-2">
|
||||||
<form class="grid grid-cols-1 gap-3">
|
<button @click="toggleGeolocation"
|
||||||
|
:title="error?.message ?? (hasLocation ? 'Désactiver la géolocalisation' : 'Me localiser')" :class="[
|
||||||
|
'size-9 grid place-items-center border shadow rounded-full cursor-pointer transition-colors',
|
||||||
|
hasLocation
|
||||||
|
? 'bg-primary text-primary-foreground border-primary'
|
||||||
|
: 'bg-slate-50 text-slate-950 border-transparent hover:bg-background hover:text-primary hover:border-primary',
|
||||||
|
error ? 'text-destructive border-destructive hover:text-destructive hover:border-destructive' : ''
|
||||||
|
]">
|
||||||
|
<PhSpinner v-if="isRequesting" :size="20" class="animate-spin" />
|
||||||
|
<PhMapPin v-else :size="20" weight="fill" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<form class="p-2 bg-slate-50 text-slate-950 rounded-xs grid grid-cols-1 gap-3">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend
|
<legend
|
||||||
class="mb-1.5 text-sm font-medium relative isolate before:contents-[''] before:block before:w-full before:bg-amber-500/15 before:h-2 before:absolute before:bottom-0.5 before:-z-10">
|
class="mb-1.5 text-sm font-medium relative isolate before:contents-[''] before:block before:w-full before:bg-amber-500/15 before:h-2 before:absolute before:bottom-0.5 before:-z-10">
|
||||||
@@ -43,5 +90,5 @@ defineProps<{
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
</aside>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export const SPOTS_MIN = 1
|
|||||||
export const SPOTS_MAX = 99
|
export const SPOTS_MAX = 99
|
||||||
|
|
||||||
export const useMap = defineStore('map', () => {
|
export const useMap = defineStore('map', () => {
|
||||||
|
// Map config and options
|
||||||
const zoom = ref(10)
|
const zoom = ref(10)
|
||||||
const minZoom = 8
|
const minZoom = 8
|
||||||
const center = ref<PointTuple>([48.11180645878813, -1.6637869497745246])
|
const center = ref<PointTuple>([48.11180645878813, -1.6637869497745246])
|
||||||
@@ -18,9 +19,14 @@ export const useMap = defineStore('map', () => {
|
|||||||
zoomControl: false,
|
zoomControl: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cluster layers options
|
||||||
const maxClusterRadius = 40
|
const maxClusterRadius = 40
|
||||||
const disableClusteringAtZoom = 17
|
const disableClusteringAtZoom = 17
|
||||||
|
|
||||||
|
// Geolocation
|
||||||
|
const userCoords = ref<Omit<GeolocationCoordinates, 'toJSON'> | null>(null)
|
||||||
|
|
||||||
|
// Active filters
|
||||||
const filterUncovered = ref(true)
|
const filterUncovered = ref(true)
|
||||||
const filterCovered = ref(true)
|
const filterCovered = ref(true)
|
||||||
const filterKorrigo = ref(true)
|
const filterKorrigo = ref(true)
|
||||||
@@ -36,9 +42,10 @@ export const useMap = defineStore('map', () => {
|
|||||||
center,
|
center,
|
||||||
maxBounds,
|
maxBounds,
|
||||||
maxBoundsViscosity,
|
maxBoundsViscosity,
|
||||||
|
extraOptions,
|
||||||
maxClusterRadius,
|
maxClusterRadius,
|
||||||
disableClusteringAtZoom,
|
disableClusteringAtZoom,
|
||||||
extraOptions,
|
userCoords,
|
||||||
filterUncovered,
|
filterUncovered,
|
||||||
filterCovered,
|
filterCovered,
|
||||||
filterKorrigo,
|
filterKorrigo,
|
||||||
|
|||||||
Reference in New Issue
Block a user