fix(favorites): adjust favorite button visibility and functionality

- removed favorite button from Discover cards

- added call button for taxis in Favorites view

- added favorite button in Shuttle details

- added Shuttles category in Favorites view
This commit is contained in:
2026-03-04 16:34:47 -05:00
parent ef5955cea2
commit 35e2a6d632
6 changed files with 94 additions and 31 deletions

View File

@ -4,7 +4,6 @@ import { businessService } from '@/services/businessService'
import type { Business } from '@/types'
import { useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import FavoriteButton from '@/components/FavoriteButton.vue'
import { analyticsService } from '@/services/analyticsService'
import { getImageUrl } from '@/utils/imageUrl'
import AuthGuard from '@/components/common/AuthGuard.vue'
@ -242,9 +241,6 @@ function resetFilters() {
class="biz-img"
@error="(e) => (e.target as HTMLImageElement).src = getImageUrl(null, 'business')"
/>
<div class="biz-fav">
<FavoriteButton item-type="business" :item-id="biz.id" :item-name="biz.name" :item-image="biz.image_url || undefined" />
</div>
<span class="biz-cat-badge">
<span class="material-icons" style="font-size:0.875rem">{{ catIcon(biz.category || '') }}</span>
{{ catName(biz.category || '') }}
@ -320,9 +316,6 @@ function resetFilters() {
@error="(e) => (e.target as HTMLImageElement).src = getImageUrl(null, 'business')"
/>
<div class="featured-gradient"></div>
<div class="featured-fav">
<FavoriteButton item-type="business" :item-id="biz.id" :item-name="biz.name" :item-image="biz.image_url || undefined" />
</div>
<div class="featured-info">
<span class="featured-cat">
<span class="material-icons" style="font-size:0.8rem">{{ catIcon(biz.category || '') }}</span>
@ -358,9 +351,6 @@ function resetFilters() {
class="biz-img"
@error="(e) => (e.target as HTMLImageElement).src = getImageUrl(null, 'business')"
/>
<div class="biz-fav">
<FavoriteButton item-type="business" :item-id="biz.id" :item-name="biz.name" :item-image="biz.image_url || undefined" />
</div>
<span class="biz-cat-badge">
<span class="material-icons" style="font-size:0.875rem">{{ catIcon(biz.category || '') }}</span>
{{ catName(biz.category || '') }}
@ -648,13 +638,6 @@ function resetFilters() {
background: linear-gradient(to top, rgba(0,0,0,0.75) 40%, transparent 70%);
}
.featured-fav {
position: absolute;
top: 0.625rem;
right: 0.625rem;
z-index: 2;
}
.featured-info {
position: absolute;
bottom: 0;
@ -738,12 +721,6 @@ function resetFilters() {
object-fit: cover;
}
.biz-fav {
position: absolute;
top: 0.5rem;
right: 0.5rem;
}
.biz-cat-badge {
position: absolute;
bottom: 0.5rem;

View File

@ -3,6 +3,7 @@ import { ref, computed, watch } from 'vue'
import { useRouter } from 'vue-router'
import { useFavoritesStore } from '@/stores/favorites'
import { useAuthStore } from '@/stores/auth'
import { useTaxiStore } from '@/stores/taxi'
import { useI18n } from 'vue-i18n'
import { getImageUrl as utilGetImageUrl } from '@/utils/imageUrl'
import LoadingBranded from '@/components/common/LoadingBranded.vue'
@ -11,11 +12,13 @@ const router = useRouter()
const { t } = useI18n()
const favoritesStore = useFavoritesStore()
const authStore = useAuthStore()
const taxiStore = useTaxiStore()
const selectedFilter = ref('all')
const filters = computed(() => [
{ key: 'all', label: t('common.all'), icon: 'star' },
{ key: 'routes', label: t('favorites.tabs.routes'), icon: 'directions_bus' },
{ key: 'shuttles', label: 'Viajes Turísticos', icon: 'airport_shuttle' },
{ key: 'taxis', label: t('favorites.tabs.taxis'), icon: 'local_taxi' },
{ key: 'businesses',label: t('favorites.tabs.businesses'), icon: 'store' },
{ key: 'coupons', label: t('favorites.tabs.coupons'), icon: 'confirmation_number' },
@ -28,11 +31,17 @@ watch(
(authenticated) => {
if (authenticated) {
favoritesStore.loadFavorites()
taxiStore.silentReload()
}
},
{ immediate: true }
)
function getTaxiPhone(id: string) {
const taxi = taxiStore.taxis.find(t => t.id === id)
return taxi?.phone_number || ''
}
function getImageUrl(path?: string) {
return utilGetImageUrl(path, 'business')
}
@ -44,10 +53,11 @@ async function removeFavorite(event: Event, itemType: string, itemId: string) {
function navigateToItem(item: any) {
if (item.item_type === 'route') router.push({ path: '/schedules', query: { routeId: item.item_id } })
else if (item.item_type === 'taxi') router.push('/taxi')
else if (item.item_type === 'taxi') router.push('/transporte/taxis')
else if (item.item_type === 'business') router.push('/business/' + item.item_id)
else if (item.item_type === 'coupon') router.push('/coupons')
else if (item.item_type === 'stop') router.push({ path: '/map', query: { stopId: item.item_id } })
else if (item.item_type === 'shuttle') router.push({ name: 'ShuttleDetalle', params: { id: item.item_id } })
}
const visibleRoutes = computed(() =>
@ -65,12 +75,15 @@ const visibleCoupons = computed(() =>
const visibleStops = computed(() =>
(selectedFilter.value === 'all' || selectedFilter.value === 'stops') ? favoritesStore.stops : []
)
const visibleShuttles = computed(() =>
(selectedFilter.value === 'all' || selectedFilter.value === 'shuttles') ? favoritesStore.shuttles : []
)
const totalFavorites = computed(() => favoritesStore.favorites.length)
const hasVisibleItems = computed(() =>
visibleRoutes.value.length + visibleTaxis.value.length +
visibleBusinesses.value.length + visibleCoupons.value.length +
visibleStops.value.length > 0
visibleStops.value.length + visibleShuttles.value.length > 0
)
</script>
@ -181,6 +194,15 @@ const hasVisibleItems = computed(() =>
<p class="card-name">{{ item.item_name }}</p>
<p class="card-sub">{{ t('favorites.availability') }}</p>
</div>
<a
v-if="getTaxiPhone(item.item_id)"
:href="'tel:' + getTaxiPhone(item.item_id)"
class="call-btn"
@click.stop
title="Llamar ahora"
>
<span class="material-icons">phone_in_talk</span>
</a>
<button class="heart-btn heart-btn--active" @click.stop="removeFavorite($event, item.item_type, item.item_id)" :title="t('favorites.removeTitle')">
<span class="material-icons">favorite</span>
</button>
@ -188,6 +210,33 @@ const hasVisibleItems = computed(() =>
</div>
</section>
<!-- SHUTTLES -->
<section v-if="visibleShuttles.length > 0" class="fav-section">
<div class="section-label">
<span class="material-icons">airport_shuttle</span>
<span>Viajes Turísticos</span>
</div>
<div class="card-list">
<div
v-for="item in visibleShuttles"
:key="item.id"
class="card card--row"
@click="navigateToItem(item)"
>
<div class="card-thumb card-thumb--img">
<img :src="getImageUrl(item.item_image)" :alt="item.item_name" />
</div>
<div class="card-info">
<p class="card-name">{{ item.item_name }}</p>
<p class="card-sub">Ver detalles</p>
</div>
<button class="heart-btn heart-btn--active" @click.stop="removeFavorite($event, item.item_type, item.item_id)">
<span class="material-icons">favorite</span>
</button>
</div>
</div>
</section>
<!-- NEGOCIOS -->
<section v-if="visibleBusinesses.length > 0" class="fav-section">
<div class="section-label">
@ -524,6 +573,32 @@ const hasVisibleItems = computed(() =>
transform: scale(1.1);
}
.call-btn {
background: var(--active-color);
border: none;
width: 38px;
height: 38px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #101820;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
flex-shrink: 0;
margin-right: -4px;
}
.call-btn:hover {
transform: scale(1.1);
box-shadow: 0 4px 15px rgba(254, 231, 21, 0.3);
}
.call-btn .material-icons {
font-size: 20px;
}
.heart-btn--overlay {
position: absolute;
top: 0.5rem;

View File

@ -7,6 +7,7 @@ import { getImageUrl } from '@/utils/imageUrl'
import { analyticsService } from '@/services/analyticsService'
import { useI18n } from 'vue-i18n'
import LoadingBranded from '@/components/common/LoadingBranded.vue'
import FavoriteButton from '@/components/FavoriteButton.vue'
const route = useRoute()
const router = useRouter()
@ -73,6 +74,13 @@ const getTripTypeLabel = (type: string) => {
<h1 class="font-bold text-[var(--text-primary)] text-lg truncate flex-1">
{{ shuttle?.company_name || t('shuttle.detailTitle') }}
</h1>
<FavoriteButton
v-if="shuttle"
item-type="shuttle"
:item-id="shuttle.id"
:item-name="shuttle.company_name || shuttle.origin + ' - ' + shuttle.destination"
:item-image="shuttle.image_url || undefined"
/>
</div>
<!-- Loading -->