feat: intégration de @tanstack/vue-query pour la gestion des requêtes dans l'application Vue, ajout de nouveaux composables pour les chapitres et les détails des mangas, et mise à jour du store pour une meilleure gestion des états de chargement et d'erreur

This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2025-03-30 16:58:05 +02:00
parent fd2d3cd640
commit 71242433e6
10 changed files with 355 additions and 169 deletions

View File

@@ -0,0 +1,23 @@
import { computed } from 'vue';
import { useQuery } from '@tanstack/vue-query';
import { ApiMangaRepository } from '../../infrastructure/api/apiMangaRepository';
export function useMangaChapters(mangaId) {
const mangaRepository = new ApiMangaRepository();
const query = useQuery({
queryKey: ['manga', mangaId, 'chapters'],
queryFn: async () => {
if (!mangaId.value) {
return Promise.resolve([]); // Retourne un tableau vide si pas d'ID
}
const response = await mangaRepository.getChapters(mangaId.value);
// Assure de toujours retourner un tableau
return Array.isArray(response) ? response : response?.items ?? [];
},
enabled: computed(() => !!mangaId.value)
});
// Retourne le résultat de useQuery (contenant data, isLoading, etc.)
return query;
}

View File

@@ -0,0 +1,31 @@
import { computed } from 'vue';
import { useQuery } from '@tanstack/vue-query';
import { ApiMangaRepository } from '../../infrastructure/api/apiMangaRepository';
// Accepte un ID de manga (peut être une ref, un computed ref, ou une valeur simple)
export function useMangaDetails(mangaId) {
const mangaRepository = new ApiMangaRepository();
// Assure que mangaId est une ref ou une computed pour la réactivité de la queryKey
// Si ce n'est pas déjà le cas, mais généralement on passera une computed( () => route.params.id )
// const mangaIdRef = computed(() => unref(mangaId)); // unref est utile si on accepte des valeurs simples aussi
const query = useQuery({
// La queryKey doit être réactive à mangaId
queryKey: ['manga', mangaId], // mangaId est déjà une computed ref, donc c'est bon
queryFn: () => {
// Vérifier que l'ID a une valeur avant d'appeler l'API
if (!mangaId.value) {
// Retourner null ou undefined si pas d'ID, pour éviter un appel API invalide
// TanStack Query gère aussi l'option 'enabled' pour cela
return Promise.resolve(null); // ou throw new Error("ID manquant");
}
return mangaRepository.getMangaById(mangaId.value);
},
// Activer la requête seulement si mangaId a une valeur truthy
enabled: computed(() => !!mangaId.value)
});
// Retourne tous les états et données fournis par useQuery
return query;
}

View File

@@ -0,0 +1,51 @@
import { computed } from 'vue';
import { useMangaChapters } from './useMangaChapters'; // Importe le composable des chapitres
export function useMangaVolumes(mangaId) {
// Utilise le composable des chapitres pour récupérer les données brutes et les états
const { data: rawChaptersData, isLoading, isFetching, error, status } = useMangaChapters(mangaId);
// Calcule les volumes à partir des données des chapitres
const volumes = computed(() => {
const chaptersArray = rawChaptersData.value || []; // Utilise la data retournée par useMangaChapters
if (chaptersArray.length === 0) return [];
const volumeMap = new Map();
chaptersArray.forEach(chapter => {
const volumeNumber = chapter.volume || 'Unknown';
if (!volumeMap.has(volumeNumber)) {
volumeMap.set(volumeNumber, {
number: volumeNumber,
downloadedChapter: 0,
totalChapter: 0,
chapters: []
});
}
const volumeEntry = volumeMap.get(volumeNumber);
volumeEntry.chapters.push({
...chapter,
isAvailable: Boolean(chapter.isAvailable)
});
volumeEntry.totalChapter++;
if (chapter.isAvailable) {
volumeEntry.downloadedChapter++;
}
});
return Array.from(volumeMap.values()).sort((a, b) => {
const numA = a.number === 'Unknown' ? -Infinity : Number(a.number);
const numB = b.number === 'Unknown' ? -Infinity : Number(b.number);
return numB - numA;
});
});
// Retourne les volumes calculés et propage les états pertinents de useMangaChapters
return {
volumes, // Les données transformées
isLoading, // L'état de chargement initial des chapitres
isFetching, // L'état de rafraîchissement des chapitres
error, // L'erreur potentielle lors du fetch des chapitres
status // L'état global ('pending', 'error', 'success')
// On pourrait aussi retourner rawChaptersData si nécessaire ailleurs
};
}