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.

270 lines
5.6 KiB

  1. <template>
  2. <div class="picker-wrap">
  3. <!-- <pre style="position: fixed; z-index: 500; right: 0; top: 7rem; font-size: 0.6rem; color: orange;">
  4. {{ selectedAirport }}
  5. </pre> -->
  6. <label v-if="!origin">
  7. start here
  8. </label>
  9. <label v-if="origin">
  10. land here
  11. </label>
  12. <v-select
  13. :value="selectedAirportComp"
  14. label="iata"
  15. :options="airports"
  16. :filter-by="filterBy"
  17. :components="{OpenIndicator, Deselect}"
  18. @input="changeAirport"
  19. >
  20. <template #no-options="{ search, searching }">
  21. <template v-if="searching">
  22. We didn't find any airports or towns called <em>{{ search }}</em>.
  23. </template>
  24. <!-- <em
  25. v-else
  26. style="opacity: 0.5;"
  27. >
  28. Start typing to search for an airport.
  29. </em> -->
  30. </template>
  31. <template #selected-option="option">
  32. <div class="picker-item">
  33. <div class="picker-item__section">
  34. <div class="picker-item__iata">
  35. {{ option.iata }}
  36. </div>
  37. </div>
  38. <div class="picker-item__section">
  39. <div class="picker-item__name">
  40. {{ option.name }}
  41. </div>
  42. <div class="picker-item__muni">
  43. {{ option.municipality }}
  44. </div>
  45. </div>
  46. </div>
  47. </template>
  48. <template #option="option">
  49. <div class="picker-item">
  50. <div class="picker-item__section">
  51. <div class="picker-item__iata">
  52. {{ option.iata }}
  53. </div>
  54. </div>
  55. <div class="picker-item__section">
  56. <div class="picker-item__name">
  57. {{ option.name }}
  58. </div>
  59. <div class="picker-item__muni">
  60. {{ option.municipality }}
  61. </div>
  62. </div>
  63. </div>
  64. </template>
  65. <template #search="{ events, attributes }">
  66. <input
  67. :placeholder="placeholder"
  68. type="search"
  69. class="vs__search"
  70. v-bind="attributes"
  71. v-on="events"
  72. >
  73. </template>
  74. <template v-if="origin" #list-header>
  75. <li class="picker-warning">
  76. fly from <strong>{{ origin.iata }}</strong> to {{ airports.length > 1 ? "these" : "this" }} <strong>{{ airports.length }}</strong> {{ airports.length > 1 ? "airports" : "airport" }}
  77. </li>
  78. </template>
  79. </v-select>
  80. </div>
  81. </template>
  82. <script>
  83. import OpenIndicator from './OpenIndicator.vue'
  84. import Deselect from './Deselect.vue'
  85. export default {
  86. // ClearButton,
  87. props: {
  88. airports: {
  89. type: [Array],
  90. default () {
  91. return []
  92. }
  93. },
  94. selectedAirport: {
  95. type: [Object],
  96. default () {
  97. return {
  98. iata: '',
  99. lat: '',
  100. long: '',
  101. icon: '',
  102. name: '',
  103. municipality: '',
  104. type: '',
  105. search: ''
  106. }
  107. }
  108. },
  109. origin: {
  110. type: [Object],
  111. default () {
  112. return null
  113. }
  114. }
  115. },
  116. data: () => ({
  117. OpenIndicator,
  118. filterBy: (option, label, search) => {
  119. const temp = search.toLowerCase()
  120. return option.search.toLowerCase().includes(temp)
  121. }
  122. }),
  123. computed: {
  124. Deselect () {
  125. return this.selectedAirportComp.iata ? Deselect : ''
  126. },
  127. selectedAirportComp () {
  128. return {
  129. iata: this.selectedAirport.iata,
  130. lat: this.selectedAirport.lat,
  131. long: this.selectedAirport.long,
  132. icon: this.selectedAirport.icon,
  133. name: this.selectedAirport.name,
  134. municipality: this.selectedAirport.municipality,
  135. type: this.selectedAirport.type,
  136. search: this.selectedAirport.search,
  137. label: this.selectedAirport.label
  138. }
  139. },
  140. placeholder () {
  141. return (this.selectedAirport.iata) ? '' : 'town or airport'
  142. }
  143. },
  144. methods: {
  145. changeAirport (value) {
  146. if (value) {
  147. this.$emit('select-airport', value)
  148. } else {
  149. this.$emit('deselect-airport', value)
  150. }
  151. }
  152. }
  153. }
  154. </script>
  155. <style>
  156. .picker-wrap {
  157. margin: 1rem;
  158. position: relative;
  159. width: min(100vw - 2rem, 500px);
  160. }
  161. .picker-wrap:last-of-type {
  162. margin-top: 0;
  163. }
  164. .picker-wrap .vs__search {
  165. font-size: 3rem !important;
  166. padding: 0.5rem;
  167. }
  168. .vs__search::placeholder {
  169. color: #bbb;
  170. }
  171. .vs__dropdown-toggle {
  172. background: #eee;
  173. border: 0;
  174. border-radius: 0.5rem 3rem 3rem 3rem;
  175. padding-right: 0.5rem;
  176. padding-left: 0.5rem;
  177. padding-bottom: 0;
  178. }
  179. .vs__selected-options {
  180. padding: 0;
  181. }
  182. .picker-wrap .vs__search,
  183. .picker-wrap .vs__search:focus {
  184. margin: 0;
  185. }
  186. .picker-wrap .vs__actions {
  187. padding: 0;
  188. }
  189. .picker-item {
  190. padding: 0.5rem;
  191. display: flex;
  192. flex-direction: row;
  193. align-items: center;
  194. }
  195. .picker-item__section {
  196. display: flex;
  197. flex-direction: column;
  198. }
  199. .picker-item__name {
  200. font-size: 1rem;
  201. line-height: 1.1;
  202. white-space: normal;
  203. }
  204. .picker-item__muni {
  205. color: #007fff;
  206. line-height: 1.1;
  207. font-weight: 500;
  208. padding-top: 0.25rem;
  209. white-space: normal;
  210. }
  211. .picker-item__iata {
  212. font-size: 3rem;
  213. margin-right: 1rem;
  214. }
  215. .vs--single .vs__selected {
  216. position: absolute;
  217. }
  218. .vs__dropdown-option--highlight {
  219. background: #007fff;
  220. }
  221. .vs__dropdown-option--highlight .picker-item__muni {
  222. color: #eee;
  223. }
  224. </style>
  225. <style scoped>
  226. label {
  227. display: block;
  228. color: gray;
  229. position: absolute;
  230. z-index: 1;
  231. text-transform: uppercase;
  232. font-weight: 300;
  233. top: 0.3rem;
  234. left: 0.5rem;
  235. letter-spacing: 0.13rem;
  236. font-size: 0.8rem;
  237. }
  238. .picker-warning {
  239. background: hotpink;
  240. color: white;
  241. padding: 1rem;
  242. font-size: 1.5rem;
  243. pointer-events: none;
  244. }
  245. </style>