<template>
|
|
<div id="map-wrap">
|
|
<client-only>
|
|
<l-map ref="myMap" v-bind="map">
|
|
<v-marker-cluster v-if="!selectedOrigin.key">
|
|
<l-marker
|
|
v-for="airport in airports_orig"
|
|
:key="airport.iata"
|
|
:lat-lng="[airport.lat, airport.long]"
|
|
>
|
|
<l-icon
|
|
:icon-anchor="[16, 37]"
|
|
class-name="airport-icon orig-icon unselected"
|
|
>
|
|
<div class="map__icon-muni">
|
|
{{ airport.municipality }} ►
|
|
</div>
|
|
</l-icon>
|
|
<l-popup class="map__popup">
|
|
<div class="map__popup-iata">
|
|
{{ airport.iata }}
|
|
</div>
|
|
<div class="map__popup-muni">
|
|
{{ airport.municipality }}
|
|
</div>
|
|
<div class="map__popup-buttons">
|
|
<button class="btn btn--primary btn--map" @click="makeOrigin(airport)">
|
|
start here ►
|
|
</button>
|
|
</div>
|
|
</l-popup>
|
|
</l-marker>
|
|
</v-marker-cluster>
|
|
<v-marker-cluster v-if="selectedOrigin.key && !selectedDestination.key">
|
|
<l-marker
|
|
v-for="airport in airports_dest"
|
|
:key="airport.iata"
|
|
:lat-lng="[airport.lat, airport.long]"
|
|
>
|
|
<l-icon
|
|
:icon-anchor="[16, 37]"
|
|
class-name="airport-icon dest-icon unselected"
|
|
>
|
|
<div class="map__icon-muni">
|
|
{{ airport.municipality }} ■
|
|
</div>
|
|
</l-icon>
|
|
<l-popup class="map__popup">
|
|
<div class="map__popup-iata">
|
|
{{ airport.iata }}
|
|
</div>
|
|
<div class="map__popup-muni">
|
|
{{ airport.municipality }}
|
|
</div>
|
|
<div class="map__popup-buttons">
|
|
<button
|
|
class="btn btn--primary btn--map"
|
|
@click="makeDestination(airport)"
|
|
>
|
|
land here ■
|
|
</button>
|
|
<button class="btn btn--secondary btn--map" @click="makeOrigin(airport)">
|
|
start here ►
|
|
</button>
|
|
</div>
|
|
</l-popup>
|
|
</l-marker>
|
|
</v-marker-cluster>
|
|
<l-marker v-if="selectedOrigin.key" v-bind="selectedOrigin">
|
|
<l-icon
|
|
:icon-anchor="[16, 37]"
|
|
class-name="airport-icon orig-icon selected"
|
|
>
|
|
<div class="map__icon-muni">
|
|
{{ selectedOrigin.municipality }}
|
|
</div>
|
|
</l-icon>
|
|
<l-popup class="map__popup">
|
|
<div class="map__popup-iata">
|
|
{{ selectedOrigin.iata }}
|
|
</div>
|
|
<div class="map__popup-muni">
|
|
{{ selectedOrigin.municipality }}
|
|
</div>
|
|
<div class="map__popup-buttons">
|
|
<button class="btn btn--cancel btn--map" @click="clearOrigin()">
|
|
remove
|
|
</button>
|
|
</div>
|
|
</l-popup>
|
|
</l-marker>
|
|
<l-marker v-if="selectedDestination.key" v-bind="selectedDestination">
|
|
<l-icon
|
|
:icon-anchor="[16, 37]"
|
|
class-name="airport-icon dest-icon selected"
|
|
>
|
|
<div class="map__icon-muni">
|
|
{{ selectedDestination.municipality }}
|
|
</div>
|
|
</l-icon>
|
|
<l-popup class="map__popup">
|
|
<div class="map__popup-iata">
|
|
{{ selectedDestination.iata }}
|
|
</div>
|
|
<div class="map__popup-muni">
|
|
{{ selectedDestination.municipality }}
|
|
</div>
|
|
<div class="map__popup-buttons">
|
|
<button class="btn btn--cancel btn--map" @click="clearDestination()">
|
|
remove
|
|
</button>
|
|
</div>
|
|
</l-popup>
|
|
</l-marker>
|
|
<!-- <l-polyline :lat-lngs="polyline.latlngs" :color="polyline.color" /> -->
|
|
<!-- <l-tile-layer v-bind="tileLayer" :url="mapBoxUrl" /> -->
|
|
<l-tile-layer :url="osmUrl" :attribution="osmAttribution" />
|
|
</l-map>
|
|
</client-only>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
data () {
|
|
return {
|
|
map: {
|
|
zoom: 3,
|
|
minZoom: 3,
|
|
maxZoom: 13,
|
|
center: {
|
|
lat: 63.8333,
|
|
lng: -152
|
|
},
|
|
bounds: [
|
|
[
|
|
71.0394374664382,
|
|
-178.4706617597655
|
|
],
|
|
[
|
|
50.44556513009691,
|
|
-127.25240004101528
|
|
]
|
|
]
|
|
},
|
|
mapBoxAccessToken: 'pk.eyJ1IjoiZmx5bG9jYWwiLCJhIjoiY2t0OHUxZXB6MTVueTJ4cGVwOHRuc2s2NyJ9.YF9frLvISHfOuT7nqs3TNg',
|
|
mapBoxAttribution: 'FlyLocal | Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
|
|
osmUrl: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
|
|
osmAttribution:
|
|
'© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
|
|
mapBoxUrl: 'https://api.mapbox.com/styles/v1/flylocal/ckt9x8aho0igb18mmm9ks2fsv/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoiZmx5bG9jYWwiLCJhIjoiY2t0OHUxZXB6MTVueTJ4cGVwOHRuc2s2NyJ9.YF9frLvISHfOuT7nqs3TNg',
|
|
// address: {
|
|
// long: '',
|
|
// display: ''
|
|
// },
|
|
// polyline: {
|
|
// color: 'red',
|
|
// latlngs: []
|
|
// },
|
|
airports_orig: [],
|
|
airports_dest: [],
|
|
airportFetch_filterFormula: 'AND(Is_Origin=1,{IsCurrent-AsOrigin}=\'Yes\')',
|
|
airportFetch_fields: [
|
|
'Airport_IATA',
|
|
'Icon_Url',
|
|
'Latitude_Deg',
|
|
'Longitude_Deg',
|
|
'Municipality',
|
|
'Type'
|
|
],
|
|
airportFetch_sort: '&sort[0][field]=Airport_IATA&sort[0][direction]=asc',
|
|
selectedOrigin: {
|
|
key: '',
|
|
iata: '',
|
|
'lat-lng': [],
|
|
municipality: ''
|
|
},
|
|
selectedDestination: {
|
|
key: '',
|
|
iata: '',
|
|
'lat-lng': [],
|
|
municipality: ''
|
|
}
|
|
}
|
|
},
|
|
async fetch () {
|
|
let response2 = {}
|
|
let mapData2 = {}
|
|
|
|
const response = await fetch(`https://api.airtable.com/v0/appiQwfVZixRgRICe/Airports_IATA?filterByFormula=${this.airportFetch_filterFormula}${this.airportFetch_fields_string}${this.airportFetch_sort}`, {
|
|
method: 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
Authorization: 'Bearer keyJ2ht64ZSN57AG1'
|
|
}
|
|
})
|
|
|
|
if (await response.offset) {
|
|
response2 = fetch(`https://api.airtable.com/v0/appiQwfVZixRgRICe/Airports_IATA?filterByFormula=${this.airportFetch_filterFormula}&fields[]=Airport_IATA&fields[]=Icon_Url&fields[]=Latitude_Deg&fields[]=Longitude_Deg&sort[0][field]=Airport_IATA&sort[0][direction]=asc&offset=${response.offset}`, {
|
|
method: 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
Authorization: 'Bearer keyJ2ht64ZSN57AG1'
|
|
}
|
|
})
|
|
mapData2 = await response2.json()
|
|
}
|
|
|
|
const mapData = await response.json()
|
|
|
|
const r1 = mapData.records
|
|
const r2 = mapData2.records
|
|
|
|
console.log(r2)
|
|
|
|
// const mapDataTotal = [...r1, ...r2]
|
|
|
|
const mapDataTotal = [...r1]
|
|
|
|
this.airports_orig = mapDataTotal.map((record) => {
|
|
return {
|
|
iata: record.fields.Airport_IATA,
|
|
lat: record.fields.Latitude_Deg,
|
|
long: record.fields.Longitude_Deg,
|
|
icon: record.fields.Icon_Url,
|
|
municipality: record.fields.Municipality,
|
|
type: record.fields.Type
|
|
}
|
|
})
|
|
},
|
|
computed: {
|
|
airportFetch_fields_string () {
|
|
const vm = this
|
|
const array = vm.airportFetch_fields.map((field) => {
|
|
return '&fields[]=' + field
|
|
})
|
|
return array.join('')
|
|
},
|
|
mapBoxApiUrl () {
|
|
return `https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=${this.mapBoxAccessToken}`
|
|
},
|
|
tileLayer () {
|
|
return {
|
|
// url: this.mapBoxApiUrl,
|
|
maxZoom: 18,
|
|
// id: 'flylocal/ckt9x8aho0igb18mmm9ks2fsv',
|
|
tileSize: 512,
|
|
zoomOffset: -1,
|
|
accessToken: 'your.mapbox.access.token',
|
|
attribution: this.mapBoxAttribution
|
|
}
|
|
}
|
|
},
|
|
methods: {
|
|
makeOrigin (airport) {
|
|
this.selectedOrigin = {
|
|
key: airport.iata,
|
|
iata: airport.iata,
|
|
'lat-lng': [airport.lat, airport.long],
|
|
municipality: airport.municipality
|
|
}
|
|
this.fetchDestinations(airport.iata)
|
|
},
|
|
makeDestination (airport) {
|
|
this.selectedDestination = {
|
|
key: airport.iata,
|
|
iata: airport.iata,
|
|
'lat-lng': [airport.lat, airport.long],
|
|
municipality: airport.municipality
|
|
}
|
|
},
|
|
clearOrigin () {
|
|
this.selectedOrigin = {
|
|
key: '',
|
|
iata: '',
|
|
'lat-lng': [],
|
|
municipality: ''
|
|
}
|
|
this.selectedDestination = {
|
|
key: '',
|
|
iata: '',
|
|
'lat-lng': [],
|
|
municipality: ''
|
|
}
|
|
},
|
|
clearDestination () {
|
|
this.selectedDestination = {
|
|
key: '',
|
|
iata: '',
|
|
'lat-lng': [],
|
|
municipality: ''
|
|
}
|
|
},
|
|
async fetchDestinations (iata) {
|
|
const airportFetchDestfilterFormula = `AND(Is_Destination=1,{IsCurrent-AsDest}="Yes",(FIND("${iata}", Associated_Origin_Search)>0))`
|
|
|
|
const test = `https://api.airtable.com/v0/appiQwfVZixRgRICe/Airports_IATA?filterByFormula=${airportFetchDestfilterFormula}${this.airportFetch_fields_string}${this.airportFetch_sort}`
|
|
|
|
console.log(test)
|
|
|
|
const response = await fetch(`https://api.airtable.com/v0/appiQwfVZixRgRICe/Airports_IATA?filterByFormula=${airportFetchDestfilterFormula}${this.airportFetch_fields_string}${this.airportFetch_sort}`, {
|
|
method: 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
Authorization: 'Bearer keyJ2ht64ZSN57AG1'
|
|
}
|
|
})
|
|
|
|
const mapData = await response.json()
|
|
|
|
this.airports_dest = mapData.records.map((record) => {
|
|
return {
|
|
iata: record.fields.Airport_IATA,
|
|
lat: record.fields.Latitude_Deg,
|
|
long: record.fields.Longitude_Deg,
|
|
icon: record.fields.Icon_Url,
|
|
municipality: record.fields.Municipality,
|
|
type: record.fields.Type
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="css" >
|
|
:root {
|
|
--map-shadow: 5px 3px 10px rgb(0 0 0 / 20%);
|
|
}
|
|
|
|
#map-wrap {
|
|
height: 100vh;
|
|
}
|
|
|
|
.map__icon-muni {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.map__popup {
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.map__popup-iata {
|
|
white-space: nowrap;
|
|
font-size: 3em;
|
|
line-height: 1;
|
|
}
|
|
|
|
.map__popup-muni {
|
|
white-space: nowrap;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.map__popup-buttons {
|
|
display: flex;
|
|
flex-direction: row;
|
|
gap: 0.5em;
|
|
}
|
|
|
|
.leaflet-popup {
|
|
top: 0 !important;
|
|
left: 0 !important;
|
|
}
|
|
|
|
.leaflet-popup-content-wrapper {
|
|
border-radius: 0.2rem 1.5rem 1.5rem 1.5rem;
|
|
box-shadow: var(--map-shadow);
|
|
}
|
|
|
|
.leaflet-popup-tip-container,
|
|
.leaflet-popup-close-button {
|
|
display: none;
|
|
}
|
|
|
|
.leaflet-popup-content {
|
|
margin: 0.75rem;
|
|
}
|
|
|
|
.airport-icon {
|
|
padding: 0.55rem;
|
|
border-radius: 0.2rem 1.5rem 1.5rem 1.5rem;
|
|
box-shadow: var(--map-shadow);
|
|
text-align: center;
|
|
width: auto !important;
|
|
height: auto !important;
|
|
margin: 0 !important;
|
|
border: 0.2rem solid transparent;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.airport-icon.orig-icon {
|
|
background-color: white;
|
|
color: black;
|
|
}
|
|
|
|
.airport-icon.orig-icon:hover {
|
|
border-color: #007fff;
|
|
}
|
|
|
|
.airport-icon.dest-icon {
|
|
background-color: #ddd;
|
|
color: black;
|
|
}
|
|
|
|
.airport-icon.orig-icon.selected {
|
|
border-color: #007fff;
|
|
}
|
|
|
|
.airport-icon.dest-icon:hover {
|
|
background-color: #007fff;
|
|
color: white;
|
|
}
|
|
|
|
.airport-icon.dest-icon.selected {
|
|
background-color: #007fff;
|
|
color: white;
|
|
}
|
|
|
|
#map-wrap .marker-cluster-small {
|
|
background-color: rgba(47, 151, 255, 0.15);
|
|
}
|
|
|
|
#map-wrap .marker-cluster-small div {
|
|
background-color: rgba(0, 127, 255, 0.15);
|
|
}
|
|
|
|
#map-wrap .marker-cluster-medium {
|
|
background-color: rgba(47, 151, 255, 0.5);
|
|
}
|
|
|
|
#map-wrap .marker-cluster-medium div {
|
|
background-color: rgba(0, 127, 255, 0.5);
|
|
}
|
|
|
|
#map-wrap .marker-cluster-large {
|
|
background-color: rgba(47, 151, 255, 0.9);
|
|
}
|
|
|
|
#map-wrap .marker-cluster-large div {
|
|
background-color: rgba(0, 127, 255, 0.9);
|
|
}
|
|
|
|
/* .marker-cluster {
|
|
background-clip: padding-box;
|
|
border-radius: 20px;
|
|
}
|
|
|
|
.marker-cluster div {
|
|
width: 30px;
|
|
height: 30px;
|
|
margin-left: 5px;
|
|
margin-top: 5px;
|
|
text-align: center;
|
|
border-radius: 15px;
|
|
font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
|
|
}
|
|
|
|
.marker-cluster span {
|
|
line-height: 30px;
|
|
} */
|
|
|
|
.btn {
|
|
border-radius: 999px;
|
|
padding: 0.4em 0.8em;
|
|
font-size: 1rem;
|
|
white-space: nowrap;
|
|
transition: 0.2s all;
|
|
}
|
|
|
|
.btn.btn--primary {
|
|
background: #007fff;
|
|
color: #fff;
|
|
}
|
|
|
|
.btn.btn--primary:hover {
|
|
background: #72b9ff;
|
|
color: #fff;
|
|
}
|
|
|
|
.btn.btn--cancel {
|
|
background: red;
|
|
color: #fff;
|
|
}
|
|
|
|
.btn.btn--cancel:hover {
|
|
background: rgb(255, 83, 83);
|
|
color: #fff;
|
|
}
|
|
|
|
.btn.btn--secondary {
|
|
background: #ccc;
|
|
color: #000;
|
|
}
|
|
|
|
.btn.btn--secondary:hover {
|
|
background: rgb(151, 151, 151);
|
|
color: #000;
|
|
}
|
|
|
|
/* .btn.btn--map {
|
|
//..
|
|
} */
|
|
|
|
</style>
|