traxxx-web/components/movies/search.vue

103 lines
1.7 KiB
Vue
Raw Normal View History

<template>
<VDropdown
:disabled="disabled"
class="trigger"
@show="focus"
>
<slot />
<template #popper>
<div>
<input
ref="queryInput"
v-model="query"
placeholder="Search movie"
class="input"
@input="search"
>
<ul class="movies nolist">
<li
v-for="movie in movies"
:key="`movie-${movie.id}`"
v-close-popper
class="movie"
@click="emit('movie', movie); query = '';"
>{{ movie.title }} ({{ [format(movie.effectiveDate, 'yyyy')].filter(Boolean).join(', ') }})
<img
v-if="movie.covers.length > 0"
:src="getPath(movie.covers[0], 'thumbnail')"
class="avatar"
>
</li>
</ul>
</div>
</template>
</VDropdown>
</template>
<script setup>
import { ref } from 'vue';
import { format } from 'date-fns';
import { get } from '#/src/api.js';
import getPath from '#/src/get-path.js';
const movies = ref([]);
const query = ref(null);
const queryInput = ref(null);
defineProps({
disabled: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(['movie']);
async function search() {
const data = await get('/movies', { q: query.value });
movies.value = data.movies;
}
function focus() {
setTimeout(() => {
queryInput.value?.focus();
}, 100);
}
</script>
<style scoped>
.trigger {
height: 100%;
overflow: hidden;
}
.movie {
display: block;
padding: .25rem .5rem;
&:hover {
background: var(--glass-weak-50);
color: var(--primary);
cursor: pointer;
.avatar {
display: block;
}
}
}
.avatar {
position: fixed;
display: none;
left: 7rem;
width: 8rem;
border-radius: .25rem;
box-shadow: 0 0 3px var(--shadow-weak-10);
pointer-events: none;
}
</style>