add toolbars tools to recipe sections

This commit is contained in:
hay-kot 2021-05-05 10:42:11 -08:00
commit 697fa16010
17 changed files with 132 additions and 46 deletions

View file

@ -1,7 +1,7 @@
const baseURL = "/api/"; const baseURL = "/api/";
import axios from "axios"; import axios from "axios";
import { store } from "../store"; import { store } from "../store";
import utils from "@/utils"; import { utils } from "@/utils";
axios.defaults.headers.common["Authorization"] = `Bearer ${store.getters.getToken}`; axios.defaults.headers.common["Authorization"] = `Bearer ${store.getters.getToken}`;

View file

@ -21,7 +21,7 @@
<script> <script>
import { api } from "@/api"; import { api } from "@/api";
import utils from "@/utils"; import { utils } from "@/utils";
import MealPlanCard from "./MealPlanCard"; import MealPlanCard from "./MealPlanCard";
export default { export default {
components: { components: {

View file

@ -82,7 +82,7 @@
const CREATE_EVENT = "created"; const CREATE_EVENT = "created";
import DatePicker from "@/components/FormHelpers/DatePicker"; import DatePicker from "@/components/FormHelpers/DatePicker";
import { api } from "@/api"; import { api } from "@/api";
import utils from "@/utils"; import { utils } from "@/utils";
import MealPlanCard from "./MealPlanCard"; import MealPlanCard from "./MealPlanCard";
export default { export default {
components: { components: {

View file

@ -56,7 +56,7 @@
import BulkAdd from "@/components/Recipe/Parts/Helpers/BulkAdd"; import BulkAdd from "@/components/Recipe/Parts/Helpers/BulkAdd";
import VueMarkdown from "@adapttive/vue-markdown"; import VueMarkdown from "@adapttive/vue-markdown";
import draggable from "vuedraggable"; import draggable from "vuedraggable";
import utils from "@/utils"; import { utils } from "@/utils";
export default { export default {
components: { components: {
BulkAdd, BulkAdd,

View file

@ -66,7 +66,7 @@
<script> <script>
import VueMarkdown from "@adapttive/vue-markdown"; import VueMarkdown from "@adapttive/vue-markdown";
import utils from "@/utils"; import { utils } from "@/utils";
export default { export default {
components: { components: {
VueMarkdown, VueMarkdown,

View file

@ -35,7 +35,7 @@
<script> <script>
import VueMarkdown from "@adapttive/vue-markdown"; import VueMarkdown from "@adapttive/vue-markdown";
import utils from "@/utils"; import { utils } from "@/utils";
export default { export default {
components: { components: {
VueMarkdown, VueMarkdown,

View file

@ -124,7 +124,7 @@
</template> </template>
<script> <script>
import utils from "@/utils"; import { utils } from "@/utils";
import { api } from "@/api"; import { api } from "@/api";
export default { export default {

View file

@ -88,7 +88,7 @@
<script> <script>
import Nutrition from "@/components/Recipe/Parts/Nutrition"; import Nutrition from "@/components/Recipe/Parts/Nutrition";
import VueMarkdown from "@adapttive/vue-markdown"; import VueMarkdown from "@adapttive/vue-markdown";
import utils from "@/utils"; import { utils } from "@/utils";
import RecipeChips from "./RecipeChips"; import RecipeChips from "./RecipeChips";
import Rating from "@/components/Recipe/Parts/Rating"; import Rating from "@/components/Recipe/Parts/Rating";
import Notes from "@/components/Recipe/Parts/Notes"; import Notes from "@/components/Recipe/Parts/Notes";

View file

@ -6,21 +6,28 @@
</v-icon> </v-icon>
<v-toolbar-title class="headline"> {{ title }} </v-toolbar-title> <v-toolbar-title class="headline"> {{ title }} </v-toolbar-title>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-menu offset-y v-if="$listeners.sortRecent || $listeners.sort"> <v-btn text @click="navigateRandom">
Random
</v-btn>
<v-menu offset-y v-if="$listeners.sort">
<template v-slot:activator="{ on, attrs }"> <template v-slot:activator="{ on, attrs }">
<v-btn-toggle group>
<v-btn text v-bind="attrs" v-on="on"> <v-btn text v-bind="attrs" v-on="on">
{{ $t("general.sort") }} {{ $t("general.sort") }}
</v-btn> </v-btn>
</v-btn-toggle>
</template> </template>
<v-list> <v-list>
<v-list-item @click="$emit('sortRecent')"> <v-list-item @click="sortRecipes(EVENTS.az)">
<v-list-item-title>{{ $t("general.recent") }}</v-list-item-title>
</v-list-item>
<v-list-item @click="$emit('sort')">
<v-list-item-title>{{ $t("general.sort-alphabetically") }}</v-list-item-title> <v-list-item-title>{{ $t("general.sort-alphabetically") }}</v-list-item-title>
</v-list-item> </v-list-item>
<v-list-item @click="sortRecipes(EVENTS.rating)">
<v-list-item-title>{{ $t("general.rating") }}</v-list-item-title>
</v-list-item>
<v-list-item @click="sortRecipes(EVENTS.updated)">
<v-list-item-title>{{ $t("general.updated") }}</v-list-item-title>
</v-list-item>
<v-list-item @click="sortRecipes(EVENTS.created)">
<v-list-item-title>{{ $t("general.created") }}</v-list-item-title>
</v-list-item>
</v-list> </v-list>
</v-menu> </v-menu>
</v-app-bar> </v-app-bar>
@ -76,6 +83,9 @@
<script> <script>
import RecipeCard from "../Recipe/RecipeCard"; import RecipeCard from "../Recipe/RecipeCard";
import MobileRecipeCard from "@/components/Recipe/MobileRecipeCard"; import MobileRecipeCard from "@/components/Recipe/MobileRecipeCard";
import { utils } from "@/utils";
const SORT_EVENT = "sort";
export default { export default {
components: { components: {
RecipeCard, RecipeCard,
@ -106,6 +116,12 @@ export default {
return { return {
cardLimit: 30, cardLimit: 30,
loading: false, loading: false,
EVENTS: {
az: "az",
rating: "rating",
created: "created",
updated: "updated",
},
}; };
}, },
watch: { watch: {
@ -144,6 +160,31 @@ export default {
await new Promise(r => setTimeout(r, 1000)); await new Promise(r => setTimeout(r, 1000));
this.loading = false; this.loading = false;
}, },
navigateRandom() {
const recipe = utils.recipe.randomRecipe(this.recipes);
this.$router.push(`/recipe/${recipe.slug}`);
},
sortRecipes(sortType) {
let sortTarget = [...this.recipes];
switch (sortType) {
case this.EVENTS.az:
utils.recipe.sortAToZ(sortTarget);
break;
case this.EVENTS.rating:
utils.recipe.sortByRating(sortTarget);
break;
case this.EVENTS.created:
utils.recipe.sortByCreated(sortTarget);
break;
case this.EVENTS.updated:
utils.recipe.sortByUpdated(sortTarget);
break;
default:
console.log("Unknown Event", sortType);
return;
}
this.$emit(SORT_EVENT, sortTarget);
},
}, },
}; };
</script> </script>

View file

@ -36,6 +36,7 @@
"close": "Close", "close": "Close",
"confirm": "Confirm", "confirm": "Confirm",
"create": "Create", "create": "Create",
"created": "Created",
"current-parenthesis": "(Current)", "current-parenthesis": "(Current)",
"dashboard": "Dashboard", "dashboard": "Dashboard",
"delete": "Delete", "delete": "Delete",
@ -63,6 +64,7 @@
"no": "No", "no": "No",
"ok": "OK", "ok": "OK",
"options": "Options:", "options": "Options:",
"rating": "Rating",
"random": "Random", "random": "Random",
"recent": "Recent", "recent": "Recent",
"recipes": "Recipes", "recipes": "Recipes",
@ -83,6 +85,7 @@
"token": "Token", "token": "Token",
"tuesday": "Tuesday", "tuesday": "Tuesday",
"update": "Update", "update": "Update",
"updated": "Updated",
"upload": "Upload", "upload": "Upload",
"url": "URL", "url": "URL",
"users": "Users", "users": "Users",

View file

@ -54,7 +54,7 @@
<script> <script>
import { api } from "@/api"; import { api } from "@/api";
import utils from "@/utils"; import { utils } from "@/utils";
import NewMeal from "@/components/MealPlan/MealPlanNew"; import NewMeal from "@/components/MealPlan/MealPlanNew";
import EditPlan from "@/components/MealPlan/MealPlanEditor"; import EditPlan from "@/components/MealPlan/MealPlanEditor";
import ShoppingListDialog from "@/components/MealPlan/ShoppingListDialog"; import ShoppingListDialog from "@/components/MealPlan/ShoppingListDialog";

View file

@ -36,7 +36,7 @@
<script> <script>
import { api } from "@/api"; import { api } from "@/api";
import utils from "@/utils"; import { utils } from "@/utils";
export default { export default {
data() { data() {
return { return {

View file

@ -5,9 +5,8 @@
title-icon="" title-icon=""
:sortable="true" :sortable="true"
:title="$t('page.all-recipes')" :title="$t('page.all-recipes')"
:recipes="allRecipes" :recipes="shownRecipes"
@sort="sortAZ" @sort="assignSorted"
@sort-recent="sortRecent"
/> />
</v-container> </v-container>
</template> </template>
@ -22,6 +21,7 @@ export default {
data() { data() {
return { return {
loading: false, loading: false,
sortedResults: [],
}; };
}, },
async mounted() { async mounted() {
@ -35,13 +35,17 @@ export default {
allRecipes() { allRecipes() {
return this.$store.getters.getAllRecipes; return this.$store.getters.getAllRecipes;
}, },
shownRecipes() {
if (this.sortedResults.length > 0) {
return this.sortedResults;
} else {
return this.allRecipes;
}
},
}, },
methods: { methods: {
sortAZ() { assignSorted(val) {
this.allRecipes.sort((a, b) => (a.name > b.name ? 1 : -1)); this.sortedResults = val;
},
sortRecent() {
this.allRecipes.sort((a, b) => (a.dateAdded > b.dateAdded ? -1 : 1));
}, },
}, },
}; };

View file

@ -47,31 +47,20 @@
</v-col> </v-col>
</v-row> </v-row>
<v-row v-if="fuzzyRecipes"> <CardSection title-icon="mdi-mag" :recipes="showRecipes" :hardLimit="maxResults" @sort="assignFuzzy" />
<v-col :sm="6" :md="6" :lg="4" :xl="3" v-for="item in fuzzyRecipes.slice(0, maxResults)" :key="item.name">
<RecipeCard
:name="item.item.name"
:description="item.item.description"
:slug="item.item.slug"
:rating="item.item.rating"
:image="item.item.image"
:tags="item.item.tags"
/>
</v-col>
</v-row>
</v-card> </v-card>
</v-container> </v-container>
</template> </template>
<script> <script>
import Fuse from "fuse.js"; import Fuse from "fuse.js";
import RecipeCard from "@/components/Recipe/RecipeCard";
import CategoryTagSelector from "@/components/FormHelpers/CategoryTagSelector"; import CategoryTagSelector from "@/components/FormHelpers/CategoryTagSelector";
import CardSection from "@/components/UI/CardSection";
import FilterSelector from "./FilterSelector.vue"; import FilterSelector from "./FilterSelector.vue";
export default { export default {
components: { components: {
RecipeCard, CardSection,
CategoryTagSelector, CategoryTagSelector,
FilterSelector, FilterSelector,
}, },
@ -88,6 +77,7 @@ export default {
exclude: false, exclude: false,
matchAny: false, matchAny: false,
}, },
sortedResults: [],
includeCategories: [], includeCategories: [],
includeTags: [], includeTags: [],
options: { options: {
@ -126,16 +116,31 @@ export default {
}, },
fuzzyRecipes() { fuzzyRecipes() {
if (this.searchString.trim() === "") { if (this.searchString.trim() === "") {
return this.filteredRecipes.map(x => ({ item: x })); return this.filteredRecipes;
} }
const result = this.fuse.search(this.searchString.trim()); const result = this.fuse.search(this.searchString.trim());
return result; return result.map(x => x.item);
}, },
isSearching() { isSearching() {
return this.searchString && this.searchString.length > 0; return this.searchString && this.searchString.length > 0;
}, },
showRecipes() {
if (this.sortedResults.length > 0) {
return this.sortedResults;
} else {
return this.fuzzyRecipes;
}
},
},
watch: {
showRecipes(val) {
console.log(val);
},
}, },
methods: { methods: {
assignFuzzy(val) {
this.sortedResults = val;
},
check(filterBy, recipeList, matchAny, exclude) { check(filterBy, recipeList, matchAny, exclude) {
let isMatch = true; let isMatch = true;
if (filterBy.length === 0) return isMatch; if (filterBy.length === 0) return isMatch;

View file

@ -3,7 +3,7 @@ import ThisWeek from "@/pages/MealPlan/ThisWeek";
import { api } from "@/api"; import { api } from "@/api";
import i18n from "@/i18n.js"; import i18n from "@/i18n.js";
import utils from "@/utils"; import { utils } from "@/utils";
export const mealRoutes = [ export const mealRoutes = [
{ {

View file

@ -1,4 +1,5 @@
import { vueApp } from "../main"; import { vueApp } from "../main";
import { recipe } from "@/utils/recipe";
// TODO: Migrate to Mixins // TODO: Migrate to Mixins
const notifyHelpers = { const notifyHelpers = {
@ -9,7 +10,8 @@ const notifyHelpers = {
info: "notify-info-color", info: "notify-info-color",
}; };
export default { export const utils = {
recipe: recipe,
getImageURL(image) { getImageURL(image) {
return `/api/recipes/${image}/image?image_type=small`; return `/api/recipes/${image}/image?image_type=small`;
}, },

View file

@ -0,0 +1,31 @@
export const recipe = {
/**
* Sorts a list of recipes in place
* @param {Array<Object>} list of recipes
* @param {Boolean} inverse - Z or A First
*/
sortAToZ(list) {
list.sort((a, b) => {
var textA = a.name.toUpperCase();
var textB = b.name.toUpperCase();
return textA < textB ? -1 : textA > textB ? 1 : 0;
});
},
sortByCreated(list) {
list.sort((a, b) => (a.dateAdded > b.dateAdded ? -1 : 1));
},
sortUpdated(list) {
list.sort((a, b) => (a.dateUpdated > b.dateUpdated ? -1 : 1));
},
sortByRating(list) {
list.sort((a, b) => (a.rating > b.rating ? -1 : 1));
},
/**
*
* @param {Array<Object>} list
* @returns String / Recipe Slug
*/
randomRecipe(list) {
return list[Math.floor(Math.random() * list.length)];
},
};