From 75f8e1686c108be74f6c92c7564a56b882b7803f Mon Sep 17 00:00:00 2001 From: "ext.jeremy.guillot@maxicoffee.domains" Date: Fri, 20 Jun 2025 15:33:54 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20ajout=20de=20la=20gestion=20des=20sourc?= =?UTF-8?q?es=20pr=C3=A9f=C3=A9r=C3=A9es=20pour=20les=20mangas,=20incluant?= =?UTF-8?q?=20la=20r=C3=A9cup=C3=A9ration=20et=20la=20configuration=20des?= =?UTF-8?q?=20sources=20via=20l'API,=20ainsi=20que=20l'int=C3=A9gration=20?= =?UTF-8?q?d'une=20modale=20pour=20l'interface=20utilisateur.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infrastructure/api/apiMangaRepository.js | 32 ++ .../components/MangaPreferredSourcesModal.vue | 191 ++++++++++++ .../composables/useMangaPreferredSources.js | 52 ++++ .../manga/presentation/pages/MangaDetails.vue | 73 ++++- config/packages/api_platform.yaml | 1 + public/api-docs.json | 284 ++++++++++++++++++ .../Command/SetMangaPreferredSources.php | 26 ++ .../CommandHandler/ScrapeChapterHandler.php | 1 + .../SetMangaPreferredSourcesHandler.php | 39 +++ .../Query/GetMangaPreferredSources.php | 14 + .../GetMangaPreferredSourcesHandler.php | 71 +++++ .../GetMangaPreferredSourcesResponse.php | 18 ++ .../Repository/MangaRepositoryInterface.php | 9 + .../Repository/SourceRepositoryInterface.php | 23 ++ .../Dto/MangaPreferredSourcesDetail.php | 13 + .../GetMangaPreferredSourcesResource.php | 81 +++++ .../SetMangaPreferredSourcesResource.php | 54 ++++ ...SetMangaPreferredSourcesStateProcessor.php | 38 +++ .../GetMangaPreferredSourcesStateProvider.php | 46 +++ ...SymfonySetMangaPreferredSourcesHandler.php | 21 ++ .../Persistence/LegacyMangaRepository.php | 39 ++- .../Persistence/LegacySourceRepository.php | 83 +++-- 22 files changed, 1168 insertions(+), 41 deletions(-) create mode 100644 assets/vue/app/domain/manga/presentation/components/MangaPreferredSourcesModal.vue create mode 100644 assets/vue/app/domain/manga/presentation/composables/useMangaPreferredSources.js create mode 100644 src/Domain/Scraping/Application/Command/SetMangaPreferredSources.php create mode 100644 src/Domain/Scraping/Application/CommandHandler/SetMangaPreferredSourcesHandler.php create mode 100644 src/Domain/Scraping/Application/Query/GetMangaPreferredSources.php create mode 100644 src/Domain/Scraping/Application/QueryHandler/GetMangaPreferredSourcesHandler.php create mode 100644 src/Domain/Scraping/Application/Response/GetMangaPreferredSourcesResponse.php create mode 100644 src/Domain/Scraping/Infrastructure/ApiPlatform/Dto/MangaPreferredSourcesDetail.php create mode 100644 src/Domain/Scraping/Infrastructure/ApiPlatform/Resource/GetMangaPreferredSourcesResource.php create mode 100644 src/Domain/Scraping/Infrastructure/ApiPlatform/Resource/SetMangaPreferredSourcesResource.php create mode 100644 src/Domain/Scraping/Infrastructure/ApiPlatform/State/Processor/SetMangaPreferredSourcesStateProcessor.php create mode 100644 src/Domain/Scraping/Infrastructure/ApiPlatform/State/Provider/GetMangaPreferredSourcesStateProvider.php create mode 100644 src/Domain/Scraping/Infrastructure/CommandHandler/SymfonySetMangaPreferredSourcesHandler.php 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 @@