Files
SIB/frontend/src/components/FavoriteButton.vue

141 lines
2.8 KiB
Vue

<template>
<button
class="favorite-btn"
:class="{ 'is-favorite': isFavorited, 'is-loading': isLoading }"
@click.stop="handleToggle"
:title="isFavorited ? 'Quitar de favoritos' : 'Agregar a favoritos'"
>
<span class="material-icons heart-icon">
{{ isFavorited ? 'favorite' : 'favorite_border' }}
</span>
</button>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useFavoritesStore } from '@/stores/favorites'
import { useAuthStore } from '@/stores/auth'
const props = defineProps<{
itemType: 'coupon' | 'business' | 'taxi' | 'route' | 'stop'
itemId: string
itemName?: string
itemImage?: string
}>()
const favoritesStore = useFavoritesStore()
const authStore = useAuthStore()
const isLoading = ref(false)
const isFavorited = computed(() => {
return favoritesStore.isFavorite(props.itemType, props.itemId)
})
onMounted(() => {
// Load favorites if authenticated and not loaded yet
if (authStore.isAuthenticated && favoritesStore.favorites.length === 0) {
favoritesStore.loadFavorites()
}
})
async function handleToggle() {
if (!authStore.isAuthenticated) {
// Optionally redirect to login or show message
alert('Debes iniciar sesión para agregar favoritos')
return
}
isLoading.value = true
try {
await favoritesStore.toggleFavorite(
props.itemType,
props.itemId,
props.itemName,
props.itemImage
)
} catch (error) {
console.error('Error toggling favorite:', error)
} finally {
isLoading.value = false
}
}
</script>
<style scoped>
.favorite-btn {
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(10px);
border: none;
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
position: relative;
overflow: hidden;
}
.favorite-btn:hover {
transform: scale(1.1);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.favorite-btn:active {
transform: scale(0.95);
}
.heart-icon {
color: #e91e63;
font-size: 22px;
transition: all 0.3s;
position: relative;
z-index: 1;
}
.favorite-btn.is-favorite .heart-icon {
animation: heartBeat 0.5s ease;
}
.favorite-btn.is-loading {
pointer-events: none;
opacity: 0.6;
}
.favorite-btn.is-loading .heart-icon {
animation: pulse 1s ease-in-out infinite;
}
@keyframes heartBeat {
0%, 100% {
transform: scale(1);
}
25% {
transform: scale(1.3);
}
50% {
transform: scale(1.1);
}
75% {
transform: scale(1.2);
}
}
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
/* Dark mode support */
.dark .favorite-btn {
background: rgba(30, 30, 30, 0.9);
}
</style>