Skip to main content
The favorites system allows users to save Pokemon to a personalized collection for quick access.

Overview

The favorites feature provides:
  • Add Pokemon to favorites from detail pages
  • View all favorites in a dedicated page
  • Remove Pokemon from favorites
  • State persistence using Pinia store
  • Visual indicators for favorited Pokemon

Pinia Store

Favorites are managed using a Pinia store for centralized state management:
import { defineStore } from "pinia";
import { ref } from "vue"

export const useFavoritosStore = defineStore('favoritos',()=>{
    const favoritos=ref([]);
    const anyadir = (poke)=>{
        favoritos.value.push(poke.name);
    }
    const eliminar = (poke)=>{
        favoritos.value.splice(favoritos.value.indexOf(poke),1);
    }
    return {
        favoritos,
        anyadir,
        eliminar
    }
})
The store uses Vue 3’s Composition API style with ref() for reactive state.

Adding to Favorites

From the Pokemon detail page, users can add Pokemon to their favorites:
<script setup>
import { useFavoritosStore } from '@/stores/favoritos';
import { storeToRefs } from 'pinia';
import { computed } from 'vue';

const useFavorito = useFavoritosStore();
const { anyadir } = useFavorito;
const { favoritos } = storeToRefs(useFavorito);

const addToFavorites = () => {
    anyadir(datos.value);
    notificationMessage.value =${datos.value.name} se ha añadido a favoritos!`;
    showNotification.value = true;
    
    setTimeout(() => {
        showNotification.value = false;
    }, 3000);
};

const isFavorite = computed(() => {
    return favoritos.value.some(pokemon => pokemon.name === datos.value?.name);
});
</script>

<template>
    <button 
        @click="addToFavorites" 
        class="favorite-button"
        :class="{ 'is-favorite': isFavorite }"
    >
        {{ isFavorite ? '★ En favoritos' : '☆ Añadir a favoritos' }}
    </button>
</template>

Favorites Page

The dedicated favorites page displays all saved Pokemon:
<script setup>
import { storeToRefs } from "pinia";
import { useFavoritosStore } from '@/stores/favoritos';
import { ref, onMounted } from 'vue';

const useFavoritos = useFavoritosStore();
const { eliminar } = useFavoritos;
const { favoritos } = storeToRefs(useFavoritos);
const pokemons = ref([]);

const cargarFavoritos = async () => {
    pokemons.value = []; // Limpiar el array antes de cargar
    for (const name of favoritos.value) {
        try {
            const response = await fetch(`https://pokeapi.co/api/v2/pokemon/${name.toLowerCase()}`);
            const data = await response.json();
            pokemons.value.push({
                name: data.name,
                image: data.sprites.other['official-artwork'].front_default || data.sprites.front_default,
                id: data.id
            });
        } catch (error) {
            console.error(`Error cargando datos de ${name}:`, error);
        }
    }
};

const eliminarFavorito = async (pokemonName) => {
    eliminar(pokemonName);
    await cargarFavoritos(); // Recargar la lista después de eliminar
};

onMounted(cargarFavoritos);
</script>
The favorites page fetches full Pokemon data for each saved favorite to display images and details.

Removing from Favorites

Users can remove Pokemon from their favorites collection:
<template>
    <div v-for="pokemon in pokemons" :key="pokemon.name" class="pokemon-card">
        <RouterLink :to="`/pokemons/${pokemon.name}`" class="pokemon-link">
            <img :src="pokemon.image" :alt="pokemon.name" class="pokemon-image" />
            <h3 class="pokemon-name">{{ pokemon.name.charAt(0).toUpperCase() + pokemon.name.slice(1) }}</h3>
            <p class="pokemon-id">#{{ String(pokemon.id).padStart(3, '0') }}</p>
        </RouterLink>
        <button @click="eliminarFavorito(pokemon.name)" class="remove-button">
            <span class="material-icons"></span> Quitar de favoritos
        </button>
    </div>
</template>

Empty State

When no favorites are saved, a helpful empty state is displayed:
<div v-if="pokemons.length === 0" class="empty-state">
    <p>No tienes ningún Pokémon en favoritos</p>
</div>

Visual Feedback

When adding a Pokemon to favorites, a notification appears:
<div class="notification" v-if="showNotification">
    {{ notificationMessage }}
</div>
.notification {
    position: fixed;
    top: 20px;
    left: 50%;
    transform: translateX(-50%);
    background-color: #2f855a;
    color: white;
    padding: 12px 24px;
    border-radius: 8px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
    z-index: 1000;
    animation: slideIn 0.3s ease-out forwards;
}

@keyframes slideIn {
    from {
        transform: translate(-50%, -100%);
        opacity: 0;
    }
    to {
        transform: translate(-50%, 0);
        opacity: 1;
    }
}

State Management Flow

1

Initialize Store

The Pinia store is initialized with an empty favorites array.
2

Add Favorite

User clicks “Add to Favorites” button, which calls anyadir() method with Pokemon data.
3

Update State

The Pokemon’s name is pushed to the favoritos array in the store.
4

Reactive UI

All components using storeToRefs(useFavoritos) automatically update to reflect the new state.
5

Display Collection

The favorites page fetches full data for each saved Pokemon and displays them.

Data Structure

The store maintains a simple array of Pokemon names:
favoritos.value = ['pikachu', 'charizard', 'mewtwo']
When displaying favorites, full Pokemon data is fetched:
{
    name: 'pikachu',
    image: 'https://raw.githubusercontent.com/.../25.png',
    id: 25
}
Storing only names keeps the state lightweight, while full data is fetched on-demand when viewing the favorites page.

Pokemon Details

View detailed Pokemon information and add to favorites

Pokemon Browser

Browse all Pokemon to find favorites

Build docs developers (and LLMs) love