Files
vuelato/app/components/SearchForm.vue
Alejandro Martinez b8906efc80
Some checks failed
ci / ci (22, ubuntu-latest) (push) Has been cancelled
Initial commit: Vuelato - buscador de vuelos
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>
2026-04-10 23:37:06 +02:00

170 lines
4.6 KiB
Vue

<script setup lang="ts">
const emit = defineEmits<{
search: [data: {
mode: string
departures: string[]
destination: string[]
dateFrom: string
dateTo: string
stayMinDays: number
stayMaxDays: number
passengers: { adult: number; child: number; infant: number }
maxStops: number | null
budget: number | null
}]
}>()
defineProps<{
compact?: boolean
}>()
const { homeAirports, defaultPassengers } = useUserPreferences()
const mode = ref('roundtrip')
const departures = ref('')
const destination = ref('')
const dateFrom = ref('')
const dateTo = ref('')
const stayMinDays = ref(2)
const stayMaxDays = ref(6)
const passengers = ref({ adult: 2, child: 0, infant: 0 })
const maxStops = ref<number | null>(null)
const budget = ref(500)
const showBudget = ref(false)
// Apply user preferences when available
watch(homeAirports, (airports) => {
if (airports.length && !departures.value) {
departures.value = airports.join(',')
}
}, { immediate: true })
watch(defaultPassengers, (p) => {
if (p.adult > 0) passengers.value = { ...p }
}, { immediate: true })
const showDestination = computed(() => mode.value !== 'explore')
const showDateTo = computed(() => mode.value !== 'oneway')
const showStayDuration = computed(() => ['roundtrip', 'multicity'].includes(mode.value))
const isWeekend = computed(() => mode.value === 'weekend')
const isExplore = computed(() => mode.value === 'explore')
function submit() {
emit('search', {
mode: mode.value,
departures: departures.value.split(',').map(s => s.trim().toUpperCase()).filter(Boolean),
destination: destination.value.split(',').map(s => s.trim().toUpperCase()).filter(Boolean),
dateFrom: dateFrom.value,
dateTo: dateTo.value || dateFrom.value,
stayMinDays: stayMinDays.value,
stayMaxDays: stayMaxDays.value,
passengers: passengers.value,
maxStops: maxStops.value,
budget: showBudget.value ? budget.value : null
})
}
</script>
<template>
<form class="space-y-4" @submit.prevent="submit">
<SearchModeTabs v-model="mode" />
<div :class="compact ? 'space-y-3' : 'space-y-4'">
<!-- Origen -->
<UFormField label="Origen">
<SearchAirportInput
v-model="departures"
placeholder="Buscar aeropuerto..."
icon="i-lucide-plane-takeoff"
multiple
/>
</UFormField>
<!-- Destino (no en modo explorar) -->
<UFormField v-if="showDestination" label="Destino">
<SearchAirportInput
v-model="destination"
placeholder="NTE"
icon="i-lucide-plane-landing"
multiple
/>
</UFormField>
<!-- Fechas -->
<SearchDateRangePicker
v-model:date-from="dateFrom"
v-model:date-to="dateTo"
:single-date="!showDateTo"
/>
<!-- Estancia (roundtrip, multicity) -->
<SearchStayDurationPicker
v-if="showStayDuration"
v-model:min-days="stayMinDays"
v-model:max-days="stayMaxDays"
/>
<!-- Weekend hint -->
<UAlert
v-if="isWeekend"
color="info"
icon="i-lucide-info"
title="Busca vuelos de viernes a domingo automaticamente"
/>
<!-- Explore hint -->
<UAlert
v-if="isExplore"
color="info"
icon="i-lucide-compass"
title="Descubre destinos baratos desde tu aeropuerto"
/>
<!-- Pasajeros en popover -->
<UFormField label="Pasajeros">
<UPopover>
<UButton
:label="`${passengers.adult + passengers.child + passengers.infant} pasajero(s)`"
icon="i-lucide-users"
color="neutral"
variant="outline"
block
class="justify-start"
/>
<template #content>
<div class="p-4 w-64">
<PassengerPicker v-model="passengers" />
</div>
</template>
</UPopover>
</UFormField>
<!-- Opciones avanzadas -->
<div class="flex flex-wrap gap-4 items-end">
<div>
<p class="text-xs text-muted mb-1">Escalas</p>
<SearchMaxStopsFilter v-model="maxStops" />
</div>
<UButton
:label="showBudget ? 'Ocultar presupuesto' : 'Presupuesto max'"
icon="i-lucide-wallet"
color="neutral"
variant="ghost"
size="xs"
@click="showBudget = !showBudget"
/>
</div>
<SearchBudgetSlider v-if="showBudget" v-model="budget" />
</div>
<UButton
type="submit"
:label="isExplore ? 'Explorar destinos' : 'Buscar vuelos'"
icon="i-lucide-search"
size="lg"
block
/>
</form>
</template>