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>
88 lines
2.6 KiB
Vue
88 lines
2.6 KiB
Vue
<script setup lang="ts">
|
|
const user = useSupabaseUser()
|
|
const { trackedSearches, loading, update, remove, fetchAll } = useTrackedSearches()
|
|
const router = useRouter()
|
|
|
|
const showCreateForm = ref(false)
|
|
|
|
useSeoMeta({ title: 'Vuelato - Seguimiento de precios' })
|
|
|
|
watch(user, (u) => {
|
|
if (!u) navigateTo('/auth')
|
|
}, { immediate: true })
|
|
|
|
async function onToggle(id: string, active: boolean) {
|
|
await update(id, { is_active: active })
|
|
}
|
|
|
|
async function onRemove(id: string) {
|
|
await remove(id)
|
|
}
|
|
|
|
function onDetail(id: string) {
|
|
router.push(`/tracking/${id}`)
|
|
}
|
|
|
|
function onCreated() {
|
|
showCreateForm.value = false
|
|
fetchAll()
|
|
}
|
|
|
|
const activeCount = computed(() => trackedSearches.value.filter(s => s.is_active).length)
|
|
</script>
|
|
|
|
<template>
|
|
<div v-if="user">
|
|
<UPageHero title="Seguimiento de precios" description="Busquedas automaticas que monitorizan fluctuaciones de precio" />
|
|
|
|
<UPageSection>
|
|
<div class="max-w-3xl mx-auto space-y-4">
|
|
<!-- Actions -->
|
|
<div class="flex items-center justify-between">
|
|
<p class="text-sm text-muted">
|
|
{{ trackedSearches.length }} seguimiento{{ trackedSearches.length !== 1 ? 's' : '' }}
|
|
<span v-if="activeCount > 0"> ({{ activeCount }} activo{{ activeCount !== 1 ? 's' : '' }})</span>
|
|
</p>
|
|
<UButton
|
|
v-if="!showCreateForm"
|
|
label="Nuevo seguimiento"
|
|
icon="i-lucide-plus"
|
|
size="sm"
|
|
@click="showCreateForm = true"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Create form -->
|
|
<TrackingCreateTrackingForm
|
|
v-if="showCreateForm"
|
|
@created="onCreated"
|
|
@cancel="showCreateForm = false"
|
|
/>
|
|
|
|
<!-- Loading -->
|
|
<div v-if="loading" class="space-y-3">
|
|
<USkeleton v-for="i in 3" :key="i" class="h-28 w-full" />
|
|
</div>
|
|
|
|
<!-- Empty -->
|
|
<div v-else-if="trackedSearches.length === 0 && !showCreateForm" class="text-center py-12">
|
|
<UIcon name="i-lucide-bell" class="text-4xl text-neutral-300 mb-2" />
|
|
<p class="text-neutral-500">No tienes busquedas en seguimiento</p>
|
|
<p class="text-sm text-neutral-400 mt-1">Crea una para monitorizar precios automaticamente</p>
|
|
<UButton label="Crear seguimiento" icon="i-lucide-plus" class="mt-3" @click="showCreateForm = true" />
|
|
</div>
|
|
|
|
<!-- Search cards -->
|
|
<TrackingTrackedSearchCard
|
|
v-for="search in trackedSearches"
|
|
:key="search.id"
|
|
:search="search"
|
|
@toggle="onToggle"
|
|
@remove="onRemove"
|
|
@detail="onDetail"
|
|
/>
|
|
</div>
|
|
</UPageSection>
|
|
</div>
|
|
</template>
|