multiple recipes per day

This commit is contained in:
hay-kot 2021-05-21 23:05:45 -07:00
commit c204a5e628
13 changed files with 323 additions and 159 deletions

View file

@ -1,14 +1,45 @@
<template> <template>
<v-row> <v-row>
<SearchDialog ref="mealselect" @select="setSlug" /> <SearchDialog ref="mealselect" @select="setSlug" />
<v-col cols="12" sm="12" md="6" lg="4" xl="3" v-for="(meal, index) in value" :key="index"> <v-col cols="12" sm="12" md="6" lg="4" xl="3" v-for="(planDay, index) in value" :key="index">
<v-hover v-slot="{ hover }" :open-delay="50"> <v-hover v-slot="{ hover }" :open-delay="50">
<v-card :class="{ 'on-hover': hover }" :elevation="hover ? 12 : 2"> <v-card :class="{ 'on-hover': hover }" :elevation="hover ? 12 : 2">
<v-img height="200" :src="getImage(meal.slug)" @click="openSearch(index)"></v-img> <CardImage large :slug="planDay.meals[0].slug" icon-size="200" @click="openSearch(index, modes.primary)">
</CardImage>
<v-card-title class="my-n3 mb-n6"> <v-card-title class="my-n3 mb-n6">
{{ $d(new Date(meal.date.split("-")), "short") }} {{ $d(new Date(planDay.date.split("-")), "short") }}
</v-card-title> </v-card-title>
<v-card-subtitle> {{ meal.name }}</v-card-subtitle> <v-card-subtitle class="mb-0 pb-0"> {{ planDay.meals[0].name }}</v-card-subtitle>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="info" outlined small @click="openSearch(index, modes.sides)">
<v-icon small class="mr-1">
mdi-plus
</v-icon>
Side
</v-btn>
</v-card-actions>
<v-divider class="mx-2"></v-divider>
<v-list dense>
<v-list-item v-for="(recipe, i) in planDay.meals.slice(1)" :key="i">
<v-list-item-avatar>
<v-img :alt="recipe.slug" :src="getImage(recipe.slug)"></v-img>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title v-text="recipe.name"></v-list-item-title>
</v-list-item-content>
<v-list-item-icon>
<v-btn icon @click="removeSide(index, i + 1)">
<v-icon color="error">
mdi-delete
</v-icon>
</v-btn>
</v-list-item-icon>
</v-list-item>
</v-list>
</v-card> </v-card>
</v-hover> </v-hover>
</v-col> </v-col>
@ -18,37 +49,71 @@
<script> <script>
import SearchDialog from "../UI/Search/SearchDialog"; import SearchDialog from "../UI/Search/SearchDialog";
import { api } from "@/api"; import { api } from "@/api";
import CardImage from "../Recipe/CardImage.vue";
export default { export default {
components: { components: {
SearchDialog, SearchDialog,
CardImage,
}, },
props: { props: {
value: Array, value: Array,
}, },
data() { data() {
return { return {
recipeData: [],
cardData: [],
activeIndex: 0, activeIndex: 0,
mode: "PRIMARY",
modes: {
primary: "PRIMARY",
sides: "SIDES",
},
}; };
}, },
watch: {
value(val) {
console.log(val);
},
},
mounted() {
console.log(this.value);
},
methods: { methods: {
getImage(slug) { getImage(slug) {
if (slug) { if (slug) {
return api.recipes.recipeSmallImage(slug); return api.recipes.recipeSmallImage(slug);
} }
}, },
setSlug(name, slug) { setSide(name, slug) {
let index = this.activeIndex; const meal = { name: name, slug: slug };
this.value[index]["slug"] = slug; this.value[this.activeIndex]["meals"].push(meal);
this.value[index]["name"] = name;
}, },
openSearch(index) { setPrimary(name, slug) {
this.value[this.activeIndex]["meals"][0]["slug"] = slug;
this.value[this.activeIndex]["meals"][0]["name"] = name;
},
setSlug(name, slug) {
switch (this.mode) {
case this.modes.primary:
this.setPrimary(name, slug);
break;
default:
this.setSide(name, slug);
break;
}
},
openSearch(index, mode) {
this.mode = mode;
this.activeIndex = index; this.activeIndex = index;
this.$refs.mealselect.open(); this.$refs.mealselect.open();
}, },
removeSide(dayIndex, sideIndex) {
this.value[dayIndex]["meals"].splice(sideIndex, 1);
},
}, },
}; };
</script> </script>
<style></style> <style>
.relative-card {
position: relative;
}
</style>

