From d0b5cf95aed8048ae538afdd8470b4bc72eb6e0e Mon Sep 17 00:00:00 2001 From: ysandler Date: Sun, 18 May 2025 11:38:11 -0500 Subject: [PATCH] feat: added meals tables --- src/collections/Meals/Ingredients.ts | 103 ++++++ src/collections/Meals/MealItems.ts | 157 +++++++++ src/collections/Meals/Meals.ts | 142 +++++++++ .../Meals/hooks/beforeChangeMeal.ts | 69 ++++ .../Meals/hooks/beforeChangeMealItems.ts | 69 ++++ src/collections/Meals/index.ts | 8 + src/payload-types.ts | 297 ++++++++++++++++++ src/payload.config.ts | 3 +- src/plugins/index.ts | 3 + 9 files changed, 850 insertions(+), 1 deletion(-) create mode 100644 src/collections/Meals/Ingredients.ts create mode 100644 src/collections/Meals/MealItems.ts create mode 100644 src/collections/Meals/Meals.ts create mode 100644 src/collections/Meals/hooks/beforeChangeMeal.ts create mode 100644 src/collections/Meals/hooks/beforeChangeMealItems.ts create mode 100644 src/collections/Meals/index.ts diff --git a/src/collections/Meals/Ingredients.ts b/src/collections/Meals/Ingredients.ts new file mode 100644 index 0000000..d76d75d --- /dev/null +++ b/src/collections/Meals/Ingredients.ts @@ -0,0 +1,103 @@ +import { CollectionConfig } from "payload"; + +export const Ingredients: CollectionConfig = { + slug: 'ingredients', + admin: { + useAsTitle: 'name', + }, + fields: [ + { + name: 'name', + type: 'text', + unique: true, + }, + { + name: 'description', + type: 'textarea', + }, + { + type: 'row', + fields: [ + { + name: 'calories', + type: 'number', + admin: { + description: 'per 100g', + width: '25%', + } + }, + { + name: 'protein', + type: 'number', + admin: { + description: 'per 100g', + width: '25%', + } + }, + { + name: 'carbohydrates', + type: 'number', + admin: { + description: 'per 100g', + width: '25%', + } + }, + { + name: 'fat', + type: 'number', + admin: { + description: 'per 100g', + width: '25%', + } + }, + ], + }, + { + type: 'row', + fields: [ + { + name: 'canBeKosher', + type: 'checkbox', + admin: { + description: 'Is capable of being vertified Kosher. Not a declaration that ingredient is Kosher.', + width: '20%', + }, + }, + { + name: 'canBeHalal', + type: 'checkbox', + admin: { + description: 'Is capable of being vertified Halal. Not a declaration that ingredient is Halal.', + width: '20%', + }, + }, + { + name: 'canBeVegan', + type: 'checkbox', + admin: { + description: 'Is capable of being vertified Vegan. Not a declaration that ingredient is Vegan.', + width: '20%', + }, + }, + { + name: 'canBeVegetarian', + type: 'checkbox', + admin: { + description: 'Is capable of being vertified Vegetarian. Not a declaration that ingredient is Vegetarian.', + width: '20%', + }, + }, + { + name: 'canBeGlutenFree', + type: 'checkbox', + admin: { + description: 'Is capable of being vertified Gluten Free. Not a declaration that ingredient is Gluten Free.', + width: '20%', + }, + }, + ], + }, + // TODO: Add Relationship to Common Allergens + ], +} + diff --git a/src/collections/Meals/MealItems.ts b/src/collections/Meals/MealItems.ts new file mode 100644 index 0000000..0fe1fc1 --- /dev/null +++ b/src/collections/Meals/MealItems.ts @@ -0,0 +1,157 @@ +import { CollectionConfig, PaginatedDocs } from "payload"; +import { MealItem } from "@/payload-types"; +import { setMealItemNutritionOnChange } from "./hooks/beforeChangeMealItems"; + +export const MealItems: CollectionConfig = { + slug: 'mealItems', + admin: { + description: 'Items that make up a meal, such as mashed potatoes, salad, grilled chicken, etc.', + useAsTitle: 'name', + }, + fields: [ + { + type: 'row', + fields: [ + { + name: 'name', + type: 'text', + admin: { + width: '75%', + } + }, + { + name: 'servingSize', + type: 'number', + admin: { + description: 'in Grams', + width: '25%', + } + }, + ], + }, + { + name: 'description', + type: 'textarea', + }, + { + type: 'row', + fields: [ + { + name: 'calories', + type: 'number', + admin: { + description: 'per Serving, calculated from ingredients', + width: '25%', + }, + }, + { + name: 'protein', + type: 'number', + admin: { + description: 'per Serving, calculated from ingredients', + width: '25%', + }, + }, + { + name: 'carbohydrates', + type: 'number', + admin: { + description: 'per Serving, calculated from ingredients', + width: '25%', + }, + }, + { + name: 'fat', + type: 'number', + admin: { + description: 'per Serving, calculated from ingredients', + width: '25%', + }, + }, + ] + }, + { + type: 'row', + fields: [ + { + name: 'canBeKosher', + type: 'checkbox', + admin: { + description: 'Calculated from ingredients. Is capable of being vertified Kosher. Not a declaration that ingredient is Kosher.', + width: '20%', + }, + }, + { + name: 'canBeHalal', + type: 'checkbox', + admin: { + description: 'Calculated from ingredients. Is capable of being vertified Halal. Not a declaration that ingredient is Halal.', + width: '20%', + }, + }, + { + name: 'canBeVegan', + type: 'checkbox', + admin: { + description: 'Calculated from ingredients. Is capable of being vertified Vegan. Not a declaration that ingredient is Vegan.', + width: '20%', + }, + }, + { + name: 'canBeVegetarian', + type: 'checkbox', + admin: { + description: 'Calculated from ingredients. Is capable of being vertified Vegetarian. Not a declaration that ingredient is Vegetarian.', + width: '20%', + }, + }, + { + name: 'canBeGlutenFree', + type: 'checkbox', + admin: { + description: 'Calculated from ingredients. Is capable of being vertified Gluten Free. Not a declaration that ingredient is Gluten Free.', + width: '20%', + }, + }, + ], + }, + { + name: 'instructions', + type: 'richText', + }, + { + name: 'neededIngredients', + type: 'array', + fields: [ + { + type: 'row', + fields: [ + { + name: 'quantity', + type: 'number', + admin: { + description: 'as 100g intervals. (value of 3 = 300g)', + width: '25%', + } + }, + { + name: 'ingredient', + type: 'relationship', + relationTo: 'ingredients', + hasMany: false, + admin: { + width: '75%', + } + }, + ] + } + ] + } + ], + hooks: { + beforeChange: [ + setMealItemNutritionOnChange + ] + } +} + diff --git a/src/collections/Meals/Meals.ts b/src/collections/Meals/Meals.ts new file mode 100644 index 0000000..882267b --- /dev/null +++ b/src/collections/Meals/Meals.ts @@ -0,0 +1,142 @@ +import { CollectionConfig } from "payload"; +import { setMealNutritionOnChange } from "./hooks/beforeChangeMeal"; + +export const Meals: CollectionConfig = { + slug: 'meals', + admin: { + useAsTitle: 'name', + }, + fields: [ + { + name: 'name', + type: 'text', + }, + { + name: 'description', + type: 'textarea' + }, + { + name: 'excludeItemInstructions', + type: 'checkbox', + }, + { + name: 'instructions', + type: 'richText', + }, + { + type: 'row', + fields: [ + { + name: 'calories', + type: 'number', + admin: { + description: 'per Serving, calculated from ingredients', + width: '25%', + }, + }, + { + name: 'protein', + type: 'number', + admin: { + description: 'per Serving, calculated from ingredients', + width: '25%', + }, + }, + { + name: 'carbohydrates', + type: 'number', + admin: { + description: 'per Serving, calculated from ingredients', + width: '25%', + }, + }, + { + name: 'fat', + type: 'number', + admin: { + description: 'per Serving, calculated from ingredients', + width: '25%', + }, + }, + ] + }, + { + type: 'row', + fields: [ + { + name: 'canBeKosher', + type: 'checkbox', + admin: { + description: 'Calculated from ingredients. Is capable of being vertified Kosher. Not a declaration that ingredient is Kosher.', + width: '20%', + }, + }, + { + name: 'canBeHalal', + type: 'checkbox', + admin: { + description: 'Calculated from ingredients. Is capable of being vertified Halal. Not a declaration that ingredient is Halal.', + width: '20%', + }, + }, + { + name: 'canBeVegan', + type: 'checkbox', + admin: { + description: 'Calculated from ingredients. Is capable of being vertified Vegan. Not a declaration that ingredient is Vegan.', + width: '20%', + }, + }, + { + name: 'canBeVegetarian', + type: 'checkbox', + admin: { + description: 'Calculated from ingredients. Is capable of being vertified Vegetarian. Not a declaration that ingredient is Vegetarian.', + width: '20%', + }, + }, + { + name: 'canBeGlutenFree', + type: 'checkbox', + admin: { + description: 'Calculated from ingredients. Is capable of being vertified Gluten Free. Not a declaration that ingredient is Gluten Free.', + width: '20%', + }, + }, + ], + }, + { + name: 'items', + type: 'array', + fields: [ + { + type: 'row', + fields: [ + { + name: 'item', + type: 'relationship', + relationTo: 'mealItems', + hasMany: false, + admin: { + width: '75%', + }, + }, + { + name: 'quantity', + type: 'number', + admin: { + description: 'as Servings', + width: '25%', + } + } + ] + }, + ], + }, + ], + hooks: { + beforeChange: [ + setMealNutritionOnChange + ] + } +} diff --git a/src/collections/Meals/hooks/beforeChangeMeal.ts b/src/collections/Meals/hooks/beforeChangeMeal.ts new file mode 100644 index 0000000..b107858 --- /dev/null +++ b/src/collections/Meals/hooks/beforeChangeMeal.ts @@ -0,0 +1,69 @@ +import { Meal } from "@/payload-types" +type ItemNeeded = Extract>[0] +import { BeforeChangeHook } from "node_modules/payload/dist/collections/config/types" + +export const setMealNutritionOnChange: BeforeChangeHook = async (args) => { + const data = args.data as Partial + const payload = args.req.payload + + if (!data.items?.length) { + const zeroedOutNutrition: Partial = { + calories: 0, + carbohydrates: 0, + fat: 0, + protein: 0, + canBeKosher: false, + canBeHalal: false, + canBeVegan: false, + canBeVegetarian: false, + canBeGlutenFree: false, + } + return { ...data, ...zeroedOutNutrition } + } + + const itemsPromises = data.items?.map(async (i: ItemNeeded) => { + return await payload.findByID({ + collection: 'mealItems', + id: i.item as number || 0, + select: { + calories: true, + protein: true, + carbohydrates: true, + fat: true, + canBeGlutenFree: true, + canBeHalal: true, + canBeKosher: true, + canBeVegan: true, + canBeVegetarian: true, + }, + }) + }) || [] + + const items = await Promise.all(itemsPromises) + + const updatedNutrition: Partial = { + calories: items.reduce((previousValue, item) => { + const quantity = data.items?.find(i => i.item === item.id)?.quantity || 1 + return previousValue + ((item?.calories || 0) * quantity) + }, 0), + carbohydrates: items.reduce((previousValue, item) => { + const quantity = data.items?.find(i => i.item === item.id)?.quantity || 1 + return previousValue + ((item?.carbohydrates || 0) * quantity) + }, 0), + fat: items.reduce((previousValue, item) => { + const quantity = data.items?.find(i => i.item === item.id)?.quantity || 1 + return previousValue + ((item?.fat || 0) * quantity) + }, 0), + protein: items.reduce((previousValue, item) => { + const quantity = data.items?.find(i => i.item === item.id)?.quantity || 1 + return previousValue + ((item?.protein || 0) * quantity) + }, 0), + canBeKosher: !items.find(i => !i.canBeKosher), + canBeHalal: !items.find(i => !i.canBeHalal), + canBeVegan: !items.find(i => !i.canBeVegan), + canBeVegetarian: !items.find(i => !i.canBeVegetarian), + canBeGlutenFree: !items.find(i => !i.canBeGlutenFree), + } + + return { ...data, ...updatedNutrition } +} diff --git a/src/collections/Meals/hooks/beforeChangeMealItems.ts b/src/collections/Meals/hooks/beforeChangeMealItems.ts new file mode 100644 index 0000000..feb6254 --- /dev/null +++ b/src/collections/Meals/hooks/beforeChangeMealItems.ts @@ -0,0 +1,69 @@ +import { MealItem } from "@/payload-types" +type ItemNeededIngredient = Extract>[0] +import { BeforeChangeHook } from "node_modules/payload/dist/collections/config/types" + +export const setMealItemNutritionOnChange: BeforeChangeHook = async (args) => { + const data = args.data as Partial + const payload = args.req.payload + + if (!data.neededIngredients?.length) { + const zeroedOutNutrition: Partial = { + calories: 0, + carbohydrates: 0, + fat: 0, + protein: 0, + canBeKosher: false, + canBeHalal: false, + canBeVegan: false, + canBeVegetarian: false, + canBeGlutenFree: false, + } + return { ...data, ...zeroedOutNutrition } + } + + const neededIngredientsPromises = data.neededIngredients?.map(async (i: ItemNeededIngredient) => { + return await payload.findByID({ + collection: 'ingredients', + id: i.ingredient as number || 0, + select: { + calories: true, + protein: true, + carbohydrates: true, + fat: true, + canBeGlutenFree: true, + canBeHalal: true, + canBeKosher: true, + canBeVegan: true, + canBeVegetarian: true, + }, + }) + }) || [] + + const ingredients = await Promise.all(neededIngredientsPromises) + + const updatedNutrition: Partial = { + calories: ingredients.reduce((previousValue, ingredient) => { + const quantity = data.neededIngredients?.find(i => i.ingredient === ingredient.id)?.quantity || 1 + return previousValue + ((ingredient?.calories || 0) * quantity) + }, 0), + carbohydrates: ingredients.reduce((previousValue, ingredient) => { + const quantity = data.neededIngredients?.find(i => i.ingredient === ingredient.id)?.quantity || 1 + return previousValue + ((ingredient?.carbohydrates || 0) * quantity) + }, 0), + fat: ingredients.reduce((previousValue, ingredient) => { + const quantity = data.neededIngredients?.find(i => i.ingredient === ingredient.id)?.quantity || 1 + return previousValue + ((ingredient?.fat || 0) * quantity) + }, 0), + protein: ingredients.reduce((previousValue, ingredient) => { + const quantity = data.neededIngredients?.find(i => i.ingredient === ingredient.id)?.quantity || 1 + return previousValue + ((ingredient?.protein || 0) * quantity) + }, 0), + canBeKosher: !ingredients.find(i => !i.canBeKosher), + canBeHalal: !ingredients.find(i => !i.canBeHalal), + canBeVegan: !ingredients.find(i => !i.canBeVegan), + canBeVegetarian: !ingredients.find(i => !i.canBeVegetarian), + canBeGlutenFree: !ingredients.find(i => !i.canBeGlutenFree), + } + + return { ...data, ...updatedNutrition } +} diff --git a/src/collections/Meals/index.ts b/src/collections/Meals/index.ts new file mode 100644 index 0000000..8f1b22c --- /dev/null +++ b/src/collections/Meals/index.ts @@ -0,0 +1,8 @@ +import { Ingredients } from "./Ingredients"; +import { MealItems } from "./MealItems"; +import { Meals } from "./Meals"; + +export { Ingredients, MealItems, Meals } + + + diff --git a/src/payload-types.ts b/src/payload-types.ts index 1e786bb..9269a09 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -79,6 +79,9 @@ export interface Config { equipments: Equipment; workouts: Workout; workoutTypes: WorkoutType; + ingredients: Ingredient; + mealItems: MealItem; + meals: Meal; redirects: Redirect; forms: Form; 'form-submissions': FormSubmission; @@ -102,6 +105,9 @@ export interface Config { equipments: EquipmentsSelect | EquipmentsSelect; workouts: WorkoutsSelect | WorkoutsSelect; workoutTypes: WorkoutTypesSelect | WorkoutTypesSelect; + ingredients: IngredientsSelect | IngredientsSelect; + mealItems: MealItemsSelect | MealItemsSelect; + meals: MealsSelect | MealsSelect; redirects: RedirectsSelect | RedirectsSelect; forms: FormsSelect | FormsSelect; 'form-submissions': FormSubmissionsSelect | FormSubmissionsSelect; @@ -886,6 +892,207 @@ export interface WorkoutType { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "ingredients". + */ +export interface Ingredient { + id: number; + tenant?: (number | null) | Tenant; + name?: string | null; + description?: string | null; + /** + * per 100g + */ + calories?: number | null; + /** + * per 100g + */ + protein?: number | null; + /** + * per 100g + */ + carbohydrates?: number | null; + /** + * per 100g + */ + fat?: number | null; + /** + * Is capable of being vertified Kosher. Not a declaration that ingredient is Kosher. + */ + canBeKosher?: boolean | null; + /** + * Is capable of being vertified Halal. Not a declaration that ingredient is Halal. + */ + canBeHalal?: boolean | null; + /** + * Is capable of being vertified Vegan. Not a declaration that ingredient is Vegan. + */ + canBeVegan?: boolean | null; + /** + * Is capable of being vertified Vegetarian. Not a declaration that ingredient is Vegetarian. + */ + canBeVegetarian?: boolean | null; + /** + * Is capable of being vertified Gluten Free. Not a declaration that ingredient is Gluten Free. + */ + canBeGlutenFree?: boolean | null; + updatedAt: string; + createdAt: string; +} +/** + * Items that make up a meal, such as mashed potatoes, salad, grilled chicken, etc. + * + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "mealItems". + */ +export interface MealItem { + id: number; + tenant?: (number | null) | Tenant; + name?: string | null; + /** + * in Grams + */ + servingSize?: number | null; + description?: string | null; + /** + * per Serving, calculated from ingredients + */ + calories?: number | null; + /** + * per Serving, calculated from ingredients + */ + protein?: number | null; + /** + * per Serving, calculated from ingredients + */ + carbohydrates?: number | null; + /** + * per Serving, calculated from ingredients + */ + fat?: number | null; + /** + * Calculated from ingredients. Is capable of being vertified Kosher. Not a declaration that ingredient is Kosher. + */ + canBeKosher?: boolean | null; + /** + * Calculated from ingredients. Is capable of being vertified Halal. Not a declaration that ingredient is Halal. + */ + canBeHalal?: boolean | null; + /** + * Calculated from ingredients. Is capable of being vertified Vegan. Not a declaration that ingredient is Vegan. + */ + canBeVegan?: boolean | null; + /** + * Calculated from ingredients. Is capable of being vertified Vegetarian. Not a declaration that ingredient is Vegetarian. + */ + canBeVegetarian?: boolean | null; + /** + * Calculated from ingredients. Is capable of being vertified Gluten Free. Not a declaration that ingredient is Gluten Free. + */ + canBeGlutenFree?: boolean | null; + instructions?: { + root: { + type: string; + children: { + type: string; + version: number; + [k: string]: unknown; + }[]; + direction: ('ltr' | 'rtl') | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + [k: string]: unknown; + } | null; + neededIngredients?: + | { + /** + * as 100g intervals. (value of 3 = 300g) + */ + quantity?: number | null; + ingredient?: (number | null) | Ingredient; + id?: string | null; + }[] + | null; + updatedAt: string; + createdAt: string; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "meals". + */ +export interface Meal { + id: number; + tenant?: (number | null) | Tenant; + name?: string | null; + description?: string | null; + excludeItemInstructions?: boolean | null; + instructions?: { + root: { + type: string; + children: { + type: string; + version: number; + [k: string]: unknown; + }[]; + direction: ('ltr' | 'rtl') | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + [k: string]: unknown; + } | null; + /** + * per Serving, calculated from ingredients + */ + calories?: number | null; + /** + * per Serving, calculated from ingredients + */ + protein?: number | null; + /** + * per Serving, calculated from ingredients + */ + carbohydrates?: number | null; + /** + * per Serving, calculated from ingredients + */ + fat?: number | null; + /** + * Calculated from ingredients. Is capable of being vertified Kosher. Not a declaration that ingredient is Kosher. + */ + canBeKosher?: boolean | null; + /** + * Calculated from ingredients. Is capable of being vertified Halal. Not a declaration that ingredient is Halal. + */ + canBeHalal?: boolean | null; + /** + * Calculated from ingredients. Is capable of being vertified Vegan. Not a declaration that ingredient is Vegan. + */ + canBeVegan?: boolean | null; + /** + * Calculated from ingredients. Is capable of being vertified Vegetarian. Not a declaration that ingredient is Vegetarian. + */ + canBeVegetarian?: boolean | null; + /** + * Calculated from ingredients. Is capable of being vertified Gluten Free. Not a declaration that ingredient is Gluten Free. + */ + canBeGlutenFree?: boolean | null; + items?: + | { + item?: (number | null) | MealItem; + /** + * as Servings + */ + quantity?: number | null; + id?: string | null; + }[] + | null; + updatedAt: string; + createdAt: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "redirects". @@ -1106,6 +1313,18 @@ export interface PayloadLockedDocument { relationTo: 'workoutTypes'; value: number | WorkoutType; } | null) + | ({ + relationTo: 'ingredients'; + value: number | Ingredient; + } | null) + | ({ + relationTo: 'mealItems'; + value: number | MealItem; + } | null) + | ({ + relationTo: 'meals'; + value: number | Meal; + } | null) | ({ relationTo: 'redirects'; value: number | Redirect; @@ -1569,6 +1788,84 @@ export interface WorkoutTypesSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "ingredients_select". + */ +export interface IngredientsSelect { + tenant?: T; + name?: T; + description?: T; + calories?: T; + protein?: T; + carbohydrates?: T; + fat?: T; + canBeKosher?: T; + canBeHalal?: T; + canBeVegan?: T; + canBeVegetarian?: T; + canBeGlutenFree?: T; + updatedAt?: T; + createdAt?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "mealItems_select". + */ +export interface MealItemsSelect { + tenant?: T; + name?: T; + servingSize?: T; + description?: T; + calories?: T; + protein?: T; + carbohydrates?: T; + fat?: T; + canBeKosher?: T; + canBeHalal?: T; + canBeVegan?: T; + canBeVegetarian?: T; + canBeGlutenFree?: T; + instructions?: T; + neededIngredients?: + | T + | { + quantity?: T; + ingredient?: T; + id?: T; + }; + updatedAt?: T; + createdAt?: T; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "meals_select". + */ +export interface MealsSelect { + tenant?: T; + name?: T; + description?: T; + excludeItemInstructions?: T; + instructions?: T; + calories?: T; + protein?: T; + carbohydrates?: T; + fat?: T; + canBeKosher?: T; + canBeHalal?: T; + canBeVegan?: T; + canBeVegetarian?: T; + canBeGlutenFree?: T; + items?: + | T + | { + item?: T; + quantity?: T; + id?: T; + }; + updatedAt?: T; + createdAt?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "redirects_select". diff --git a/src/payload.config.ts b/src/payload.config.ts index 8055d79..33daec6 100644 --- a/src/payload.config.ts +++ b/src/payload.config.ts @@ -19,6 +19,7 @@ import { getServerSideURL } from './utilities/getURL' import { Tenants } from './collections/Tenants' import { Equipments, Exercises, ExerciseTypes, MuscleGroups } from './collections/Exercises' import { Workouts, WorkoutTypes } from './collections/Workouts' +import { Ingredients, MealItems, Meals } from './collections/Meals' const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) @@ -67,7 +68,7 @@ export default buildConfig({ connectionString: process.env.DATABASE_URI || '', }, }), - collections: [Pages, Posts, Media, Categories, Users, Tenants, Exercises, ExerciseTypes, MuscleGroups, Equipments, Workouts, WorkoutTypes], + collections: [Pages, Posts, Media, Categories, Users, Tenants, Exercises, ExerciseTypes, MuscleGroups, Equipments, Workouts, WorkoutTypes, Ingredients, MealItems, Meals], cors: [getServerSideURL()].filter(Boolean), globals: [Header, Footer], plugins: [ diff --git a/src/plugins/index.ts b/src/plugins/index.ts index ed61a6b..c58ad53 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -105,6 +105,9 @@ export const plugins: Plugin[] = [ equipments: {}, workouts: {}, workoutTypes: {}, + ingredients: {}, + mealItems: {}, + meals: {}, }, tenantsArrayField: { includeDefaultField: false,