This commit is contained in:
Hayden
2020-12-24 16:37:38 -09:00
commit beed8576c2
137 changed files with 40218 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
<template>
<v-card>
<v-card-title class="accent white--text"> Edit Meal Plan </v-card-title>
<v-card-text> </v-card-text>
<v-card-text>
<MealPlanCard v-model="mealPlan.meals" />
<v-row align="center" justify="end">
<v-card-actions>
<v-btn color="success" text @click="update"> Update </v-btn>
<v-spacer></v-spacer>
</v-card-actions>
</v-row>
</v-card-text>
</v-card>
</template>
<script>
import api from "../../api";
import utils from "../../utils";
import MealPlanCard from "./MealPlanCard";
export default {
components: {
MealPlanCard,
},
props: {
mealPlan: Object,
},
methods: {
formatDate(timestamp) {
let dateObject = new Date(timestamp);
return utils.getDateAsPythonDate(dateObject);
},
async update() {
this.process();
await api.mealPlans.update(this.mealPlan.uid, this.mealPlan);
this.$emit("updated");
},
},
};
</script>
<style>
</style>

View File

@@ -0,0 +1,76 @@
<template>
<v-row>
<MealSelect
:forceDialog="dialog"
@close="dialog = false"
@select="setSlug($event)"
/>
<v-col
cols="12"
sm="12"
md="6"
lg="4"
xl="3"
v-for="(meal, index) in value"
:key="index"
>
<v-hover v-slot="{ hover }" :open-delay="50">
<v-card :class="{ 'on-hover': hover }" :elevation="hover ? 12 : 2">
<v-img
height="200"
:src="getImage(meal.slug)"
@click="selectRecipe(index)"
></v-img>
<v-card-title class="my-n3 mb-n6">{{ meal.dateText }}</v-card-title>
<v-card-subtitle> {{ meal.slug }}</v-card-subtitle>
</v-card>
</v-hover>
</v-col>
</v-row>
</template>
<script>
import utils from "../../utils";
import MealSelect from "./MealSelect";
export default {
components: {
MealSelect,
},
props: {
value: Array,
},
data() {
return {
recipeData: [],
cardData: [],
activeIndex: 0,
dialog: false,
};
},
methods: {
getImage(slug) {
if (slug) {
return utils.getImageURL(slug);
}
},
setSlug(slug) {
let index = this.activeIndex;
this.value[index]["slug"] = slug;
},
selectRecipe(index) {
this.activeIndex = index;
this.dialog = true;
},
getProperty(index, property) {
try {
return this.recipeData[index][property];
} catch {
return null;
}
},
},
};
</script>
<style>
</style>

View File

@@ -0,0 +1,124 @@
<template>
<div>
<EditPlan
v-if="editMealPlan"
:meal-plan="editMealPlan"
@updated="planUpdated"
/>
<NewMeal v-else @created="requestMeals" />
<v-card class="my-1">
<v-card-title class="accent white--text"> Meal Plans </v-card-title>
<v-timeline align-top :dense="$vuetify.breakpoint.smAndDown">
<v-timeline-item
class="px-1"
v-for="(mealplan, i) in plannedMeals"
:key="i"
color="accent lighten-2"
icon="mdi-silverware-variant"
fill-dot
>
<v-card color="accent lighten-2" dark>
<v-card-title class="title">
{{ formatDate(mealplan.startDate) }} -
{{ formatDate(mealplan.endDate) }}
</v-card-title>
<v-card-text class="white text--primary">
<v-row dense align="center">
<v-col></v-col>
<v-col
v-for="(meal, index) in mealplan.meals"
:key="generateKey(meal.slug, index)"
>
<v-img
class="rounded-lg"
:src="getImage(meal.image)"
height="80"
width="80"
>
</v-img>
</v-col>
<v-col></v-col>
</v-row>
<v-btn
color="accent lighten-2"
class="mx-0"
outlined
@click="editPlan(mealplan.uid)"
>
Edit
</v-btn>
<v-btn
color="error lighten-2"
class="mx-2"
outlined
@click="deletePlan(mealplan.uid)"
>
Delete
</v-btn>
</v-card-text>
</v-card>
</v-timeline-item>
</v-timeline>
</v-card>
</div>
</template>
<script>
import api from "../../api";
import utils from "../../utils";
import NewMeal from "./NewMeal";
import EditPlan from "./EditPlan";
export default {
components: {
NewMeal,
EditPlan,
},
data: () => ({
plannedMeals: [],
editMealPlan: null,
}),
async mounted() {
this.requestMeals();
},
methods: {
async requestMeals() {
const response = await api.mealPlans.all();
this.plannedMeals = response.data;
},
generateKey(name, index) {
return utils.generateUniqueKey(name, index);
},
formatDate(timestamp) {
let dateObject = new Date(timestamp);
return utils.getDateAsTextAlt(dateObject);
},
getImage(image) {
return utils.getImageURL(image);
},
editPlan(id) {
this.plannedMeals.forEach((element) => {
if (element.uid === id) {
console.log(element);
this.editMealPlan = element;
}
});
},
planUpdated() {
this.editMealPlan = null;
this.requestMeals();
},
deletePlan(id) {
api.mealPlans.delete(id);
this.requestMeals();
},
},
};
</script>
<style>
</style>

