gpstracker/frontend/src/components/PointInfo.vue
Fabio Manganiello 5dfde74ccf Major bootstrap.
- Migrated frontend to Vue.

- Migrated frontend map to OL API.

- Extended environment variables.

- README.

- Country information/flag integration.

- Implemented generic db/repo.
2025-02-22 16:31:43 +01:00

113 lines
2.7 KiB
Vue

<template>
<div class="popup" :class="{ hidden: !point }" ref="popup">
<div class="popup-content" v-if="point">
<button @click="$emit('close')">Close</button>
<div class="point-info">
<h2 class="address" v-if="point.address">{{ point.address }}</h2>
<h2 class="latlng" v-else>{{ point.latitude }}, {{ point.longitude }}</h2>
<p class="latlng" v-if="point.address">{{ point.latitude }}, {{ point.longitude }}</p>
<p class="locality" v-if="point.locality">{{ point.locality }}</p>
<p class="postal-code" v-if="point.postalCode">{{ point.postalCode }}</p>
<p class="country" v-if="country">
<span class="flag" v-if="countryFlag">{{ countryFlag }}&nbsp; </span>
<span class="name">{{ country.name }}</span>,&nbsp;
<span class="continent">{{ country.continent }}</span>
</p>
<p class="timestamp" v-if="timeString">{{ timeString }}</p>
</div>
</div>
</div>
</template>
<script lang="ts">
import GPSPoint from '../models/GPSPoint';
import Map from 'ol/Map';
import Overlay from 'ol/Overlay';
import type { TCountryCode } from 'countries-list';
import { getCountryData, getEmojiFlag } from 'countries-list';
export default {
emit: ['close'],
props: {
point: {
type: [GPSPoint, null],
},
},
data() {
return {
popup: null as Overlay | null,
}
},
computed: {
country() {
const cc = this.point?.country as string | undefined
if (cc?.length) {
return getCountryData(cc.toUpperCase() as TCountryCode)
}
return null
},
countryFlag() {
return this.country ? getEmojiFlag(this.country.iso2 as TCountryCode) : null
},
timeString(): string | null {
return this.point?.timestamp ? new Date(this.point.timestamp).toLocaleString() : null
},
},
methods: {
bindPopup(map: Map) {
this.popup = new Overlay({
element: this.$refs.popup as HTMLElement,
autoPan: true,
})
// @ts-ignore
map.addOverlay(this.popup)
},
setPosition(coordinates: number[]) {
if (this.popup) {
this.popup.setPosition(coordinates)
}
},
},
}
</script>
<style lang="scss" scoped>
@import "ol/ol.css";
.popup {
position: absolute;
background: var(--color-background);
min-width: 20em;
padding: 1em;
border-radius: 1em;
box-shadow: 2px 2px 2px 2px var(--color-border);
&.hidden {
padding: 0;
border-radius: 0;
box-shadow: none;
width: 0;
height: 0;
min-width: 0;
pointer-events: none;
}
p.latlng {
font-size: 0.8em;
}
.timestamp {
color: var(--color-heading);
font-weight: bold;
font-size: 0.9em;
}
}
</style>