Mostrando detalhes do filme
Vamos agora, possibilitar a exibição de detalhes de um filme ao clicar em um cartão de filme.
Criando um store
Vamos criar um arquivo chamado src/stores/movie.js
e adicionar o seguinte código:
import { reactive, computed } from 'vue';
import { defineStore } from 'pinia';
import api from '@/plugins/axios';
export const useMovieStore = defineStore('movie', () => {
const state = reactive({
currentMovie: {},
});
const currentMovie = computed(() => state.currentMovie);
const getMovieDetail = async (movieId) => {
const response = await api.get(`movie/${movieId}`);
state.currentMovie = response.data;
};
return { currentMovie, getMovieDetail };
});
Note que estamos criando uma store chamada movie
e estamos retornando a propriedade computada currentMovie
e a função getMovieDetail
. A propriedade currentMovie
vai armazenar o filme atual selecionado e a função getMovieDetail
vai buscar os detalhes do filme na API e armazenar na propriedade currentMovie
.
Também, existe uma integração com a store
de template para que seja possível mostrar o ícone de carregando enquanto os detalhes do filme são buscados na API.
Alterando o componente MoviesView.vue
Vamos aquivo editar o arquivo src/views/MoviesView.vue
, procurar para tag img
com a capa do filme e adicionar um listener para o evento click
que vai chamar a função showMovieDetails
passando o id
do filme como parâmetro. O código deve ficar assim:
<img
:src="`https://image.tmdb.org/t/p/w500${movie.poster_path}`"
:alt="movie.title"
@click="openMovie(movie.id)"
/>
Agora, vamos editar o bloco script
e adicionar o seguinte código:
import { useRouter } from 'vue-router'
const router = useRouter()
...
function openMovie(movieId) {
router.push({ name: 'MovieDetails', params: { movieId } });
}
Note que estamos importando o hook useRouter
do vue-router
e estamos criando uma função chamada openMovie
que recebe o id
do filme como parâmetro. Essa função vai redirecionar o usuário para a rota MovieDetails
passando o id
do filme como parâmetro.
Criando o componente MovieDetailsView.vue
Vamos criar um novo componente chamado MovieDetailsView.vue
, na pasta src/views/
e vamos adicionar o seguinte código:
<script setup>
import { defineProps, onMounted } from 'vue';
import { useMovieStore } from '@/stores/movie';
const movieStore = useMovieStore();
const props = defineProps({
movieId: {
type: Number,
required: true,
},
});
onMounted(async () => {
await movieStore.getMovieDetail(props.movieId);
});
</script>
<template>
<div class="main">
<div class="content">
<img
:src="`https://image.tmdb.org/t/p/w185${movieStore.currentMovie.poster_path}`"
:alt="movieStore.currentMovie.title"
/>
<div class="details">
<h1>Filme: {{ movieStore.currentMovie.title }}</h1>
<p>{{ movieStore.currentMovie.tagline }}</p>
<p>{{ movieStore.currentMovie.overview }}</p>
<p>Orçamento: ${{ movieStore.currentMovie.budget }}</p>
<p>Avaliação: {{ movieStore.currentMovie.vote_average }}</p>
</div>
</div>
</div>
<p>Produtoras</p>
<div class="companies">
<template
v-for="company in movieStore.currentMovie.production_companies"
:key="company.id"
>
<img
v-if="company.logo_path"
:src="`https://image.tmdb.org/t/p/w92${company.logo_path}`"
:alt="company.name"
/>
<p v-else>{{ company.name }}</p>
</template>
</div>
</template>
<style scoped>
.companies {
display: flex;
flex-direction: row;
column-gap: 3rem;
align-items: center;
margin-bottom: 2rem;
}
</style>
Esse código é um pouco mais complexo, mas não se preocupe, vamos explicar cada parte dele.
Inicialmente, importamos o hook useMovieStore
da store movie
e criamos uma variável reativa chamada movieStore
que vai armazenar a instância da store movie
.
Em seguida, criamos uma propriedade chamada movieId
que vai receber o id
do filme como parâmetro. Essa propriedade é obrigatória e deve ser do tipo Number
.
Também, criamos um hook onMounted
que vai chamar a função getMovieDetail
da store movie
passando o id
do filme como parâmetro. Essa função vai buscar os detalhes do filme na API e armazenar na propriedade currentMovie
da store movie
.
Por fim, no bloco template
, usamos a propriedade computada currentMovie
da store movie
para mostrar os detalhes do filme. Note que, para acessar a propriedade computada currentMovie
da store movie
, usamos a variável reativa movieStore
.
Nesse exemplo, não foram realizadas muitas estilizações em CSS, mas você pode fazer isso se quiser.
Alterando as rotas
Vamos editar o arquivo src/router/index.js
e adicionar a seguinte rota:
{
path: '/movie/:movieId',
name: 'MovieDetails',
component: () => import('../views/MovieDetailsView.vue'),
props: true,
},