View File

@@ -0,0 +1,102 @@
<template>
<v-row justify="center">
<v-dialog v-model="dialog" persistent max-width="800">
<v-card>
<v-card-title class="headline"> Choose a Recipe </v-card-title>
<v-card-text>
<v-autocomplete
:items="avaiableRecipes"
v-model="selected"
clearable
return
dense
hide-details
hide-selected
item-text="slug"
label="Search for a Recipe"
single-line
>
<template v-slot:no-data>
<v-list-item>
<v-list-item-title>
Search for your Favorite
<strong>Recipe</strong>
</v-list-item-title>
</v-list-item>
</template>
<template v-slot:item="{ item }">
<v-row align="center" @click="dialog = false">
<v-col sm="2">
<v-img
max-height="100"
max-width="100"
:src="getImage(item.image)"
></v-img>
</v-col>
<v-col sm="10">
<h3>
{{ item.name }}
</h3>
</v-col>
</v-row>
</template>
</v-autocomplete>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="secondary" text @click="dialog = false"> Close </v-btn>
<v-btn color="secondary" text @click="dialog = false"> Select </v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
import utils from "../../utils";
export default {
props: {
forceDialog: Boolean,
},
data() {
return {
dialog: false,
selected: "",
};
},
watch: {
forceDialog() {
this.dialog = this.forceDialog;
},
selected() {
if (this.selected) {
this.$emit("select", this.selected);
}
},
dialog() {
if (this.dialog === false) {
this.$emit("close");
} else {
this.selected = "";
}
},
},
computed: {
avaiableRecipes() {
return this.$store.getters.getRecentRecipes;
},
},
methods: {
getImage(slug) {
return utils.getImageURL(slug);
},
},
};
</script>
<style>
</style>

View File

