munch-ease-frontend/src/components/RecipeSearchBox.vue
2024-01-17 20:17:22 +11:00

98 lines
No EOL
2.2 KiB
Vue

<template>
<div class="recipe-search-box" @focusout="recipes = []">
<input type="text" v-model="searchTerm" @keyup.enter="search" @keyup.exit="clear" @focusin="search"
placeholder="Add a recipe..." />
<ul v-if="recipes?.length" class="dropdown">
<li class="recipe" v-for="recipe in recipes" :key="recipe.id" @mousedown="selectRecipe(recipe)">
<recipe-card :recipe="recipe" />
</li>
</ul>
</div>
</template>
<script>
import data from '@/data.js'
import RecipeCard from './RecipeCard.vue';
export default {
name: 'RecipeSearchBox',
components: { RecipeCard },
data() {
return {
searchTerm: '',
recipes: [],
timeouts: [],
}
},
watch: {
searchTerm() {
const searchTerm = this.searchTerm;
if (searchTerm) {
this.timeouts.push(setTimeout(() => {
if (searchTerm === this.searchTerm) {
this.search();
}
}, 200));
}
}
},
methods: {
async search() {
this.recipes = await data.searchRecipes(this.searchTerm) ?? this.recipes;
},
selectRecipe(recipe) {
this.$emit('select-recipe', recipe);
this.searchTerm = '';
this.recipes = [];
}
}
}
</script>
<style scoped>
.recipe-search-box {
position: relative;
}
.recipe-search-box input {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
outline: none;
}
.recipe-search-box .dropdown {
position: absolute;
top: 100%;
width: 100%;
margin: auto;
background-color: #fff;
border: 1px solid #ccc;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
.recipe-search-box .dropdown {
list-style-type: none;
margin: 0;
padding: 0;
max-height: 40vh;
overflow-y: scroll;
}
.recipe-search-box .dropdown li {
padding: 8px;
cursor: pointer;
border-bottom: 1px solid #ccc;
}
.recipe-search-box .dropdown li:last-child {
border-bottom: none;
}
.recipe-search-box .dropdown li:hover {
background-color: #eee;
}
</style>