mirror of
https://github.com/rjNemo/meal_planner
synced 2026-06-06 02:26:49 +00:00
use debounce search on search page
This commit is contained in:
parent
72824daf63
commit
6f5f66d02e
4 changed files with 93 additions and 62 deletions
|
|
@ -1,6 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const searchQuery = ref((route.query.q as string) || "");
|
||||
|
||||
const { execute } = useRecipeRandom();
|
||||
|
||||
const handleRandomClick = async () => {
|
||||
|
|
@ -9,6 +11,31 @@ const handleRandomClick = async () => {
|
|||
}
|
||||
await execute();
|
||||
};
|
||||
|
||||
const debouncedSearch = useDebounceFn(async (query: string) => {
|
||||
if (searchQuery.value.trim()) {
|
||||
router.push({
|
||||
path: "/search",
|
||||
query: { q: query.trim() },
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (searchQuery.value.trim()) {
|
||||
router.push({
|
||||
path: "/search",
|
||||
query: { q: searchQuery.value.trim() },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (route.path === "/search") {
|
||||
// Watch for changes in searchQuery
|
||||
watch(searchQuery, (newQuery) => {
|
||||
debouncedSearch(newQuery);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -49,7 +76,7 @@ const handleRandomClick = async () => {
|
|||
</ul>
|
||||
</div>
|
||||
<div class="navbar-end gap-2">
|
||||
<recipe-search />
|
||||
<recipe-search @search="handleSubmit" v-model="searchQuery" />
|
||||
<button class="btn btn-primary" @click="handleRandomClick">Random</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@
|
|||
<input
|
||||
type="text"
|
||||
class="grow"
|
||||
placeholder="Search"
|
||||
v-model="searchQuery"
|
||||
placeholder="Search recipes..."
|
||||
v-model="model"
|
||||
@focus="isFocused = true"
|
||||
@blur="isFocused = false"
|
||||
@keydown.enter="$emit('search')"
|
||||
/>
|
||||
<kbd class="kbd kbd-sm" :class="{ 'opacity-50': !isFocused }">⌘</kbd>
|
||||
<kbd class="kbd kbd-sm" :class="{ 'opacity-50': !isFocused }">K</kbd>
|
||||
|
|
@ -16,21 +17,11 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const searchQuery = ref("");
|
||||
defineEmits(["search"]);
|
||||
const model = defineModel<string>();
|
||||
|
||||
const isFocused = ref(false);
|
||||
|
||||
// Debounced search function
|
||||
const debouncedSearch = useDebounceFn(async (query: string) => {
|
||||
const { data, status, error } = await useRecipeSearch(query);
|
||||
console.log("result", data.value, status.value, error.value);
|
||||
}, 500);
|
||||
|
||||
// Watch for changes in searchQuery
|
||||
watch(searchQuery, (newQuery) => {
|
||||
debouncedSearch(newQuery);
|
||||
});
|
||||
|
||||
// Optional: Handle keyboard shortcut
|
||||
onMounted(() => {
|
||||
const handleKeydown = (e: KeyboardEvent) => {
|
||||
if ((e.metaKey || e.ctrlKey) && e.key === "k") {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,26 @@
|
|||
<script setup lang="ts">
|
||||
import type { Recipe } from "~/types/recipe";
|
||||
|
||||
const route = useRoute();
|
||||
const searchQuery = computed(() => route.query.q as string);
|
||||
const searchResults = ref<Recipe[]>([]);
|
||||
const { data, status, error, execute } = await useRecipeSearch(
|
||||
searchQuery.value || "",
|
||||
);
|
||||
|
||||
const { data, status, error } = await useRecipeSearch(searchQuery.value || "");
|
||||
searchResults.value = data.value;
|
||||
|
||||
watch(searchQuery, async (newQuery) => {
|
||||
const { data, status, error, execute } = await useRecipeSearch(
|
||||
newQuery.trim(),
|
||||
);
|
||||
searchResults.value = data.value;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container mx-auto px-4">
|
||||
<div v-if="status" class="flex justify-center my-8">
|
||||
<div v-if="false" class="flex justify-center my-8">
|
||||
<span class="loading loading-spinner loading-lg text-primary"></span>
|
||||
</div>
|
||||
|
||||
|
|
@ -33,7 +46,7 @@ const { data, status, error } = await useRecipeSearch(searchQuery.value || "");
|
|||
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 my-8"
|
||||
>
|
||||
<div
|
||||
v-for="recipe in data"
|
||||
v-for="recipe in searchResults"
|
||||
:key="recipe.id"
|
||||
class="card bg-base-100 shadow-xl"
|
||||
>
|
||||
|
|
@ -42,8 +55,8 @@ const { data, status, error } = await useRecipeSearch(searchQuery.value || "");
|
|||
<h2 class="card-title">{{ recipe.title }}</h2>
|
||||
<p>{{ recipe.category }} • {{ recipe.origin }}</p>
|
||||
<div class="card-actions justify-end">
|
||||
<NuxtLink :to="`/recipe/${recipe.id}`" class="btn btn-primary"
|
||||
>View Recipe</NuxtLink
|
||||
<nuxt-link :to="`/${recipe.id}`" class="btn btn-primary"
|
||||
>View Recipe</nuxt-link
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -21,47 +21,47 @@ const mealSchema = z.object({
|
|||
strMealThumb: z.string().url(),
|
||||
strTags: z.string().nullable(),
|
||||
strYoutube: z.string(),
|
||||
strIngredient1: z.string().optional(),
|
||||
strIngredient2: z.string().optional(),
|
||||
strIngredient3: z.string().optional(),
|
||||
strIngredient4: z.string().optional(),
|
||||
strIngredient5: z.string().optional(),
|
||||
strIngredient6: z.string().optional(),
|
||||
strIngredient7: z.string().optional(),
|
||||
strIngredient8: z.string().optional(),
|
||||
strIngredient9: z.string().optional(),
|
||||
strIngredient10: z.string().optional(),
|
||||
strIngredient11: z.string().optional(),
|
||||
strIngredient12: z.string().optional(),
|
||||
strIngredient13: z.string().optional(),
|
||||
strIngredient14: z.string().optional(),
|
||||
strIngredient15: z.string().optional(),
|
||||
strIngredient16: z.string().optional(),
|
||||
strIngredient17: z.string().optional(),
|
||||
strIngredient18: z.string().optional(),
|
||||
strIngredient19: z.string().optional(),
|
||||
strIngredient20: z.string().optional(),
|
||||
strMeasure1: z.string().optional(),
|
||||
strMeasure2: z.string().optional(),
|
||||
strMeasure3: z.string().optional(),
|
||||
strMeasure4: z.string().optional(),
|
||||
strMeasure5: z.string().optional(),
|
||||
strMeasure6: z.string().optional(),
|
||||
strMeasure7: z.string().optional(),
|
||||
strMeasure8: z.string().optional(),
|
||||
strMeasure9: z.string().optional(),
|
||||
strMeasure10: z.string().optional(),
|
||||
strMeasure11: z.string().optional(),
|
||||
strMeasure12: z.string().optional(),
|
||||
strMeasure13: z.string().optional(),
|
||||
strMeasure14: z.string().optional(),
|
||||
strMeasure15: z.string().optional(),
|
||||
strMeasure16: z.string().optional(),
|
||||
strMeasure17: z.string().optional(),
|
||||
strMeasure18: z.string().optional(),
|
||||
strMeasure19: z.string().optional(),
|
||||
strMeasure20: z.string().optional(),
|
||||
strSource: z.string().optional(),
|
||||
strIngredient1: z.string().nullish(),
|
||||
strIngredient2: z.string().nullish(),
|
||||
strIngredient3: z.string().nullish(),
|
||||
strIngredient4: z.string().nullish(),
|
||||
strIngredient5: z.string().nullish(),
|
||||
strIngredient6: z.string().nullish(),
|
||||
strIngredient7: z.string().nullish(),
|
||||
strIngredient8: z.string().nullish(),
|
||||
strIngredient9: z.string().nullish(),
|
||||
strIngredient10: z.string().nullish(),
|
||||
strIngredient11: z.string().nullish(),
|
||||
strIngredient12: z.string().nullish(),
|
||||
strIngredient13: z.string().nullish(),
|
||||
strIngredient14: z.string().nullish(),
|
||||
strIngredient15: z.string().nullish(),
|
||||
strIngredient16: z.string().nullish(),
|
||||
strIngredient17: z.string().nullish(),
|
||||
strIngredient18: z.string().nullish(),
|
||||
strIngredient19: z.string().nullish(),
|
||||
strIngredient20: z.string().nullish(),
|
||||
strMeasure1: z.string().nullish(),
|
||||
strMeasure2: z.string().nullish(),
|
||||
strMeasure3: z.string().nullish(),
|
||||
strMeasure4: z.string().nullish(),
|
||||
strMeasure5: z.string().nullish(),
|
||||
strMeasure6: z.string().nullish(),
|
||||
strMeasure7: z.string().nullish(),
|
||||
strMeasure8: z.string().nullish(),
|
||||
strMeasure9: z.string().nullish(),
|
||||
strMeasure10: z.string().nullish(),
|
||||
strMeasure11: z.string().nullish(),
|
||||
strMeasure12: z.string().nullish(),
|
||||
strMeasure13: z.string().nullish(),
|
||||
strMeasure14: z.string().nullish(),
|
||||
strMeasure15: z.string().nullish(),
|
||||
strMeasure16: z.string().nullish(),
|
||||
strMeasure17: z.string().nullish(),
|
||||
strMeasure18: z.string().nullish(),
|
||||
strMeasure19: z.string().nullish(),
|
||||
strMeasure20: z.string().nullish(),
|
||||
strSource: z.string().nullish(),
|
||||
strImageSource: z.string().nullable(),
|
||||
strCreativeCommonsConfirmed: z.string().nullable(),
|
||||
dateModified: z.string().optional().nullable(),
|
||||
|
|
|
|||
Loading…
Reference in a new issue