You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

467 lines
12 KiB

<template>
<div :class="['page-container', { 'nav-is-showing': isPickerVisible }]">
<header>
<div class="header__col">
<Logo />
<div v-if="!selectedOrig.iata" class="logo-blurb">
from one of {{ airports_orig.length }} airports
</div>
<div v-if="selectedOrig.iata && !selectedDest.iata && airports_dest.length > 1" class="logo-blurb">
to one of {{ airports_dest.length }} beautiful destinations
</div>
</div>
<div class="header__col">
<div v-show="!isPickerVisible">
<button class="btn btn--primary" @click="showPicker">
tap the map or search 🔎
</button>
</div>
<div v-show="isPickerVisible">
<button class="btn btn--primary" @click="showPicker">
hide search
</button>
</div>
</div>
<div class="header__col">
<button
class="btn btn--primary"
@click="showSidebar"
>
</button>
</div>
</header>
<!-- <pre style="position: fixed; z-index: 500; right: 0; top: 2rem; font-size: 0.6rem; color: gray;">
{{ selectedOrig }}
{{ selectedDest }}
</pre> -->
<main>
<nav :class="['nav', { 'nav--show': isPickerVisible },{ 'nav--hide': !isPickerVisible }]">
<AirportPicker
:airports="airports_orig"
:selected-airport="selectedOrig"
@select-airport="makeOrigin"
@deselect-airport="clearOrigin"
/>
<AirportPicker
v-show="selectedOrig.iata"
:airports="airports_dest"
:selected-airport="selectedDest"
@select-airport="makeDestination"
@deselect-airport="clearDestination"
/>
</nav>
<Map
:airports-orig="airports_orig"
:airports-dest="airports_dest"
:selected-orig="selectedOrig"
:selected-dest="selectedDest"
@make-origin="makeOrigin"
@make-destination="makeDestination"
@clear-origin="clearOrigin"
@clear-destination="clearDestination"
/>
<aside
:class="['sidebar-container',{ 'sidebar-container--hide': !isSidebarVisible },{ 'sidebar-container--show': isSidebarVisible }]"
>
<div class="sidebar">
sidebar info
</div>
</aside>
<div :class="['flyout-container',{ 'flyout-container--hide': !selectedOrig.iata || !selectedDest.iata },{ 'flyout-container--show': selectedOrig.iata && selectedDest.iata }]">
<FlightsFlyout
:selected-orig="selectedOrig"
:selected-dest="selectedDest"
/>
</div>
</main>
</div>
</template>
<script>
// import AirportPicker from '../components/AirportPicker.vue'
export default {
// components: { AirportPicker },
data () {
return {
color: 'red',
mountains: [
{
slug: 'sluggy',
title: 'titly'
}
],
isSidebarVisible: false,
isPickerVisible: false,
airports_orig: [],
airports_dest: [],
airportFetch_filterFormula: 'AND(Is_Origin=1,{IsCurrent-AsOrigin}=\'Yes\')',
airportFetch_fields: [
'Airport_IATA',
'Icon_Url',
'Latitude_Deg',
'Longitude_Deg',
'Municipality',
'Airport_Name',
'Type',
'Search_Field'
],
airportFetch_sort: '&sort[0][field]=Airport_IATA&sort[0][direction]=asc',
selectedOrig: {
iata: '',
lat: '',
long: '',
icon: '',
name: '',
municipality: '',
type: '',
search: ''
},
selectedDest: {
iata: '',
lat: '',
long: '',
icon: '',
name: '',
municipality: '',
type: '',
search: ''
},
emptyAirport: {
iata: '',
lat: '',
long: '',
icon: '',
name: '',
municipality: '',
type: '',
search: ''
}
}
},
async fetch () {
this.mountains = await fetch(
'https://api.nuxtjs.dev/mountains'
).then(res => res.json())
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,
name: record.fields.Airport_Name,
municipality: record.fields.Municipality,
type: record.fields.Type,
search: record.fields.Search_Field
}
})
},
computed: {
airportFetch_fields_string () {
const vm = this
const array = vm.airportFetch_fields.map((field) => {
return '&fields[]=' + field
})
return array.join('')
}
},
created () {
// console.log(this.$route.path)
if (this.$route && this.$route.params && this.$route.params.o) {
this.fetchSingleAirport(this.$route.params.o, true)
}
if (this.$route && this.$route.params && this.$route.params.d) {
this.fetchSingleAirport(this.$route.params.d, false)
}
},
// watch: {
// history (to, from) {
// console.log(`routed from ${from} to ${to}`)
// }
// },
methods: {
makeOrigin (airport) {
// console.log(airport)
this.selectedOrig = { ...airport }
this.selectedDest = { ...this.emptyAirport }
history.pushState(
{},
null,
'/go/' + encodeURIComponent(airport.iata)
)
this.fetchDestinations(airport.iata)
},
makeDestination (airport) {
this.selectedDest = { ...airport }
history.pushState(
{},
null,
'/go/' + encodeURIComponent(this.selectedOrig.iata) + '/' + encodeURIComponent(airport.iata)
)
},
clearOrigin () {
this.selectedOrig = { ...this.emptyAirport }
this.selectedDest = { ...this.emptyAirport }
history.pushState(
{},
null,
'/go/'
)
},
clearDestination () {
this.selectedDest = { ...this.emptyAirport }
history.pushState(
{},
null,
'/go/' + encodeURIComponent(this.selectedOrig.iata)
)
},
async fetchDestinations (iata) {
const airportFetchDestfilterFormula = `AND(Is_Destination=1,{IsCurrent-AsDest}="Yes",(FIND("${iata}", Associated_Origin_Search)>0))`
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()
// console.log('mapData.records length: ' + mapData.records.length)
// console.log('this.airports_dest length (before): ' + this.airports_dest.length)
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,
name: record.fields.Airport_Name,
municipality: record.fields.Municipality,
type: record.fields.Type,
search: record.fields.Search_Field
}
})
// this.$refs.flMap.mapObject.fitBounds(this.markers.map((m) => { return [m.lat, m.lng] }))
// console.log('this.airports_dest length (after)' + this.airports_dest.length)
},
async fetchSingleAirport (iata, isOrig) {
const airportFetchFilterFormula =
isOrig
? `AND(Is_Origin=1,{IsCurrent-AsOrigin}="Yes",Airport_IATA="${iata}")`
: `AND(Is_Destination=1,{IsCurrent-AsDest}="Yes",Airport_IATA="${iata}")`
const response = await fetch(`https://api.airtable.com/v0/appiQwfVZixRgRICe/Airports_IATA?filterByFormula=${airportFetchFilterFormula}${this.airportFetch_fields_string}`, {
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Authorization: 'Bearer keyJ2ht64ZSN57AG1'
}
})
const mapData = await response.json()
const thisAirport = {
iata: mapData.records[0].fields.Airport_IATA,
lat: mapData.records[0].fields.Latitude_Deg,
long: mapData.records[0].fields.Longitude_Deg,
icon: mapData.records[0].fields.Icon_Url,
name: mapData.records[0].fields.Airport_Name,
municipality: mapData.records[0].fields.Municipality,
type: mapData.records[0].fields.Type,
search: mapData.records[0].fields.Search_Field
}
switch (isOrig) {
case true:
this.selectedOrig = { ...thisAirport }
this.fetchDestinations(thisAirport.iata)
break
case false:
this.selectedDest = { ...thisAirport }
break
default:
break
}
},
showPicker () {
this.isPickerVisible = !this.isPickerVisible
},
showSidebar () {
this.isSidebarVisible = !this.isSidebarVisible
}
}
}
</script>
<style>
html,
body,
#__nuxt,
#__layout,
.page-container,
main {
height: 100%;
}
header {
position: fixed;
top: 0;
width: 100vw;
z-index: 403;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
padding: 1rem;
}
.header__col:nth-child(2) {
text-align: center;
}
.header__col:nth-child(3) {
text-align: right;
}
.logo-blurb {
position: relative;
left: 4.5rem;
color: white;
top: -0.8rem;
}
main {
display: flex;
flex-direction: column;
/* grid-template-rows: min-content 1fr; */
}
.nav {
flex: 0 0 auto;
/* position: fixed;
top: 0;
padding-top: 4rem;
width: 100vw;
z-index: 401; */
background: white;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
:root {
--m-s: 0.1s;
--h-s: 0.3s;
--d: calc(var(--h-s) - var(--m-s));
}
.nav--hide {
transition: margin-top var(--m-s) linear var(--h-s), max-height var(--h-s) linear 0s;
margin-top: 0;
max-height: 0;
}
.nav--show {
margin-top: 3.5rem;
max-height: 250px;
transition: margin-top var(--m-s) linear 0s, max-height var(--h-s) linear var(--m-s);
}
.btn--nav-open {
padding: 1rem;
display: block;
}
.flyout-container {
z-index: 401;
position: fixed;
bottom: 0;
display: flex;
justify-content: center;
width: 100vw;
transition: all 0.3s;
pointer-events: none;
}
.flyout-container.flyout-container--hide {
transform: translateY(200px);
}
.flyout-container.flyout-container--show {
transform: translateY(0);
}
.sidebar-container {
z-index: 402;
position: fixed;
top: 0;
right: 0;
display: flex;
justify-content: flex-start;
height: 100vh;
transition: all 0.3s;
pointer-events: none;
}
.sidebar-container.sidebar-container--hide {
transform: translateX(200px);
}
.sidebar-container.sidebar-container--show {
transform: translateX(0);
}
.sidebar {
background: white;
padding: 3rem;
border-radius: 3rem 0 0 3rem;
pointer-events: all;
}
</style>