diff --git a/Seasoned.Frontend/app/assets/css/gallery.css b/Seasoned.Frontend/app/assets/css/gallery.css index 02f5f95..a665f68 100644 --- a/Seasoned.Frontend/app/assets/css/gallery.css +++ b/Seasoned.Frontend/app/assets/css/gallery.css @@ -189,4 +189,58 @@ .cancel-btn:hover { background-color: rgba(140, 74, 50, 0.05) !important; +} + +.search-bar .v-field { + background-color: #FBF6E9 !important; + border: 1px solid #e2d7ba !important; + transition: all 0.3s ease; +} + +.search-bar input::placeholder { + color: #86571D !important; + opacity: 0.7 !important; + font-family: 'Libre Baskerville', serif !important; + font-style: italic; + -webkit-text-fill-color: #86571D !important; +} + +.search-bar .v-field__input, +.search-bar input { + color: #2e1e0a !important; + font-family: 'Libre Baskerville', serif !important; + font-size: 1.0rem !important; + opacity: 1 !important; + -webkit-text-fill-color: #2e1e0a !important; +} + +.search-bar .v-field--focused { + border-color: #556b2f !important; + background-color: #556b2f0d !important; +} + +.mdi-auto-fix { + animation: pulse-green 1.5s infinite; +} + +@keyframes pulse-green { + 0% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.5; transform: scale(1.1); } + 100% { opacity: 1; transform: scale(1); } +} + +.search-bar .v-field__clearable { + margin-right: 4px; +} + +.search-bar .v-field__clearable .v-icon { + color: #8c4a32 !important; + opacity: 0.6; + font-size: 1.2rem !important; + transition: all 0.2s ease; +} + +.search-bar .v-field__clearable .v-icon:hover { + opacity: 1; + transform: scale(1.1); } \ No newline at end of file diff --git a/Seasoned.Frontend/app/pages/gallery.vue b/Seasoned.Frontend/app/pages/gallery.vue index acfbe08..de02520 100644 --- a/Seasoned.Frontend/app/pages/gallery.vue +++ b/Seasoned.Frontend/app/pages/gallery.vue @@ -12,6 +12,27 @@

Your Recipe Collection

+ + + + + + + + @@ -223,6 +244,9 @@ const selectedRecipe = ref(null) const isEditing = ref(false) const originalRecipe = ref(null) const config = useRuntimeConfig() +const searchQuery = ref('') +const isSearching = ref(false) +let debounceTimeout = null onMounted(async () => { await fetchRecipes() @@ -325,4 +349,31 @@ const sortedRecipes = computed(() => { return new Date(b.createdAt) - new Date(a.createdAt) }) }) + +const performSearch = async () => { + if (!searchQuery.value) { + await fetchRecipes() + return + } + + try { + isSearching.value = true + const data = await $fetch(`${config.public.apiBase}api/recipe/search`, { + params: { query: searchQuery.value }, + credentials: 'include' + }) + recipes.value = data + } catch (err) { + console.error("The Chef couldn't find those flavors:", err) + } finally { + isSearching.value = false + } +} + +watch(searchQuery, (newVal) => { + clearTimeout(debounceTimeout) + debounceTimeout = setTimeout(() => { + performSearch() + }, 600) +}) \ No newline at end of file