mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 14:33:33 -07:00
add tag pages
This commit is contained in:
parent
c504c793f9
commit
fbb10b8a5b
6 changed files with 85 additions and 7 deletions
|
@ -2,12 +2,12 @@
|
||||||
<div v-if="items && items.length > 0">
|
<div v-if="items && items.length > 0">
|
||||||
<h2 class="mt-4">{{ title }}</h2>
|
<h2 class="mt-4">{{ title }}</h2>
|
||||||
<v-chip
|
<v-chip
|
||||||
:to="`/recipes/${getSlug(category)}`"
|
|
||||||
label
|
label
|
||||||
class="ma-1"
|
class="ma-1"
|
||||||
color="accent"
|
color="accent"
|
||||||
dark
|
dark
|
||||||
v-for="category in items"
|
v-for="category in items"
|
||||||
|
:to="`/recipes/${urlParam}/${getSlug(category)}`"
|
||||||
:key="category"
|
:key="category"
|
||||||
>
|
>
|
||||||
{{ category }}
|
{{ category }}
|
||||||
|
@ -20,7 +20,7 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
items: Array,
|
items: Array,
|
||||||
title: String,
|
title: String,
|
||||||
category: {
|
isCategory: {
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -28,13 +28,23 @@ export default {
|
||||||
allCategories() {
|
allCategories() {
|
||||||
return this.$store.getters.getAllCategories;
|
return this.$store.getters.getAllCategories;
|
||||||
},
|
},
|
||||||
|
allTags() {
|
||||||
|
return this.$store.getters.getAllTags;
|
||||||
|
},
|
||||||
|
urlParam() {
|
||||||
|
return this.isCategory ? 'category' : 'tag'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getSlug(name) {
|
getSlug(name) {
|
||||||
if (!name) return;
|
if (!name) return;
|
||||||
if (this.category) {
|
|
||||||
|
if (this.isCategory) {
|
||||||
const matches = this.allCategories.filter(x => x.name == name);
|
const matches = this.allCategories.filter(x => x.name == name);
|
||||||
if (matches.length > 0) return matches[0].slug;
|
if (matches.length > 0) return matches[0].slug;
|
||||||
|
} else {
|
||||||
|
const matches = this.allTags.filter(x => x.name == name);
|
||||||
|
if (matches.length > 0) return matches[0].slug;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -34,7 +34,11 @@
|
||||||
<Ingredients :ingredients="ingredients" />
|
<Ingredients :ingredients="ingredients" />
|
||||||
<div v-if="medium">
|
<div v-if="medium">
|
||||||
<RecipeChips :title="$t('recipe.categories')" :items="categories" />
|
<RecipeChips :title="$t('recipe.categories')" :items="categories" />
|
||||||
<RecipeChips :title="$t('recipe.tags')" :items="tags" />
|
<RecipeChips
|
||||||
|
:title="$t('recipe.tags')"
|
||||||
|
:items="tags"
|
||||||
|
:isCategory="false"
|
||||||
|
/>
|
||||||
<Notes :notes="notes" />
|
<Notes :notes="notes" />
|
||||||
</div>
|
</div>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
61
frontend/src/pages/Recipes/TagPage.vue
Normal file
61
frontend/src/pages/Recipes/TagPage.vue
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
<template>
|
||||||
|
<v-container>
|
||||||
|
<CategorySidebar />
|
||||||
|
<CardSection
|
||||||
|
:sortable="true"
|
||||||
|
:title="title"
|
||||||
|
:recipes="recipes"
|
||||||
|
:card-limit="9999"
|
||||||
|
@sort="sortAZ"
|
||||||
|
@sort-recent="sortRecent"
|
||||||
|
/>
|
||||||
|
</v-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { api } from "@/api";
|
||||||
|
import CardSection from "@/components/UI/CardSection";
|
||||||
|
import CategorySidebar from "@/components/UI/CategorySidebar";
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
CardSection,
|
||||||
|
CategorySidebar,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
title: "",
|
||||||
|
recipes: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currentTag() {
|
||||||
|
return this.$route.params.tag;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
async currentCategory() {
|
||||||
|
this.getRecipes();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getRecipes();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getRecipes() {
|
||||||
|
let data = await api.tags.getRecipesInTag(this.currentTag);
|
||||||
|
console.log(data);
|
||||||
|
this.title = data.name;
|
||||||
|
this.recipes = data.recipes;
|
||||||
|
},
|
||||||
|
sortAZ() {
|
||||||
|
this.recipes.sort((a, b) => (a.name > b.name ? 1 : -1));
|
||||||
|
},
|
||||||
|
sortRecent() {
|
||||||
|
this.recipes.sort((a, b) => (a.dateAdded > b.dateAdded ? -1 : 1));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
|
@ -6,6 +6,7 @@ import NewRecipe from "@/pages/Recipe/NewRecipe";
|
||||||
import CustomPage from "@/pages/Recipes/CustomPage";
|
import CustomPage from "@/pages/Recipes/CustomPage";
|
||||||
import AllRecipes from "@/pages/Recipes/AllRecipes";
|
import AllRecipes from "@/pages/Recipes/AllRecipes";
|
||||||
import CategoryPage from "@/pages/Recipes/CategoryPage";
|
import CategoryPage from "@/pages/Recipes/CategoryPage";
|
||||||
|
import TagPage from "@/pages/Recipes/TagPage";
|
||||||
import Planner from "@/pages/MealPlan/Planner";
|
import Planner from "@/pages/MealPlan/Planner";
|
||||||
import Debug from "@/pages/Debug";
|
import Debug from "@/pages/Debug";
|
||||||
import LoginPage from "@/pages/LoginPage";
|
import LoginPage from "@/pages/LoginPage";
|
||||||
|
@ -33,7 +34,8 @@ export const routes = [
|
||||||
{ path: "/search", component: SearchPage },
|
{ path: "/search", component: SearchPage },
|
||||||
{ path: "/recipes/all", component: AllRecipes },
|
{ path: "/recipes/all", component: AllRecipes },
|
||||||
{ path: "/pages/:customPage", component: CustomPage },
|
{ path: "/pages/:customPage", component: CustomPage },
|
||||||
{ path: "/recipes/:category", component: CategoryPage },
|
{ path: "/recipes/tag/:tag", component: TagPage },
|
||||||
|
{ path: "/recipes/category/:category", component: CategoryPage },
|
||||||
{ path: "/recipe/:recipe", component: ViewRecipe },
|
{ path: "/recipe/:recipe", component: ViewRecipe },
|
||||||
{ path: "/new/", component: NewRecipe },
|
{ path: "/new/", component: NewRecipe },
|
||||||
{ path: "/meal-plan/planner", component: Planner },
|
{ path: "/meal-plan/planner", component: Planner },
|
||||||
|
|
|
@ -2,6 +2,7 @@ from fastapi import APIRouter, Depends
|
||||||
from mealie.db.database import db
|
from mealie.db.database import db
|
||||||
from mealie.db.db_setup import generate_session
|
from mealie.db.db_setup import generate_session
|
||||||
from mealie.routes.deps import get_current_user
|
from mealie.routes.deps import get_current_user
|
||||||
|
from mealie.schema.category import RecipeTagResponse
|
||||||
from mealie.schema.snackbar import SnackResponse
|
from mealie.schema.snackbar import SnackResponse
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ async def get_all_recipe_tags(session: Session = Depends(generate_session)):
|
||||||
return db.tags.get_all_limit_columns(session, ["slug", "name"])
|
return db.tags.get_all_limit_columns(session, ["slug", "name"])
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{tag}")
|
@router.get("/{tag}", response_model=RecipeTagResponse)
|
||||||
def get_all_recipes_by_tag(tag: str, session: Session = Depends(generate_session)):
|
def get_all_recipes_by_tag(tag: str, session: Session = Depends(generate_session)):
|
||||||
""" Returns a list of recipes associated with the provided tag. """
|
""" Returns a list of recipes associated with the provided tag. """
|
||||||
return db.tags.get(session, tag)
|
return db.tags.get(session, tag)
|
||||||
|
|
|
@ -27,5 +27,5 @@ class TagBase(CategoryBase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class RecipeTagResponse(TagBase):
|
class RecipeTagResponse(RecipeCategoryResponse):
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue