munch-ease-frontend/src/components/recipes/RecipeSearchBox.vue

113 lines
2.1 KiB
Vue
Raw Normal View History

2024-01-13 23:09:15 +00:00
<template>
2025-10-18 02:08:22 +00:00
<div class="recipe-search-box" @focusout="recipes = []">
<input
type="text"
v-model="searchTerm"
@keyup.enter="search"
@keyup.exit="clear"
@focusin="search"
:placeholder="placeholder"
/>
<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>
2024-01-13 23:09:15 +00:00
</template>
<script>
2025-10-18 01:36:55 +00:00
import { searchRecipes } from '@/api/recipes'
2025-10-18 02:08:22 +00:00
import RecipeCard from './RecipeCard.vue'
2024-01-14 01:46:45 +00:00
2024-01-13 23:09:15 +00:00
export default {
2025-10-18 02:08:22 +00:00
name: 'RecipeSearchBox',
components: { RecipeCard },
props: {
placeholder: { type: String, default: 'Add a recipe...' },
},
data() {
return {
searchTerm: '',
recipes: [],
timeouts: [],
}
},
watch: {
searchTerm() {
const searchTerm = this.searchTerm
if (searchTerm) {
this.timeouts.push(
setTimeout(() => {
if (searchTerm === this.searchTerm) {
this.search()
}
}, 200)
)
}
},
2025-10-18 02:08:22 +00:00
},
methods: {
async search() {
this.recipes = (await searchRecipes(this.searchTerm)) ?? this.recipes
2024-01-13 23:09:15 +00:00
},
2025-10-18 02:08:22 +00:00
selectRecipe(recipe) {
this.$emit('select-recipe', recipe)
this.searchTerm = ''
this.recipes = []
2024-01-13 23:09:15 +00:00
},
2025-10-18 02:08:22 +00:00
},
2024-01-13 23:09:15 +00:00
}
</script>
<style scoped>
2024-01-14 01:46:45 +00:00
.recipe-search-box {
2025-10-18 02:08:22 +00:00
position: relative;
2024-01-14 01:46:45 +00:00
}
2024-01-13 23:09:15 +00:00
2024-01-14 01:46:45 +00:00
.recipe-search-box input {
2025-10-18 02:08:22 +00:00
width: calc(100% - 2em);
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
outline: none;
2024-01-13 23:09:15 +00:00
}
2024-01-14 01:46:45 +00:00
.recipe-search-box .dropdown {
2025-10-18 02:08:22 +00:00
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;
list-style-type: none;
margin: 0;
padding: 0;
max-height: 40vh;
overflow-y: scroll;
2024-01-13 23:09:15 +00:00
}
2024-01-14 01:46:45 +00:00
.recipe-search-box .dropdown li {
2025-10-18 02:08:22 +00:00
padding: 8px;
cursor: pointer;
border-bottom: 1px solid #ccc;
2024-01-13 23:09:15 +00:00
}
2024-01-14 01:46:45 +00:00
.recipe-search-box .dropdown li:last-child {
2025-10-18 02:08:22 +00:00
border-bottom: none;
2024-01-13 23:09:15 +00:00
}
2024-01-14 01:46:45 +00:00
.recipe-search-box .dropdown li:hover {
2025-10-18 02:08:22 +00:00
background-color: #eee;
2024-01-13 23:09:15 +00:00
}
2025-10-18 02:08:22 +00:00
</style>