enrecipes/app/components/MealPlanner.vue

391 lines
10 KiB
Vue
Raw Permalink Normal View History

2020-11-15 21:13:06 +00:00
<template>
2021-04-01 10:55:35 +00:00
<Page @loaded="onPageLoad" actionBarHidden="true">
<GridLayout rows="*, auto" columns="*">
<ScrollView
@scroll="!edit && onScroll($event)"
rowSpan="2"
scrollBarIndicatorVisible="false"
>
<StackLayout>
<Label class="pageTitle" :text="'planner' | L" />
<GridLayout
class="calendar"
columns="*, *, *, *, *, *, *"
rows="auto, auto, auto, auto, auto, auto, auto, auto"
2021-02-28 15:10:26 +00:00
>
2021-04-01 10:55:35 +00:00
<Button class="ico navBtn" :text="icon.left" @tap="prevMonth" />
<Label
class="monthName"
col="1"
colSpan="5"
:text="$options.filters.L(mNames[month]) + ' ' + year"
/>
<Button
class="ico navBtn"
col="6"
:text="icon.right"
@tap="nextMonth"
/>
<Label
class="dayName"
row="1"
:col="i"
2021-04-12 18:09:48 +00:00
v-for="(d, i) in getDayNames"
2021-04-01 10:55:35 +00:00
:key="d"
:text="d | L"
/>
<Button
class="min day"
:class="{
tb: isToday(d),
activeDay: isActive(d),
hasPlans: hasPlans(d),
}"
:row="getrow(i)"
:col="i % 7"
v-for="(d, i) in getCal"
:key="i"
:text="d ? d : null"
@tap="setToday(d)"
/>
</GridLayout>
<StackLayout class="dayPlan">
<StackLayout
v-for="(mealType, index) in mealTimesWithRecipes"
:key="'mealType' + index"
2021-02-28 15:10:26 +00:00
>
2021-04-01 10:55:35 +00:00
<GridLayout columns="auto, auto">
<Label
class="periodLabel tb"
:class="mealType"
:text="mealType | L"
/>
<Button
:visibility="edit ? 'visible' : 'hidden'"
col="1"
class="ico"
:text="icon.plus"
@tap="addRecipe(mealType)"
/>
</GridLayout>
2021-02-28 15:10:26 +00:00
<GridLayout
2021-04-01 10:55:35 +00:00
:columns="`*, ${edit ? 'auto' : 0}`"
v-for="(recipeID, index) in getRecipes[mealType]"
:key="mealType + index"
2021-02-28 15:10:26 +00:00
>
2021-04-01 10:55:35 +00:00
<Button
2021-02-28 15:10:26 +00:00
class="recipeTitle"
:text="getRecipeTitle(recipeID)"
2021-04-01 10:55:35 +00:00
@tap="viewRecipe(recipeID)"
/>
<Button
:visibility="edit ? 'visible' : 'hidden'"
col="1"
class="ico x"
:text="icon.x"
@tap="removeRecipe(recipeID, mealType)"
2021-02-28 15:10:26 +00:00
/>
</GridLayout>
2021-04-01 10:55:35 +00:00
</StackLayout>
2021-02-28 15:10:26 +00:00
</StackLayout>
</StackLayout>
2021-04-01 10:55:35 +00:00
</ScrollView>
<GridLayout
row="1"
@loaded="onAppBarLoad"
class="appbar"
2021-04-12 18:09:48 +00:00
:hidden="showUndo"
2021-04-01 10:55:35 +00:00
columns="auto, *, auto, auto"
>
<Button class="ico" :text="icon.back" @tap="$navigateBack()" />
<Button
class="ico"
:text="icon.tod"
2021-04-12 18:09:48 +00:00
:hidden="isExactlyToday"
2021-04-01 10:55:35 +00:00
@tap="goToToday"
col="2"
/>
<Button
class="ico fab"
:text="edit ? icon.done : icon.edit"
@tap="toggleEditMode"
col="3"
/>
</GridLayout>
<GridLayout
row="1"
class="appbar snackBar"
2021-04-12 18:09:48 +00:00
:hidden="!showUndo"
2021-04-01 10:55:35 +00:00
columns="auto, *, auto"
>
2021-04-12 18:09:48 +00:00
<Button :text="countdown" class="ico countdown tb" />
2021-04-01 10:55:35 +00:00
<Label class="title" col="1" :text="snackMsg | L" />
2021-04-12 18:09:48 +00:00
<Button class="ico fab" :text="icon.undo" @tap="undoDel" col="3" />
2021-02-28 15:10:26 +00:00
</GridLayout>
2021-04-01 10:55:35 +00:00
</GridLayout>
2021-02-28 15:10:26 +00:00
</Page>
2020-11-15 21:13:06 +00:00
</template>
<script>
2021-04-12 18:09:48 +00:00
import { ApplicationSettings, Observable, CoreTypes } from "@nativescript/core";
2021-02-28 15:10:26 +00:00
import { mapState, mapActions } from "vuex";
import ViewRecipe from "./ViewRecipe.vue";
import ActionDialogWithSearch from "./modal/ActionDialogWithSearch.vue";
2021-04-01 10:55:35 +00:00
let undoTimer;
2020-11-15 21:13:06 +00:00
export default {
data() {
return {
appTheme: "Light",
2021-02-28 15:10:26 +00:00
mealTimes: ["breakfast", "lunch", "dinner", "snacks"],
2021-04-12 18:09:48 +00:00
dNames: ["MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"],
2021-01-23 17:20:15 +00:00
year: 2021,
2021-02-28 15:10:26 +00:00
mNames: [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
2021-01-23 17:20:15 +00:00
],
month: 0,
today: null,
edit: false,
2021-04-01 10:55:35 +00:00
scrollPos: 1,
appbar: null,
countdown: 5,
snackMsg: null,
showUndo: false,
undo: false,
2021-02-28 15:10:26 +00:00
};
2020-11-15 21:13:06 +00:00
},
computed: {
2021-04-12 18:09:48 +00:00
...mapState(["icon", "recipes", "mealPlans", "mondayFirst"]),
2021-01-23 17:20:15 +00:00
todaysTime() {
2021-02-28 15:10:26 +00:00
return new Date(this.year, this.month, this.today, 0).getTime();
2020-11-23 09:49:58 +00:00
},
getRecipes() {
2021-02-28 15:10:26 +00:00
if (this.mealPlans.length) {
return this.mealPlans.reduce((acc, e) => {
if (e.date == this.todaysTime) {
acc[e.type] = [...(acc[e.type] || []), e.title];
2020-11-23 09:49:58 +00:00
}
2021-02-28 15:10:26 +00:00
return acc;
}, {});
} else return 0;
2020-11-23 09:49:58 +00:00
},
2021-04-12 18:09:48 +00:00
getDayNames() {
if (!this.mondayFirst) this.dNames.unshift(this.dNames.pop());
return this.dNames;
},
2021-01-23 17:20:15 +00:00
getCal() {
2021-02-28 15:10:26 +00:00
let y = this.year;
let m = this.month;
let ds = new Date(y, m + 1, 0).getDate();
let fd = new Date(y, m, 1).getDay();
2021-04-12 18:09:48 +00:00
if (this.mondayFirst) fd -= 1;
2021-02-28 15:10:26 +00:00
let days = new Array(fd).fill(0);
for (let i = 1; i <= ds; i++) {
days.push(i);
2020-11-23 09:49:58 +00:00
}
2021-01-23 17:20:15 +00:00
return days;
2020-11-23 09:49:58 +00:00
},
2021-04-01 10:55:35 +00:00
isExactlyToday() {
let d = new Date();
return (
this.year == d.getFullYear() &&
this.month == d.getMonth() &&
this.today == d.getDate()
);
},
mealTimesWithRecipes() {
return this.mealTimes.filter(
(e) => (this.getRecipes[e] && this.getRecipes[e].length) || this.edit
);
},
2020-11-15 21:13:06 +00:00
},
methods: {
2021-02-28 15:10:26 +00:00
...mapActions([
2021-04-01 10:55:35 +00:00
"setComponent",
2021-02-28 15:10:26 +00:00
"addMealPlanAction",
"deleteMealPlanAction",
]),
onPageLoad(args) {
const page = args.object;
page.bindingContext = new Observable();
2021-04-01 10:55:35 +00:00
this.setComponent("MealPlanner");
2021-02-28 15:10:26 +00:00
if (!this.today || this.today === new Date().getDate()) this.goToToday();
2020-11-23 09:49:58 +00:00
},
2021-04-01 10:55:35 +00:00
onAppBarLoad({ object }) {
this.appbar = object;
},
onScroll(args) {
let scrollUp;
let y = args.scrollY;
if (y) {
scrollUp = y < this.scrollPos;
this.scrollPos = Math.abs(y);
let ab = this.appbar.translateY;
if (!scrollUp && ab == 0) {
2021-04-12 18:09:48 +00:00
this.appbar.animate({
translate: { x: 0, y: 64 },
duration: 250,
curve: CoreTypes.AnimationCurve.ease,
});
2021-04-01 10:55:35 +00:00
} else if (scrollUp && ab == 64) {
2021-04-12 18:09:48 +00:00
this.appbar.animate({
translate: { x: 0, y: 0 },
duration: 250,
curve: CoreTypes.AnimationCurve.ease,
});
2021-04-01 10:55:35 +00:00
}
}
2021-01-13 05:02:48 +00:00
},
2020-11-15 21:13:06 +00:00
// HELPERS
2021-04-01 10:55:35 +00:00
showAppBar() {
this.appbar.translateY = 0;
},
2021-02-28 15:10:26 +00:00
getrow(i) {
return Math.floor(2 + i / 7);
2020-11-15 21:13:06 +00:00
},
2021-02-28 15:10:26 +00:00
getDate(index) {
let date = new Date();
date.setDate(date.getDate() + index);
return date.getTime();
},
2021-02-28 15:10:26 +00:00
getRecipeTitle(id) {
let recipe = this.recipes.filter((e) => e.id === id)[0];
return recipe ? recipe.title : `[ ${this.$options.filters.L("resNF")} ]`;
},
2021-01-23 17:20:15 +00:00
// NAVIGATION HANDLERS
2021-02-28 15:10:26 +00:00
viewRecipe(recipeID) {
let recipe = this.recipes.filter((e) => e.id === recipeID)[0];
if (recipe) {
this.$navigateTo(ViewRecipe, {
2020-11-23 09:49:58 +00:00
props: {
filterTrylater: true,
recipeID,
},
2021-02-28 15:10:26 +00:00
});
2020-11-23 09:49:58 +00:00
}
},
2021-01-23 17:20:15 +00:00
// CALENDAR
prevMonth() {
2021-02-28 15:10:26 +00:00
if (this.month == 0) {
this.year--;
this.month = 11;
} else this.month--;
2021-04-01 10:55:35 +00:00
this.showAppBar();
2021-01-23 17:20:15 +00:00
},
nextMonth() {
2021-02-28 15:10:26 +00:00
if (this.month == 11) {
this.year++;
this.month = 0;
} else this.month++;
2021-04-01 10:55:35 +00:00
this.showAppBar();
2021-01-23 17:20:15 +00:00
},
goToToday() {
2021-02-28 15:10:26 +00:00
let d = new Date();
this.year = d.getFullYear();
this.month = d.getMonth();
this.today = d.getDate();
2021-04-01 10:55:35 +00:00
this.showAppBar();
2021-01-23 17:20:15 +00:00
},
2021-02-28 15:10:26 +00:00
isToday(date) {
let d = new Date();
return (
this.year == d.getFullYear() &&
this.month == d.getMonth() &&
date == d.getDate()
);
2021-01-23 17:20:15 +00:00
},
2021-02-28 15:10:26 +00:00
isActive(date) {
return this.today == date;
2021-01-23 17:20:15 +00:00
},
2021-02-28 15:10:26 +00:00
hasPlans(date) {
let d = new Date(this.year, this.month, date, 0).getTime();
return this.mealPlans.filter((e) => e.date == d).length;
2021-01-23 17:20:15 +00:00
},
2021-02-28 15:10:26 +00:00
setToday(date) {
if (date) this.today = date;
2021-01-23 17:20:15 +00:00
},
2021-02-28 15:10:26 +00:00
newMealPlan(title, date, type, index) {
this.addMealPlanAction({
2021-01-23 17:20:15 +00:00
title,
date: date ? date : this.todaysTime,
type,
2021-02-28 15:10:26 +00:00
index,
});
2021-01-23 17:20:15 +00:00
},
2021-04-01 10:55:35 +00:00
toggleEditMode() {
this.edit = !this.edit;
},
// DATA HANDLERS
2021-02-28 15:10:26 +00:00
addRecipe(type) {
let filteredRecipes = this.recipes.filter((e) =>
this.getRecipes[type] ? !this.getRecipes[type].includes(e.id) : true
);
this.$showModal(ActionDialogWithSearch, {
props: {
2021-01-13 05:02:48 +00:00
title: "selRec",
recipes: filteredRecipes,
},
2021-02-28 15:10:26 +00:00
}).then((title) => {
title && this.newMealPlan(title, null, type, null);
});
},
2021-02-28 15:10:26 +00:00
removeRecipe(title, type) {
let date = this.todaysTime;
let index = this.mealPlans.findIndex(
(e) => e.title === title && e.type === type && e.date === date
);
2021-01-13 05:02:48 +00:00
let mealPlan = {
2021-01-23 17:20:15 +00:00
title,
date,
type,
2021-02-28 15:10:26 +00:00
index,
};
this.deleteMealPlanAction(mealPlan);
2021-04-01 10:55:35 +00:00
this.showUndoBar("recRm").then((res) =>
this.newMealPlan(title, date, type, index)
);
2021-02-28 15:10:26 +00:00
},
2021-04-01 10:55:35 +00:00
showUndoBar(message) {
return new Promise((resolve, reject) => {
2021-04-12 18:09:48 +00:00
clearTimeout(undoTimer);
2021-04-01 10:55:35 +00:00
this.showUndo = true;
this.snackMsg = message;
this.countdown = 5;
let a = 5;
undoTimer = setInterval(() => {
if (this.undo) {
this.showUndo = this.undo = false;
clearTimeout(undoTimer);
resolve(true);
}
this.countdown = Math.round((a -= 0.1));
if (this.countdown < 1) {
this.showUndo = false;
clearTimeout(undoTimer);
reject(true);
}
}, 100);
2021-02-28 15:10:26 +00:00
});
},
2021-04-01 10:55:35 +00:00
undoDel() {
this.undo = true;
},
2020-11-15 21:13:06 +00:00
},
created() {
2021-02-28 15:10:26 +00:00
this.appTheme = ApplicationSettings.getString("appTheme", "Light");
2020-11-15 21:13:06 +00:00
},
2021-02-28 15:10:26 +00:00
};
2020-11-15 21:13:06 +00:00
</script>