frontend category management

This commit is contained in:
hayden 2021-01-30 20:58:16 -09:00
commit f000dffde2
13 changed files with 272 additions and 80 deletions

View file

@ -1,6 +1,6 @@
<template>
<v-app>
<v-app-bar dense app color="primary" dark class="d-print-none">
<v-app-bar clipped-left dense app color="primary" dark class="d-print-none">
<v-btn @click="$router.push('/')" icon>
<v-icon size="40"> mdi-silverware-variant </v-icon>
</v-btn>

View file

@ -1,15 +1,20 @@
import { baseURL } from "./api-utils";
import { apiReq } from "./api-utils";
const categoryBase = baseURL + "category/";
const categoryBase = baseURL + "/recipes/categories";
const categoryURLs = {
get_all: `${categoryBase}all`,
};
get_all: `${categoryBase}/all/`,
get_category: (category) => `${categoryBase}/${category}/`,
};
export default {
async get_all() {
let response = await apiReq.get(categoryURLs.get_all);
return response;
},
}
async get_all() {
let response = await apiReq.get(categoryURLs.get_all);
return response.data;
},
async get_recipes_in_category(category) {
let response = await apiReq.get(categoryURLs.get_category(category));
return response.data;
},
};

View file

@ -119,36 +119,34 @@ export default {
},
data() {
return {
homeCategories: [],
homeCategories: null,
showLimit: null,
categories: ["breakfast"],
showRecent: true,
};
},
mounted() {
this.getOptions();
},
computed: {
categories() {
return this.$store.getters.getCategories;
},
},
methods: {
getOptions() {
let options = this.$store.getters.getHomePageSettings;
this.showLimit = options.showLimit;
this.categories = options.categories;
this.showRecent = options.showRecent;
this.homeCategories = options.homeCategories;
this.showLimit = this.$store.getters.getShowLimit;
this.showRecent = this.$store.getters.getShowRecent;
this.homeCategories = this.$store.getters.getHomeCategories;
},
deleteActiveCategory(index) {
this.homeCategories.splice(index, 1);
},
saveSettings() {
let payload = {
showRecent: this.showRecent,
showLimit: this.showLimit,
categories: this.categories,
homeCategories: this.homeCategories,
};
this.$store.commit("setHomePageSettings", payload);
console.log("Saving Settings");
console.log(this.homeCategories);
this.$store.commit("setShowRecent", this.showRecent);
this.$store.commit("setShowLimit", this.showLimit);
this.$store.commit("setHomeCategories", this.homeCategories);
},
},
};

View file

