Bruno Predot

lintfix

1 module.exports = { 1 module.exports = {
  2 + // https://dev.to/tao/adding-eslint-and-prettier-to-nuxt-3-2023-5bg
2 root: true, 3 root: true,
3 extends: ["@nuxtjs/eslint-config", "plugin:prettier/recommended"], 4 extends: ["@nuxtjs/eslint-config", "plugin:prettier/recommended"],
  5 + env: {
  6 + browser: true,
  7 + node: true,
  8 + },
  9 + parser: "vue-eslint-parser",
  10 + parserOptions: {
  11 + parser: "@typescript-eslint/parser",
  12 + },
  13 + plugins: [],
  14 + // add your custom rules here
  15 + rules: {},
4 }; 16 };
@@ -2,16 +2,22 @@ @@ -2,16 +2,22 @@
2 //#region --Props--. 2 //#region --Props--.
3 import { useDateFormat } from "@vueuse/core"; 3 import { useDateFormat } from "@vueuse/core";
4 import { FilmIcon } from "lucide-vue-next"; 4 import { FilmIcon } from "lucide-vue-next";
  5 +import type { MovieInterface } from "~/interfaces/movie";
5 //#endregion 6 //#endregion
6 7
7 //#region --Props--. 8 //#region --Props--.
8 -defineProps({ 9 +/** Typescript typage */
9 - movie: { 10 +defineProps<{
10 - type: Object, 11 + movie: MovieInterface;
11 - required: true, 12 +}>();
12 - nullable: false, 13 +/** Ancien typage */
13 - }, 14 +// defineProps({
14 -}); 15 +// movie: {
  16 +// type: Object,
  17 +// required: true,
  18 +// nullable: false,
  19 +// },
  20 +// });
