Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Bruno Predot
/
tmdb_test
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
Bruno Predot
2025-04-24 20:57:17 +0200
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
501cc3bd01778b4329116a1bcf497fa5b0c39232
501cc3bd
1 parent
3a480273
Gestion des events search et clear de la searchBar
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
43 additions
and
11 deletions
components/MoviesList.vue
components/SearchBar.vue
components/MoviesList.vue
View file @
501cc3b
...
...
@@ -6,7 +6,7 @@ import { useTMDB } from "~/composables/tMDB";
import { Movie } from "~/models/movie";
import { FilmIcon } from "lucide-vue-next";
import type { MovieInterface } from "~/interfaces/movie";
import { useDateFormat } from
'@vueuse/core'
import { useDateFormat } from
"@vueuse/core";
//#endregion
//#region --Declaration--.
...
...
@@ -26,7 +26,7 @@ const observer = ref<IntersectionObserver | null>(null);
//#region --Computed--.
const movies = computed(() => {
return useRepo(Movie).query().orderBy("popularity",
'desc'
).get() as unknown as MovieInterface[];
return useRepo(Movie).query().orderBy("popularity",
"desc"
).get() as unknown as MovieInterface[];
});
//#endregion
...
...
@@ -40,7 +40,11 @@ const fetchMovies = async (page: number) => {
isLoadingMore.value = true;
const data = await fetchPopularMovies(page);
// Save in Movie model.
isInitialLoading.value ? useRepo(Movie).fresh(data.results) : useRepo(Movie).save(data.results);
if (isInitialLoading.value) {
useRepo(Movie).fresh(data.results);
} else {
useRepo(Movie).save(data.results);
}
totalPages.value = data.total_pages;
currentPage.value = page;
...
...
@@ -63,6 +67,15 @@ function createIntersectionObserver() {
{ threshold: 1.0 },
);
}
function handleSearchEvent(event: string) {
console.log(event);
}
function handleClearSearchEvent() {
console.log("clear event");
}
//#endregion
//#region --Global event--.
...
...
@@ -94,7 +107,11 @@ onBeforeUnmount(() => {
<section>
<h1 class="text-4xl font-bold mb-8 text-center">Découvrez les films populaires</h1>
<!-- Barre de recherche -->
<search-bar placeholder="Rechercher un film..." />
<search-bar
placeholder="Rechercher un film..."
@event:search="handleSearchEvent"
@event:clear_search="handleClearSearchEvent"
/>
<!-- Loading Skeleton -->
<skeleton-movies-loader v-if="isInitialLoading" :is-initial-loading="isInitialLoading" :skeleton-number="20" />
<!-- Liste des films -->
...
...
@@ -108,10 +125,10 @@ onBeforeUnmount(() => {
<div class="relative pb-[150%]">
<img
v-if="movie.poster_path"
:src="`https://image.tmdb.org/t/p/w500${movie.poster_path}`"
:alt="movie.title"
:src="`https://image.tmdb.org/t/p/w500${movie.poster_path}`"
class="absolute inset-0 w-full h-full object-cover"
>
/
>
<div v-else class="absolute inset-0 w-full h-full bg-gray-700 flex items-center justify-center">
<FilmIcon :size="48" class="text-gray-500" />
</div>
...
...
@@ -123,13 +140,13 @@ onBeforeUnmount(() => {
</div>
<div class="p-4">
<h2 class="text-lg font-bold mb-1 line-clamp-1">{{ movie.title }}</h2>
<p class="text-sm text-gray-400">{{ useDateFormat(movie.release_date,
'DD-MM-YYYY'
) }}</p>
<p class="text-sm text-gray-400">{{ useDateFormat(movie.release_date,
"DD-MM-YYYY"
) }}</p>
</div>
</div>
</div>
<!-- Élément observé pour le défilement infini -->
<div ref="loadMoreTrigger" class="h-10 mt-4"/>
<div ref="loadMoreTrigger" class="h-10 mt-4"
/>
</section>
</template>
...
...
components/SearchBar.vue
View file @
501cc3b
...
...
@@ -2,10 +2,11 @@
//#region --import--.
import { SearchIcon, XIcon } from "lucide-vue-next";
import { ref } from "vue";
import { useDebounceFn } from "@vueuse/core";
//#endregion
//#region --Emits--.
// const emit = defineEmits([
]);
const emit = defineEmits(['event:search', 'event:clear_search'
]);
//#endregion
//#region --Props--.
...
...
@@ -22,6 +23,20 @@ defineProps({
//#region --Data/refs--.
const searchQuery = ref("");
//#endregion
//#region --Function--.
/**
* Debounced function
*/
const handleSearchEvent = useDebounceFn(() => {
emit('event:search', searchQuery.value);
}, 500);
function handleClearSearchEvent() {
searchQuery.value = '';
emit('event:clear_search')
}
//#endregion
</script>
<template>
...
...
@@ -33,12 +48,12 @@ const searchQuery = ref("");
:placeholder="placeholder"
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"
type="text"
@input="
console.log('debouncedSearch à prévoir')
"
@input="
handleSearchEvent
"
/>
<button
v-if="searchQuery"
class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-white"
@click="
console.log('clearSearch à prévoir')
"
@click="
handleClearSearchEvent
"
>
<XIcon :size="20" />
</button>
...
...
Please
register
or
login
to post a comment