Perf: Fase 3 PWA Caché optimizado y Scroll Infinito progresivo en Vistas
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, ref, computed } from 'vue'
|
||||
import { onMounted, onUnmounted, ref, computed, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useTaxiStore } from '@/stores/taxi'
|
||||
import { analyticsService } from '@/services/analyticsService'
|
||||
@ -19,6 +19,11 @@ const onlyEnglish = ref(false)
|
||||
const corregimientos = ['all', 'Boquete', 'David - Boquete', 'Boquete - David', 'Aeropuerto - Boquete']
|
||||
const shifts = ['all', 'dia', 'tarde', 'noche']
|
||||
|
||||
// Infinite Scroll
|
||||
const displayLimit = ref(12)
|
||||
const observerTarget = ref<HTMLElement | null>(null)
|
||||
let observer: IntersectionObserver | null = null
|
||||
|
||||
function fetchData() {
|
||||
taxiStore.loadTaxis()
|
||||
}
|
||||
@ -31,6 +36,18 @@ function handleRefocus() {
|
||||
onMounted(async () => {
|
||||
analyticsService.logEvent({ event_name: 'screen_view', screen_name: 'TaxisLocales' })
|
||||
window.addEventListener('app-refocus', handleRefocus)
|
||||
|
||||
// Infinite Scroll Observer
|
||||
observer = new IntersectionObserver((entries) => {
|
||||
if (entries[0]?.isIntersecting) {
|
||||
displayLimit.value += 12
|
||||
}
|
||||
}, { rootMargin: '400px' })
|
||||
|
||||
if (observerTarget.value && observer) {
|
||||
observer.observe(observerTarget.value)
|
||||
}
|
||||
|
||||
if(taxiStore.taxis.length === 0) {
|
||||
await fetchData()
|
||||
}
|
||||
@ -38,6 +55,13 @@ onMounted(async () => {
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('app-refocus', handleRefocus)
|
||||
if (observer) {
|
||||
observer.disconnect()
|
||||
}
|
||||
})
|
||||
|
||||
watch([selectedZone, selectedShift, onlyEnglish], () => {
|
||||
displayLimit.value = 12
|
||||
})
|
||||
|
||||
const filteredTaxis = computed(() => {
|
||||
@ -50,6 +74,10 @@ const filteredTaxis = computed(() => {
|
||||
})
|
||||
})
|
||||
|
||||
const visibleTaxis = computed(() => {
|
||||
return filteredTaxis.value.slice(0, displayLimit.value)
|
||||
})
|
||||
|
||||
const isOnline = (taxi: Taxi) => {
|
||||
if (!taxi.shifts) return false
|
||||
return taxi.shifts.includes('dia') || taxi.shifts.includes('tarde')
|
||||
@ -139,7 +167,7 @@ function getShiftLabel(shift: string) {
|
||||
:message="t('shuttle.auth.message')"
|
||||
>
|
||||
<div class="taxis-grid">
|
||||
<div v-for="taxi in filteredTaxis" :key="taxi.id" v-memo="[taxi.id]" class="taxi-card-new glass-effect">
|
||||
<div v-for="taxi in visibleTaxis" :key="taxi.id" v-memo="[taxi.id]" class="taxi-card-new glass-effect">
|
||||
<div class="card-top">
|
||||
<div class="driver-avatar-wrap">
|
||||
<div class="driver-avatar">
|
||||
@ -201,6 +229,9 @@ function getShiftLabel(shift: string) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Infinite Scroll Trigger -->
|
||||
<div ref="observerTarget" class="h-10 w-full mt-4"></div>
|
||||
|
||||
<div v-if="filteredTaxis.length === 0" class="empty-state">
|
||||
<span class="material-icons">no_accounts</span>
|
||||
<p>{{ t('taxi.noTaxisAvailable') }}</p>
|
||||
|
||||
Reference in New Issue
Block a user