Listando filmes
Vamos agora listar os filmes ao clicar no gênero. Para isso, vamos alterar o componente MoviesView.vue para que ele liste os filmes ao clicar no gênero. Inicialmente, vamos adicionar um listener ao evento click do elemento li que contém o gênero. Para isso, vamos alterar o bloco template do arquivo MoviesView.vue para o seguinte conteúdo:
<template>
...
<li
v-for="genre in genres"
:key="genre.id"
@click="listMovies(genre.id)"
class="genre-item"
>
{{ genre.name }}
</li>
...
</template>
Note que adicionamos o listener ao evento click do elemento li que contém o gênero. Esse listener chama o método listMovies passando o id do gênero como parâmetro. Além disso, as demais partes do código permanecem inalteradas. Agora, vamos adicionar o método listMovies no bloco script do arquivo MoviesView.vue:
<script setup>
...
const movies = ref([]);
const listMovies = async (genreId) => {
const response = await api.get('discover/movie', {
params: {
with_genres: genreId,
language: 'pt-BR'
}
});
movies.value = response.data.results
};
...
</script>
Neste exemplo, criamos uma variável reativa movies que armazena a lista de filmes. Além disso, criamos o método listMovies que recebe o id do gênero como parâmetro (chamado de genreId). Esse método faz uma requisição para a rota discover/movie da API do TMDB passando o genreId como parâmetro. Em seguida, o método atribui a lista de filmes retornada pela API à variável reativa movies. As demais partes do código permanecem inalteradas. Agora, vamos alterar o bloco template do arquivo MoviesView.vue, adicionando o seguinte conteúdo, depois de fechar a tag </ul>:
<div class="movie-list">
<div v-for="movie in movies" :key="movie.id" class="movie-card">
<img
:src="`https://image.tmdb.org/t/p/w500${movie.poster_path}`"
:alt="movie.title"
/>
<div class="movie-details">
<p class="movie-title">{{ movie.title }}</p>
<p class="movie-release-date">{{ movie.release_date }}</p>
<p class="movie-genres">{{ movie.genre_ids }}</p>
</div>
</div>
</div>
Neste caso, criamos um elemento div com a classe movie-list que contém um elemento div para cada filme (comportamento garantido pelo v-for). Cada elemento div com a classe movie-card contém:
- uma imagem com o cartaz do filme,
- um elemento
divcom a classemovie-detailsque contém:- o título,
- a data de lançamento e
- os gêneros do filme.
Note que utilizamos a interpolação para definir o valor do atributo
srcda imagem. Além disso, utilizamos a interpolação para definir o valor dos textos dos elementospque contém o título, a data de lançamento e os gêneros do filme.
Agora, vamos adicionar o seguinte estilo no bloco style do arquivo MoviesView.vue:
.movie-list {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.movie-card {
width: 15rem;
height: 30rem;
border-radius: 0.5rem;
overflow: hidden;
box-shadow: 0 0 0.5rem #000;
}
.movie-card img {
width: 100%;
height: 20rem;
border-radius: 0.5rem;
box-shadow: 0 0 0.5rem #000;
}
.movie-details {
padding: 0 0.5rem;
}
.movie-title {
font-size: 1.1rem;
font-weight: bold;
line-height: 1.3rem;
height: 3.2rem;
}
Neste caso, definimos 5 regras de estilos CSS:
- para o elemento
divcom a classemovie-list- a propriedade
displaycom o valorflex: define que o elemento deve ser exibido como um flex container. - a propriedade
flex-wrapcom o valorwrap: define que os elementos devem ser exibidos em várias linhas. - a propriedade
gapcom o valor1rem: define o espaçamento entre os elementos como 1 vez o tamanho da fonte.
- a propriedade
- para o elemento
divcom a classemovie-card- a propriedade
widthcom o valor15rem: define a largura do elemento como 15 vezes o tamanho da fonte. - a propriedade
heightcom o valor30rem: define a altura do elemento como 30 vezes o tamanho da fonte. - a propriedade
border-radiuscom o valor0.5rem: define o raio da borda como 0.5 vezes o tamanho da fonte. - a propriedade
overflowcom o valorhidden: define que o conteúdo que ultrapassar o tamanho do elemento deve ser ocultado. - a propriedade
box-shadowcom o valor0 0 0.5rem #000: define um sombreamento de 0.5 vezes o tamanho da fonte.
- a propriedade
- para a imagem
- a propriedade
widthcom o valor100%: define a largura da imagem como 100% do tamanho do elemento pai. - a propriedade
heightcom o valor20rem: define a altura da imagem como 20 vezes o tamanho da fonte. - a propriedade
border-radiuscom o valor0.5rem: define o raio da borda como 0.5 vezes o tamanho da fonte. - a propriedade
box-shadowcom o valor0 0 0.5rem #000: define um sombreamento de 0.5 vezes o tamanho da fonte.
- a propriedade
- para o elemento
divcom a classemovie-details- a propriedade
paddingcom o valor0 0.5rem: define o espaçamento interno como 0 vezes o tamanho da fonte na vertical e 0.5 vezes o tamanho da fonte na horizontal.
- a propriedade
- para o elemento
pcom a classemovie-title- a propriedade
font-sizecom o valor1.1rem: define o tamanho da fonte como 1.1 vezes o tamanho da fonte. - a propriedade
font-weightcom o valorbold: define o peso da fonte como negrito. - a propriedade
line-heightcom o valor1.3rem: define a altura da linha como 1.3 vezes o tamanho da fonte. - a propriedade
heightcom o valor3.2rem: define a altura do elemento como 3.2 vezes o tamanho da fonte.
- a propriedade
Por fim, faremos uma pequena alteração na definação de estilo da classe .genre-list para adicionar uma margem inferior, como segue:
.genre-list {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 2rem;
list-style: none;
margin-bottom: 2rem;
}
Note que nesse caso adicionamos a propriedade margin-bottom com o valor 2rem para definir uma margem inferior de 2 vezes o tamanho da fonte.
Exercícios
Fazer a listagem de programas de TV ao clicar no gênero. Note que no caso dos programas de TV, a rota da API é discover/tv e o parâmetro para filtrar por gênero é with_genres. Além disso, o nome do campo que contém o título do programa de TV é name, o nome original é original_name e o nome do campo que contém a data de lançamento é first_air_date.
< TMDB: ajustes nos estilos TMDB: Visualizar como carregando >