Bruno Predot

Merge branch 'hotfix/0.3.4'

@@ -26,15 +26,9 @@ defineProps({ @@ -26,15 +26,9 @@ defineProps({
26 :alt="movie.title" 26 :alt="movie.title"
27 :src="`https://image.tmdb.org/t/p/w500${movie.poster_path}`" 27 :src="`https://image.tmdb.org/t/p/w500${movie.poster_path}`"
28 class="absolute inset-0 w-full h-full object-cover" 28 class="absolute inset-0 w-full h-full object-cover"
29 - >  
30 - <div  
31 - v-else  
32 - class="absolute inset-0 w-full h-full bg-gray-700 flex items-center justify-center"  
33 - >  
34 - <FilmIcon  
35 - :size="48"  
36 - class="text-gray-500"  
37 /> 29 />
  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" />
38 </div> 32 </div>
39 <div 33 <div
40 class="absolute top-2 right-2 bg-primary text-white rounded-full w-10 h-10 flex items-center justify-center font-bold" 34 class="absolute top-2 right-2 bg-primary text-white rounded-full w-10 h-10 flex items-center justify-center font-bold"
@@ -35,49 +35,27 @@ watch( @@ -35,49 +35,27 @@ watch(
35 <template> 35 <template>
36 <section> 36 <section>
37 <!-- Liste des commentaires --> 37 <!-- Liste des commentaires -->
38 - <section 38 + <section v-if="comments.length > 0" class="mt-10">
39 - v-if="comments.length > 0"  
40 - class="mt-10"  
41 - >  
42 <h2>Commentaires publiés</h2> 39 <h2>Commentaires publiés</h2>
43 - <div 40 + <div v-for="(comment, index) in comments" :key="index" class="bg-gray-800 rounded-lg p-6 mb-4">
44 - v-for="(comment, index) in comments"  
45 - :key="index"  
46 - class="bg-gray-800 rounded-lg p-6 mb-4"  
47 - >  
48 <div class="flex justify-between items-start mb-2"> 41 <div class="flex justify-between items-start mb-2">
49 <section> 42 <section>
50 - <h4 class="font-bold text-lg"> 43 + <h4 class="font-bold text-lg">Par {{ comment.username }}</h4>
51 - Par {{ comment.username }} 44 + <p class="text-sm text-gray-400">Le {{ useDateFormat(comment.createdAt, "DD-MM-YYYY") }}</p>
52 - </h4>  
53 - <p class="text-sm text-gray-400">  
54 - Le {{ useDateFormat(comment.createdAt, "DD-MM-YYYY") }}  
55 - </p>  
56 </section> 45 </section>
57 <section class="bg-primary text-white rounded-full w-10 h-10 flex items-center justify-center font-bold"> 46 <section class="bg-primary text-white rounded-full w-10 h-10 flex items-center justify-center font-bold">
58 {{ comment.rating }} 47 {{ comment.rating }}
59 </section> 48 </section>
60 </div> 49 </div>
61 - <p 50 + <p :id="`message${index}`" class="text-gray-300">
62 - :id="`message${index}`"  
63 - class="text-gray-300"  
64 - >  
65 {{ comment.message }} 51 {{ comment.message }}
66 </p> 52 </p>
67 </div> 53 </div>
68 </section> 54 </section>
69 <!-- Si aucun commentaire --> 55 <!-- Si aucun commentaire -->
70 - <section 56 + <section v-else class="text-center py-8 bg-gray-800 rounded-lg mt-10">
71 - v-else 57 + <MessageSquareIcon :size="48" class="mx-auto mb-3 text-gray-600" />
72 - class="text-center py-8 bg-gray-800 rounded-lg mt-10" 58 + <p class="text-gray-400">Aucun commentaire pour le moment. Soyez le premier à donner votre avis !</p>
73 - >  
74 - <MessageSquareIcon  
75 - :size="48"  
76 - class="mx-auto mb-3 text-gray-600"  
77 - />  
78 - <p class="text-gray-400">  
79 - Aucun commentaire pour le moment. Soyez le premier à donner votre avis !  
80 - </p>  
81 </section> 59 </section>
82 </section> 60 </section>
83 </template> 61 </template>
@@ -151,9 +151,7 @@ onBeforeUnmount(() => { @@ -151,9 +151,7 @@ onBeforeUnmount(() => {
151 151
152 <template> 152 <template>
153 <section> 153 <section>
154 - <h1 class="text-4xl font-bold mb-8 text-center"> 154 + <h1 class="text-4xl font-bold mb-8 text-center">Découvrez les films populaires</h1>
155 - Découvrez les films populaires  
156 - </h1>  
157 <!-- Barre de recherche --> 155 <!-- Barre de recherche -->
158 <ui-components-search-bar 156 <ui-components-search-bar
159 placeholder="Rechercher un film..." 157 placeholder="Rechercher un film..."
@@ -169,46 +167,24 @@ onBeforeUnmount(() => { @@ -169,46 +167,24 @@ onBeforeUnmount(() => {
169 /> 167 />
170 168
171 <!-- Liste des films --> 169 <!-- Liste des films -->
172 - <div 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">
173 - v-else-if="movies.length > 0" 171 + <div v-for="movie in movies" :key="movie.id">
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 - >  
180 <movie-card :movie="movie" /> 172 <movie-card :movie="movie" />
181 </div> 173 </div>
182 </div> 174 </div>
183 175
184 <!-- Message si aucun film trouvé --> 176 <!-- Message si aucun film trouvé -->
185 - <section 177 + <section v-else-if="searchQuery && !movies.length" class="text-center py-12">
186 - v-else-if="searchQuery && !movies.length" 178 + <SearchXIcon :size="64" class="mx-auto mb-4 text-gray-600" />
187 - class="text-center py-12" 179 + <h3 class="text-xl font-bold mb-2">Aucun film trouvé</h3>
188 - > 180 + <p class="text-gray-400">Essayez avec un autre terme de recherche</p>
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>  
199 </section> 181 </section>
200 182
201 <!-- Loader pour le chargement de plus de films --> 183 <!-- Loader pour le chargement de plus de films -->
202 - <ui-components-loader 184 + <ui-components-loader :is-initial-loading="isInitialLoading" :is-loading="isLoadingMore" />
203 - :is-initial-loading="isInitialLoading"  
204 - :is-loading="isLoadingMore"  
205 - />  
206 185
207 <!-- Élément observé pour le défilement infini --> 186 <!-- Élément observé pour le défilement infini -->
208 - <div 187 + <div ref="loadMoreTrigger" class="h-10 mt-4" />
209 - ref="loadMoreTrigger"  
210 - class="h-10 mt-4"  
211 - />  
212 </section> 188 </section>
213 </template> 189 </template>
214 190
@@ -17,11 +17,7 @@ defineProps({ @@ -17,11 +17,7 @@ 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 20 + <span v-for="genre in genres" :key="genre.id" class="px-3 py-1 bg-gray-800 rounded-full text-sm">
21 - v-for="genre in genres"  
22 - :key="genre.id"  
23 - class="px-3 py-1 bg-gray-800 rounded-full text-sm"  
24 - >  
25 {{ genre.name }} 21 {{ genre.name }}
26 </span> 22 </span>
27 </div> 23 </div>
@@ -34,9 +34,7 @@ const formatVoteCount = (count: number) => { @@ -34,9 +34,7 @@ const formatVoteCount = (count: number) => {
34 {{ score.toFixed(1) }} 34 {{ score.toFixed(1) }}
35 </section> 35 </section>
36 <section> 36 <section>
37 - <p class="font-semibold"> 37 + <p class="font-semibold">Note TMDB</p>
38 - Note TMDB  
39 - </p>  
40 <div class="text-sm text-gray-400"> 38 <div class="text-sm text-gray-400">
41 {{ formatVoteCount(nbVote) }} 39 {{ formatVoteCount(nbVote) }}
42 </div> 40 </div>
@@ -123,22 +123,13 @@ function handleMessageEvent(event: string) { @@ -123,22 +123,13 @@ function handleMessageEvent(event: string) {
123 } 123 }
124 " 124 "
125 > 125 >
126 - <span 126 + <span v-if="isSubmitting" class="flex items-center justify-center">
127 - v-if="isSubmitting"  
128 - class="flex items-center justify-center"  
129 - >  
130 <span class="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin mr-2" /> 127 <span class="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin mr-2" />
131 Envoi en cours... 128 Envoi en cours...
132 </span> 129 </span>
133 <span v-else>Publier le commentaire</span> 130 <span v-else>Publier le commentaire</span>
134 </v-btn> 131 </v-btn>
135 - <v-btn 132 + <v-btn class="mt-6 mr-4" color="primary" @click="clear"> effacer </v-btn>
136 - class="mt-6 mr-4"  
137 - color="primary"  
138 - @click="clear"  
139 - >  
140 - effacer  
141 - </v-btn>  
142 </VForm> 133 </VForm>
143 </section> 134 </section>
144 </template> 135 </template>
@@ -17,10 +17,7 @@ defineProps({ @@ -17,10 +17,7 @@ defineProps({
17 </script> 17 </script>
18 18
19 <template> 19 <template>
20 - <section 20 + <section v-if="isLoading && !isInitialLoading" class="flex justify-center mt-8">
21 - v-if="isLoading && !isInitialLoading"  
22 - class="flex justify-center mt-8"  
23 - >  
24 <div class="w-10 h-10 border-4 border-primary border-t-transparent rounded-full animate-spin" /> 21 <div class="w-10 h-10 border-4 border-primary border-t-transparent rounded-full animate-spin" />
25 </section> 22 </section>
26 </template> 23 </template>
@@ -20,20 +20,9 @@ defineProps({ @@ -20,20 +20,9 @@ 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 23 + <v-img v-if="src" :alt="title" :src="`https://image.tmdb.org/t/p/w500${src}`" class="w-full h-auto" />
24 - v-if="src" 24 + <div v-else class="aspect-[2/3] bg-gray-700 flex items-center justify-center">
25 - :alt="title" 25 + <FilmIcon :size="64" class="text-gray-500" />
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 - />  
37 </div> 26 </div>
38 </div> 27 </div>
39 </section> 28 </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,10 +57,7 @@ function handleClearSearchEvent() { @@ -57,10 +57,7 @@ function handleClearSearchEvent() {
57 > 57 >
58 <XIcon :size="20" /> 58 <XIcon :size="20" />
59 </button> 59 </button>
60 - <button 60 + <button v-else class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400">
61 - v-else  
62 - class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400"  
63 - >  
64 <SearchIcon :size="20" /> 61 <SearchIcon :size="20" />
65 </button> 62 </button>
66 </div> 63 </div>
@@ -18,15 +18,8 @@ defineProps({ @@ -18,15 +18,8 @@ defineProps({
18 18
19 <template> 19 <template>
20 <!-- Skeleton loader pendant le chargement initial --> 20 <!-- Skeleton loader pendant le chargement initial -->
21 - <section 21 + <section v-if="isInitialLoading" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
22 - v-if="isInitialLoading" 22 + <div v-for="i in skeletonNumber" :key="i" class="bg-gray-800 rounded-lg overflow-hidden shadow-lg animate-pulse">
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 - >  
30 <div class="h-80 bg-gray-700" /> 23 <div class="h-80 bg-gray-700" />
31 <div class="p-4"> 24 <div class="p-4">
32 <div class="h-6 bg-gray-700 rounded mb-3" /> 25 <div class="h-6 bg-gray-700 rounded mb-3" />
@@ -79,16 +79,9 @@ watch( @@ -79,16 +79,9 @@ watch(
79 79
80 <template> 80 <template>
81 <div> 81 <div>
82 - <editor 82 + <editor v-model="content" :api-key="runtimeConfig.public.apiTinyMceSecret" :init="init" />
83 - v-model="content"  
84 - :api-key="runtimeConfig.public.apiTinyMceSecret"  
85 - :init="init"  
86 - />  
87 </div> 83 </div>
88 - <div 84 + <div v-if="errorMessage" class="text-red-500 text-sm mt-1">
89 - v-if="errorMessage"  
90 - class="text-red-500 text-sm mt-1"  
91 - >  
92 {{ errorMessage }} 85 {{ errorMessage }}
93 </div> 86 </div>
94 </template> 87 </template>
@@ -3,10 +3,7 @@ @@ -3,10 +3,7 @@
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 6 + <v-col cols="12" sm="4">
7 - cols="12"  
8 - sm="4"  
9 - >  
10 <v-skeleton-loader 7 <v-skeleton-loader
11 class="mx-auto border bg-gray-800" 8 class="mx-auto border bg-gray-800"
12 color="#1f2937" 9 color="#1f2937"
@@ -15,10 +12,7 @@ @@ -15,10 +12,7 @@
15 type="paragraph, image" 12 type="paragraph, image"
16 /> 13 />
17 </v-col> 14 </v-col>
18 - <v-col 15 + <v-col cols="12" sm="8">
19 - cols="12"  
20 - sm="8"  
21 - >  
22 <v-skeleton-loader 16 <v-skeleton-loader
23 class="mx-auto mt-10" 17 class="mx-auto mt-10"
24 color="#1f2937" 18 color="#1f2937"
This diff is collapsed. Click to expand it.
@@ -51,6 +51,7 @@ @@ -51,6 +51,7 @@
51 "jsdom": "^26.1.0", 51 "jsdom": "^26.1.0",
52 "playwright-core": "^1.52.0", 52 "playwright-core": "^1.52.0",
53 "prettier": "^3.5.3", 53 "prettier": "^3.5.3",
  54 + "typescript-eslint": "^8.32.1",
54 "vitest": "^3.1.2" 55 "vitest": "^3.1.2"
55 } 56 }
56 } 57 }
@@ -153,16 +153,9 @@ onMounted(() => { @@ -153,16 +153,9 @@ 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 156 + <div v-else-if="movie" class="relative">
157 - v-else-if="movie"  
158 - class="relative"  
159 - >  
160 <!-- Backdrop image --> 157 <!-- Backdrop image -->
161 - <ui-components-backdrop-image 158 + <ui-components-backdrop-image v-if="movie.backdrop_path" :src="movie.backdrop_path" :title="movie.title" />
162 - v-if="movie.backdrop_path"  
163 - :src="movie.backdrop_path"  
164 - :title="movie.title"  
165 - />  
166 159
167 <!-- Contenu principal --> 160 <!-- Contenu principal -->
168 <div class="container mx-auto px-4 py-8 relative z-10 pt-20"> 161 <div class="container mx-auto px-4 py-8 relative z-10 pt-20">
@@ -170,64 +163,41 @@ onMounted(() => { @@ -170,64 +163,41 @@ onMounted(() => {
170 class="flex items-center text-gray-400 hover:text-white mb-8 transition-colors" 163 class="flex items-center text-gray-400 hover:text-white mb-8 transition-colors"
171 @click="navigateTo('/')" 164 @click="navigateTo('/')"
172 > 165 >
173 - <ArrowLeftIcon 166 + <ArrowLeftIcon :size="20" class="mr-2" />
174 - :size="20"  
175 - class="mr-2"  
176 - />  
177 Retour 167 Retour
178 </button> 168 </button>
179 169
180 <div class="flex flex-col md:flex-row gap-8"> 170 <div class="flex flex-col md:flex-row gap-8">
181 <!-- Poster --> 171 <!-- Poster -->
182 - <ui-components-poster 172 + <ui-components-poster v-if="movie.poster_path" :src="movie.poster_path" :title="movie.title" />
183 - v-if="movie.poster_path"  
184 - :src="movie.poster_path"  
185 - :title="movie.title"  
186 - />  
187 173
188 <!-- Informations du film --> 174 <!-- Informations du film -->
189 <section class="w-full md:w-2/3 lg:w-3/4"> 175 <section class="w-full md:w-2/3 lg:w-3/4">
190 <h1 class="text-3xl md:text-4xl font-bold mb-2"> 176 <h1 class="text-3xl md:text-4xl font-bold mb-2">
191 {{ movie.title }} 177 {{ movie.title }}
192 </h1> 178 </h1>
193 - <p 179 + <p v-if="movie.release_date" class="text-gray-400 mb-4">
194 - v-if="movie.release_date"  
195 - class="text-gray-400 mb-4"  
196 - >  
197 {{ useDateFormat(movie.release_date, "DD-MM-YYYY") }} • {{ formatRuntime(movie.runtime) }} 180 {{ useDateFormat(movie.release_date, "DD-MM-YYYY") }} • {{ formatRuntime(movie.runtime) }}
198 </p> 181 </p>
199 182
200 <!-- Note et votes --> 183 <!-- Note et votes -->
201 - <details-score-and-vote 184 + <details-score-and-vote :nb-vote="movie.vote_count" :score="movie.vote_average" />
202 - :nb-vote="movie.vote_count"  
203 - :score="movie.vote_average"  
204 - />  
205 185
206 <!-- Genres --> 186 <!-- Genres -->
207 <details-movie-gender :genres="movie.genres" /> 187 <details-movie-gender :genres="movie.genres" />
208 188
209 <!-- Synopsis --> 189 <!-- Synopsis -->
210 <div class="mb-6"> 190 <div class="mb-6">
211 - <h2 class="text-xl font-bold mb-2"> 191 + <h2 class="text-xl font-bold mb-2">Synopsis</h2>
212 - Synopsis  
213 - </h2>  
214 <p class="text-gray-300"> 192 <p class="text-gray-300">
215 {{ movie.overview || "Aucun synopsis disponible." }} 193 {{ movie.overview || "Aucun synopsis disponible." }}
216 </p> 194 </p>
217 </div> 195 </div>
218 196
219 <!-- Réalisateur et têtes d'affiche --> 197 <!-- Réalisateur et têtes d'affiche -->
220 - <div 198 + <div v-if="movie.credit" class="mb-6">
221 - v-if="movie.credit" 199 + <h2 class="text-xl font-bold mb-2">Équipe</h2>
222 - class="mb-6" 200 + <div v-if="director" class="mb-2">
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 - >  
231 <span class="font-semibold">Réalisateur:</span> {{ director.name }} 201 <span class="font-semibold">Réalisateur:</span> {{ director.name }}
232 </div> 202 </div>
233 <div v-if="movie.credit.cast.length > 0"> 203 <div v-if="movie.credit.cast.length > 0">
@@ -242,9 +212,7 @@ onMounted(() => { @@ -242,9 +212,7 @@ onMounted(() => {
242 </div> 212 </div>
243 </div> 213 </div>
244 <!-- Comments form. --> 214 <!-- Comments form. -->
245 - <h3 class="text-xl font-bold mt-8 mb-4"> 215 + <h3 class="text-xl font-bold mt-8 mb-4">Ajouter un commentaire</h3>
246 - Ajouter un commentaire  
247 - </h3>  
248 <form-movie-comment-form @event:submit="handleSubmitEvent" /> 216 <form-movie-comment-form @event:submit="handleSubmitEvent" />
249 217
250 <!-- Liste des commentaires --> 218 <!-- Liste des commentaires -->
@@ -255,20 +223,10 @@ onMounted(() => { @@ -255,20 +223,10 @@ onMounted(() => {
255 </div> 223 </div>
256 224
257 <!-- Erreur --> 225 <!-- Erreur -->
258 - <section 226 + <section v-else class="container mx-auto px-4 py-16 text-center">
259 - v-else 227 + <AlertTriangleIcon :size="64" class="mx-auto mb-4 text-red-500" />
260 - class="container mx-auto px-4 py-16 text-center" 228 + <h2 class="text-2xl font-bold mb-2">Film non trouvé</h2>
261 - > 229 + <p class="text-gray-400 mb-6">Nous n'avons pas pu trouver le film que vous cherchez.</p>
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>  
272 <button 230 <button
273 class="px-6 py-2 bg-primary text-white font-bold rounded-md hover:bg-primary-dark transition-colors" 231 class="px-6 py-2 bg-primary text-white font-bold rounded-md hover:bg-primary-dark transition-colors"
274 @click="navigateTo('/')" 232 @click="navigateTo('/')"