Étape 11 – Ajouter un système de favoris
🎯 Objectifs de l’étape
Dans cette étape, vous allez permettre à l’utilisateur de marquer un Pokémon comme favori.
Chaque carte affichera une icône en forme de cœur ❤️ sur laquelle on peut cliquer pour ajouter ou retirer un favori.
Vous apprendrez à :
- utiliser une icône Vuetify conditionnelle,
- manipuler des données via Pinia (toggleFavorite),
- afficher l’état favori d’un Pokémon (plein ou vide),
- ajouter une animation CSS au changement d’état,
- charger automatiquement les favoris au démarrage de l’application.
📁 Étapes à suivre
1. Modifier PokemonCard.vue
Dans le composant PokemonCard.vue, ajoutez un bouton en haut à droite de la carte pour gérer les favoris.
Ajoutez d’abord l’import du store :
import {usePokemonStore} from '@/stores/pokemonStore'
const pokemonStore = usePokemonStore()Puis ajoutez le bouton dans la carte :
<v-btn
icon
variant="plain"
class="position-absolute top-0 right-0 mt-2 mr-2"
@click.prevent="pokemonStore.toggleFavorite(pokemon)"
>
<v-icon :color="pokemonStore.isFavorite(pokemon) ? 'red' : ''">
{{ pokemonStore.isFavorite(pokemon) ? 'mdi-heart' : 'mdi-heart-outline' }}
</v-icon>
</v-btn>2. Charger les favoris au démarrage
L'action toggleFavorite qui permet d’ajouter ou de retirer un Pokémon des favoris sauvegarde automatiquement les favoris dans le localStorage afin de les conserver même après un redémarrage du navigateur.
Dans cette version, les favoris sont bien sauvegardés et aussi restaurés directement à l'initialisation du store pokemonStore grâce à la méthode loadFavorites() déjà présente dans votre projet.
/**
* Charge les favoris depuis le stockage local du navigateur (localStorage).
* Cette méthode est appelée au démarrage pour restaurer les favoris précédents.
*/
loadFavorites () {
try {
// Récupérer les favoris depuis localStorage
const savedFavorites = localStorage.getItem('pokemon_favorites')
if (savedFavorites) {
// Parser le JSON et stocker dans le state
this.favorites = JSON.parse(savedFavorites)
console.log('💾 Favoris chargés depuis le navigateur:', this.favorites.length, 'éléments')
} else {
// Pas de favoris sauvegardés, initialiser un tableau vide
this.favorites = []
console.log('💾 Aucun favori sauvegardé trouvé')
}
} catch (error) {
// En cas d'erreur (données corrompues), réinitialiser
console.error('❌ Erreur lors du chargement des favoris:', error)
this.favorites = []
}
},Celle-ci est implicitement appelé lors de l'appel fonction init, qui sert à initialiser le store dans App.vue.
<script setup>
// Importation du composant MenuPrincipal pour l'en-tête de l'application
import MenuPrincipal from '@/components/AppHeader.vue'
// Importation du lifecycle hook `onMounted` pour exécuter du code après que le composant a été monté
import { onMounted } from 'vue'
// Importation des magasins d'état pour l'authentification et les Pokémon
import { useAuthStore } from '@/stores/authStore'
import { usePokemonStore } from '@/stores/pokemonStore'
// Actions à effectuer après le montage du composant (onMounted)
onMounted(async () => {
// Récupération du magasin d'Authentification
const authStore = useAuthStore()
// Récupération du token d'authentification depuis le localStorage
authStore.loadToken()
// Récupération du magasin des Pokémon
const pokemonStore = usePokemonStore()
await pokemonStore.init()
})
</script>Voici le code complet de la méthode init dans le store pokemonStore :
async init () {
console.log('🚀 Initialisation du store Pokémon...')
this.isLoading = true
try {
await Promise.all([
this.fetchTypes({ withLoader: false }),
this.fetchPokemons({ withLoader: false }),
])
// Charger les favoris sauvegardés dans le navigateur
this.loadFavorites()
console.log('✅ Store Pokémon initialisé')
} catch (error) {
console.error('❌ Erreur lors de l\'initialisation du store Pokémon:', error)
} finally {
this.isLoading = false
}
console.log('ℹ️ Les requêtes utilisent maintenant la configuration axios globale')
},WARNING
Ces bouts de codes ne sont présents qu'à titre informatif, vous n'avez pas besoin de les implémenter puisqu'ils sont déjà présents dans votre projet.
🔄 Fonctionnement du système de favoris
Le store pokemonStore fournit déjà plusieurs fonctions prêtes à l’emploi :
| Fonction | Rôle |
|---|---|
toggleFavorite(pokemon) | ajoute ou retire un Pokémon des favoris |
isFavorite(pokemon) | retourne true si le Pokémon est favori |
loadFavorites() | charge les favoris depuis l'API |
Ces fonctions permettent une persistance des favoris même après redémarrage du navigateur.
✅ Résultat attendu
- Un cœur vide (🤍) s’affiche sur les cartes non favorites
- Un cœur rouge (❤️) s’affiche si le Pokémon est marqué comme favori
- Le clic sur l’icône ajoute ou retire un favori en temps réel
- Les favoris sont sauvegardés et restaurés automatiquement
🧪 Test à effectuer
- Cliquez sur plusieurs icônes de cœur
- Rafraîchissez la page
- Vérifiez que l’état des favoris est conservé
📘 Documentation utile
💡 Astuces bonus
- Vous pouvez ajouter une animation CSS au changement d’état du cœur
- Changez la position du bouton avec des classes utilitaires comme
absolute,top,right, etc.