improved search ui

This commit is contained in:
Hayden 2021-01-13 11:43:47 -09:00
commit a1e6252508
4 changed files with 66 additions and 42 deletions

View file

@ -1,7 +1,7 @@
<template> <template>
<v-app> <v-app>
<v-app-bar dense app color="primary" dark class="d-print-none"> <v-app-bar dense app color="primary" dark class="d-print-none">
<v-btn @click="$router.push('/')" icon class="d-flex align-center"> <v-btn @click="$router.push('/')" icon>
<v-icon size="40"> mdi-silverware-variant </v-icon> <v-icon size="40"> mdi-silverware-variant </v-icon>
</v-btn> </v-btn>
<div btn class="pl-2"> <div btn class="pl-2">
@ -9,8 +9,15 @@
</div> </div>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-expand-x-transition>
<v-btn icon @click="$router.push('/search')"> <SearchBar
class="mt-7"
v-if="search"
:show-results="true"
@selected="navigateFromSearch"
/>
</v-expand-x-transition>
<v-btn icon @click="toggleSearch">
<v-icon>mdi-magnify</v-icon> <v-icon>mdi-magnify</v-icon>
</v-btn> </v-btn>
@ -28,6 +35,7 @@
<script> <script>
import Menu from "./components/UI/Menu"; import Menu from "./components/UI/Menu";
import SearchBar from "./components/UI/SearchBar";
import AddRecipeFab from "./components/UI/AddRecipeFab"; import AddRecipeFab from "./components/UI/AddRecipeFab";
import SnackBar from "./components/UI/SnackBar"; import SnackBar from "./components/UI/SnackBar";
import Vuetify from "./plugins/vuetify"; import Vuetify from "./plugins/vuetify";
@ -38,6 +46,7 @@ export default {
Menu, Menu,
AddRecipeFab, AddRecipeFab,
SnackBar, SnackBar,
SearchBar,
}, },
watch: { watch: {
@ -83,6 +92,9 @@ export default {
this.search = true; this.search = true;
} }
}, },
navigateFromSearch(slug) {
this.$router.push(`/recipe/${slug}`);
},
}, },
}; };
</script> </script>

View file

@ -1,40 +1,42 @@
<template> <template>
<div> <div>
<v-text-field <v-autocomplete
label="Search" :items="autoResults"
v-model="search" item-value="item.slug"
item-text="item.name"
dense
light
label="Search Mealie"
:search-input.sync="search"
hide-no-data
cache-items
solo solo
></v-text-field> >
<v-card v-if="search && showResults"> <template
<v-hover v-if="showResults"
square v-slot:item="{ item }"
v-for="(item, index) in result.slice(0, 5)" style="max-width: 750px"
:key="index"
v-slot="{ hover }"
> >
<v-card <v-list-item-avatar>
class="color-transition" <v-img :src="getImage(item.item.image)"></v-img>
@click="$router.push(`/recipe/${item.item.slug}`)" </v-list-item-avatar>
:color="hover ? highlightColor : null" <v-list-item-content @click="selected(item.item.slug)">
> <v-list-item-title>
<v-row dense no-gutters> {{ item.item.name }}
<v-col cols="12" md="2" sm="6"> <v-rating
<v-img dense
:src="getImage(item.item.image)" v-if="item.item.rating"
width="100%" :value="item.item.rating"
height="100%" size="12"
rounded
>
</v-img>
</v-col>
<v-col cols="12" md="10" sm="6">
<v-card-title> {{ item.item.name }}</v-card-title>
<v-card-text> {{ item.item.description }}</v-card-text></v-col
> >
</v-row> </v-rating>
</v-card> </v-list-item-title>
</v-hover> <v-list-item-subtitle>
</v-card> {{ item.item.description }}
</v-list-item-subtitle>
</v-list-item-content>
</template>
</v-autocomplete>
</div> </div>
</template> </template>
@ -52,6 +54,7 @@ export default {
return { return {
search: "", search: "",
result: [], result: [],
autoResults: [],
isDark: false, isDark: false,
options: { options: {
shouldSort: true, shouldSort: true,
@ -74,21 +77,26 @@ export default {
fuse() { fuse() {
return new Fuse(this.data, this.options); return new Fuse(this.data, this.options);
}, },
highlightColor() {
return this.isDark ? "primary lighten-5" : "primary lighten-5";
},
}, },
watch: { watch: {
search() { search() {
if (this.search.trim() === "") this.result = this.list; if (this.search.trim() === "") this.result = this.list;
else this.result = this.fuse.search(this.search.trim()); else this.result = this.fuse.search(this.search.trim());
console.log("test");
this.$emit("results", this.result); this.$emit("results", this.result);
if (this.showResults === true) {
this.autoResults = this.result;
}
}, },
}, },
methods: { methods: {
getImage(image) { getImage(image) {
return utils.getImageURL(image); return utils.getImageURL(image);
}, },
selected(slug) {
this.$emit("selected", slug);
},
}, },
}; };
</script> </script>

View file

@ -1,9 +1,9 @@
<template> <template>
<div> <div>
<v-row justify="center"> <v-row justify="center">
<v-col cols="1"> </v-col> <v-col cols="1"> </v-col>
<v-col> <v-col>
<SearchBar @results="updateResults" /> <SearchBar @results="updateResults" :show-results="false" />
</v-col> </v-col>
<v-col cols="2"> <v-col cols="2">
<v-btn icon> <v-btn icon>
@ -11,6 +11,7 @@
</v-btn> </v-btn>
</v-col> </v-col>
</v-row> </v-row>
<v-row v-if="searchResults"> <v-row v-if="searchResults">
<v-col <v-col
:sm="6" :sm="6"

View file

@ -6,7 +6,7 @@ from db.sql.model_base import SqlAlchemyBase
class RecipeModel(SqlAlchemyBase): class RecipeModel(SqlAlchemyBase):
__tablename__ = 'recipes' __tablename__ = "recipes"
# id = mongoengine.UUIDField(primary_key=True) # id = mongoengine.UUIDField(primary_key=True)
name = sa.Column(sa.String) name = sa.Column(sa.String)
description = sa.Column(sa.String) description = sa.Column(sa.String)
@ -24,8 +24,11 @@ class RecipeModel(SqlAlchemyBase):
notes = orm.relation("Note") notes = orm.relation("Note")
rating = sa.Column(sa.Integer) rating = sa.Column(sa.Integer)
orgURL = sa.Column(sa.String) orgURL = sa.Column(sa.String)
# extras = extras = orm.relation("ApiExtras")
class ApiExtras(SqlAlchemyBase):
key: sa.Column(sa.String)
value: sa.Column(sa.String)
class Category(SqlAlchemyBase): class Category(SqlAlchemyBase):
name = sa.Column(sa.String, index=True) name = sa.Column(sa.String, index=True)