15 //#endregion 21 //#endregion
16 </script> 22 </script>
17 23
@@ -26,9 +32,15 @@ defineProps({ @@ -26,9 +32,15 @@ defineProps({
26 :alt="movie.title" 32 :alt="movie.title"
27 :src="`https://image.tmdb.org/t/p/w500${movie.poster_path}`" 33 :src="`https://image.tmdb.org/t/p/w500${movie.poster_path}`"
28 class="absolute inset-0 w-full h-full object-cover" 34 class="absolute inset-0 w-full h-full object-cover"
  35 + >
  36 + <div
  37 + v-else
  38 + class="absolute inset-0 w-full h-full bg-gray-700 flex items-center justify-center"
  39 + >
  40 + <FilmIcon
  41 + :size="48"
  42 + class="text-gray-500"
29 /> 43 />
30 - <div v-else class="absolute inset-0 w-full h-full bg-gray-700 flex items-center justify-center">  
31 - <FilmIcon :size="48" class="text-gray-500" />  
32 </div> 44 </div>
33 <div 45 <div
34 class="absolute top-2 right-2 bg-primary text-white rounded-full w-10 h-10 flex items-center justify-center font-bold" 46 class="absolute top-2 right-2 bg-primary text-white rounded-full w-10 h-10 flex items-center justify-center font-bold"
@@ -5,13 +5,18 @@ import { MessageSquareIcon } from "lucide-vue-next"; @@ -5,13 +5,18 @@ import { MessageSquareIcon } from "lucide-vue-next";
5 //#endregion 5 //#endregion
6 6
7 //#region --Props--. 7 //#region --Props--.
8 -const props = defineProps({ 8 +/** Typescript typage */
9 - comments: { 9 +const props = defineProps<{
10 - type: Array<MovieCommentInterface>, 10 + comments: Array<MovieCommentInterface>;
11 - required: true, 11 +}>();
12 - nullable: false, 12 +/** Ancien typage */
13 - }, 13 +// const props = defineProps({
14 -}); 14 +// comments: {
  15 +// type: Array<MovieCommentInterface>,
  16 +// required: true,
  17 +// nullable: false,
  18 +// },
  19 +// });
15 //#endregion 20 //#endregion
16 21
17 //#region --Watch--. 22 //#region --Watch--.
@@ -35,27 +40,49 @@ watch( @@ -35,27 +40,49 @@ watch(
35 <template> 40 <template>
36 <section> 41 <section>
37 <!-- Liste des commentaires --> 42 <!-- Liste des commentaires -->
38 - <section v-if="comments.length > 0" class="mt-10"> 43 + <section
  44 + v-if="comments.length > 0"
  45 + class="mt-10"
  46 + >
39 <h2>Commentaires publiés</h2> 47 <h2>Commentaires publiés</h2>
40 - <div v-for="(comment, index) in comments" :key="index" class="bg-gray-800 rounded-lg p-6 mb-4"> 48 + <div
  49 + v-for="(comment, index) in comments"
  50 + :key="index"
  51 + class="bg-gray-800 rounded-lg p-6 mb-4"
  52 + >
41 <div class="flex justify-between items-start mb-2"> 53 <div class="flex justify-between items-start mb-2">
42 <section> 54 <section>
43 - <h4 class="font-bold text-lg">Par {{ comment.username }}</h4> 55 + <h4 class="font-bold text-lg">
44 - <p class="text-sm text-gray-400">Le {{ useDateFormat(comment.createdAt, "DD-MM-YYYY") }}</p> 56 + Par {{ comment.username }}
  57 + </h4>
  58 + <p class="text-sm text-gray-400">
  59 + Le {{ useDateFormat(comment.createdAt, "DD-MM-YYYY") }}
  60 + </p>
45 </section> 61 </section>
46 <section class="bg-primary text-white rounded-full w-10 h-10 flex items-center justify-center font-bold"> 62 <section class="bg-primary text-white rounded-full w-10 h-10 flex items-center justify-center font-bold">
47 {{ comment.rating }} 63 {{ comment.rating }}
48 </section> 64 </section>
49 </div> 65 </div>
50 - <p :id="`message${index}`" class="text-gray-300"> 66 + <p
  67 + :id="`message${index}`"
  68 + class="text-gray-300"
  69 + >
51 {{ comment.message }} 70 {{ comment.message }}
52 </p> 71 </p>
53 </div> 72 </div>
54 </section> 73 </section>
55 <!-- Si aucun commentaire --> 74 <!-- Si aucun commentaire -->
56 - <section v-else class="text-center py-8 bg-gray-800 rounded-lg mt-10"> 75 + <section
57 - <MessageSquareIcon :size="48" class="mx-auto mb-3 text-gray-600" /> 76 + v-else
58 - <p class="text-gray-400">Aucun commentaire pour le moment. Soyez le premier à donner votre avis !</p> 77 + class="text-center py-8 bg-gray-800 rounded-lg mt-10"
  78 + >
  79 + <MessageSquareIcon
  80 + :size="48"
  81 + class="mx-auto mb-3 text-gray-600"
  82 + />
  83 + <p class="text-gray-400">
  84 + Aucun commentaire pour le moment. Soyez le premier à donner votre avis !
  85 + </p>
59 </section> 86 </section>
60 </section> 87 </section>
61 </template> 88 </template>
@@ -151,7 +151,9 @@ onBeforeUnmount(() => { @@ -151,7 +151,9 @@ onBeforeUnmount(() => {
151 151
152 <template> 152 <template>
153 <section> 153 <section>
154 - <h1 class="text-4xl font-bold mb-8 text-center">Découvrez les films populaires</h1> 154 + <h1 class="text-4xl font-bold mb-8 text-center">
  155 + Découvrez les films populaires
  156 + </h1>
155 <!-- Barre de recherche --> 157 <!-- Barre de recherche -->
156 <ui-components-search-bar 158 <ui-components-search-bar
157 placeholder="Rechercher un film..." 159 placeholder="Rechercher un film..."
@@ -167,24 +169,46 @@ onBeforeUnmount(() => { @@ -167,24 +169,46 @@ onBeforeUnmount(() => {
167 /> 169 />
168 170
169 <!-- Liste des films --> 171 <!-- Liste des films -->
170 - <div v-else-if="movies.length > 0" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"> 172 + <div
171 - <div v-for="movie in movies" :key="movie.id"> 173 + v-else-if="movies.length > 0"
  174 + class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"
  175 + >
  176 + <div
  177 + v-for="movie in movies"
  178 + :key="movie.id"
  179 + >
172 <movie-card :movie="movie" /> 180 <movie-card :movie="movie" />
173 </div> 181 </div>
174 </div> 182 </div>
175 183
176 <!-- Message si aucun film trouvé --> 184 <!-- Message si aucun film trouvé -->
177 - <section v-else-if="searchQuery && !movies.length" class="text-center py-12"> 185 + <section
178 - <SearchXIcon :size="64" class="mx-auto mb-4 text-gray-600" /> 186 + v-else-if="searchQuery && !movies.length"
179 - <h3 class="text-xl font-bold mb-2">Aucun film trouvé</h3> 187 + class="text-center py-12"
180 - <p class="text-gray-400">Essayez avec un autre terme de recherche</p> 188 + >
  189 + <SearchXIcon
  190 + :size="64"
  191 + class="mx-auto mb-4 text-gray-600"
  192 + />
  193 + <h3 class="text-xl font-bold mb-2">
  194 + Aucun film trouvé
  195 + </h3>
  196 + <p class="text-gray-400">
  197 + Essayez avec un autre terme de recherche
  198 + </p>
181 </section> 199 </section>
182 200
183 <!-- Loader pour le chargement de plus de films --> 201 <!-- Loader pour le chargement de plus de films -->
184 - <ui-components-loader :is-initial-loading="isInitialLoading" :is-loading="isLoadingMore" /> 202 + <ui-components-loader
  203 + :is-initial-loading="isInitialLoading"
  204 + :is-loading="isLoadingMore"
  205 + />
185 206
186 <!-- Élément observé pour le défilement infini --> 207 <!-- Élément observé pour le défilement infini -->
187 - <div ref="loadMoreTrigger" class="h-10 mt-4" /> 208 + <div
  209 + ref="loadMoreTrigger"
  210 + class="h-10 mt-4"
  211 + />
188 </section> 212 </section>
189 </template> 213 </template>
190 214
@@ -17,7 +17,11 @@ defineProps({ @@ -17,7 +17,11 @@ defineProps({
17 <template> 17 <template>
18 <section class="mb-6"> 18 <section class="mb-6">
19 <div class="flex flex-wrap gap-2"> 19 <div class="flex flex-wrap gap-2">
20 - <span v-for="genre in genres" :key="genre.id" class="px-3 py-1 bg-gray-800 rounded-full text-sm"> 20 + <span
  21 + v-for="genre in genres"
  22 + :key="genre.id"
  23 + class="px-3 py-1 bg-gray-800 rounded-full text-sm"
  24 + >
21 {{ genre.name }} 25 {{ genre.name }}
22 </span> 26 </span>
23 </div> 27 </div>
1 <script lang="ts" setup> 1 <script lang="ts" setup>
2 //#region --Props--. 2 //#region --Props--.
3 -defineProps({ 3 +/** Typescript typage */
4 - score: { 4 +defineProps<{
5 - type: Number, 5 + score: number;
6 - required: true, 6 + nbVote: number;
7 - nullable: false, 7 +}>();
8 - }, 8 +/** Ancien typage */
9 - nbVote: { 9 +// defineProps({
10 - type: Number, 10 +// score: {
11 - required: true, 11 +// type: Number,
12 - nullable: false, 12 +// required: true,
13 - }, 13 +// nullable: false,
14 -}); 14 +// },
  15 +// nbVote: {
  16 +// type: Number,
  17 +// required: true,
  18 +// nullable: false,
  19 +// },
  20 +// });
15 //#endregion 21 //#endregion
16 22
17 //#region --Function--. 23 //#region --Function--.
@@ -34,7 +40,9 @@ const formatVoteCount = (count: number) => { @@ -34,7 +40,9 @@ const formatVoteCount = (count: number) => {
34 {{ score.toFixed(1) }} 40 {{ score.toFixed(1) }}
35 </section> 41 </section>
36 <section> 42 <section>
37 - <p class="font-semibold">Note TMDB</p> 43 + <p class="font-semibold">
  44 + Note TMDB
  45 + </p>
38 <div class="text-sm text-gray-400"> 46 <div class="text-sm text-gray-400">
39 {{ formatVoteCount(nbVote) }} 47 {{ formatVoteCount(nbVote) }}
40 </div> 48 </div>
@@ -123,13 +123,22 @@ function handleMessageEvent(event: string) { @@ -123,13 +123,22 @@ function handleMessageEvent(event: string) {
123 } 123 }
124 " 124 "
125 > 125 >
126 - <span v-if="isSubmitting" class="flex items-center justify-center"> 126 + <span
  127 + v-if="isSubmitting"
  128 + class="flex items-center justify-center"
  129 + >
127 <span class="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin mr-2" /> 130 <span class="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin mr-2" />
128 Envoi en cours... 131 Envoi en cours...
129 </span> 132 </span>
130 <span v-else>Publier le commentaire</span> 133 <span v-else>Publier le commentaire</span>
131 </v-btn> 134 </v-btn>
132 - <v-btn class="mt-6 mr-4" color="primary" @click="clear"> effacer </v-btn> 135 + <v-btn
  136 + class="mt-6 mr-4"
  137 + color="primary"
  138 + @click="clear"
  139 + >
  140 + effacer
  141 + </v-btn>
133 </VForm> 142 </VForm>
134 </section> 143 </section>
135 </template> 144 </template>
@@ -17,7 +17,10 @@ defineProps({ @@ -17,7 +17,10 @@ defineProps({
17 </script> 17 </script>
18 18
19 <template> 19 <template>
20 - <section v-if="isLoading && !isInitialLoading" class="flex justify-center mt-8"> 20 + <section
  21 + v-if="isLoading && !isInitialLoading"
  22 + class="flex justify-center mt-8"
  23 + >
21 <div class="w-10 h-10 border-4 border-primary border-t-transparent rounded-full animate-spin" /> 24 <div class="w-10 h-10 border-4 border-primary border-t-transparent rounded-full animate-spin" />
22 </section> 25 </section>
23 </template> 26 </template>
@@ -20,9 +20,20 @@ defineProps({ @@ -20,9 +20,20 @@ defineProps({
20 <template> 20 <template>
21 <section class="w-full md:w-1/3 lg:w-1/4"> 21 <section class="w-full md:w-1/3 lg:w-1/4">
22 <div class="rounded-lg overflow-hidden shadow-lg bg-gray-800"> 22 <div class="rounded-lg overflow-hidden shadow-lg bg-gray-800">
23 - <v-img v-if="src" :alt="title" :src="`https://image.tmdb.org/t/p/w500${src}`" class="w-full h-auto" /> 23 + <v-img
24 - <div v-else class="aspect-[2/3] bg-gray-700 flex items-center justify-center"> 24 + v-if="src"
25 - <FilmIcon :size="64" class="text-gray-500" /> 25 + :alt="title"
  26 + :src="`https://image.tmdb.org/t/p/w500${src}`"
  27 + class="w-full h-auto"
  28 + />
  29 + <div
  30 + v-else
  31 + class="aspect-[2/3] bg-gray-700 flex items-center justify-center"
  32 + >
  33 + <FilmIcon
  34 + :size="64"
  35 + class="text-gray-500"
  36 + />
26 </div> 37 </div>
27 </div> 38 </div>
28 </section> 39 </section>
@@ -49,7 +49,7 @@ function handleClearSearchEvent() { @@ -49,7 +49,7 @@ function handleClearSearchEvent() {
49 class="w-full px-4 py-3 bg-gray-800 rounded-full text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-primary" 49 class="w-full px-4 py-3 bg-gray-800 rounded-full text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-primary"
50 type="text" 50 type="text"
51 @input="handleSearchEvent" 51 @input="handleSearchEvent"
52 - /> 52 + >
53 <button 53 <button
54 v-if="searchQuery" 54 v-if="searchQuery"
55 class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-white" 55 class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-white"
@@ -57,7 +57,10 @@ function handleClearSearchEvent() { @@ -57,7 +57,10 @@ function handleClearSearchEvent() {
57 > 57 >
58 <XIcon :size="20" /> 58 <XIcon :size="20" />
59 </button> 59 </button>
60 - <button v-else class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400"> 60 + <button
  61 + v-else
  62 + class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400"
  63 + >
61 <SearchIcon :size="20" /> 64 <SearchIcon :size="20" />
62 </button> 65 </button>
63 </div> 66 </div>
@@ -18,8 +18,15 @@ defineProps({ @@ -18,8 +18,15 @@ defineProps({
18 18
19 <template> 19 <template>
20 <!-- Skeleton loader pendant le chargement initial --> 20 <!-- Skeleton loader pendant le chargement initial -->
21 - <section v-if="isInitialLoading" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"> 21 + <section
22 - <div v-for="i in skeletonNumber" :key="i" class="bg-gray-800 rounded-lg overflow-hidden shadow-lg animate-pulse"> 22 + v-if="isInitialLoading"
  23 + class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6"
  24 + >
  25 + <div
  26 + v-for="i in skeletonNumber"
  27 + :key="i"
  28 + class="bg-gray-800 rounded-lg overflow-hidden shadow-lg animate-pulse"
  29 + >
23 <div class="h-80 bg-gray-700" /> 30 <div class="h-80 bg-gray-700" />
24 <div class="p-4"> 31 <div class="p-4">
25 <div class="h-6 bg-gray-700 rounded mb-3" /> 32 <div class="h-6 bg-gray-700 rounded mb-3" />
@@ -79,9 +79,16 @@ watch( @@ -79,9 +79,16 @@ watch(
79 79
80 <template> 80 <template>
81 <div> 81 <div>
82 - <editor v-model="content" :api-key="runtimeConfig.public.apiTinyMceSecret" :init="init" /> 82 + <editor
  83 + v-model="content"
  84 + :api-key="runtimeConfig.public.apiTinyMceSecret"
  85 + :init="init"
  86 + />
83 </div> 87 </div>
84 - <div v-if="errorMessage" class="text-red-500 text-sm mt-1"> 88 + <div
  89 + v-if="errorMessage"
  90 + class="text-red-500 text-sm mt-1"
  91 + >
85 {{ errorMessage }} 92 {{ errorMessage }}
86 </div> 93 </div>
87 </template> 94 </template>
@@ -3,7 +3,10 @@ @@ -3,7 +3,10 @@
3 <template> 3 <template>
4 <v-container class="bg-gray-900"> 4 <v-container class="bg-gray-900">
5 <v-row class="bg-gray-900"> 5 <v-row class="bg-gray-900">
6 - <v-col cols="12" sm="4"> 6 + <v-col
  7 + cols="12"
  8 + sm="4"
  9 + >
7 <v-skeleton-loader 10 <v-skeleton-loader
8 class="mx-auto border bg-gray-800" 11 class="mx-auto border bg-gray-800"
9 color="#1f2937" 12 color="#1f2937"
@@ -12,7 +15,10 @@ @@ -12,7 +15,10 @@
12 type="paragraph, image" 15 type="paragraph, image"
13 /> 16 />
14 </v-col> 17 </v-col>
15 - <v-col cols="12" sm="8"> 18 + <v-col
  19 + cols="12"
  20 + sm="8"
  21 + >
16 <v-skeleton-loader 22 <v-skeleton-loader
17 class="mx-auto mt-10" 23 class="mx-auto mt-10"
18 color="#1f2937" 24 color="#1f2937"
@@ -21,6 +21,12 @@ export default defineNuxtConfig({ @@ -21,6 +21,12 @@ export default defineNuxtConfig({
21 21
22 // css: ['~/assets/css/main.scss'], 22 // css: ['~/assets/css/main.scss'],
23 23
  24 + eslint: {
  25 + config: {
  26 + stylistic: true,
  27 + },
  28 + },
  29 +
24 modules: [ 30 modules: [
25 "@nuxt/eslint", 31 "@nuxt/eslint",
26 "@nuxt/icon", 32 "@nuxt/icon",
@@ -22,8 +22,8 @@ @@ -22,8 +22,8 @@
22 "@vitejs/plugin-vue": "^5.2.3", 22 "@vitejs/plugin-vue": "^5.2.3",
23 "@vuelidate/core": "^2.0.3", 23 "@vuelidate/core": "^2.0.3",
24 "@vuelidate/validators": "^2.0.4", 24 "@vuelidate/validators": "^2.0.4",
25 - "@vueuse/core": "^13.1.0", 25 + "@vueuse/core": "^13.2.0",
26 - "@vueuse/nuxt": "^13.1.0", 26 + "@vueuse/nuxt": "^13.2.0",
27 "eslint": "^9.25.1", 27 "eslint": "^9.25.1",
28 "lucide-vue-next": "^0.503.0", 28 "lucide-vue-next": "^0.503.0",
29 "nuxt": "^3.16.2", 29 "nuxt": "^3.16.2",
@@ -36,6 +36,7 @@ @@ -36,6 +36,7 @@
36 "devDependencies": { 36 "devDependencies": {
37 "@nuxt/test-utils": "^3.17.2", 37 "@nuxt/test-utils": "^3.17.2",
38 "@nuxtjs/tailwindcss": "^6.13.2", 38 "@nuxtjs/tailwindcss": "^6.13.2",
  39 + "@typescript-eslint/parser": "^8.32.1",
39 "@vue/test-utils": "^2.4.6", 40 "@vue/test-utils": "^2.4.6",
40 "eslint-config-prettier": "^10.1.2", 41 "eslint-config-prettier": "^10.1.2",
41 "eslint-plugin-prettier": "^5.2.6", 42 "eslint-plugin-prettier": "^5.2.6",
@@ -44,7 +45,8 @@ @@ -44,7 +45,8 @@
44 "playwright-core": "^1.52.0", 45 "playwright-core": "^1.52.0",
45 "prettier": "^3.5.3", 46 "prettier": "^3.5.3",
46 "typescript-eslint": "^8.32.1", 47 "typescript-eslint": "^8.32.1",
47 - "vitest": "^3.1.2" 48 + "vitest": "^3.1.2",
  49 + "vue-eslint-parser": "^10.1.3"
48 } 50 }
49 }, 51 },
50 "node_modules/@alloc/quick-lru": { 52 "node_modules/@alloc/quick-lru": {
@@ -6212,14 +6214,14 @@ @@ -6212,14 +6214,14 @@
6212 } 6214 }
6213 }, 6215 },
6214 "node_modules/@vueuse/core": { 6216 "node_modules/@vueuse/core": {
6215 - "version": "13.1.0", 6217 + "version": "13.2.0",
6216 - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.1.0.tgz", 6218 + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.2.0.tgz",
6217 - "integrity": "sha512-PAauvdRXZvTWXtGLg8cPUFjiZEddTqmogdwYpnn60t08AA5a8Q4hZokBnpTOnVNqySlFlTcRYIC8OqreV4hv3Q==", 6219 + "integrity": "sha512-n5TZoIAxbWAQ3PqdVPDzLgIRQOujFfMlatdI+f7ditSmoEeNpPBvp7h2zamzikCmrhFIePAwdEQB6ENccHr7Rg==",
6218 "license": "MIT", 6220 "license": "MIT",
6219 "dependencies": { 6221 "dependencies": {
6220 "@types/web-bluetooth": "^0.0.21", 6222 "@types/web-bluetooth": "^0.0.21",
6221 - "@vueuse/metadata": "13.1.0", 6223 + "@vueuse/metadata": "13.2.0",
6222 - "@vueuse/shared": "13.1.0" 6224 + "@vueuse/shared": "13.2.0"
6223 }, 6225 },
6224 "funding": { 6226 "funding": {
6225 "url": "https://github.com/sponsors/antfu" 6227 "url": "https://github.com/sponsors/antfu"
@@ -6228,6 +6230,18 @@ @@ -6228,6 +6230,18 @@
6228 "vue": "^3.5.0" 6230 "vue": "^3.5.0"
6229 } 6231 }
6230 }, 6232 },
  6233 + "node_modules/@vueuse/core/node_modules/@vueuse/shared": {
  6234 + "version": "13.2.0",
  6235 + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.2.0.tgz",
  6236 + "integrity": "sha512-vx9ZPDF5HcU9up3Jgt3G62dMUfZEdk6tLyBAHYAG4F4n73vpaA7J5hdncDI/lS9Vm7GA/FPlbOmh9TrDZROTpg==",
  6237 + "license": "MIT",
  6238 + "funding": {
  6239 + "url": "https://github.com/sponsors/antfu"
  6240 + },
  6241 + "peerDependencies": {
  6242 + "vue": "^3.5.0"
  6243 + }
  6244 + },
6231 "node_modules/@vueuse/integrations": { 6245 "node_modules/@vueuse/integrations": {
6232 "version": "13.1.0", 6246 "version": "13.1.0",
6233 "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-13.1.0.tgz", 6247 "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-13.1.0.tgz",
@@ -6294,6 +6308,32 @@ @@ -6294,6 +6308,32 @@
6294 } 6308 }
6295 } 6309 }
6296 }, 6310 },
  6311 + "node_modules/@vueuse/integrations/node_modules/@vueuse/core": {
  6312 + "version": "13.1.0",
  6313 + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.1.0.tgz",
  6314 + "integrity": "sha512-PAauvdRXZvTWXtGLg8cPUFjiZEddTqmogdwYpnn60t08AA5a8Q4hZokBnpTOnVNqySlFlTcRYIC8OqreV4hv3Q==",
  6315 + "license": "MIT",
  6316 + "dependencies": {
  6317 + "@types/web-bluetooth": "^0.0.21",
  6318 + "@vueuse/metadata": "13.1.0",
  6319 + "@vueuse/shared": "13.1.0"
  6320 + },
  6321 + "funding": {
  6322 + "url": "https://github.com/sponsors/antfu"
  6323 + },
  6324 + "peerDependencies": {
  6325 + "vue": "^3.5.0"
  6326 + }
  6327 + },
  6328 + "node_modules/@vueuse/integrations/node_modules/@vueuse/metadata": {
  6329 + "version": "13.1.0",
  6330 + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.1.0.tgz",
  6331 + "integrity": "sha512-+TDd7/a78jale5YbHX9KHW3cEDav1lz1JptwDvep2zSG8XjCsVE+9mHIzjTOaPbHUAk5XiE4jXLz51/tS+aKQw==",
  6332 + "license": "MIT",
  6333 + "funding": {
  6334 + "url": "https://github.com/sponsors/antfu"
  6335 + }
  6336 + },
6297 "node_modules/@vueuse/math": { 6337 "node_modules/@vueuse/math": {
6298 "version": "13.1.0", 6338 "version": "13.1.0",
6299 "resolved": "https://registry.npmjs.org/@vueuse/math/-/math-13.1.0.tgz", 6339 "resolved": "https://registry.npmjs.org/@vueuse/math/-/math-13.1.0.tgz",
@@ -6310,23 +6350,23 @@ @@ -6310,23 +6350,23 @@
6310 } 6350 }
6311 }, 6351 },
6312 "node_modules/@vueuse/metadata": { 6352 "node_modules/@vueuse/metadata": {
6313 - "version": "13.1.0", 6353 + "version": "13.2.0",
6314 - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.1.0.tgz", 6354 + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.2.0.tgz",
6315 - "integrity": "sha512-+TDd7/a78jale5YbHX9KHW3cEDav1lz1JptwDvep2zSG8XjCsVE+9mHIzjTOaPbHUAk5XiE4jXLz51/tS+aKQw==", 6355 + "integrity": "sha512-kPpzuQCU0+D8DZCzK0iPpIcXI+6ufWSgwnjJ6//GNpEn+SHViaCtR+XurzORChSgvpHO9YC8gGM97Y1kB+UabA==",
6316 "license": "MIT", 6356 "license": "MIT",
6317 "funding": { 6357 "funding": {
6318 "url": "https://github.com/sponsors/antfu" 6358 "url": "https://github.com/sponsors/antfu"
6319 } 6359 }
6320 }, 6360 },
6321 "node_modules/@vueuse/nuxt": { 6361 "node_modules/@vueuse/nuxt": {
6322 - "version": "13.1.0", 6362 + "version": "13.2.0",
6323 - "resolved": "https://registry.npmjs.org/@vueuse/nuxt/-/nuxt-13.1.0.tgz", 6363 + "resolved": "https://registry.npmjs.org/@vueuse/nuxt/-/nuxt-13.2.0.tgz",
6324 - "integrity": "sha512-4xdxwKanLY4+z+/ZgSZcJvwuHlgZMU3km7z4lhlbLl6WZTKS3BiztnRzcrdt4zjU512oTlH5nsPNhUhV0KXiOA==", 6364 + "integrity": "sha512-vLEyR2njEpugSOi12SuWwrClFxXrG/X20XExvkdHhIZ2R5qhm3wbmThUmHZ9K8AJI1+Y1m/qJUzmrac2FtLreA==",
6325 "license": "MIT", 6365 "license": "MIT",
6326 "dependencies": { 6366 "dependencies": {
6327 - "@nuxt/kit": "^3.16.2", 6367 + "@nuxt/kit": "^3.17.3",
6328 - "@vueuse/core": "13.1.0", 6368 + "@vueuse/core": "13.2.0",
6329 - "@vueuse/metadata": "13.1.0", 6369 + "@vueuse/metadata": "13.2.0",
6330 "local-pkg": "^1.1.1" 6370 "local-pkg": "^1.1.1"
6331 }, 6371 },
6332 "funding": { 6372 "funding": {
@@ -6337,6 +6377,80 @@ @@ -6337,6 +6377,80 @@
6337 "vue": "^3.5.0" 6377 "vue": "^3.5.0"
6338 } 6378 }
6339 }, 6379 },
  6380 + "node_modules/@vueuse/nuxt/node_modules/@nuxt/kit": {
  6381 + "version": "3.17.3",
  6382 + "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.17.3.tgz",
  6383 + "integrity": "sha512-aw6u6mT3TnM/MmcCRDMv3i9Sbm5/ZMSJgDl+N+WsrWNDIQ2sWmsqdDkjb/HyXF20SNwc2891hRBkaQr3hG2mhA==",
  6384 + "license": "MIT",
  6385 + "dependencies": {
  6386 + "c12": "^3.0.3",
  6387 + "consola": "^3.4.2",
  6388 + "defu": "^6.1.4",
  6389 + "destr": "^2.0.5",
  6390 + "errx": "^0.1.0",
  6391 + "exsolve": "^1.0.5",
  6392 + "ignore": "^7.0.4",
  6393 + "jiti": "^2.4.2",
  6394 + "klona": "^2.0.6",
  6395 + "knitwork": "^1.2.0",
  6396 + "mlly": "^1.7.4",
  6397 + "ohash": "^2.0.11",
  6398 + "pathe": "^2.0.3",
  6399 + "pkg-types": "^2.1.0",
  6400 + "scule": "^1.3.0",
  6401 + "semver": "^7.7.1",
  6402 + "std-env": "^3.9.0",
  6403 + "tinyglobby": "^0.2.13",
  6404 + "ufo": "^1.6.1",
  6405 + "unctx": "^2.4.1",
  6406 + "unimport": "^5.0.1",
  6407 + "untyped": "^2.0.0"
  6408 + },
  6409 + "engines": {
  6410 + "node": ">=18.12.0"
  6411 + }
  6412 + },
  6413 + "node_modules/@vueuse/nuxt/node_modules/tinyglobby": {
  6414 + "version": "0.2.13",
  6415 + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
  6416 + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
  6417 + "license": "MIT",
  6418 + "dependencies": {
  6419 + "fdir": "^6.4.4",
  6420 + "picomatch": "^4.0.2"
  6421 + },
  6422 + "engines": {
  6423 + "node": ">=12.0.0"
  6424 + },
  6425 + "funding": {
  6426 + "url": "https://github.com/sponsors/SuperchupuDev"
  6427 + }
  6428 + },
  6429 + "node_modules/@vueuse/nuxt/node_modules/unimport": {
  6430 + "version": "5.0.1",
  6431 + "resolved": "https://registry.npmjs.org/unimport/-/unimport-5.0.1.tgz",
  6432 + "integrity": "sha512-1YWzPj6wYhtwHE+9LxRlyqP4DiRrhGfJxdtH475im8ktyZXO3jHj/3PZ97zDdvkYoovFdi0K4SKl3a7l92v3sQ==",
  6433 + "license": "MIT",
  6434 + "dependencies": {
  6435 + "acorn": "^8.14.1",
  6436 + "escape-string-regexp": "^5.0.0",
  6437 + "estree-walker": "^3.0.3",
  6438 + "local-pkg": "^1.1.1",
  6439 + "magic-string": "^0.30.17",
  6440 + "mlly": "^1.7.4",
  6441 + "pathe": "^2.0.3",
  6442 + "picomatch": "^4.0.2",
  6443 + "pkg-types": "^2.1.0",
  6444 + "scule": "^1.3.0",
  6445 + "strip-literal": "^3.0.0",
  6446 + "tinyglobby": "^0.2.13",
  6447 + "unplugin": "^2.3.2",
  6448 + "unplugin-utils": "^0.2.4"
  6449 + },
  6450 + "engines": {
  6451 + "node": ">=18.12.0"
  6452 + }
  6453 + },
6340 "node_modules/@vueuse/shared": { 6454 "node_modules/@vueuse/shared": {
6341 "version": "13.1.0", 6455 "version": "13.1.0",
6342 "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.1.0.tgz", 6456 "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.1.0.tgz",
@@ -30,8 +30,8 @@ @@ -30,8 +30,8 @@
30 "@vitejs/plugin-vue": "^5.2.3", 30 "@vitejs/plugin-vue": "^5.2.3",
31 "@vuelidate/core": "^2.0.3", 31 "@vuelidate/core": "^2.0.3",
32 "@vuelidate/validators": "^2.0.4", 32 "@vuelidate/validators": "^2.0.4",
33 - "@vueuse/core": "^13.1.0", 33 + "@vueuse/core": "^13.2.0",
34 - "@vueuse/nuxt": "^13.1.0", 34 + "@vueuse/nuxt": "^13.2.0",
35 "eslint": "^9.25.1", 35 "eslint": "^9.25.1",
36 "lucide-vue-next": "^0.503.0", 36 "lucide-vue-next": "^0.503.0",
37 "nuxt": "^3.16.2", 37 "nuxt": "^3.16.2",
@@ -44,6 +44,7 @@ @@ -44,6 +44,7 @@
44 "devDependencies": { 44 "devDependencies": {
45 "@nuxt/test-utils": "^3.17.2", 45 "@nuxt/test-utils": "^3.17.2",
46 "@nuxtjs/tailwindcss": "^6.13.2", 46 "@nuxtjs/tailwindcss": "^6.13.2",
  47 + "@typescript-eslint/parser": "^8.32.1",
47 "@vue/test-utils": "^2.4.6", 48 "@vue/test-utils": "^2.4.6",
48 "eslint-config-prettier": "^10.1.2", 49 "eslint-config-prettier": "^10.1.2",
49 "eslint-plugin-prettier": "^5.2.6", 50 "eslint-plugin-prettier": "^5.2.6",
@@ -52,6 +53,7 @@ @@ -52,6 +53,7 @@
52 "playwright-core": "^1.52.0", 53 "playwright-core": "^1.52.0",
53 "prettier": "^3.5.3", 54 "prettier": "^3.5.3",
54 "typescript-eslint": "^8.32.1", 55 "typescript-eslint": "^8.32.1",
55 - "vitest": "^3.1.2" 56 + "vitest": "^3.1.2",
  57 + "vue-eslint-parser": "^10.1.3"
56 } 58 }
57 } 59 }
@@ -153,9 +153,16 @@ onMounted(() => { @@ -153,9 +153,16 @@ onMounted(() => {
153 <ui-components-skeleton-movie-detail-loader v-if="isLoading" /> 153 <ui-components-skeleton-movie-detail-loader v-if="isLoading" />
154 154
155 <!-- Contenu du film --> 155 <!-- Contenu du film -->
156 - <div v-else-if="movie" class="relative"> 156 + <div
  157 + v-else-if="movie"
  158 + class="relative"
  159 + >
157 <!-- Backdrop image --> 160 <!-- Backdrop image -->
158 - <ui-components-backdrop-image v-if="movie.backdrop_path" :src="movie.backdrop_path" :title="movie.title" /> 161 + <ui-components-backdrop-image
  162 + v-if="movie.backdrop_path"
  163 + :src="movie.backdrop_path"
  164 + :title="movie.title"
  165 + />
159 166
160 <!-- Contenu principal --> 167 <!-- Contenu principal -->
161 <div class="container mx-auto px-4 py-8 relative z-10 pt-20"> 168 <div class="container mx-auto px-4 py-8 relative z-10 pt-20">
@@ -163,41 +170,64 @@ onMounted(() => { @@ -163,41 +170,64 @@ onMounted(() => {
163 class="flex items-center text-gray-400 hover:text-white mb-8 transition-colors" 170 class="flex items-center text-gray-400 hover:text-white mb-8 transition-colors"
164 @click="navigateTo('/')" 171 @click="navigateTo('/')"
165 > 172 >
166 - <ArrowLeftIcon :size="20" class="mr-2" /> 173 + <ArrowLeftIcon
  174 + :size="20"
  175 + class="mr-2"
  176 + />
167 Retour 177 Retour
168 </button> 178 </button>
169 179
170 <div class="flex flex-col md:flex-row gap-8"> 180 <div class="flex flex-col md:flex-row gap-8">
171 <!-- Poster --> 181 <!-- Poster -->
172 - <ui-components-poster v-if="movie.poster_path" :src="movie.poster_path" :title="movie.title" /> 182 + <ui-components-poster
  183 + v-if="movie.poster_path"
  184 + :src="movie.poster_path"
  185 + :title="movie.title"
  186 + />
173 187
174 <!-- Informations du film --> 188 <!-- Informations du film -->
175 <section class="w-full md:w-2/3 lg:w-3/4"> 189 <section class="w-full md:w-2/3 lg:w-3/4">
176 <h1 class="text-3xl md:text-4xl font-bold mb-2"> 190 <h1 class="text-3xl md:text-4xl font-bold mb-2">
177 {{ movie.title }} 191 {{ movie.title }}
178 </h1> 192 </h1>
179 - <p v-if="movie.release_date" class="text-gray-400 mb-4"> 193 + <p
  194 + v-if="movie.release_date"
  195 + class="text-gray-400 mb-4"
  196 + >
180 {{ useDateFormat(movie.release_date, "DD-MM-YYYY") }} • {{ formatRuntime(movie.runtime) }} 197 {{ useDateFormat(movie.release_date, "DD-MM-YYYY") }} • {{ formatRuntime(movie.runtime) }}
181 </p> 198 </p>
182 199
183 <!-- Note et votes --> 200 <!-- Note et votes -->
184 - <details-score-and-vote :nb-vote="movie.vote_count" :score="movie.vote_average" /> 201 + <details-score-and-vote
  202 + :nb-vote="movie.vote_count"
  203 + :score="movie.vote_average"
  204 + />
185 205
186 <!-- Genres --> 206 <!-- Genres -->
187 <details-movie-gender :genres="movie.genres" /> 207 <details-movie-gender :genres="movie.genres" />
188 208
189 <!-- Synopsis --> 209 <!-- Synopsis -->
190 <div class="mb-6"> 210 <div class="mb-6">
191 - <h2 class="text-xl font-bold mb-2">Synopsis</h2> 211 + <h2 class="text-xl font-bold mb-2">
  212 + Synopsis
  213 + </h2>
192 <p class="text-gray-300"> 214 <p class="text-gray-300">
193 {{ movie.overview || "Aucun synopsis disponible." }} 215 {{ movie.overview || "Aucun synopsis disponible." }}
194 </p> 216 </p>
195 </div> 217 </div>
196 218
197 <!-- Réalisateur et têtes d'affiche --> 219 <!-- Réalisateur et têtes d'affiche -->
198 - <div v-if="movie.credit" class="mb-6"> 220 + <div
199 - <h2 class="text-xl font-bold mb-2">Équipe</h2> 221 + v-if="movie.credit"
200 - <div v-if="director" class="mb-2"> 222 + class="mb-6"
  223 + >
  224 + <h2 class="text-xl font-bold mb-2">
  225 + Équipe
  226 + </h2>
  227 + <div
  228 + v-if="director"
  229 + class="mb-2"
  230 + >
201 <span class="font-semibold">Réalisateur:</span> {{ director.name }} 231 <span class="font-semibold">Réalisateur:</span> {{ director.name }}
202 </div> 232 </div>
203 <div v-if="movie.credit.cast.length > 0"> 233 <div v-if="movie.credit.cast.length > 0">
@@ -212,7 +242,9 @@ onMounted(() => { @@ -212,7 +242,9 @@ onMounted(() => {
212 </div> 242 </div>
213 </div> 243 </div>
214 <!-- Comments form. --> 244 <!-- Comments form. -->
215 - <h3 class="text-xl font-bold mt-8 mb-4">Ajouter un commentaire</h3> 245 + <h3 class="text-xl font-bold mt-8 mb-4">
  246 + Ajouter un commentaire
  247 + </h3>
216 <form-movie-comment-form @event:submit="handleSubmitEvent" /> 248 <form-movie-comment-form @event:submit="handleSubmitEvent" />
217 249
218 <!-- Liste des commentaires --> 250 <!-- Liste des commentaires -->
@@ -223,10 +255,20 @@ onMounted(() => { @@ -223,10 +255,20 @@ onMounted(() => {
223 </div> 255 </div>
224 256
225 <!-- Erreur --> 257 <!-- Erreur -->
226 - <section v-else class="container mx-auto px-4 py-16 text-center"> 258 + <section
227 - <AlertTriangleIcon :size="64" class="mx-auto mb-4 text-red-500" /> 259 + v-else
228 - <h2 class="text-2xl font-bold mb-2">Film non trouvé</h2> 260 + class="container mx-auto px-4 py-16 text-center"
229 - <p class="text-gray-400 mb-6">Nous n'avons pas pu trouver le film que vous cherchez.</p> 261 + >
  262 + <AlertTriangleIcon
  263 + :size="64"
  264 + class="mx-auto mb-4 text-red-500"
  265 + />
  266 + <h2 class="text-2xl font-bold mb-2">
  267 + Film non trouvé
  268 + </h2>
  269 + <p class="text-gray-400 mb-6">
  270 + Nous n'avons pas pu trouver le film que vous cherchez.
  271 + </p>
230 <button 272 <button
231 class="px-6 py-2 bg-primary text-white font-bold rounded-md hover:bg-primary-dark transition-colors" 273 class="px-6 py-2 bg-primary text-white font-bold rounded-md hover:bg-primary-dark transition-colors"
232 @click="navigateTo('/')" 274 @click="navigateTo('/')"