ui improvements + mealplanner search

This commit is contained in:
hay-kot 2021-02-13 18:47:41 -09:00
commit 4493894162
11 changed files with 93 additions and 42 deletions

View file

@ -150,4 +150,5 @@ export default {
*::-webkit-scrollbar-thumb {
background: grey;
}
</style>

View file

@ -8,13 +8,14 @@ const prefix = baseURL + "recipes/";
const recipeURLs = {
allRecipes: baseURL + "recipes",
allRecipesByCategory: prefix + "category",
create: prefix + "create",
createByURL: prefix + "create-url",
recipe: (slug) => prefix + slug,
update: (slug) => prefix + slug,
delete: (slug) => prefix + slug,
recipeImage: (slug) => `${prefix}${slug}/image`,
updateImage: (slug) => `${prefix}${slug}/image`,
recipe: slug => prefix + slug,
update: slug => prefix + slug,
delete: slug => prefix + slug,
recipeImage: slug => `${prefix}${slug}/image`,
updateImage: slug => `${prefix}${slug}/image`,
};
export default {
@ -27,6 +28,14 @@ export default {
return response;
},
async getAllByCategory(categories) {
let response = await apiReq.post(
recipeURLs.allRecipesByCategory,
categories
);
return response.data;
},
async create(recipeData) {
let response = await apiReq.post(recipeURLs.create, recipeData);
return response.data;
@ -67,7 +76,7 @@ export default {
keys: recipeKeys,
num: num,
},
paramsSerializer: (params) => {
paramsSerializer: params => {
return qs.stringify(params, { arrayFormat: "repeat" });
},
});

View file

@ -96,6 +96,7 @@ export default {
return {
isLoading: false,
meals: [],
items: [],
// Dates
startDate: null,
@ -117,11 +118,13 @@ export default {
}
},
},
async mounted() {
let settings = await api.settings.requestAll();
console.log(settings);
this.items = await api.recipes.getAllByCategory(settings.planCategories);
},
computed: {
items() {
return this.$store.getters.getRecentRecipes;
},
actualStartDate() {
return Date.parse(this.startDate);
},

View file

@ -6,7 +6,19 @@
:to="route ? `/recipe/${slug}` : ''"
@click="$emit('click')"
>
<v-img height="200" :src="getImage(image)"></v-img>
<v-img height="200" :src="getImage(image)">
<v-expand-transition v-if="description">
<div
v-if="hover"
class="d-flex transition-fast-in-fast-out secondary v-card--reveal "
style="height: 100%;"
>
<v-card-text class="v-card--text-show white--text">
{{ description }}
</v-card-text>
</div>
</v-expand-transition>
</v-img>
<v-card-title class="my-n3 mb-n6">{{ name | truncate(30) }}</v-card-title>
<v-card-actions class="">
@ -23,16 +35,7 @@
></v-rating>
</v-col>
<v-col></v-col>
<v-col align="end">
<v-tooltip top color="secondary" max-width="400" open-delay="50">
<template v-slot:activator="{ on, attrs }">
<v-btn color="secondary" v-on="on" v-bind="attrs" text>{{
$t("recipe.description")
}}</v-btn>
</template>
<span>{{ description }}</span>
</v-tooltip>
</v-col>
<v-col align="end"> </v-col>
</v-row>
</v-card-actions>
</v-card>
@ -61,4 +64,15 @@ export default {
</script>
<style>
.v-card--reveal {
align-items: center;
bottom: 0;
justify-content: center;
opacity: 0.8;
position: absolute;
width: 100%;
}
.v-card--text-show {
opacity: 1 !important;
}
</style>

View file

@ -57,6 +57,7 @@ export default {
return {
searchSlug: "",
search: " ",
data: [],
result: [],
autoResults: [],
isDark: false,
@ -67,27 +68,31 @@ export default {
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: ["name", "slug"],
keys: ["name", "slug", "description"],
},
};
},
mounted() {
this.isDark = this.$store.getters.getIsDark;
this.data = this.$store.getters.getRecentRecipes;
},
computed: {
data() {
return this.$store.getters.getRecentRecipes;
},
fuse() {
return new Fuse(this.data, this.options);
},
},
watch: {
search() {
if (this.search.trim() === "") this.result = this.list;
else this.result = this.fuse.search(this.search.trim());
try {
this.result = this.fuse.search(this.search.trim());
} catch {
this.result = this.data
.map(x => ({ item: x }))
.sort((a, b) => (a.name > b.name ? 1 : -1));
}
console.log(this.result);
this.$emit("results", this.result);
if (this.showResults === true) {
this.autoResults = this.result;
}

View file

@ -1,6 +1,6 @@
<template>
<div class="text-center">
<v-dialog v-model="dialog" min-height="700" max-width="1000">
<v-dialog v-model="dialog" height="100%" max-width="1200">
<v-card min-height="725" height="100%">
<v-card-text>
<v-card-title></v-card-title>
@ -22,7 +22,7 @@
:md="6"
:lg="4"
:xl="3"
v-for="item in searchResults.slice(0, 10)"
v-for="item in searchResults.slice(0, 24)"
:key="item.item.name"
>
<RecipeCard
@ -58,6 +58,7 @@ export default {
},
methods: {
updateResults(results) {
console.log(results);
this.searchResults = results;
},
emitSelect(name, slug) {

View file

@ -15,7 +15,7 @@ const mutations = {
state.showLimit = payload;
},
setCategories(state, payload) {
state.categories = payload;
state.categories = payload.sort((a, b) => (a.name > b.name ? 1 : -1));
},
setHomeCategories(state, payload) {
state.homeCategories = payload;

View file

@ -47,7 +47,6 @@ const store = new Vuex.Store({
},
setMealPlanCategories(state, payload) {
console.log(payload);
state.mealPlanCategories = payload;
},
},

View file

@ -100,11 +100,17 @@ class BaseDocument:
match_key = self.primary_key
result = (
session.query(self.sql_model).filter_by(**{match_key: match_value}).one()
session.query(self.sql_model)
.filter_by(**{match_key: match_value})
.limit(limit)
.all()
)
db_entry = result.dict()
db_entries = [x.dict() for x in result]
return db_entry
if limit == 1:
return db_entries[0]
return db_entries
def create(self, session: Session, document: dict) -> dict:
"""Creates a new database entry for the given SQL Alchemy Model.

View file

@ -4,6 +4,7 @@ from db.database import db
from db.db_setup import generate_session
from fastapi import APIRouter, Depends, Query
from models.recipe_models import AllRecipeRequest
from slugify import slugify
from sqlalchemy.orm.session import Session
router = APIRouter(tags=["Query All Recipes"])
@ -71,13 +72,23 @@ def get_all_recipes_post(
return db.recipes.get_all_limit_columns(session, body.properties, body.limit)
@router.post("/api/category")
async def filter_by_category(
categories: list, session: Session = Depends(generate_session)
):
@router.post("/api/recipes/category")
def filter_by_category(categories: list, session: Session = Depends(generate_session)):
""" pass a list of categories and get a list of recipes associated with those categories """
#! This should be refactored into a single database call, but I couldn't figure it out
in_category = [db.categories.get(session, cat) for cat in categories]
#! This should be refactored into a single database call, but I couldn't figure it out
in_category = [
db.categories.get(session, slugify(cat), limit=1) for cat in categories
]
in_category = [cat.get("recipes") for cat in in_category]
in_category = [item for sublist in in_category for item in sublist]
return in_category
@router.post("/api/recipes/tag")
async def filter_by_tags(tags: list, session: Session = Depends(generate_session)):
""" pass a list of tags and get a list of recipes associated with those tags"""
#! This should be refactored into a single database call, but I couldn't figure it out
in_tags = [db.tags.get(session, slugify(tag), limit=1) for tag in tags]
in_tags = [tag.get("recipes") for tag in in_tags]
in_tags = [item for sublist in in_tags for item in sublist]
return in_tags

View file

@ -69,8 +69,10 @@ def delete_recipe(recipe_slug: str, db: Session = Depends(generate_session)):
async def get_recipe_img(recipe_slug: str):
""" Takes in a recipe slug, returns the static image """
recipe_image = read_image(recipe_slug)
return FileResponse(recipe_image)
if recipe_image:
return FileResponse(recipe_image)
else:
return
@router.put("/{recipe_slug}/image")