mirror of
https://github.com/rjNemo/meal_planner
synced 2026-06-11 21:06:43 +00:00
autofocus search field on search page
This commit is contained in:
parent
5bd9f2c382
commit
7decbe7cbe
2 changed files with 28 additions and 13 deletions
|
|
@ -9,7 +9,8 @@
|
||||||
placeholder="Search recipes..."
|
placeholder="Search recipes..."
|
||||||
@focus="isFocused = true"
|
@focus="isFocused = true"
|
||||||
@blur="isFocused = false"
|
@blur="isFocused = false"
|
||||||
>
|
:autofocus="autofocus"
|
||||||
|
/>
|
||||||
<kbd
|
<kbd
|
||||||
class="hidden md:inline-block kbd kbd-sm"
|
class="hidden md:inline-block kbd kbd-sm"
|
||||||
:class="{ 'opacity-50': !isFocused }"
|
:class="{ 'opacity-50': !isFocused }"
|
||||||
|
|
@ -27,6 +28,9 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const model = defineModel<string>();
|
const model = defineModel<string>();
|
||||||
|
const props = defineProps<{
|
||||||
|
autofocus?: boolean;
|
||||||
|
}>();
|
||||||
const isFocused = ref(false);
|
const isFocused = ref(false);
|
||||||
|
|
||||||
// Debounced navigation
|
// Debounced navigation
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,24 @@ import type { Recipe } from "~/types/recipe";
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const searchQuery = computed(() => route.query.q as string);
|
const searchQuery = computed(() => route.query.q as string);
|
||||||
const searchResults = ref<Recipe[]>([]);
|
const searchResults = ref<Recipe[]>([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
const { data, status, error } = await useRecipeSearch(searchQuery.value || "");
|
if (searchQuery.value) {
|
||||||
if (error.value) {
|
loading.value = true;
|
||||||
throw createError({
|
const { data, error } = await useRecipeSearch(searchQuery.value);
|
||||||
statusCode: 500,
|
if (error.value) {
|
||||||
message: error.value.message,
|
throw createError({
|
||||||
});
|
statusCode: 500,
|
||||||
|
message: error.value.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
searchResults.value = data.value!;
|
||||||
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
searchResults.value = data.value;
|
|
||||||
|
|
||||||
watch(searchQuery, async (newQuery) => {
|
watch(searchQuery, async (newQuery) => {
|
||||||
|
loading.value = true;
|
||||||
const { data, error } = await useRecipeSearch(newQuery.trim());
|
const { data, error } = await useRecipeSearch(newQuery.trim());
|
||||||
if (error.value) {
|
if (error.value) {
|
||||||
throw createError({
|
throw createError({
|
||||||
|
|
@ -24,21 +30,26 @@ watch(searchQuery, async (newQuery) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
searchResults.value = data.value;
|
searchResults.value = data.value!;
|
||||||
|
loading.value = false;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container mx-auto px-4">
|
<div class="container mx-auto px-4">
|
||||||
<div v-if="status === 'pending'" class="flex justify-center my-8">
|
<recipe-search
|
||||||
|
class="md:hidden mb-6"
|
||||||
|
:initial-query="searchQuery"
|
||||||
|
:autofocus="true"
|
||||||
|
/>
|
||||||
|
<div v-if="loading" class="flex justify-center my-8">
|
||||||
<span class="loading loading-spinner loading-lg text-primary" />
|
<span class="loading loading-spinner loading-lg text-primary" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-else-if="searchResults.length > 0"
|
v-if="searchResults.length > 0"
|
||||||
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 my-8"
|
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 my-8"
|
||||||
>
|
>
|
||||||
<recipe-search class="md:hidden mb-6" :initial-query="searchQuery" />
|
|
||||||
<div
|
<div
|
||||||
v-for="recipe in searchResults"
|
v-for="recipe in searchResults"
|
||||||
:key="recipe.id"
|
:key="recipe.id"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue