Showing
7 changed files
with
63 additions
and
133 deletions
| @@ -38,20 +38,13 @@ async function fetchMovies(page: number) { | @@ -38,20 +38,13 @@ async function fetchMovies(page: number) { | ||
| 38 | try { | 38 | try { | 
| 39 | isLoadingMore.value = true; | 39 | isLoadingMore.value = true; | 
| 40 | const data = await fetchPopularMovies(page); | 40 | const data = await fetchPopularMovies(page); | 
| 41 | - // Save in Movie model. | 41 | + // Save in Movie model. If first fetch, erase old data before save or, add to store collection. | 
| 42 | - if (isInitialLoading.value) { | 42 | + isInitialLoading.value ? useRepo(Movie).fresh(data.results) : useRepo(Movie).save(data.results); | 
| 43 | - // First fetch, erase old data before save. | ||
| 44 | - useRepo(Movie).fresh(data.results); | ||
| 45 | - } | ||
| 46 | - else { | ||
| 47 | - // Add to store collection. | ||
| 48 | - useRepo(Movie).save(data.results); | ||
| 49 | - } | ||
| 50 | totalPages.value = data.total_pages; | 43 | totalPages.value = data.total_pages; | 
| 51 | currentPage.value = page; | 44 | currentPage.value = page; | 
| 52 | } | 45 | } | 
| 53 | catch (error) { | 46 | catch (error) { | 
| 54 | - console.error("Error fetching popular movies:", error); | 47 | + throw new Error(`Error fetching popular movies: ${error}`); | 
| 55 | } | 48 | } | 
| 56 | finally { | 49 | finally { | 
| 57 | isInitialLoading.value = false; | 50 | isInitialLoading.value = false; | 
| @@ -72,24 +65,16 @@ async function search(query: string, page: number) { | @@ -72,24 +65,16 @@ async function search(query: string, page: number) { | ||
| 72 | } | 65 | } | 
| 73 | try { | 66 | try { | 
| 74 | isLoadingMore.value = true; | 67 | isLoadingMore.value = true; | 
| 75 | - if (page === 1) { | 68 | + if (page === 1) isInitialLoading.value = true; | 
| 76 | - isInitialLoading.value = true; | ||
| 77 | - } | ||
| 78 | const data = await searchMovies(query, page); | 69 | const data = await searchMovies(query, page); | 
| 79 | - // Save in Movie model. | 70 | + | 
| 80 | - if (isInitialLoading.value) { | 71 | + // Save in Movie model. If first fetch, erase old data before save or, add to store collection. | 
| 81 | - // First fetch, erase old data before save. | 72 | + isInitialLoading.value ? useRepo(Movie).fresh(data.results) : useRepo(Movie).save(data.results); | 
| 82 | - useRepo(Movie).fresh(data.results); | ||
| 83 | - } | ||
| 84 | - else { | ||
| 85 | - // Add to store collection. | ||
| 86 | - useRepo(Movie).save(data.results); | ||
| 87 | - } | ||
| 88 | totalPages.value = data.total_pages; | 73 | totalPages.value = data.total_pages; | 
| 89 | currentPage.value = page; | 74 | currentPage.value = page; | 
| 90 | } | 75 | } | 
| 91 | catch (error) { | 76 | catch (error) { | 
| 92 | - console.error("Error searching movies:", error); | 77 | + throw new Error(`Error searching movies: ${error}`); | 
| 93 | } | 78 | } | 
| 94 | finally { | 79 | finally { | 
| 95 | isInitialLoading.value = false; | 80 | isInitialLoading.value = false; | 
| @@ -101,16 +86,8 @@ function createIntersectionObserver() { | @@ -101,16 +86,8 @@ function createIntersectionObserver() { | ||
| 101 | return new IntersectionObserver( | 86 | return new IntersectionObserver( | 
| 102 | (entries) => { | 87 | (entries) => { | 
| 103 | const [entry] = entries; | 88 | const [entry] = entries; | 
| 104 | - if (entry.isIntersecting && !isLoadingMore.value && currentPage.value < totalPages.value) { | 89 | + // Continue searching query if already active or, continue fetching popular movies. | 
| 105 | - if (searchQuery.value) { | 90 | + if (entry.isIntersecting && !isLoadingMore.value && currentPage.value < totalPages.value) searchQuery.value ? search(searchQuery.value, currentPage.value + 1) : fetchMovies(currentPage.value + 1); | 
| 106 | - // Continue searching query if already active. | ||
| 107 | - search(searchQuery.value, currentPage.value + 1); | ||
| 108 | - } | ||
| 109 | - else { | ||
| 110 | - // Continue fetching popular movies. | ||
| 111 | - fetchMovies(currentPage.value + 1); | ||
| 112 | - } | ||
| 113 | - } | ||
| 114 | }, | 91 | }, | 
| 115 | { threshold: 1.0 }, | 92 | { threshold: 1.0 }, | 
| 116 | ); | 93 | ); | 
| @@ -137,21 +114,15 @@ onMounted(() => { | @@ -137,21 +114,15 @@ onMounted(() => { | ||
| 137 | fetchMovies(1); | 114 | fetchMovies(1); | 
| 138 | // Création et stockage dans la ref de l'instance IntersectionObserver. | 115 | // Création et stockage dans la ref de l'instance IntersectionObserver. | 
| 139 | observer.value = createIntersectionObserver(); | 116 | observer.value = createIntersectionObserver(); | 
| 140 | - if (loadMoreTrigger.value) { | ||
| 141 | // Début d'observation de la div pour le défilement infini. | 117 | // Début d'observation de la div pour le défilement infini. | 
| 142 | - observer.value.observe(loadMoreTrigger.value); | 118 | + if (loadMoreTrigger.value) observer.value.observe(loadMoreTrigger.value); | 
| 143 | - } | ||
| 144 | 119 | ||
| 145 | - if (loadMoreTrigger.value) { | 120 | + if (loadMoreTrigger.value) observer.value.observe(loadMoreTrigger.value); | 
| 146 | - observer.value.observe(loadMoreTrigger.value); | ||
| 147 | - } | ||
| 148 | }); | 121 | }); | 
| 149 | 122 | ||
| 150 | onBeforeUnmount(() => { | 123 | onBeforeUnmount(() => { | 
| 151 | // Disconnect the observer when the component is unmounted. | 124 | // Disconnect the observer when the component is unmounted. | 
| 152 | - if (observer.value) { | 125 | + if (observer.value) observer.value.disconnect(); | 
| 153 | - observer.value.disconnect(); | ||
| 154 | - } | ||
| 155 | }); | 126 | }); | 
| 156 | // #endregion | 127 | // #endregion | 
| 157 | </script> | 128 | </script> | 
| @@ -13,9 +13,7 @@ defineProps<{ | @@ -13,9 +13,7 @@ defineProps<{ | ||
| 13 | * @param count | 13 | * @param count | 
| 14 | */ | 14 | */ | 
| 15 | function formatVoteCount(count: number) { | 15 | function formatVoteCount(count: number) { | 
| 16 | - if (count >= 1000) { | 16 | + if (count >= 1000) return `${(count / 1000).toFixed(1)}k votes`; | 
| 17 | - return `${(count / 1000).toFixed(1)}k votes`; | ||
| 18 | - } | ||
| 19 | return `${count} votes`; | 17 | return `${count} votes`; | 
| 20 | } | 18 | } | 
| 21 | // #endregion | 19 | // #endregion | 
| @@ -117,9 +117,7 @@ function handleMessageEvent(event: string) { | @@ -117,9 +117,7 @@ function handleMessageEvent(event: string) { | ||
| 117 | @click=" | 117 | @click=" | 
| 118 | async () => { | 118 | async () => { | 
| 119 | const validForm = await v$.$validate(); | 119 | const validForm = await v$.$validate(); | 
| 120 | - if (validForm) { | 120 | + if (validForm) submitComment(); | 
| 121 | - submitComment(); | ||
| 122 | - } | ||
| 123 | } | 121 | } | 
| 124 | " | 122 | " | 
| 125 | > | 123 | > | 
| @@ -69,9 +69,7 @@ watch(content, (newValue) => { | @@ -69,9 +69,7 @@ watch(content, (newValue) => { | ||
| 69 | watch( | 69 | watch( | 
| 70 | () => props.modelValue, | 70 | () => props.modelValue, | 
| 71 | (newValue) => { | 71 | (newValue) => { | 
| 72 | - if (newValue !== content.value) { | 72 | + if (newValue !== content.value) content.value = newValue; | 
| 73 | - content.value = newValue; | ||
| 74 | - } | ||
| 75 | }, | 73 | }, | 
| 76 | ); | 74 | ); | 
| 77 | // #endregion | 75 | // #endregion | 
| @@ -12,15 +12,11 @@ export function useTMDB() { | @@ -12,15 +12,11 @@ export function useTMDB() { | ||
| 12 | const fetchPopularMovies = async (page: number) => { | 12 | const fetchPopularMovies = async (page: number) => { | 
| 13 | try { | 13 | try { | 
| 14 | const response = await fetch(`${apiUrl}/movie/popular?api_key=${apiKey}&language=fr-FR&page=${page}`); | 14 | const response = await fetch(`${apiUrl}/movie/popular?api_key=${apiKey}&language=fr-FR&page=${page}`); | 
| 15 | - if (!response.ok) { | 15 | + if (!response.ok) throw new Error("An error occurred when fetching popular movies"); | 
| 16 | - console.error("An error occurred when fetching popular movies:"); | ||
| 17 | - } | ||
| 18 | - else { | ||
| 19 | return await response.json(); | 16 | return await response.json(); | 
| 20 | } | 17 | } | 
| 21 | - } | ||
| 22 | catch (error) { | 18 | catch (error) { | 
| 23 | - console.error("Error fetching popular movies:", error); | 19 | + throw new Error(`Error fetching popular movies: ${error}`); | 
| 24 | } | 20 | } | 
| 25 | }; | 21 | }; | 
| 26 | 22 | ||
| @@ -34,15 +30,11 @@ export function useTMDB() { | @@ -34,15 +30,11 @@ export function useTMDB() { | ||
| 34 | const response = await fetch( | 30 | const response = await fetch( | 
| 35 | `${apiUrl}/search/movie?api_key=${apiKey}&language=fr-FR&query=${encodeURIComponent(query)}&page=${page}`, | 31 | `${apiUrl}/search/movie?api_key=${apiKey}&language=fr-FR&query=${encodeURIComponent(query)}&page=${page}`, | 
| 36 | ); | 32 | ); | 
| 37 | - if (!response.ok) { | 33 | + if (!response.ok) throw new Error("An error occurred when searching movies"); | 
| 38 | - console.error("An error occurred when searching movies:"); | ||
| 39 | - } | ||
| 40 | - else { | ||
| 41 | return await response.json(); | 34 | return await response.json(); | 
| 42 | } | 35 | } | 
| 43 | - } | ||
| 44 | catch (error) { | 36 | catch (error) { | 
| 45 | - console.error("Error searching movies:", error); | 37 | + throw new Error(`Error searching movies: ${error}`); | 
| 46 | } | 38 | } | 
| 47 | }; | 39 | }; | 
| 48 | 40 | ||
| @@ -53,15 +45,11 @@ export function useTMDB() { | @@ -53,15 +45,11 @@ export function useTMDB() { | ||
| 53 | const fetchMovieDetails = async (id: number | string) => { | 45 | const fetchMovieDetails = async (id: number | string) => { | 
| 54 | try { | 46 | try { | 
| 55 | const response = await fetch(`${apiUrl}/movie/${id}?api_key=${apiKey}&language=fr-FR`); | 47 | const response = await fetch(`${apiUrl}/movie/${id}?api_key=${apiKey}&language=fr-FR`); | 
| 56 | - if (!response.ok) { | 48 | + if (!response.ok) throw new Error("An error occurred when fetching movie details"); | 
| 57 | - console.error("An error occurred when fetching movie details:"); | ||
| 58 | - } | ||
| 59 | - else { | ||
| 60 | return await response.json(); | 49 | return await response.json(); | 
| 61 | } | 50 | } | 
| 62 | - } | ||
| 63 | catch (error) { | 51 | catch (error) { | 
| 64 | - console.error("Error fetching details:", error); | 52 | + throw new Error(`Error fetching details: ${error}`); | 
| 65 | } | 53 | } | 
| 66 | }; | 54 | }; | 
| 67 | 55 | ||
| @@ -71,15 +59,11 @@ export function useTMDB() { | @@ -71,15 +59,11 @@ export function useTMDB() { | ||
| 71 | const fetchMovieCredits = async (id: number | string) => { | 59 | const fetchMovieCredits = async (id: number | string) => { | 
| 72 | try { | 60 | try { | 
| 73 | const response = await fetch(`${apiUrl}/movie/${id}/credits?api_key=${apiKey}&language=fr-FR`); | 61 | const response = await fetch(`${apiUrl}/movie/${id}/credits?api_key=${apiKey}&language=fr-FR`); | 
| 74 | - if (!response.ok) { | 62 | + if (!response.ok) throw new Error("An error occurred when fetching movie credits"); | 
| 75 | - console.error("An error occurred when fetching movie credits:"); | ||
| 76 | - } | ||
| 77 | - else { | ||
| 78 | return await response.json(); | 63 | return await response.json(); | 
| 79 | } | 64 | } | 
| 80 | - } | ||
| 81 | catch (error) { | 65 | catch (error) { | 
| 82 | - console.error("Error fetching movie credits:", error); | 66 | + throw new Error(`Error fetching movie credits: ${error}`); | 
| 83 | } | 67 | } | 
| 84 | }; | 68 | }; | 
| 85 | 69 | 
| 1 | import antfu from "@antfu/eslint-config"; | 1 | import antfu from "@antfu/eslint-config"; | 
| 2 | 2 | ||
| 3 | export default antfu({ | 3 | export default antfu({ | 
| 4 | -// Type of the project. 'lib' for libraries, the default is 'app' | 4 | + // `.eslintignore` is no longer supported in Flat config, use `ignores` instead. | 
| 5 | - type: "app", | 5 | + ignores: [ | 
| 6 | + "**/fixtures", | ||
| 7 | + "**/.cache", | ||
| 8 | + "**/.data", | ||
| 9 | + "**/.gitignore", | ||
| 10 | + "**/.env", | ||
| 11 | + "**/.env.dist", | ||
| 12 | + "**/.output", | ||
| 13 | + "**/.nitro", | ||
| 14 | + "**/.nuxt", | ||
| 15 | + "**/assets", | ||
| 16 | + "**/dist", | ||
| 17 | + "**/logs", | ||
| 18 | + "**/node_modules", | ||
| 19 | + "**/public", | ||
| 20 | + "**/server", | ||
| 21 | + ], | ||
| 6 | 22 | ||
| 23 | + // Disable jsonc and yaml support. | ||
| 24 | + jsonc: false, | ||
| 25 | + markdown: false, | ||
| 26 | + | ||
| 27 | + // personnal rules. | ||
| 7 | rules: { | 28 | rules: { | 
| 8 | "antfu/if-newline": 0, | 29 | "antfu/if-newline": 0, | 
| 9 | "antfu/curly": 0, | 30 | "antfu/curly": 0, | 
| 10 | }, | 31 | }, | 
| 11 | 32 | ||
| 12 | - // Enable stylistic formatting rules | 33 | + // Enable stylistic formatting rules. | 
| 13 | // stylistic: true, | 34 | // stylistic: true, | 
| 14 | - | 35 | + // Or customize the stylistic rules. | 
| 15 | - // Or customize the stylistic rules | ||
| 16 | stylistic: { | 36 | stylistic: { | 
| 17 | indent: 2, // 4, or 'tab' | 37 | indent: 2, // 4, or 'tab' | 
| 18 | semi: true, | 38 | semi: true, | 
| 19 | stylistic: true, | 39 | stylistic: true, | 
| 20 | - quotes: "double", // 'single' or 'double' | 40 | + quotes: "double", // 'single' or 'double'. | 
| 21 | }, | 41 | }, | 
| 22 | 42 | ||
| 43 | + // Type of the project. 'lib' for libraries, the default is 'app'. | ||
| 44 | + type: "app", | ||
| 45 | + | ||
| 23 | // TypeScript and Vue are autodetected, you can also explicitly enable them: | 46 | // TypeScript and Vue are autodetected, you can also explicitly enable them: | 
| 24 | typescript: true, | 47 | typescript: true, | 
| 25 | vue: true, | 48 | vue: true, | 
| 26 | 49 | ||
| 27 | - // Disable jsonc and yaml support | ||
| 28 | - jsonc: false, | ||
| 29 | - markdown: false, | ||
| 30 | yaml: false, | 50 | yaml: false, | 
| 31 | - | ||
| 32 | - // `.eslintignore` is no longer supported in Flat config, use `ignores` instead | ||
| 33 | - ignores: [ | ||
| 34 | - "**/fixtures", | ||
| 35 | - "**/.cache", | ||
| 36 | - "**/.data", | ||
| 37 | - "**/.gitignore", | ||
| 38 | - "**/.env", | ||
| 39 | - "**/.env.dist", | ||
| 40 | - "**/.output", | ||
| 41 | - "**/.nitro", | ||
| 42 | - "**/.nuxt", | ||
| 43 | - "**/assets", | ||
| 44 | - "**/dist", | ||
| 45 | - "**/logs", | ||
| 46 | - "**/node_modules", | ||
| 47 | - "**/public", | ||
| 48 | - "**/server", | ||
| 49 | - ], | ||
| 50 | }); | 51 | }); | 
| 51 | 52 | ||
| 52 | -// Ancienne config eslint. | 53 | +// Last eslint config. | 
| 53 | // import withNuxt from "./.nuxt/eslint.config.mjs"; | 54 | // import withNuxt from "./.nuxt/eslint.config.mjs"; | 
| 54 | // import js from "@eslint/js"; | 55 | // import js from "@eslint/js"; | 
| 55 | // import eslintPluginVue from "eslint-plugin-vue"; | 56 | // import eslintPluginVue from "eslint-plugin-vue"; | 
| @@ -27,47 +27,28 @@ const isSubmitting = ref(false); | @@ -27,47 +27,28 @@ const isSubmitting = ref(false); | ||
| 27 | 27 | ||
| 28 | // #region --Computed--. | 28 | // #region --Computed--. | 
| 29 | const movieId = computed(() => { | 29 | const movieId = computed(() => { | 
| 30 | - if (currentRoute.value.params.id) { | 30 | + if (!currentRoute.value.params.id) return null; | 
| 31 | - if (typeof currentRoute.value.params.id === "string") { | 31 | + if (typeof currentRoute.value.params.id !== "string") return null; | 
| 32 | - if (typeof Number(+currentRoute.value.params.id) === "number") { | 32 | + | 
| 33 | - return +currentRoute.value.params.id as number; | 33 | + if (typeof Number(+currentRoute.value.params.id) === "number") return +currentRoute.value.params.id as number; | 
| 34 | - } | ||
| 35 | - else { | ||
| 36 | return currentRoute.value.params.id as string; | 34 | return currentRoute.value.params.id as string; | 
| 37 | - } | ||
| 38 | - } | ||
| 39 | - else { | ||
| 40 | - return null; | ||
| 41 | - } | ||
| 42 | - } | ||
| 43 | - else { | ||
| 44 | - return null; | ||
| 45 | - } | ||
| 46 | }); | 35 | }); | 
| 47 | 36 | ||
| 48 | const movie = computed(() => { | 37 | const movie = computed(() => { | 
| 49 | - if (unref(movieId)) { | 38 | + if (!unref(movieId)) return null; | 
| 50 | return useRepo(Movie) | 39 | return useRepo(Movie) | 
| 51 | .query() | 40 | .query() | 
| 52 | .where("id", movieId.value as WhereSecondaryClosure<never> | null | undefined) | 41 | .where("id", movieId.value as WhereSecondaryClosure<never> | null | undefined) | 
| 53 | .withAll() | 42 | .withAll() | 
| 54 | .first() as unknown as MovieInterface; | 43 | .first() as unknown as MovieInterface; | 
| 55 | - } | ||
| 56 | - else { | ||
| 57 | - return null; | ||
| 58 | - } | ||
| 59 | }); | 44 | }); | 
| 60 | 45 | ||
| 61 | /** | 46 | /** | 
| 62 | * Computed property for director | 47 | * Computed property for director | 
| 63 | */ | 48 | */ | 
| 64 | const director = computed(() => { | 49 | const director = computed(() => { | 
| 65 | - if (unref(movie)?.credit?.crew) { | 50 | + if (!unref(movie)?.credit?.crew) return null; | 
| 66 | return movie.value?.credit.crew.find(person => person.job === "Director"); | 51 | return movie.value?.credit.crew.find(person => person.job === "Director"); | 
| 67 | - } | ||
| 68 | - else { | ||
| 69 | - return null; | ||
| 70 | - } | ||
| 71 | }); | 52 | }); | 
| 72 | 53 | ||
| 73 | /** | 54 | /** | 
| @@ -98,7 +79,7 @@ async function fetchDetails(id: number | string) { | @@ -98,7 +79,7 @@ async function fetchDetails(id: number | string) { | ||
| 98 | useRepo(Movie).save(data); | 79 | useRepo(Movie).save(data); | 
| 99 | } | 80 | } | 
| 100 | catch (error) { | 81 | catch (error) { | 
| 101 | - console.error("Error fetching movie details:", error); | 82 | + throw new Error(`Error fetching movie details: ${error}`); | 
| 102 | } | 83 | } | 
| 103 | finally { | 84 | finally { | 
| 104 | isLoading.value = false; | 85 | isLoading.value = false; | 
| @@ -110,8 +91,7 @@ async function fetchDetails(id: number | string) { | @@ -110,8 +91,7 @@ async function fetchDetails(id: number | string) { | ||
| 110 | * @param minutes | 91 | * @param minutes | 
| 111 | */ | 92 | */ | 
| 112 | function formatRuntime(minutes: number) { | 93 | function formatRuntime(minutes: number) { | 
| 113 | - if (!minutes) | 94 | + if (!minutes) return "Durée inconnue"; | 
| 114 | - return "Durée inconnue"; | ||
| 115 | // Find nb hours. | 95 | // Find nb hours. | 
| 116 | const hours = Math.floor(minutes / 60); | 96 | const hours = Math.floor(minutes / 60); | 
| 117 | // Find last minutes. | 97 | // Find last minutes. | 
| @@ -128,7 +108,7 @@ async function fetchCredits(id: number | string) { | @@ -128,7 +108,7 @@ async function fetchCredits(id: number | string) { | ||
| 128 | useRepo(Credit).save(data); | 108 | useRepo(Credit).save(data); | 
| 129 | } | 109 | } | 
| 130 | catch (error) { | 110 | catch (error) { | 
| 131 | - console.error("Error fetching movie credits:", error); | 111 | + throw new Error(`Error fetching movie credits: ${error}`); | 
| 132 | } | 112 | } | 
| 133 | } | 113 | } | 
| 134 | 114 | 
- 
Please register or login to post a comment