Added layer controls
This commit is contained in:
74
src/components/map/MapSidebar.vue
Normal file
74
src/components/map/MapSidebar.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<script lang="ts" setup>
|
||||
import { useMap } from '@/stores/map';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
const { activeLayers } = storeToRefs(useMap())
|
||||
|
||||
function handleTokenClick() {
|
||||
activeLayers.value.tokens = !activeLayers.value.tokens
|
||||
}
|
||||
|
||||
function handleFoodClick() {
|
||||
activeLayers.value.food = !activeLayers.value.food
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<aside class="rounded bg-background border border-border shadow-sm">
|
||||
<menu class="first:pt-0.5 last:pb-0.5">
|
||||
<li>
|
||||
<button
|
||||
class="pl-2 pr-3 py-1.5 text-xs cursor-pointer flex items-start gap-1"
|
||||
:class="{
|
||||
'text-foreground *:fill-foreground': !activeLayers.food,
|
||||
'text-emerald-600 *:fill-emerald-600': activeLayers.food
|
||||
}"
|
||||
@click="handleFoodClick"
|
||||
>
|
||||
<svg v-if="activeLayers.food" xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 256 256">
|
||||
<path d="M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Zm-34.34,77.66-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35a8,8,0,0,1,11.32,11.32Z" />
|
||||
</svg>
|
||||
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 256 256">
|
||||
<path d="M216,40V224a8,8,0,0,1-16,0V176H152a8,8,0,0,1-8-8,268.75,268.75,0,0,1,7.22-56.88c9.78-40.49,28.32-67.63,53.63-78.47A8,8,0,0,1,216,40Zm-96.11-1.31a8,8,0,1,0-15.78,2.63L111.89,88H88V40a8,8,0,0,0-16,0V88H48.11l7.78-46.68a8,8,0,1,0-15.78-2.63l-8,48A8.17,8.17,0,0,0,32,88a48.07,48.07,0,0,0,40,47.32V224a8,8,0,0,0,16,0V135.32A48.07,48.07,0,0,0,128,88a8.17,8.17,0,0,0-.11-1.31Z" />
|
||||
</svg>
|
||||
|
||||
<span>
|
||||
Restaurants
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
class="pl-2 pr-3 py-1.5 text-xs cursor-pointer flex items-start gap-1"
|
||||
:class="{
|
||||
'text-foreground *:fill-foreground': !activeLayers.tokens,
|
||||
'text-emerald-600 *:fill-emerald-600': activeLayers.tokens
|
||||
}"
|
||||
@click="handleTokenClick"
|
||||
>
|
||||
<svg v-if="activeLayers.tokens" xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 256 256">
|
||||
<path d="M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Zm-34.34,77.66-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35a8,8,0,0,1,11.32,11.32Z" />
|
||||
</svg>
|
||||
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 256 256">
|
||||
<path d="M198.51,56.09C186.44,35.4,169.92,24,152,24H104C86.08,24,69.56,35.4,57.49,56.09,46.21,75.42,40,101,40,128s6.21,52.58,17.49,71.91C69.56,220.6,86.08,232,104,232h48c17.92,0,34.44-11.4,46.51-32.09C209.79,180.58,216,155,216,128S209.79,75.42,198.51,56.09ZM199.79,120h-32a152.78,152.78,0,0,0-9.68-48H188.7C194.82,85.38,198.86,102,199.79,120Zm-20.6-64H150.46a83.13,83.13,0,0,0-12-16H152C162,40,171.4,46,179.19,56ZM152,216H138.49a83.13,83.13,0,0,0,12-16h28.73C171.4,210,162,216,152,216Zm36.7-32H158.12a152.78,152.78,0,0,0,9.68-48h32C198.86,154,194.82,170.62,188.7,184Z" />
|
||||
</svg>
|
||||
|
||||
<span>
|
||||
Monnaie de Paris
|
||||
</span>
|
||||
</button>
|
||||
</li>
|
||||
</menu>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
aside {
|
||||
position: fixed;
|
||||
top: var(--body-padding);
|
||||
left: var(--body-padding);
|
||||
z-index: 100;
|
||||
}
|
||||
</style>
|
||||
100
src/components/map/ReviewMarker.vue
Normal file
100
src/components/map/ReviewMarker.vue
Normal file
@@ -0,0 +1,100 @@
|
||||
<script setup lang="ts">
|
||||
import type { ReviewMarker } from '@/models/Markers';
|
||||
import { LMarker, LPopup, LIcon } from '@vue-leaflet/vue-leaflet'
|
||||
import type { PointTuple } from 'leaflet';
|
||||
import { computed, ref } from 'vue';
|
||||
import { cn } from '@/lib/cn';
|
||||
|
||||
defineProps<{
|
||||
marker: ReviewMarker
|
||||
}>()
|
||||
|
||||
const iconSize = ref<PointTuple>([38, 38])
|
||||
const iconAnchor = computed<PointTuple>(() => [iconSize.value[0] / 2, iconSize.value[1]])
|
||||
const popupOffset = [0, iconSize.value[0] * -0.66]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<LMarker :lat-lng="marker.coords">
|
||||
<LPopup :options="{ offset: popupOffset, maxWidth: 380, minWidth: 180 }">
|
||||
<div class="spacing">
|
||||
<h2 class="font-bold text-[1.2em] leading-5">
|
||||
{{ marker.title }}
|
||||
</h2>
|
||||
|
||||
<p v-html="marker.reviews?.[0]!!.text" />
|
||||
</div>
|
||||
</LPopup>
|
||||
|
||||
<LIcon
|
||||
:icon-size
|
||||
:icon-anchor
|
||||
:class-name="cn(
|
||||
{ 'grayscale': marker.closed }
|
||||
)"
|
||||
>
|
||||
<img v-if="marker.type === 'bar'" src="/map/icons/bar.svg" />
|
||||
<img v-if="marker.type === 'bakery'" src="/map/icons/bakery.svg" />
|
||||
<img v-if="marker.type === 'tea-shop'" src="/map/icons/tea-shop.svg" />
|
||||
<img v-if="marker.type === 'coffee-shop'" src="/map/icons/coffee-shop.svg" />
|
||||
<img v-if="marker.type === 'ice-cream'" src="/map/icons/ice-cream.svg" />
|
||||
<img v-if="marker.type === 'food-truck'" src="/map/icons/truck.svg" />
|
||||
|
||||
<template v-else-if="marker.type === 'restaurant'">
|
||||
<img v-if="marker.food === 'asian'" src="/map/icons/asian.svg" />
|
||||
<img v-else-if="marker.food === 'burgers'" src="/map/icons/burgers.svg" />
|
||||
<!-- <img v-else-if="marker.food === 'creperie'" src="/map/icons/creperie.svg" /> -->
|
||||
<!-- <img v-else-if="marker.food === 'eastern'" src="/map/icons/eastern.svg" /> -->
|
||||
<img v-else-if="marker.food === 'fast-food'" src="/map/icons/fast-food.svg" />
|
||||
<img v-else-if="marker.food === 'italian'" src="/map/icons/italian.svg" />
|
||||
<img v-else-if="marker.food === 'seafood'" src="/map/icons/seafood.svg" />
|
||||
<!-- <img v-else-if="marker.food === 'street-food'" src="/map/icons/street-food.svg" /> -->
|
||||
<img v-else-if="marker.food === 'vegetarian'" src="/map/icons/vegetarian.svg" />
|
||||
<img v-else src="/map/icons/restaurant.svg" />
|
||||
</template>
|
||||
|
||||
<div
|
||||
class="absolute -top-2 -right-2 size-5 text-center grid place-items-center rounded-full text-[0.65rem] font-bold tracking-[-0.075em]"
|
||||
:class="cn(
|
||||
{
|
||||
'text-white bg-red-500': marker.reviews?.[0]!.grade! <= 1.5,
|
||||
'text-black bg-amber-400': marker.reviews?.[0]!.grade! > 1.5 && marker.reviews?.[0]!.grade! <= 2.5,
|
||||
'text-black bg-lime-400': marker.reviews?.[0]!.grade! > 2.5 && marker.reviews?.[0]!.grade! < 4.0,
|
||||
'text-black bg-green-400': marker.reviews?.[0]!.grade! > 2.5 && marker.reviews?.[0]!.grade! < 4.5,
|
||||
'text-black bg-sky-400': marker.reviews?.[0]!.grade! >= 4.5,
|
||||
},
|
||||
marker.type === 'food-truck' && {
|
||||
'bg-red-600': marker.reviews?.[0]!.grade! <= 1.5,
|
||||
'bg-amber-500': marker.reviews?.[0]!.grade! > 1.5 && marker.reviews?.[0]!.grade! <= 2.5,
|
||||
'bg-lime-500': marker.reviews?.[0]!.grade! > 2.5 && marker.reviews?.[0]!.grade! < 4.0,
|
||||
'bg-green-500': marker.reviews?.[0]!.grade! > 2.5 && marker.reviews?.[0]!.grade! < 4.5,
|
||||
'bg-sky-400': marker.reviews?.[0]!.grade! >= 4.5,
|
||||
}
|
||||
)"
|
||||
>
|
||||
{{ marker.reviews?.[0]!.grade }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="absolute -z-10 -inset-0.5 rounded-full"
|
||||
:class="cn(
|
||||
{
|
||||
'bg-red-500': marker.reviews?.[0]!.grade! <= 1.5,
|
||||
'bg-amber-400': marker.reviews?.[0]!.grade! > 1.5 && marker.reviews?.[0]!.grade! <= 2.5,
|
||||
'bg-lime-400': marker.reviews?.[0]!.grade! > 2.5 && marker.reviews?.[0]!.grade! < 4.0,
|
||||
'bg-green-400': marker.reviews?.[0]!.grade! > 2.5 && marker.reviews?.[0]!.grade! < 4.5,
|
||||
'bg-sky-400': marker.reviews?.[0]!.grade! >= 4.5,
|
||||
'bg-slate-800': marker.type === 'food-truck'
|
||||
},
|
||||
marker.type === 'food-truck' && {
|
||||
'border-2 border-red-700': marker.reviews?.[0]!.grade! <= 1.5,
|
||||
'border-2 border-amber-600': marker.reviews?.[0]!.grade! > 1.5 && marker.reviews?.[0]!.grade! <= 2.5,
|
||||
'border-2 border-lime-600': marker.reviews?.[0]!.grade! > 2.5 && marker.reviews?.[0]!.grade! < 4.0,
|
||||
'border-2 border-green-600': marker.reviews?.[0]!.grade! > 2.5 && marker.reviews?.[0]!.grade! < 4.5,
|
||||
'border-2 border-sky-500': marker.reviews?.[0]!.grade! >= 4.5,
|
||||
}
|
||||
)"
|
||||
/>
|
||||
</LIcon>
|
||||
</LMarker>
|
||||
</template>
|
||||
45
src/components/map/TokenMarker.vue
Normal file
45
src/components/map/TokenMarker.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<script setup lang="ts">
|
||||
import type { TokenMarker } from '@/models/Markers';
|
||||
import { LMarker, LPopup, LIcon } from '@vue-leaflet/vue-leaflet'
|
||||
import type { PointTuple } from 'leaflet';
|
||||
import { computed, ref } from 'vue';
|
||||
import { cn } from '@/lib/cn';
|
||||
|
||||
defineProps<{
|
||||
marker: TokenMarker
|
||||
}>()
|
||||
|
||||
const iconSize = ref<PointTuple>([38, 38])
|
||||
const iconAnchor = computed<PointTuple>(() => [iconSize.value[0] / 2, iconSize.value[1]])
|
||||
const popupOffset = [0, iconSize.value[0] * -0.66]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<LMarker :lat-lng="marker.coords">
|
||||
<LPopup :options="{ offset: popupOffset, maxWidth: 380, minWidth: 180 }">
|
||||
<div class="spacing">
|
||||
<h2 class="font-bold text-[1.2em] leading-5">
|
||||
{{ marker.title }}
|
||||
</h2>
|
||||
|
||||
<p v-html="marker.reviews?.[0]!!.text" />
|
||||
</div>
|
||||
</LPopup>
|
||||
|
||||
<LIcon
|
||||
:icon-size
|
||||
:icon-anchor
|
||||
:class-name="cn(
|
||||
{ 'grayscale': marker.bootleg }
|
||||
)"
|
||||
>
|
||||
<img src="/map/monnaie-de-paris.png" width="40" height="40" />
|
||||
|
||||
<div
|
||||
class="absolute -top-2 -right-2 size-5 text-center grid place-items-center rounded-full text-[0.65rem] font-bold tracking-[-0.075em]"
|
||||
>
|
||||
{{ marker.reviews?.[0]!.grade }}
|
||||
</div>
|
||||
</LIcon>
|
||||
</LMarker>
|
||||
</template>
|
||||
Reference in New Issue
Block a user