Gestion des recherches de film vie le composable et implémentation dans le composant MoviesList.
Showing
2 changed files
with
73 additions
and
6 deletions
@@ -10,7 +10,7 @@ import { useDateFormat } from "@vueuse/core"; | @@ -10,7 +10,7 @@ import { useDateFormat } from "@vueuse/core"; | ||
10 | //#endregion | 10 | //#endregion |
11 | 11 | ||
12 | //#region --Declaration--. | 12 | //#region --Declaration--. |
13 | -const { fetchPopularMovies } = useTMDB(); | 13 | +const { fetchPopularMovies, searchMovies } = useTMDB(); |
14 | //#endregion | 14 | //#endregion |
15 | 15 | ||
16 | //#region --Data/refs--. | 16 | //#region --Data/refs--. |
@@ -18,6 +18,7 @@ const isInitialLoading = ref(true); | @@ -18,6 +18,7 @@ const isInitialLoading = ref(true); | ||
18 | const isLoadingMore = ref(false); | 18 | const isLoadingMore = ref(false); |
19 | const currentPage = ref(1); | 19 | const currentPage = ref(1); |
20 | const totalPages = ref(0); | 20 | const totalPages = ref(0); |
21 | +const searchQuery = ref(""); | ||
21 | /** Elément observé pour le défilement infini. */ | 22 | /** Elément observé pour le défilement infini. */ |
22 | const loadMoreTrigger = ref<HTMLElement | null>(null); | 23 | const loadMoreTrigger = ref<HTMLElement | null>(null); |
23 | /** Instance de IntersectionObserver */ | 24 | /** Instance de IntersectionObserver */ |
@@ -41,11 +42,12 @@ const fetchMovies = async (page: number) => { | @@ -41,11 +42,12 @@ const fetchMovies = async (page: number) => { | ||
41 | const data = await fetchPopularMovies(page); | 42 | const data = await fetchPopularMovies(page); |
42 | // Save in Movie model. | 43 | // Save in Movie model. |
43 | if (isInitialLoading.value) { | 44 | if (isInitialLoading.value) { |
45 | + // First fetch, erase old data before save. | ||
44 | useRepo(Movie).fresh(data.results); | 46 | useRepo(Movie).fresh(data.results); |
45 | } else { | 47 | } else { |
48 | + // Add to store collection. | ||
46 | useRepo(Movie).save(data.results); | 49 | useRepo(Movie).save(data.results); |
47 | } | 50 | } |
48 | - | ||
49 | totalPages.value = data.total_pages; | 51 | totalPages.value = data.total_pages; |
50 | currentPage.value = page; | 52 | currentPage.value = page; |
51 | } catch (error) { | 53 | } catch (error) { |
@@ -56,24 +58,69 @@ const fetchMovies = async (page: number) => { | @@ -56,24 +58,69 @@ const fetchMovies = async (page: number) => { | ||
56 | } | 58 | } |
57 | }; | 59 | }; |
58 | 60 | ||
61 | +/** | ||
62 | + * Search movies | ||
63 | + * @param query | ||
64 | + * @param page | ||
65 | + */ | ||
66 | +const search = async (query: string, page: number) => { | ||
67 | + // If empty search, fetch popular movies. | ||
68 | + if (!query.trim()) { | ||
69 | + await fetchMovies(1); | ||
70 | + return; | ||
71 | + } | ||
72 | + try { | ||
73 | + isLoadingMore.value = true; | ||
74 | + if (page === 1) { | ||
75 | + isInitialLoading.value = true; | ||
76 | + } | ||
77 | + const data = await searchMovies(query, page); | ||
78 | + // Save in Movie model. | ||
79 | + if (isInitialLoading.value) { | ||
80 | + // First fetch, erase old data before save. | ||
81 | + useRepo(Movie).fresh(data.results); | ||
82 | + } else { | ||
83 | + // Add to store collection. | ||
84 | + useRepo(Movie).save(data.results); | ||
85 | + } | ||
86 | + totalPages.value = data.total_pages; | ||
87 | + currentPage.value = page; | ||
88 | + } catch (error) { | ||
89 | + console.error("Error searching movies:", error); | ||
90 | + } finally { | ||
91 | + isInitialLoading.value = false; | ||
92 | + isLoadingMore.value = false; | ||
93 | + } | ||
94 | +}; | ||
95 | + | ||
59 | function createIntersectionObserver() { | 96 | function createIntersectionObserver() { |
60 | return new IntersectionObserver( | 97 | return new IntersectionObserver( |
61 | (entries) => { | 98 | (entries) => { |
62 | const [entry] = entries; | 99 | const [entry] = entries; |
63 | if (entry.isIntersecting && !isLoadingMore.value && currentPage.value < totalPages.value) { | 100 | if (entry.isIntersecting && !isLoadingMore.value && currentPage.value < totalPages.value) { |
101 | + if (searchQuery.value) { | ||
102 | + // Continue searching query if already active. | ||
103 | + search(searchQuery.value, currentPage.value + 1) | ||
104 | + } else { | ||
105 | + // Continue fetching popular movies. | ||
64 | fetchMovies(currentPage.value + 1); | 106 | fetchMovies(currentPage.value + 1); |
65 | } | 107 | } |
108 | + } | ||
66 | }, | 109 | }, |
67 | { threshold: 1.0 }, | 110 | { threshold: 1.0 }, |
68 | ); | 111 | ); |
69 | } | 112 | } |
70 | 113 | ||
71 | function handleSearchEvent(event: string) { | 114 | function handleSearchEvent(event: string) { |
72 | - console.log(event); | 115 | + currentPage.value = 1; |
116 | + searchQuery.value = event; | ||
117 | + search(event, 1); | ||
73 | } | 118 | } |
74 | 119 | ||
75 | function handleClearSearchEvent() { | 120 | function handleClearSearchEvent() { |
76 | - console.log("clear event"); | 121 | + searchQuery.value = ''; |
122 | + // Fetch popular movies after clear. | ||
123 | + fetchMovies(1); | ||
77 | } | 124 | } |
78 | 125 | ||
79 | //#endregion | 126 | //#endregion |
@@ -15,7 +15,7 @@ export const useTMDB = function() { | @@ -15,7 +15,7 @@ export const useTMDB = function() { | ||
15 | `${apiUrl}/movie/popular?api_key=${apiKey}&language=fr-FR&page=${page}`, | 15 | `${apiUrl}/movie/popular?api_key=${apiKey}&language=fr-FR&page=${page}`, |
16 | ); | 16 | ); |
17 | if (!response.ok) { | 17 | if (!response.ok) { |
18 | - console.error("An error occured when fetching popular movies:"); | 18 | + console.error("An error occurred when fetching popular movies:"); |
19 | } else { | 19 | } else { |
20 | return await response.json(); | 20 | return await response.json(); |
21 | } | 21 | } |
@@ -24,5 +24,25 @@ export const useTMDB = function() { | @@ -24,5 +24,25 @@ export const useTMDB = function() { | ||
24 | } | 24 | } |
25 | }; | 25 | }; |
26 | 26 | ||
27 | - return { fetchPopularMovies } | 27 | + /** |
28 | + * Search movies | ||
29 | + * @param query | ||
30 | + * @param page | ||
31 | + */ | ||
32 | + const searchMovies = async (query: string, page: number) => { | ||
33 | + try { | ||
34 | + const response = await fetch( | ||
35 | + `${apiUrl}/search/movie?api_key=${apiKey}&language=fr-FR&query=${encodeURIComponent(query)}&page=${page}`, | ||
36 | + ); | ||
37 | + if (!response.ok) { | ||
38 | + console.error("An error occurred when searching movies:"); | ||
39 | + } else { | ||
40 | + return await response.json(); | ||
41 | + } | ||
42 | + } catch (error) { | ||
43 | + console.error("Error searching movies:", error); | ||
44 | + } | ||
45 | + }; | ||
46 | + | ||
47 | + return { fetchPopularMovies, searchMovies } | ||
28 | } | 48 | } |
-
Please register or login to post a comment