@ -43,22 +43,14 @@ export default {
},
data() {
return {
categories: ["cat 1", "cat 2", "cat 3"],
usedCategories: ["recent"],
langOptions: [],
selectedLang: "en",
homeOptions: {
recipesToShow: 10,
},
};
},
mounted() {
this.getOptions();
},
watch: {
usedCategories() {
console.log(this.usedCategories);
},
selectedLang() {
this.$store.commit("setLang", this.selectedLang);
},
@ -66,6 +58,7 @@ export default {
methods: {
getOptions() {
this.langOptions = this.$store.getters.getAllLangs;
console.log(this.langOptions);
this.selectedLang = this.$store.getters.getActiveLang;
},
},

View file

@ -0,0 +1,50 @@
<template>
<v-navigation-drawer width="175px" clipped app permanent expand-on-hover>
<v-list nav dense>
<v-list-item v-for="nav in links" :key="nav.title" link :to="nav.to">
<v-list-item-icon>
<v-icon>{{ nav.icon }}</v-icon>
</v-list-item-icon>
<v-list-item-title>{{ nav.title }}</v-list-item-title>
</v-list-item>
</v-list>
</v-navigation-drawer>
</template>
<script>
export default {
data() {
return {
links: [
{
icon: "mdi-home",
to: "/",
title: "Home",
},
{
icon: "mdi-view-module",
to: "/recipes/all",
title: "All Recipes",
},
],
};
},
computed: {
allCategories() {
return this.$store.getters.getCategories;
},
},
mounted() {
this.allCategories.forEach(async (element) => {
this.links.push({
title: element,
to: `/recipes/${element}`,
icon: "mdi-tag",
});
});
},
};
</script>
<style>
</style>

View file

@ -3,7 +3,7 @@
<input ref="uploader" class="d-none" type="file" @change="onFileChanged" />
<v-btn :loading="isSelecting" @click="onButtonClick" color="accent" text>
<v-icon left> mdi-cloud-upload </v-icon>
{{ $t('general.upload') }}
{{ $t("general.upload") }}
</v-btn>
</v-form>
</template>
@ -15,7 +15,6 @@ export default {
url: String,
},
data: () => ({
defaultButtonText: this.$t("general.upload"),
file: null,
isSelecting: false,
}),

View file

@ -0,0 +1,43 @@
<template>
<div>
<CategorySidebar />
<CardSection
:sortable="true"
title="All Recipes"
:recipes="allRecipes"
:card-limit="9999"
@sort="sortAZ"
@sort-recent="sortRecent"
/>
</div>
</template>
<script>
import CardSection from "../components/UI/CardSection";
import CategorySidebar from "../components/UI/CategorySidebar";
export default {
components: {
CardSection,
CategorySidebar,
},
data() {
return {};
},
computed: {
allRecipes() {
return this.$store.getters.getRecentRecipes;
},
},
methods: {
sortAZ() {
this.allRecipes.sort((a, b) => (a.name > b.name ? 1 : -1));
},
sortRecent() {
this.allRecipes.sort((a, b) => (a.dateAdded > b.dateAdded ? -1 : 1));
},
},
};
</script>
<style>
</style>

View file

@ -0,0 +1,62 @@
<template>
<div>
<CategorySidebar />
<CardSection
:sortable="true"
:title="title"
:recipes="recipes"
:card-limit="9999"
@sort="sortAZ"
@sort-recent="sortRecent"
/>
</div>
</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: null,
recipes: [],
};
},
computed: {
currentCategory() {
return this.$route.params.category;
},
},
watch: {
async currentCategory() {
this.getRecipes();
},
},
mounted() {
this.getRecipes();
},
methods: {
async getRecipes() {
let data = await api.categories.get_recipes_in_category(
this.currentCategory
);
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>

View file

@ -1,18 +1,20 @@
<template>
<div>
<CategorySidebar/>
<CardSection
v-if="pageSettings.showRecent"
v-if="showRecent"
title="Recent"
:recipes="recentRecipes"
:card-limit="pageSettings.showLimit"
:card-limit="showLimit"
/>
<CardSection
:sortable="true"
v-for="(section, index) in recipeByCategory"
:key="index"
:title="section.title"
:title="section.name"
:recipes="section.recipes"
:card-limit="pageSettings.showLimit"
:card-limit="showLimit"
@sort="sortAZ(index)"
@sort-recent="sortRecent(index)"
/>
@ -20,34 +22,43 @@
</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 {
recipeByCategory: [
{
title: "Title 1",
recipes: this.$store.getters.getRecentRecipes,
},
{
title: "Title 2",
recipes: this.$store.getters.getRecentRecipes,
},
],
recipeByCategory: [],
};
},
computed: {
pageSettings() {
return this.$store.getters.getHomePageSettings;
showRecent() {
return this.$store.getters.getShowRecent;
},
showLimit() {
return this.$store.getters.getShowLimit;
},
homeCategories() {
return this.$store.getters.getHomeCategories;
},
recentRecipes() {
return this.$store.getters.getRecentRecipes;
},
},
async mounted() {
this.homeCategories.forEach(async (element) => {
let recipes = await this.getRecipeByCategory(element);
this.recipeByCategory.push(recipes);
});
},
methods: {
async getRecipeByCategory(category) {
return await api.categories.get_recipes_in_category(category);
},
getRecentRecipes() {
this.$store.dispatch("requestRecentRecipes");
},

View file

@ -4,6 +4,8 @@ import SearchPage from "./pages/SearchPage";
import RecipePage from "./pages/RecipePage";
import RecipeNewPage from "./pages/RecipeNewPage";
import SettingsPage from "./pages/SettingsPage";
import AllRecipesPage from "./pages/AllRecipesPage";
import CategoryPage from "./pages/CategoryPage";
import MeaplPlanPage from "./pages/MealPlanPage";
import MealPlanThisWeekPage from "./pages/MealPlanThisWeekPage";
import api from "./api";
@ -12,6 +14,8 @@ export const routes = [
{ path: "/", component: HomePage },
{ path: "/mealie", component: HomePage },
{ path: "/search", component: SearchPage },
{ path: "/recipes/all", component: AllRecipesPage },
{ path: "/recipes/:category", component: CategoryPage },
{ path: "/recipe/:recipe", component: RecipePage },
{ path: "/new/", component: RecipeNewPage },
{ path: "/settings/site", component: SettingsPage },

View file

@ -0,0 +1,44 @@
import api from "../../api";
const state = {
showRecent: true,
showLimit: 9,
categories: [],
homeCategories: [],
};
const mutations = {
setShowRecent(state, payload) {
state.showRecent = payload;
},
setShowLimit(state, payload) {
state.showLimit = payload;
},
setCategories(state, payload) {
state.categories = payload;
},
setHomeCategories(state, payload) {
state.homeCategories = payload;
},
};
const actions = {
async requestHomePageSettings() {
let categories = await api.categories.get_all();
this.commit("setCategories", categories);
},
};
const getters = {
getShowRecent: (state) => state.showRecent,
getShowLimit: (state) => state.showLimit,
getCategories: (state) => state.categories,
getHomeCategories: (state) => state.homeCategories,
};
export default {
state,
mutations,
actions,
getters,
};

View file

@ -4,27 +4,23 @@ import api from "../api";
import createPersistedState from "vuex-persistedstate";
import userSettings from "./modules/userSettings";
import language from "./modules/language";
import homePage from "./modules/homePage";
Vue.use(Vuex);
const store = new Vuex.Store({
plugins: [
createPersistedState({
paths: ["userSettings", "language"],
paths: ["userSettings", "language", "homePage"],
}),
],
modules: {
userSettings,
language,
homePage,
},
state: {
// Home Page Settings
homePageSettings: {
showRecent: true,
showLimit: 9,
categories: [],
homeCategories: [],
},
// Snackbar
snackActive: false,
snackText: "",
@ -36,9 +32,6 @@ const store = new Vuex.Store({
},
mutations: {
setHomePageSettings(state, payload) {
state.homePageSettings = payload;
},
setSnackBar(state, payload) {
state.snackText = payload.text;
state.snackType = payload.type;
@ -67,26 +60,15 @@ const store = new Vuex.Store({
this.commit("setRecentRecipes", payload);
},
async requestHomePageSettings() {
// TODO: Query Backend for Categories
this.commit("setHomePageSettings", {
showRecent: true,
showLimit: 9,
categories: ["breakfast", "lunch", "dinner"],
homeCategories: [],
});
},
},
getters: {
//
getSnackText: state => state.snackText,
getSnackActive: state => state.snackActive,
getSnackType: state => state.snackType,
getSnackText: (state) => state.snackText,
getSnackActive: (state) => state.snackActive,
getSnackType: (state) => state.snackType,
getRecentRecipes: (state) => state.recentRecipes,
getHomePageSettings: (state) => state.homePageSettings,
},
});

View file

@ -23,11 +23,12 @@ from utils.logger import logger
"""
TODO:
- [ ] Fix Duplicate Category
- [ ] Fix Duplicate Tags
- [ ] Add Endpoint
- [x] Fix Duplicate Category
- [x] Fix Duplicate Tags
- [ ] New Endpoints
- [x] Tag Endpoints
- [x] Category Endpoints
- [ ] Endpoint Tests
- [ ] Setup Database Migrations
- [ ] Finish Frontend Category Management
- [ ] Ingredient Drag-Drop / Reorder
- [ ] Refactor Endpoints