@@ -0,0 +1,207 @@
<template>
<v-card>
<v-card-title class="accent white--text">
Create a New Meal Plan
</v-card-title>
<v-card-text>
<v-row dense>
<v-col cols="12" lg="6" md="6" sm="12">
<v-menu
ref="menu1"
v-model="menu1"
:close-on-content-click="true"
transition="scale-transition"
offset-y
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on, attrs }">
<v-text-field
v-model="startComputedDateFormatted"
label="Start Date"
persistent-hint
prepend-icon="mdi-calendar"
readonly
v-bind="attrs"
v-on="on"
></v-text-field>
</template>
<v-date-picker
v-model="startDate"
no-title
@input="menu2 = false"
></v-date-picker>
</v-menu>
</v-col>
<v-col cols="12" lg="6" md="6" sm="12">
<v-menu
ref="menu2"
v-model="menu2"
:close-on-content-click="true"
transition="scale-transition"
offset-y
max-width="290px"
min-width="290px"
>
<template v-slot:activator="{ on, attrs }">
<v-text-field
v-model="endComputedDateFormatted"
label="End Date"
persistent-hint
prepend-icon="mdi-calendar"
readonly
v-bind="attrs"
v-on="on"
></v-text-field>
</template>
<v-date-picker
v-model="endDate"
no-title
@input="menu2 = false"
></v-date-picker>
</v-menu>
</v-col>
</v-row>
</v-card-text>
<v-card-text>
<MealPlanCard v-model="meals" />
</v-card-text>
<v-row align="center" justify="end">
<v-card-actions>
<v-btn color="success" @click="random" v-if="meals[1]" text>
Random
</v-btn>
<v-btn color="success" @click="save" text> Save </v-btn>
<v-spacer></v-spacer>
<v-btn icon @click="show = !show"> </v-btn>
</v-card-actions>
</v-row>
</v-card>
</template>
<script>
import api from "../../api";
import utils from "../../utils";
import MealPlanCard from "./MealPlanCard";
export default {
components: {
MealPlanCard,
},
data() {
return {
isLoading: false,
meals: [],
// Dates
startDate: null,
endDate: null,
menu1: false,
menu2: false,
};
},
watch: {
dateDif() {
this.meals = [];
for (let i = 0; i < this.dateDif; i++) {
this.meals.push({
slug: "",
date: this.getDate(i),
dateText: this.getDayText(i),
});
}
},
},
computed: {
items() {
return this.$store.getters.getRecentRecipes;
},
actualStartDate() {
return Date.parse(this.startDate);
},
actualEndDate() {
return Date.parse(this.endDate);
},
dateDif() {
let startDate = new Date(this.startDate);
let endDate = new Date(this.endDate);
let dateDif = (endDate - startDate) / (1000 * 3600 * 24) + 1;
if (dateDif <= 1) {
return null;
}
return dateDif;
},
startComputedDateFormatted() {
return this.formatDate(this.startDate);
},
endComputedDateFormatted() {
return this.formatDate(this.endDate);
},
},
methods: {
get_random(list) {
const object = list[Math.floor(Math.random() * list.length)];
return object.slug;
},
random() {
this.meals.forEach((element, index) => {
this.meals[index]["slug"] = this.get_random(this.items);
});
},
processTime(index) {
let dateText = new Date(
this.actualStartDate.valueOf() + 1000 * 3600 * 24 * index
);
return dateText;
},
getDayText(index) {
const dateObj = this.processTime(index);
return utils.getDateAsText(dateObj);
},
getDate(index) {
const dateObj = this.processTime(index);
return utils.getDateAsPythonDate(dateObj);
},
async save() {
const mealBody = {
startDate: this.startDate,
endDate: this.endDate,
meals: this.meals,
};
await api.mealPlans.create(mealBody);
this.$emit("created");
this.startDate = null;
this.endDate = null;
this.meals = [];
},
getImage(image) {
return utils.getImageURL(image);
},
formatDate(date) {
if (!date) return null;
const [year, month, day] = date.split("-");
return `${month}/${day}/${year}`;
},
parseDate(date) {
if (!date) return null;
const [month, day, year] = date.split("/");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
},
},
};
</script>
<style>
</style>

View File

@@ -0,0 +1,67 @@
<template>
<v-container fill-height>
<v-row justify="center" align="center">
<v-col sm="12">
<v-card
v-for="(meal, index) in mealPlan.meals"
:key="index"
class="my-2"
>
<v-row dense no-gutters align="center" justify="center">
<v-col order="1" md="6" sm="12">
<v-card flat>
<v-card-title> {{ meal.name }} </v-card-title>
<v-card-subtitle> {{ meal.dateText }}</v-card-subtitle>
<v-card-text> {{ meal.description }} </v-card-text>
<v-card-actions>
<v-btn
color="accent"
text
@click="$router.push(`/recipe/${meal.slug}`)"
>
View Recipe
</v-btn>
</v-card-actions>
</v-card>
</v-col>
<v-col order-sm="0" :order-md="getOrder(index)" md="6" sm="12">
<v-card>
<v-img :src="getImage(meal.image)" max-height="300"> </v-img>
</v-card>
</v-col>
</v-row>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script>
import api from "../../api";
import utils from "../../utils";
export default {
data() {
return {
mealPlan: {},
};
},
async mounted() {
this.mealPlan = await api.mealPlans.thisWeek();
console.log(this.mealPlan);
},
methods: {
getOrder(index) {
if (index % 2 == 0) return 2;
else return 0;
},
getImage(image) {
return utils.getImageURL(image);
},
},
};
</script>
<style scoped>
</style>