add gui for search

This commit is contained in:
Francesco Grazioso 2024-05-03 13:36:37 +02:00
parent 9a86ca98e8
commit 441efc6f0d
3 changed files with 207 additions and 10 deletions

View File

@ -0,0 +1,70 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import axios from 'axios';
const props = defineProps<{
title: string;
mediaType: string;
}>();
const imageUrl = ref('');
const movieApiUrl = 'https://api.themoviedb.org/3/search/movie?api_key=15d2ea6d0dc1d476efbca3eba2b9bbfb&query=';
const animeApiUrl = 'https://kitsu.io/api/edge/anime?filter[text]=';
onMounted(async () => {
const searcTerm = props.title.replace(' ', '-');
if (props.mediaType == "film") {
try {
const response = await axios.get(movieApiUrl + props.title);
if (response.data.results.length === 0) {
imageUrl.value = "https://eapp.org/wp-content/uploads/2018/05/poster_placeholder.jpg";
return;
}
imageUrl.value = "http://image.tmdb.org/t/p/w500/" + response.data.results[0].poster_path;
} catch (error) {
console.error('Error fetching movie image:', error);
}
} else {
try {
const response = await axios.get(animeApiUrl + props.title);
// if (response.data.results.length === 0) {
// imageUrl.value = "https://eapp.org/wp-content/uploads/2018/05/poster_placeholder.jpg";
// return;
// }
imageUrl.value = response.data.data[0].attributes.posterImage.small;
} catch (error) {
console.error('Error fetching anime image:', error);
}
}
});
</script>
<template>
<div class="card">
<img :src="imageUrl" :alt="title" class="card-image" />
<div class="card-title">{{ title }}</div>
</div>
</template>
<style scoped>
.card {
background-color: #313131;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.card-image {
width: 100%;
height: auto;
object-fit: cover;
}
.card-title {
padding: 12px;
font-size: 16px;
font-weight: bold;
text-align: center;
}
</style>

View File

@ -1,12 +1,21 @@
<script setup lang="ts">
import { ref } from 'vue'
const selectedOption = ref('film')
const toggleOption = () => {
selectedOption.value = selectedOption.value === 'film' ? 'anime' : 'film'
emit('update:modelValue', selectedOption.value)
}
const emit = defineEmits(['update:modelValue'])
</script>
<template>
<div class="switch-container">
<span class="switch-label-left">Film</span>
<label class="switch">
<input type="checkbox">
<input type="checkbox" :checked="selectedOption === 'anime'" @change="toggleOption">
<span class="slider round"></span>
</label>
<span class="switch-label-right">Anime</span>
@ -50,7 +59,7 @@
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
background-color: #42b883;
-webkit-transition: .4s;
transition: .4s;
}

View File

@ -1,11 +1,17 @@
<script setup lang="ts">
import search from "@/api/api";
import Toggle from "@/components/Toggle.vue";
import { ref } from 'vue'
import type { MediaItem } from "@/api/interfaces";
import Card from "@/components/Card.vue";
function testSearch() {
search('naruto', 'anime').then((res) => {
console.log(res.media[0])
const selectedOption = ref('film')
const searchedTitle = ref('')
const searchResults = ref<MediaItem[]>([])
function searchTitle() {
search(searchedTitle.value, selectedOption.value).then((res) => {
searchResults.value = res.media
}).catch((err) => {
console.log(err)
})
@ -13,8 +19,120 @@ function testSearch() {
</script>
<template>
<div>
<button @click="testSearch">test search</button>
<toggle></toggle>
<div class="search-container">
<div class="search-bar">
<input
v-model="searchedTitle"
@submit="searchTitle"
class="search-input"
type="text"
placeholder="Search for a title..."
/>
<div class="toggle-button-container">
<Toggle v-model="selectedOption" class="search-toggle"></Toggle>
<button @click="searchTitle" class="search-button">Search</button>
</div>
</div>
</div>
<div class="card-container">
<div v-for="result in searchResults" :key="result.id" class="card-item">
<Card :title="result.name" :media-type="selectedOption" />
</div>
</div>
</template>
<style scoped>
.search-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #313131;
padding: 16px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
.search-bar {
display: flex;
align-items: center;
background-color: #f5f5f5;
border-radius: 4px;
padding: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
max-width: 800px;
margin: 0 auto;
}
.search-input {
flex-grow: 1;
border: none;
background-color: transparent;
outline: none;
font-size: 16px;
padding: 8px;
}
.toggle-button-container {
display: flex;
align-items: center;
}
.search-toggle {
margin: 0 8px;
}
.search-button {
background-color: #42b883;
color: white;
border: none;
border-radius: 4px;
padding: 8px 16px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.search-button:hover {
background-color: #3a9f74;
}
.card-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
padding: 100px 20px 20px;
max-width: 1200px;
margin: 0 auto;
}
.card-item {
width: 250px;
}
@media (max-width: 768px) {
.card-container {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 480px) {
.search-bar {
flex-wrap: wrap;
}
.search-input {
flex-basis: 100%;
margin-bottom: 8px;
}
.toggle-button-container {
width: 100%;
justify-content: space-between;
}
.card-container {
grid-template-columns: 1fr;
}
}
</style>