feat: add search tab
This commit is contained in:
parent
3da3f4769c
commit
47485f941d
@ -1,6 +1,7 @@
|
||||
<script setup>
|
||||
import { useMovieStore} from './stores/movie-store';
|
||||
import Movie from './components/Movie.vue';
|
||||
import Search from './components/Search.vue';
|
||||
|
||||
const movieStore = useMovieStore();
|
||||
</script>
|
||||
@ -55,7 +56,7 @@
|
||||
</div>
|
||||
|
||||
<div class="search" v-if="movieStore.activeTab === 2">
|
||||
Search
|
||||
<Search/>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
48
src/components/Loader.vue
Normal file
48
src/components/Loader.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="lds-facebook">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.lds-facebook {
|
||||
display: block;
|
||||
margin: auto;
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
.lds-facebook div {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
width: 16px;
|
||||
background: #cef;
|
||||
animation: lds-facebook 1.2s cubic-bezier(0, 0.5, 0.5, 1) infinite;
|
||||
}
|
||||
.lds-facebook div:nth-child(1) {
|
||||
left: 8px;
|
||||
animation-delay: -0.24s;
|
||||
}
|
||||
.lds-facebook div:nth-child(2) {
|
||||
left: 32px;
|
||||
animation-delay: -0.12s;
|
||||
}
|
||||
.lds-facebook div:nth-child(3) {
|
||||
left: 56px;
|
||||
animation-delay: 0;
|
||||
}
|
||||
@keyframes lds-facebook {
|
||||
0% {
|
||||
top: 8px;
|
||||
height: 64px;
|
||||
}
|
||||
50%,
|
||||
100% {
|
||||
top: 24px;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -11,7 +11,7 @@
|
||||
</div>
|
||||
<span class="movie-overview">{{ movie.overview }}</span>
|
||||
|
||||
<div class="movie-buttons">
|
||||
<div class="movie-buttons" v-if="!isSearch">
|
||||
<button
|
||||
class="btn movie-buttons-watched"
|
||||
@click="$emit('toggle-watched')"
|
||||
@ -26,17 +26,31 @@
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="movie-buttons" v-if="isSearch">
|
||||
<button
|
||||
class="btn btn_green"
|
||||
@click="$emit('add')"
|
||||
>
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineEmits(['toggle-watched', 'remove'])
|
||||
defineEmits(['toggle-watched', 'remove', 'add'])
|
||||
defineProps({
|
||||
movie: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({})
|
||||
},
|
||||
isSearch: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
41
src/components/Search.vue
Normal file
41
src/components/Search.vue
Normal file
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<form @submit.prevent="searchStore.getMovies(searchMovie)">
|
||||
<input
|
||||
type="text"
|
||||
class="search-input"
|
||||
placeholder="Input movie"
|
||||
v-model="searchMovie"
|
||||
>
|
||||
</form>
|
||||
<Loader v-if="searchStore.loading" />
|
||||
|
||||
<Movie
|
||||
v-else
|
||||
v-for="movie in searchStore.movies"
|
||||
:movie="movie"
|
||||
:key="movie.id"
|
||||
:isSearch="true"
|
||||
@add="searchStore.addToUserMovies(movie)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useSearchStore } from '../stores/search-store';
|
||||
import Loader from '../components/Loader.vue';
|
||||
import Movie from '../components/Movie.vue';
|
||||
|
||||
const searchMovie = ref('');
|
||||
const searchStore = useSearchStore();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.search-input {
|
||||
border: 1px solid #e7e7e7;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
padding: 0 10px 0 30px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -2,26 +2,7 @@ import { defineStore } from 'pinia';
|
||||
|
||||
export const useMovieStore = defineStore('movieStore', {
|
||||
state: () => ({
|
||||
movies: [
|
||||
{
|
||||
id: 1,
|
||||
original_title: "Spider-Man",
|
||||
overview:
|
||||
"After being bitten by a genetically altered spider at Oscorp, nerdy but endearing high school student Peter Parker is endowed with amazing powers to become the superhero known as Spider-Man.",
|
||||
poster_path: "/gh4cZbhZxyTbgxQPxD0dOudNPTn.jpg",
|
||||
release_date: "2002-05-01",
|
||||
isWatched: false,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
original_title: "The Batman",
|
||||
overview:
|
||||
"In his second year of fighting crime, Batman uncovers corruption in Gotham City that connects to his own family while facing a serial killer known as the Riddler.",
|
||||
poster_path: "/b0PlSFdDwbyK0cf5RxwDpaOJQvQ.jpg",
|
||||
release_date: "2022-03-01",
|
||||
isWatched: true,
|
||||
},
|
||||
],
|
||||
movies: [],
|
||||
activeTab: 1,
|
||||
}),
|
||||
getters: {
|
||||
|
||||
37
src/stores/search-store.js
Normal file
37
src/stores/search-store.js
Normal file
@ -0,0 +1,37 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { useMovieStore } from './movie-store.js';
|
||||
|
||||
const url = `https:api.themoviedb.org/3/search/movie?api_key=${import.meta.env.VITE_API_KEY}&query=`;
|
||||
|
||||
export const useSearchStore = defineStore('search-store', {
|
||||
state: () => ({
|
||||
movies: [],
|
||||
timer: null,
|
||||
loading: false,
|
||||
}),
|
||||
actions: {
|
||||
async getMovies(search) {
|
||||
const request = async () => {
|
||||
const res = await fetch(url + search);
|
||||
const data = await res.json();
|
||||
|
||||
this.movies = data.results
|
||||
}
|
||||
|
||||
try {
|
||||
clearTimeout(this.timer);
|
||||
this.loading = true;
|
||||
await request();
|
||||
} catch (e) {
|
||||
console.log('error', e);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
addToUserMovies(obj) {
|
||||
const movieStore = useMovieStore();
|
||||
movieStore.movies.push(obj);
|
||||
movieStore.setActiveTab(1);
|
||||
}
|
||||
}
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user