View file

@ -63,14 +63,14 @@
</v-card-text> </v-card-text>
<v-card-text v-if="startDate"> <v-card-text v-if="startDate">
<MealPlanCard v-model="meals" /> <MealPlanCard v-model="planDays" />
</v-card-text> </v-card-text>
<v-row align="center" justify="end"> <v-row align="center" justify="end">
<v-card-actions class="mr-5"> <v-card-actions class="mr-5">
<v-btn color="success" @click="random" v-if="meals.length > 0" text> <v-btn color="success" @click="random" v-if="planDays.length > 0" text>
{{ $t("general.random") }} {{ $t("general.random") }}
</v-btn> </v-btn>
<v-btn color="success" @click="save" text :disabled="meals.length == 0"> <v-btn color="success" @click="save" text :disabled="planDays.length == 0">
{{ $t("general.save") }} {{ $t("general.save") }}
</v-btn> </v-btn>
</v-card-actions> </v-card-actions>
@ -92,7 +92,7 @@ export default {
data() { data() {
return { return {
isLoading: false, isLoading: false,
meals: [], planDays: [],
items: [], items: [],
// Dates // Dates
@ -106,11 +106,17 @@ export default {
watch: { watch: {
dateDif() { dateDif() {
this.meals = []; this.planDays = [];
for (let i = 0; i < this.dateDif; i++) { for (let i = 0; i < this.dateDif; i++) {
this.meals.push({ this.planDays.push({
slug: "empty",
date: this.getDate(i), date: this.getDate(i),
meals: [
{
name: "",
slug: "empty",
description: "empty",
},
],
}); });
} }
}, },
@ -172,10 +178,10 @@ export default {
}, },
random() { random() {
this.usedRecipes = [1]; this.usedRecipes = [1];
this.meals.forEach((element, index) => { this.planDays.forEach((element, index) => {
let recipe = this.getRandom(this.filteredRecipes); let recipe = this.getRandom(this.filteredRecipes);
this.meals[index]["slug"] = recipe.slug; this.planDays[index]["meals"][0]["slug"] = recipe.slug;
this.meals[index]["name"] = recipe.name; this.planDays[index]["meals"][0]["name"] = recipe.name;
this.usedRecipes.push(recipe); this.usedRecipes.push(recipe);
}); });
}, },
@ -193,11 +199,11 @@ export default {
group: this.groupSettings.name, group: this.groupSettings.name,
startDate: this.startDate, startDate: this.startDate,
endDate: this.endDate, endDate: this.endDate,
meals: this.meals, planDays: this.planDays,
}; };
if (await api.mealPlans.create(mealBody)) { if (await api.mealPlans.create(mealBody)) {
this.$emit(CREATE_EVENT); this.$emit(CREATE_EVENT);
this.meals = []; this.planDays = [];
this.startDate = null; this.startDate = null;
this.endDate = null; this.endDate = null;
} }

View file

@ -0,0 +1,85 @@
<template>
<div @click="$emit('click')">
<v-img
:height="height"
v-if="!fallBackImage"
:src="getImage(slug)"
@load="fallBackImage = false"
@error="fallBackImage = true"
>
<slot></slot>
</v-img>
<v-icon v-else color="primary" class="icon-position" :size="iconSize">
mdi-silverware-variant
</v-icon>
</div>
</template>
<script>
import { api } from "@/api";
export default {
props: {
tiny: {
type: Boolean,
default: null,
},
small: {
type: Boolean,
default: null,
},
large: {
type: Boolean,
default: null,
},
iconSize: {
default: 100,
},
slug: {
default: null,
},
height: {
default: 200,
},
},
computed: {
imageSize() {
if (this.tiny) return "tiny";
if (this.small) return "small";
if (this.large) return "large";
return "large";
},
},
watch: {
slug() {
this.fallBackImage = false;
},
},
data() {
return {
fallBackImage: false,
};
},
methods: {
getImage(image) {
switch (this.imageSize) {
case "tiny":
return api.recipes.recipeTinyImage(image);
case "small":
return api.recipes.recipeSmallImage(image);
case "large":
return api.recipes.recipeImage(image);
}
},
},
};
</script>
<style scoped>
.icon-position {
opacity: 0.8;
display: flex !important;
position: relative;
margin-left: auto !important;
margin-right: auto !important;
}
</style>

View file

@ -92,11 +92,5 @@ export default {
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.icon-position {
opacity: 0.8;
display: flex !important;
position: relative;
margin-left: auto !important;
margin-right: auto !important;
}
</style> </style>

View file

@ -17,10 +17,22 @@
{{ $d(new Date(mealplan.startDate.split("-")), "short") }} - {{ $d(new Date(mealplan.startDate.split("-")), "short") }} -
{{ $d(new Date(mealplan.endDate.split("-")), "short") }} {{ $d(new Date(mealplan.endDate.split("-")), "short") }}
</v-card-title> </v-card-title>
<v-list nav>
<v-list-item-group color="primary"> <v-list>
<v-list-group v-for="(planDay, pdi) in mealplan.planDays" :key="`planDays-${pdi}`">
<template v-slot:activator>
<v-list-item-avatar color="primary" class="headline font-weight-light white--text">
<v-img :src="getImage(planDay['meals'][0].slug)"></v-img>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title v-html="$d(new Date(planDay.date.split('-')), 'short')"></v-list-item-title>
<v-list-item-subtitle v-html="planDay['meals'][0].name"></v-list-item-subtitle>
</v-list-item-content>
</template>
<v-list-item <v-list-item
v-for="(meal, index) in mealplan.meals" three-line
v-for="(meal, index) in planDay.meals"
:key="generateKey(meal.slug, index)" :key="generateKey(meal.slug, index)"
:to="meal.slug ? `/recipe/${meal.slug}` : null" :to="meal.slug ? `/recipe/${meal.slug}` : null"
> >
@ -28,12 +40,13 @@
<v-img :src="getImage(meal.slug)"></v-img> <v-img :src="getImage(meal.slug)"></v-img>
</v-list-item-avatar> </v-list-item-avatar>
<v-list-item-content> <v-list-item-content>
<v-list-item-title v-text="meal.name"></v-list-item-title> <v-list-item-title v-html="meal.name"></v-list-item-title>
<v-list-item-subtitle v-text="$d(new Date(meal.date.split('-')), 'short')"> </v-list-item-subtitle> <v-list-item-subtitle v-html="meal.description"> </v-list-item-subtitle>
</v-list-item-content> </v-list-item-content>
</v-list-item> </v-list-item>
</v-list-item-group> </v-list-group>
</v-list> </v-list>
<v-card-actions class="mt-n5"> <v-card-actions class="mt-n5">
<v-btn color="accent lighten-2" class="mx-0" text @click="openShoppingList(mealplan.uid)"> <v-btn color="accent lighten-2" class="mx-0" text @click="openShoppingList(mealplan.uid)">
{{ $t("meal-plan.shopping-list") }} {{ $t("meal-plan.shopping-list") }}
@ -76,6 +89,7 @@ export default {
async requestMeals() { async requestMeals() {
const response = await api.mealPlans.all(); const response = await api.mealPlans.all();
this.plannedMeals = response.data; this.plannedMeals = response.data;
console.log(this.plannedMeals);
}, },
generateKey(name, index) { generateKey(name, index) {
return utils.generateUniqueKey(name, index); return utils.generateUniqueKey(name, index);

View file

@ -3,7 +3,7 @@ from logging import getLogger
from mealie.db.db_base import BaseDocument from mealie.db.db_base import BaseDocument
from mealie.db.models.event import Event, EventNotification from mealie.db.models.event import Event, EventNotification
from mealie.db.models.group import Group from mealie.db.models.group import Group
from mealie.db.models.mealplan import MealPlanModel from mealie.db.models.mealplan import MealPlan
from mealie.db.models.recipe.recipe import Category, RecipeModel, Tag from mealie.db.models.recipe.recipe import Category, RecipeModel, Tag
from mealie.db.models.settings import CustomPage, SiteSettings from mealie.db.models.settings import CustomPage, SiteSettings
from mealie.db.models.sign_up import SignUp from mealie.db.models.sign_up import SignUp
@ -12,7 +12,7 @@ from mealie.db.models.users import LongLiveToken, User
from mealie.schema.category import RecipeCategoryResponse, RecipeTagResponse from mealie.schema.category import RecipeCategoryResponse, RecipeTagResponse
from mealie.schema.event_notifications import EventNotificationIn from mealie.schema.event_notifications import EventNotificationIn
from mealie.schema.events import Event as EventSchema from mealie.schema.events import Event as EventSchema
from mealie.schema.meal import MealPlanInDB from mealie.schema.meal import MealPlanOut
from mealie.schema.recipe import Recipe from mealie.schema.recipe import Recipe
from mealie.schema.settings import CustomPageOut from mealie.schema.settings import CustomPageOut
from mealie.schema.settings import SiteSettings as SiteSettingsSchema from mealie.schema.settings import SiteSettings as SiteSettingsSchema
@ -75,8 +75,8 @@ class _Tags(BaseDocument):
class _Meals(BaseDocument): class _Meals(BaseDocument):
def __init__(self) -> None: def __init__(self) -> None:
self.primary_key = "uid" self.primary_key = "uid"
self.sql_model = MealPlanModel self.sql_model = MealPlan
self.schema = MealPlanInDB self.schema = MealPlanOut
class _Settings(BaseDocument): class _Settings(BaseDocument):
@ -120,7 +120,7 @@ class _Groups(BaseDocument):
self.sql_model = Group self.sql_model = Group
self.schema = GroupInDB self.schema = GroupInDB
def get_meals(self, session: Session, match_value: str, match_key: str = "name") -> list[MealPlanInDB]: def get_meals(self, session: Session, match_value: str, match_key: str = "name") -> list[MealPlanOut]:
"""A Helper function to get the group from the database and return a sorted list of """A Helper function to get the group from the database and return a sorted list of
Args: Args:
@ -129,7 +129,7 @@ class _Groups(BaseDocument):
match_key (str, optional): Match Key. Defaults to "name". match_key (str, optional): Match Key. Defaults to "name".
Returns: Returns:
list[MealPlanInDB]: [description] list[MealPlanOut]: [description]
""" """
group: GroupInDB = session.query(self.sql_model).filter_by(**{match_key: match_value}).one_or_none() group: GroupInDB = session.query(self.sql_model).filter_by(**{match_key: match_value}).one_or_none()

View file

@ -19,10 +19,10 @@ class Group(SqlAlchemyBase, BaseMixins):
name = sa.Column(sa.String, index=True, nullable=False, unique=True) name = sa.Column(sa.String, index=True, nullable=False, unique=True)
users = orm.relationship("User", back_populates="group") users = orm.relationship("User", back_populates="group")
mealplans = orm.relationship( mealplans = orm.relationship(
"MealPlanModel", "MealPlan",
back_populates="group", back_populates="group",
single_parent=True, single_parent=True,
order_by="MealPlanModel.startDate", order_by="MealPlan.start_date",
) )
categories = orm.relationship("Category", secondary=group2categories, single_parent=True) categories = orm.relationship("Category", secondary=group2categories, single_parent=True)

View file

@ -1,50 +1,63 @@
from typing import List
import sqlalchemy as sa
import sqlalchemy.orm as orm import sqlalchemy.orm as orm
from mealie.db.models.group import Group from mealie.db.models.group import Group
from mealie.db.models.model_base import BaseMixins, SqlAlchemyBase from mealie.db.models.model_base import BaseMixins, SqlAlchemyBase
from mealie.db.models.recipe.recipe import RecipeModel
from sqlalchemy import Column, Date, ForeignKey, Integer, String
from sqlalchemy.ext.orderinglist import ordering_list
class Meal(SqlAlchemyBase): class Meal(SqlAlchemyBase):
__tablename__ = "meal" __tablename__ = "meal"
id = sa.Column(sa.Integer, primary_key=True) id = Column(Integer, primary_key=True)
parent_id = sa.Column(sa.Integer, sa.ForeignKey("mealplan.uid")) parent_id = Column(Integer, ForeignKey("mealdays.id"))
slug = sa.Column(sa.String) position = Column(Integer)
name = sa.Column(sa.String) name = Column(String)
date = sa.Column(sa.Date) slug = Column(String)
image = sa.Column(sa.String) description = Column(String)
description = sa.Column(sa.String)
def __init__(self, slug, name="", description="", session=None) -> None:
if slug and slug != "":
recipe: RecipeModel = session.query(RecipeModel).filter(RecipeModel.slug == slug).one_or_none()
if recipe:
name = recipe.name
self.slug = recipe.slug
description = recipe.description
def __init__(self, slug, name, date, image, description, session=None) -> None:
self.slug = slug
self.name = name self.name = name
self.date = date
self.image = image
self.description = description self.description = description
class MealPlanModel(SqlAlchemyBase, BaseMixins): class MealDay(SqlAlchemyBase, BaseMixins):
__tablename__ = "mealdays"
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey("mealplan.uid"))
date = Column(Date)
meals: list[Meal] = orm.relationship(
Meal,
cascade="all, delete, delete-orphan",
order_by="Meal.position",
collection_class=ordering_list("position"),
)
def __init__(self, date, meals: list, session=None):
self.date = date
self.meals = [Meal(**m, session=session) for m in meals]
class MealPlan(SqlAlchemyBase, BaseMixins):
__tablename__ = "mealplan" __tablename__ = "mealplan"
uid = sa.Column(sa.Integer, primary_key=True, unique=True) # ! Probably Bad? uid = Column(Integer, primary_key=True, unique=True)
startDate = sa.Column(sa.Date) start_date = Column(Date)
endDate = sa.Column(sa.Date) end_date = Column(Date)
meals: List[Meal] = orm.relationship(Meal, cascade="all, delete, delete-orphan") plan_days: list[MealDay] = orm.relationship(MealDay, cascade="all, delete, delete-orphan")
group_id = sa.Column(sa.Integer, sa.ForeignKey("groups.id"))
group_id = Column(Integer, ForeignKey("groups.id"))
group = orm.relationship("Group", back_populates="mealplans") group = orm.relationship("Group", back_populates="mealplans")
def __init__(self, startDate, endDate, meals, group: str, uid=None, session=None) -> None: def __init__(self, start_date, end_date, plan_days, group: str, uid=None, session=None) -> None:
self.startDate = startDate self.start_date = start_date
self.endDate = endDate self.end_date = end_date
self.group = Group.get_ref(session, group) self.group = Group.get_ref(session, group)
self.meals = [Meal(**meal) for meal in meals] self.plan_days = [MealDay(**day, session=session) for day in plan_days]
def update(self, session, startDate, endDate, meals, uid, group) -> None:
self.__init__(
startDate=startDate,
endDate=endDate,
meals=meals,
group=group,
session=session,
)

View file

@ -2,18 +2,18 @@ from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, status
from mealie.db.database import db from mealie.db.database import db
from mealie.db.db_setup import generate_session from mealie.db.db_setup import generate_session
from mealie.routes.deps import get_current_user from mealie.routes.deps import get_current_user
from mealie.schema.meal import MealPlanIn, MealPlanInDB from mealie.schema.meal import MealPlanIn, MealPlanOut
from mealie.schema.user import GroupInDB, UserInDB from mealie.schema.user import GroupInDB, UserInDB
from mealie.services.events import create_group_event from mealie.services.events import create_group_event
from mealie.services.image import image from mealie.services.image import image
from mealie.services.meal_services import get_todays_meal, process_meals from mealie.services.meal_services import get_todays_meal, set_mealplan_dates
from sqlalchemy.orm.session import Session from sqlalchemy.orm.session import Session
from starlette.responses import FileResponse from starlette.responses import FileResponse
router = APIRouter(prefix="/api/meal-plans", tags=["Meal Plan"]) router = APIRouter(prefix="/api/meal-plans", tags=["Meal Plan"])
@router.get("/all", response_model=list[MealPlanInDB]) @router.get("/all", response_model=list[MealPlanOut])
def get_all_meals( def get_all_meals(
current_user: UserInDB = Depends(get_current_user), current_user: UserInDB = Depends(get_current_user),
session: Session = Depends(generate_session), session: Session = Depends(generate_session),
@ -31,11 +31,11 @@ def create_meal_plan(
current_user: UserInDB = Depends(get_current_user), current_user: UserInDB = Depends(get_current_user),
): ):
""" Creates a meal plan database entry """ """ Creates a meal plan database entry """
processed_plan = process_meals(session, data) set_mealplan_dates(data)
background_tasks.add_task( background_tasks.add_task(
create_group_event, "Meal Plan Created", f"Mealplan Created for '{current_user.group}'", session=session create_group_event, "Meal Plan Created", f"Mealplan Created for '{current_user.group}'", session=session
) )
return db.meals.create(session, processed_plan.dict()) return db.meals.create(session, data.dict())
@router.put("/{plan_id}") @router.put("/{plan_id}")
@ -47,8 +47,8 @@ def update_meal_plan(
current_user: UserInDB = Depends(get_current_user), current_user: UserInDB = Depends(get_current_user),
): ):
""" Updates a meal plan based off ID """ """ Updates a meal plan based off ID """
processed_plan = process_meals(session, meal_plan) set_mealplan_dates(meal_plan)
processed_plan = MealPlanInDB(uid=plan_id, **processed_plan.dict()) processed_plan = MealPlanOut(uid=plan_id, **meal_plan.dict())
try: try:
db.meals.update(session, plan_id, processed_plan.dict()) db.meals.update(session, plan_id, processed_plan.dict())
background_tasks.add_task( background_tasks.add_task(
@ -76,7 +76,7 @@ def delete_meal_plan(
raise HTTPException(status.HTTP_400_BAD_REQUEST) raise HTTPException(status.HTTP_400_BAD_REQUEST)
@router.get("/this-week", response_model=MealPlanInDB) @router.get("/this-week", response_model=MealPlanOut)
def get_this_week(session: Session = Depends(generate_session), current_user: UserInDB = Depends(get_current_user)): def get_this_week(session: Session = Depends(generate_session), current_user: UserInDB = Depends(get_current_user)):
""" Returns the meal plan data for this week """ """ Returns the meal plan data for this week """
plans = db.groups.get_meals(session, current_user.group) plans = db.groups.get_meals(session, current_user.group)

View file

@ -2,7 +2,7 @@ from fastapi import APIRouter, Depends
from mealie.db.database import db from mealie.db.database import db
from mealie.db.db_setup import generate_session from mealie.db.db_setup import generate_session
from mealie.routes.deps import get_current_user from mealie.routes.deps import get_current_user
from mealie.schema.meal import MealPlanInDB from mealie.schema.meal import MealPlanOut
from mealie.schema.recipe import Recipe from mealie.schema.recipe import Recipe
from sqlalchemy.orm.session import Session from sqlalchemy.orm.session import Session
@ -18,7 +18,7 @@ def get_shopping_list(
# ! Refactor into Single Database Call # ! Refactor into Single Database Call
mealplan = db.meals.get(session, id) mealplan = db.meals.get(session, id)
mealplan: MealPlanInDB mealplan: MealPlanOut
slugs = [x.slug for x in mealplan.meals] slugs = [x.slug for x in mealplan.meals]
recipes: list[Recipe] = [db.recipes.get(session, x) for x in slugs] recipes: list[Recipe] = [db.recipes.get(session, x) for x in slugs]
return [{"name": x.name, "recipe_ingredient": x.recipe_ingredient} for x in recipes if x] return [{"name": x.name, "recipe_ingredient": x.recipe_ingredient} for x in recipes if x]

View file

@ -1,50 +1,60 @@
from datetime import date from datetime import date
from typing import List, Optional from typing import Optional
from mealie.db.models.mealplan import MealPlanModel from fastapi_camelcase import CamelModel
from pydantic import BaseModel, validator from mealie.db.models.mealplan import MealPlan
from pydantic import validator
from pydantic.utils import GetterDict from pydantic.utils import GetterDict
class MealIn(BaseModel): class MealIn(CamelModel):
name: Optional[str]
slug: Optional[str] slug: Optional[str]
date: Optional[date] name: Optional[str]
class MealOut(MealIn):
image: Optional[str]
description: Optional[str] description: Optional[str]
class Config: class Config:
orm_mode = True orm_mode = True
class MealPlanIn(BaseModel): class MealDayIn(CamelModel):
group: str date: Optional[date]
startDate: date meals: list[MealIn]
endDate: date
meals: List[MealIn]
@validator("endDate") class Config:
def endDate_after_startDate(v, values, config, field): orm_mode = True
if "startDate" in values and v < values["startDate"]:
class MealDayOut(MealDayIn):
id: int
class Config:
orm_mode = True
class MealPlanIn(CamelModel):
group: str
start_date: date
end_date: date
plan_days: list[MealDayIn]
@validator("end_date")
def end_date_after_start_date(v, values, config, field):
if "start_date" in values and v < values["start_date"]:
raise ValueError("EndDate should be greater than StartDate") raise ValueError("EndDate should be greater than StartDate")
return v return v
class Config:
class MealPlanProcessed(MealPlanIn): orm_mode = True
meals: list[MealOut]
class MealPlanInDB(MealPlanProcessed): class MealPlanOut(MealPlanIn):
uid: str uid: int
class Config: class Config:
orm_mode = True orm_mode = True
@classmethod @classmethod
def getter_dict(_cls, name_orm: MealPlanModel): def getter_dict(_cls, name_orm: MealPlan):
return { return {
**GetterDict(name_orm), **GetterDict(name_orm),
"group": name_orm.group.name, "group": name_orm.group.name,

View file

@ -5,7 +5,7 @@ from mealie.core.config import settings
from mealie.db.models.group import Group from mealie.db.models.group import Group
from mealie.db.models.users import User from mealie.db.models.users import User
from mealie.schema.category import CategoryBase from mealie.schema.category import CategoryBase
from mealie.schema.meal import MealPlanInDB from mealie.schema.meal import MealPlanOut
from pydantic.types import constr from pydantic.types import constr
from pydantic.utils import GetterDict from pydantic.utils import GetterDict
@ -105,7 +105,7 @@ class UpdateGroup(GroupBase):
class GroupInDB(UpdateGroup): class GroupInDB(UpdateGroup):
users: Optional[list[UserOut]] users: Optional[list[UserOut]]
mealplans: Optional[list[MealPlanInDB]] mealplans: Optional[list[MealPlanOut]]
class Config: class Config:
orm_mode = True orm_mode = True

View file

@ -3,41 +3,17 @@ from typing import Union
from mealie.db.database import db from mealie.db.database import db
from mealie.db.db_setup import create_session from mealie.db.db_setup import create_session
from mealie.schema.meal import MealIn, MealOut, MealPlanIn, MealPlanInDB, MealPlanProcessed from mealie.schema.meal import MealDayIn, MealPlanIn
from mealie.schema.recipe import Recipe from mealie.schema.recipe import Recipe
from mealie.schema.user import GroupInDB from mealie.schema.user import GroupInDB
from sqlalchemy.orm.session import Session from sqlalchemy.orm.session import Session
def process_meals(session: Session, meal_plan_base: MealPlanIn) -> MealPlanProcessed: def set_mealplan_dates(meal_plan_base: MealPlanIn) -> MealPlanIn:
meals = [] for x, plan_days in enumerate(meal_plan_base.plan_days):
for x, meal in enumerate(meal_plan_base.meals): plan_days: MealDayIn
meal: MealIn
try:
recipe: Recipe = db.recipes.get(session, meal.slug)
meal_data = MealOut( plan_days.date = meal_plan_base.start_date + timedelta(days=x)
slug=recipe.slug,
name=recipe.name,
date=meal_plan_base.startDate + timedelta(days=x),
image=recipe.image,
description=recipe.description,
)
except Exception:
meal_data = MealOut(
date=meal_plan_base.startDate + timedelta(days=x),
)
meals.append(meal_data)
return MealPlanProcessed(
group=meal_plan_base.group,
meals=meals,
startDate=meal_plan_base.startDate,
endDate=meal_plan_base.endDate,
)
def get_todays_meal(session: Session, group: Union[int, GroupInDB]) -> Recipe: def get_todays_meal(session: Session, group: Union[int, GroupInDB]) -> Recipe:
@ -52,22 +28,23 @@ def get_todays_meal(session: Session, group: Union[int, GroupInDB]) -> Recipe:
Returns: Returns:
Recipe: Pydantic Recipe Object Recipe: Pydantic Recipe Object
""" """
session = session or create_session()
if isinstance(group, int): return
group: GroupInDB = db.groups.get(session, group)
today_slug = None # session = session or create_session()
for mealplan in group.mealplans: # if isinstance(group, int):
mealplan: MealPlanInDB # group: GroupInDB = db.groups.get(session, group)
for meal in mealplan.meals:
meal: MealOut
if meal.date == date.today():
today_slug = meal.slug
break
if today_slug: # today_slug = None
return db.recipes.get(session, today_slug)
else: # for mealplan in group.mealplans:
return None # for meal in mealplan.meals:
# if meal.date == date.today():
# today_slug = meal.slug
# break
# if today_slug:
# return db.recipes.get(session, today_slug)
# else:
# return None