mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 06:23:34 -07:00
mealplan redesign
This commit is contained in:
parent
14769006e2
commit
15b44eb8a3
7 changed files with 150 additions and 174 deletions
|
@ -1,10 +1,6 @@
|
|||
<template>
|
||||
<v-row>
|
||||
<MealSelect
|
||||
:forceDialog="dialog"
|
||||
@close="dialog = false"
|
||||
@select="setSlug($event)"
|
||||
/>
|
||||
<SearchDialog ref="mealselect" @select="setSlug" />
|
||||
<v-col
|
||||
cols="12"
|
||||
sm="12"
|
||||
|
@ -19,10 +15,10 @@
|
|||
<v-img
|
||||
height="200"
|
||||
:src="getImage(meal.slug)"
|
||||
@click="selectRecipe(index)"
|
||||
@click="openSearch(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-subtitle> {{ meal.name }}</v-card-subtitle>
|
||||
</v-card>
|
||||
</v-hover>
|
||||
</v-col>
|
||||
|
@ -31,10 +27,10 @@
|
|||
|
||||
<script>
|
||||
import utils from "../../utils";
|
||||
import MealSelect from "./MealSelect";
|
||||
import SearchDialog from "../UI/SearchDialog";
|
||||
export default {
|
||||
components: {
|
||||
MealSelect,
|
||||
SearchDialog,
|
||||
},
|
||||
props: {
|
||||
value: Array,
|
||||
|
@ -44,7 +40,6 @@ export default {
|
|||
recipeData: [],
|
||||
cardData: [],
|
||||
activeIndex: 0,
|
||||
dialog: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
@ -53,20 +48,14 @@ export default {
|
|||
return utils.getImageURL(slug);
|
||||
}
|
||||
},
|
||||
setSlug(slug) {
|
||||
setSlug(name, slug) {
|
||||
let index = this.activeIndex;
|
||||
this.value[index]["slug"] = slug;
|
||||
this.value[index]["name"] = name;
|
||||
},
|
||||
selectRecipe(index) {
|
||||
openSearch(index) {
|
||||
this.activeIndex = index;
|
||||
this.dialog = true;
|
||||
},
|
||||
getProperty(index, property) {
|
||||
try {
|
||||
return this.recipeData[index][property];
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
this.$refs.mealselect.open();
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
<template>
|
||||
<v-row justify="center">
|
||||
<v-dialog v-model="dialog" persistent max-width="800">
|
||||
<v-card>
|
||||
<v-card-title class="headline"> {{$t('meal-plan.choose-a-recipe')}} </v-card-title>
|
||||
<v-card-text>
|
||||
<v-autocomplete
|
||||
:items="availableRecipes"
|
||||
v-model="selected"
|
||||
clearable
|
||||
return
|
||||
dense
|
||||
hide-details
|
||||
hide-selected
|
||||
item-text="slug"
|
||||
:label="$t('search.search-for-a-recipe')"
|
||||
single-line
|
||||
>
|
||||
<template v-slot:no-data>
|
||||
<v-list-item>
|
||||
<v-list-item-title :v-html="$t('search.search-for-your-favorite-recipe')">
|
||||
</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"> {{$t('general.close')}} </v-btn>
|
||||
<v-btn color="secondary" text @click="dialog = false"> {{$t('general.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: {
|
||||
availableRecipes() {
|
||||
return this.$store.getters.getRecentRecipes;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
getImage(slug) {
|
||||
return utils.getImageURL(slug);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -25,9 +25,9 @@
|
|||
<v-col align="end">
|
||||
<v-tooltip top color="secondary" max-width="400" open-delay="50">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn color="secondary" v-on="on" v-bind="attrs" text
|
||||
>{{$t('recipe.description')}}</v-btn
|
||||
>
|
||||
<v-btn color="secondary" v-on="on" v-bind="attrs" text>{{
|
||||
$t("recipe.description")
|
||||
}}</v-btn>
|
||||
</template>
|
||||
<span>{{ description }}</span>
|
||||
</v-tooltip>
|
||||
|
@ -47,10 +47,15 @@ export default {
|
|||
description: String,
|
||||
rating: Number,
|
||||
image: String,
|
||||
route: {
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
moreInfo(recipeSlug) {
|
||||
this.$router.push(`/recipe/${recipeSlug}`);
|
||||
if (this.route) {
|
||||
this.$router.push(`/recipe/${recipeSlug}`);
|
||||
} else this.$emit("click");
|
||||
},
|
||||
getImage(image) {
|
||||
return utils.getImageURL(image);
|
||||
|
|
76
frontend/src/components/UI/SearchDialog.vue
Normal file
76
frontend/src/components/UI/SearchDialog.vue
Normal file
|
@ -0,0 +1,76 @@
|
|||
<template>
|
||||
<div class="text-center">
|
||||
<v-dialog v-model="dialog" min-height="700" max-width="1000">
|
||||
<v-card min-height="725" height="100%">
|
||||
<v-card-text>
|
||||
<v-card-title></v-card-title>
|
||||
<v-row justify="center">
|
||||
<v-col cols="1"> </v-col>
|
||||
<v-col>
|
||||
<SearchBar @results="updateResults" :show-results="false" />
|
||||
</v-col>
|
||||
<v-col cols="2">
|
||||
<v-btn icon>
|
||||
<v-icon large> mdi-filter </v-icon>
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row v-if="searchResults">
|
||||
<v-col
|
||||
:sm="6"
|
||||
:md="6"
|
||||
:lg="4"
|
||||
:xl="3"
|
||||
v-for="item in searchResults.slice(0, 10)"
|
||||
:key="item.item.name"
|
||||
>
|
||||
<RecipeCard
|
||||
:route="false"
|
||||
:name="item.item.name"
|
||||
:description="item.item.description"
|
||||
:slug="item.item.slug"
|
||||
:rating="item.item.rating"
|
||||
:image="item.item.image"
|
||||
@click="emitSelect(item.item.name, item.item.slug)"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SearchBar from "../UI/SearchBar";
|
||||
import RecipeCard from "../UI/RecipeCard";
|
||||
export default {
|
||||
components: {
|
||||
SearchBar,
|
||||
RecipeCard,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchResults: null,
|
||||
dialog: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
updateResults(results) {
|
||||
this.searchResults = results;
|
||||
},
|
||||
emitSelect(name, slug) {
|
||||
console.log(name, slug);
|
||||
this.$emit("select", name, slug);
|
||||
this.dialog = false;
|
||||
},
|
||||
open() {
|
||||
this.dialog = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
|
@ -5,66 +5,71 @@
|
|||
:meal-plan="editMealPlan"
|
||||
@updated="planUpdated"
|
||||
/>
|
||||
<NewMeal v-else @created="requestMeals" />
|
||||
<NewMeal v-else @created="requestMeals" class="mb-5" />
|
||||
|
||||
<v-card class="my-1">
|
||||
<v-card-title class="headline"> {{$t('meal-plan.meal-plans')}} </v-card-title>
|
||||
<v-card class="my-2">
|
||||
<v-card-title class="headline">
|
||||
{{ $t("meal-plan.meal-plans") }}
|
||||
</v-card-title>
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-timeline align-top :dense="$vuetify.breakpoint.smAndDown">
|
||||
<v-timeline-item
|
||||
class="mx-4"
|
||||
<v-row no-gutters>
|
||||
<v-col
|
||||
:sm="6"
|
||||
:md="6"
|
||||
:lg="4"
|
||||
:xl="3"
|
||||
v-for="(mealplan, i) in plannedMeals"
|
||||
:key="i"
|
||||
color="accent lighten-2"
|
||||
icon="mdi-silverware-variant"
|
||||
fill-dot
|
||||
>
|
||||
<v-card>
|
||||
<v-card-title class="white--text secondary lighten-1">
|
||||
<v-card class="ml-2 mt-2 mr-0">
|
||||
<v-card-title>
|
||||
{{ formatDate(mealplan.startDate) }} -
|
||||
{{ formatDate(mealplan.endDate) }}
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-row dense align="center">
|
||||
<v-col></v-col>
|
||||
<v-col
|
||||
<v-list nav>
|
||||
<v-list-item-group color="primary">
|
||||
<v-list-item
|
||||
v-for="(meal, index) in mealplan.meals"
|
||||
:key="generateKey(meal.slug, index)"
|
||||
@click="$router.push(`/recipe/${meal.slug}`)"
|
||||
>
|
||||
<v-img
|
||||
class="rounded-lg info"
|
||||
:src="getImage(meal.image)"
|
||||
height="80"
|
||||
width="80"
|
||||
<v-list-item-avatar
|
||||
color="primary"
|
||||
class="headline font-weight-light white--text"
|
||||
>
|
||||
</v-img>
|
||||
</v-col>
|
||||
<v-col></v-col>
|
||||
</v-row>
|
||||
<v-row class="mt-2 ml-1">
|
||||
<v-btn
|
||||
color="accent lighten-2"
|
||||
class="mx-0"
|
||||
text
|
||||
@click="editPlan(mealplan.uid)"
|
||||
>
|
||||
{{$t('general.edit')}}
|
||||
</v-btn>
|
||||
<v-btn
|
||||
color="error lighten-2"
|
||||
class="mx-2"
|
||||
text
|
||||
@click="deletePlan(mealplan.uid)"
|
||||
>
|
||||
{{$t('general.delete')}}
|
||||
</v-btn>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
<v-img :src="getImage(meal.image)"></v-img>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title v-text="meal.name"></v-list-item-title>
|
||||
<v-list-item-subtitle v-text="meal.dateText">
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list-item-group>
|
||||
</v-list>
|
||||
<v-card-actions class="mt-n5">
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
color="accent lighten-2"
|
||||
class="mx-0"
|
||||
text
|
||||
@click="editPlan(mealplan.uid)"
|
||||
>
|
||||
{{ $t("general.edit") }}
|
||||
</v-btn>
|
||||
<v-btn
|
||||
color="error lighten-2"
|
||||
class="mx-2"
|
||||
text
|
||||
@click="deletePlan(mealplan.uid)"
|
||||
>
|
||||
{{ $t("general.delete") }}
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-timeline-item>
|
||||
</v-timeline>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -53,17 +53,17 @@ export default {
|
|||
const dow = days[dateObject.getUTCDay()];
|
||||
const month = months[dateObject.getUTCMonth()];
|
||||
const day = dateObject.getUTCDate();
|
||||
const year = dateObject.getFullYear();
|
||||
// const year = dateObject.getFullYear();
|
||||
|
||||
return `${dow}, ${month} ${day}, ${year}`;
|
||||
return `${dow}, ${month} ${day}`;
|
||||
},
|
||||
getDateAsTextAlt(dateObject) {
|
||||
const dow = days[dateObject.getUTCDay()];
|
||||
const month = monthsShort[dateObject.getUTCMonth()];
|
||||
const day = dateObject.getUTCDate();
|
||||
const year = dateObject.getFullYear();
|
||||
// const year = dateObject.getFullYear();
|
||||
|
||||
return `${dow}, ${month} ${day}, ${year}`;
|
||||
return `${dow}, ${month} ${day}`;
|
||||
},
|
||||
getDateAsPythonDate(dateObject) {
|
||||
const month = dateObject.getMonth() + 1;
|
||||
|
|
|
@ -32,6 +32,7 @@ class Meal(BaseModel):
|
|||
|
||||
|
||||
class MealData(BaseModel):
|
||||
name: Optional[str]
|
||||
slug: str
|
||||
dateText: str
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue