diff --git a/assets/vue/app/domain/manga/infrastructure/api/apiMangaRepository.js b/assets/vue/app/domain/manga/infrastructure/api/apiMangaRepository.js index f06dd56..91738f9 100644 --- a/assets/vue/app/domain/manga/infrastructure/api/apiMangaRepository.js +++ b/assets/vue/app/domain/manga/infrastructure/api/apiMangaRepository.js @@ -141,4 +141,36 @@ export class ApiMangaRepository { throw error; } } + + async getPreferredSources(mangaId) { + try { + const response = await fetch(`/api/mangas/${mangaId}/preferred-sources`); + if (!response.ok) { + throw new Error('Failed to fetch preferred sources'); + } + return await response.json(); + } catch (error) { + console.error('API Error:', error); + throw error; + } + } + + async setPreferredSources(mangaId, sourceIds) { + try { + const response = await fetch(`/api/mangas/${mangaId}/preferred-sources`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ sourceIds }) + }); + if (!response.ok) { + throw new Error('Failed to set preferred sources'); + } + return await response.json(); + } catch (error) { + console.error('API Error:', error); + throw error; + } + } } diff --git a/assets/vue/app/domain/manga/presentation/components/MangaPreferredSourcesModal.vue b/assets/vue/app/domain/manga/presentation/components/MangaPreferredSourcesModal.vue new file mode 100644 index 0000000..8666a4a --- /dev/null +++ b/assets/vue/app/domain/manga/presentation/components/MangaPreferredSourcesModal.vue @@ -0,0 +1,191 @@ + + + diff --git a/assets/vue/app/domain/manga/presentation/composables/useMangaPreferredSources.js b/assets/vue/app/domain/manga/presentation/composables/useMangaPreferredSources.js new file mode 100644 index 0000000..fd03502 --- /dev/null +++ b/assets/vue/app/domain/manga/presentation/composables/useMangaPreferredSources.js @@ -0,0 +1,52 @@ +import { useMutation, useQuery, useQueryClient } from '@tanstack/vue-query'; +import { computed } from 'vue'; +import { ApiMangaRepository } from '../../infrastructure/api/apiMangaRepository'; + +export function useMangaPreferredSources(mangaId) { + const mangaRepository = new ApiMangaRepository(); + const queryClient = useQueryClient(); + + // Query pour récupérer les sources préférées + const preferredSourcesQuery = useQuery({ + queryKey: ['manga', mangaId, 'preferred-sources'], + queryFn: () => { + if (!mangaId.value) { + return Promise.resolve(null); + } + return mangaRepository.getPreferredSources(mangaId.value); + }, + enabled: computed(() => !!mangaId.value) + }); + + // Mutation pour sauvegarder les sources préférées + const setPreferredSourcesMutation = useMutation({ + mutationFn: ({ sourceIds }) => { + return mangaRepository.setPreferredSources(mangaId.value, sourceIds); + }, + onSuccess: () => { + // Invalider le cache pour refaire la requête de récupération + queryClient.invalidateQueries({ + queryKey: ['manga', mangaId.value, 'preferred-sources'] + }); + } + }); + + const sources = computed(() => preferredSourcesQuery.data.value?.sources || []); + const hasPreferredSources = computed(() => preferredSourcesQuery.data.value?.hasPreferredSources || false); + const isLoading = computed(() => preferredSourcesQuery.isLoading.value); + const error = computed(() => preferredSourcesQuery.error.value); + const isSaving = computed(() => setPreferredSourcesMutation.isPending.value); + + const savePreferredSources = (sourceIds) => { + return setPreferredSourcesMutation.mutate({ sourceIds }); + }; + + return { + sources, + hasPreferredSources, + isLoading, + error, + isSaving, + savePreferredSources + }; +} diff --git a/assets/vue/app/domain/manga/presentation/pages/MangaDetails.vue b/assets/vue/app/domain/manga/presentation/pages/MangaDetails.vue index 9096af3..5a4a41b 100644 --- a/assets/vue/app/domain/manga/presentation/pages/MangaDetails.vue +++ b/assets/vue/app/domain/manga/presentation/pages/MangaDetails.vue @@ -24,6 +24,17 @@ + + +
@@ -35,33 +46,38 @@