Initial commit: Vuelato - buscador de vuelos
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>
This commit is contained in:
Alejandro Martinez
2026-04-10 23:37:06 +02:00
commit b8906efc80
122 changed files with 37809 additions and 0 deletions

132
app/pages/settings.vue Normal file
View File

@@ -0,0 +1,132 @@
<script setup lang="ts">
const user = useSupabaseUser()
const { profile, loading, updateProfile, fetchProfile } = useUserPreferences()
const { showOriginTime } = useOriginTime()
useSeoMeta({ title: 'Vuelato - Preferencias' })
watch(user, (u) => {
if (!u) navigateTo('/auth')
}, { immediate: true })
const homeAirports = ref('')
const defaultAdults = ref(1)
const defaultChildren = ref(0)
const defaultInfants = ref(0)
const saving = ref(false)
const saved = ref(false)
watch(profile, (p) => {
if (!p) return
homeAirports.value = p.home_airports?.join(',') || ''
defaultAdults.value = p.default_adults ?? 1
defaultChildren.value = p.default_children ?? 0
defaultInfants.value = p.default_infants ?? 0
}, { immediate: true })
async function save() {
saving.value = true
saved.value = false
await updateProfile({
home_airports: homeAirports.value.split(',').map(s => s.trim().toUpperCase()).filter(Boolean),
default_adults: defaultAdults.value,
default_children: defaultChildren.value,
default_infants: defaultInfants.value,
})
saving.value = false
saved.value = true
setTimeout(() => { saved.value = false }, 2000)
}
</script>
<template>
<div v-if="user">
<UPageHero title="Preferencias" description="Configura tu experiencia en Vuelato" />
<UPageSection>
<div class="max-w-2xl mx-auto space-y-6">
<!-- Loading -->
<div v-if="loading" class="space-y-4">
<USkeleton class="h-12 w-full" />
<USkeleton class="h-12 w-full" />
<USkeleton class="h-12 w-full" />
</div>
<template v-else>
<!-- Busquedas -->
<UCard>
<template #header>
<h3 class="font-semibold">Busquedas</h3>
</template>
<div class="space-y-4">
<UFormField label="Aeropuertos de origen habituales">
<SearchAirportInput v-model="homeAirports" placeholder="MAD, BCN..." icon="i-lucide-plane-takeoff" multiple />
<template #hint>
<span class="text-xs text-muted">Se usaran como origen por defecto en las busquedas</span>
</template>
</UFormField>
<USeparator />
<p class="text-sm font-medium">Pasajeros por defecto</p>
<div class="grid grid-cols-3 gap-3">
<UFormField label="Adultos">
<UInput v-model.number="defaultAdults" type="number" :min="1" :max="9" class="w-full" />
</UFormField>
<UFormField label="Menores">
<UInput v-model.number="defaultChildren" type="number" :min="0" :max="9" class="w-full" />
</UFormField>
<UFormField label="Bebes">
<UInput v-model.number="defaultInfants" type="number" :min="0" :max="9" class="w-full" />
</UFormField>
</div>
</div>
<template #footer>
<div class="flex items-center gap-2">
<UButton label="Guardar" icon="i-lucide-save" size="sm" :loading="saving" @click="save" />
<Transition enter-active-class="transition-opacity" enter-from-class="opacity-0" leave-active-class="transition-opacity" leave-to-class="opacity-0">
<span v-if="saved" class="text-sm text-green-600">Guardado</span>
</Transition>
</div>
</template>
</UCard>
<!-- Visualizacion -->
<UCard>
<template #header>
<h3 class="font-semibold">Visualizacion</h3>
</template>
<div class="space-y-4">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium">Mostrar hora en origen</p>
<p class="text-xs text-muted">Muestra entre parentesis la hora equivalente en tu aeropuerto de salida</p>
</div>
<USwitch v-model="showOriginTime" />
</div>
</div>
</UCard>
<!-- Cuenta -->
<UCard>
<template #header>
<h3 class="font-semibold">Cuenta</h3>
</template>
<div class="space-y-2">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium">Email</p>
<p class="text-sm text-muted">{{ user.email }}</p>
</div>
</div>
</div>
</UCard>
</template>
</div>
</UPageSection>
</div>
</template>