Some checks failed
ci / ci (22, ubuntu-latest) (push) Has been cancelled
Nuxt 4 + Supabase + Flightics API. Incluye búsqueda de vuelos, inspiraciones, watchlist, tracking de precios y mapa interactivo. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
63 lines
2.3 KiB
Vue
63 lines
2.3 KiB
Vue
<script setup lang="ts">
|
|
import type { InspirationItem } from '~/server/utils/flightics'
|
|
|
|
const props = defineProps<{ items: InspirationItem[], from: string }>()
|
|
|
|
const { prefetch, getImage } = useDestinationImages()
|
|
const { airports, loadAirports } = useLocations()
|
|
|
|
onMounted(() => loadAirports())
|
|
|
|
function cityName(iata: string): string {
|
|
const a = airports.value.find(ap => ap.iata === iata)
|
|
return a?.city_name || iata
|
|
}
|
|
|
|
watch(() => props.items, (items) => {
|
|
const cities = items.slice(0, 12)
|
|
.map(i => cityName(i.to[0]))
|
|
.filter(c => c.length > 2)
|
|
if (cities.length) prefetch(cities)
|
|
}, { immediate: true })
|
|
</script>
|
|
|
|
<template>
|
|
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3">
|
|
<div
|
|
v-for="item in items"
|
|
:key="item.to[0]"
|
|
class="relative overflow-hidden rounded-lg cursor-pointer group h-36"
|
|
>
|
|
<img
|
|
v-if="getImage(cityName(item.to[0]))?.thumb_url"
|
|
:src="getImage(cityName(item.to[0]))!.thumb_url"
|
|
:alt="cityName(item.to[0])"
|
|
class="absolute inset-0 w-full h-full object-cover transition-transform duration-300 group-hover:scale-105"
|
|
>
|
|
<div v-else class="absolute inset-0 bg-gradient-to-br from-primary-500 to-primary-700" />
|
|
<div class="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent" />
|
|
<div class="absolute bottom-0 left-0 right-0 p-3 text-white">
|
|
<p class="font-bold text-sm truncate">{{ cityName(item.to[0]) }}</p>
|
|
<div class="flex items-center justify-between mt-0.5">
|
|
<p class="text-xs text-white/80">
|
|
{{ item.minStops === 0 ? 'Directo' : `${item.minStops} escala(s)` }}
|
|
</p>
|
|
<p class="text-lg font-bold">
|
|
{{ item.minPrice.toFixed(0) }}<span class="text-xs">€</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<a
|
|
v-if="getImage(cityName(item.to[0]))?.photographer"
|
|
:href="getImage(cityName(item.to[0]))!.photographer_url + '?utm_source=vuelato&utm_medium=referral'"
|
|
class="absolute top-1 right-1 text-[9px] text-white/50 hover:text-white/80 transition-colors"
|
|
target="_blank"
|
|
rel="noopener"
|
|
@click.stop
|
|
>
|
|
{{ getImage(cityName(item.to[0]))!.photographer }}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</template>
|