healthy-meals-core 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/bmr.d.ts +3 -0
  2. package/dist/bmr.js +14 -0
  3. package/dist/dailyMealPlanGenerator.d.ts +3 -0
  4. package/dist/dailyMealPlanGenerator.js +211 -0
  5. package/dist/data/detailed-recipes-bs.json +417 -0
  6. package/dist/data/detailed-recipes.json +744 -0
  7. package/dist/foodConversion.d.ts +55 -0
  8. package/dist/foodConversion.js +200 -0
  9. package/dist/index.d.ts +12 -0
  10. package/dist/index.js +27 -0
  11. package/dist/planner.d.ts +2 -0
  12. package/dist/planner.js +24 -0
  13. package/dist/recipeBasedMealPlanGenerator.d.ts +17 -0
  14. package/dist/recipeBasedMealPlanGenerator.js +255 -0
  15. package/dist/recipeService.d.ts +28 -0
  16. package/dist/recipeService.js +136 -0
  17. package/dist/rules/cholesterol.d.ts +2 -0
  18. package/dist/rules/cholesterol.js +7 -0
  19. package/dist/rules/diabetes.d.ts +2 -0
  20. package/dist/rules/diabetes.js +7 -0
  21. package/dist/rules/fattyLiver.d.ts +2 -0
  22. package/dist/rules/fattyLiver.js +7 -0
  23. package/dist/rules/index.d.ts +7 -0
  24. package/dist/rules/index.js +47 -0
  25. package/dist/rules/lowCarb.d.ts +2 -0
  26. package/dist/rules/lowCarb.js +7 -0
  27. package/dist/rules/triglycerides.d.ts +2 -0
  28. package/dist/rules/triglycerides.js +7 -0
  29. package/dist/src/bmr.d.ts +3 -0
  30. package/dist/src/bmr.js +13 -0
  31. package/dist/src/dailyMealPlanGenerator.d.ts +3 -0
  32. package/dist/src/dailyMealPlanGenerator.js +210 -0
  33. package/dist/src/foodConversion.d.ts +55 -0
  34. package/dist/src/foodConversion.js +199 -0
  35. package/dist/src/index.d.ts +12 -0
  36. package/dist/src/index.js +27 -0
  37. package/dist/src/planner.d.ts +2 -0
  38. package/dist/src/planner.js +23 -0
  39. package/dist/src/recipeBasedMealPlanGenerator.d.ts +17 -0
  40. package/dist/src/recipeBasedMealPlanGenerator.js +254 -0
  41. package/dist/src/recipeService.d.ts +28 -0
  42. package/dist/src/recipeService.js +136 -0
  43. package/dist/src/rules/cholesterol.d.ts +2 -0
  44. package/dist/src/rules/cholesterol.js +6 -0
  45. package/dist/src/rules/diabetes.d.ts +2 -0
  46. package/dist/src/rules/diabetes.js +6 -0
  47. package/dist/src/rules/fattyLiver.d.ts +2 -0
  48. package/dist/src/rules/fattyLiver.js +6 -0
  49. package/dist/src/rules/index.d.ts +7 -0
  50. package/dist/src/rules/index.js +46 -0
  51. package/dist/src/rules/lowCarb.d.ts +2 -0
  52. package/dist/src/rules/lowCarb.js +6 -0
  53. package/dist/src/rules/triglycerides.d.ts +2 -0
  54. package/dist/src/rules/triglycerides.js +6 -0
  55. package/dist/src/types/firestore.d.ts +100 -0
  56. package/dist/src/types/firestore.js +2 -0
  57. package/dist/src/types/openfoodfacts.d.ts +113 -0
  58. package/dist/src/types/openfoodfacts.js +3 -0
  59. package/dist/src/types/recipe.d.ts +36 -0
  60. package/dist/src/types/recipe.js +2 -0
  61. package/dist/src/types.d.ts +24 -0
  62. package/dist/src/types.js +2 -0
  63. package/dist/src/variety.d.ts +17 -0
  64. package/dist/src/variety.js +129 -0
  65. package/dist/src/weeklyMealPlanGenerator.d.ts +3 -0
  66. package/dist/src/weeklyMealPlanGenerator.js +468 -0
  67. package/dist/src/weeklyPlanner.d.ts +12 -0
  68. package/dist/src/weeklyPlanner.js +31 -0
  69. package/dist/types/firestore.d.ts +100 -0
  70. package/dist/types/firestore.js +2 -0
  71. package/dist/types/openfoodfacts.d.ts +113 -0
  72. package/dist/types/openfoodfacts.js +3 -0
  73. package/dist/types/recipe.d.ts +36 -0
  74. package/dist/types/recipe.js +2 -0
  75. package/dist/types.d.ts +24 -0
  76. package/dist/types.js +2 -0
  77. package/dist/variety.d.ts +17 -0
  78. package/dist/variety.js +130 -0
  79. package/dist/weeklyMealPlanGenerator.d.ts +3 -0
  80. package/dist/weeklyMealPlanGenerator.js +469 -0
  81. package/dist/weeklyPlanner.d.ts +12 -0
  82. package/dist/weeklyPlanner.js +32 -0
  83. package/package.json +66 -0
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.recipeService = exports.RecipeService = void 0;
7
+ const detailed_recipes_json_1 = __importDefault(require("../data/detailed-recipes.json"));
8
+ const detailed_recipes_bs_json_1 = __importDefault(require("../data/detailed-recipes-bs.json"));
9
+ class RecipeService {
10
+ constructor(locale = 'en') {
11
+ this.currentLocale = 'en';
12
+ this.recipes = detailed_recipes_json_1.default;
13
+ this.recipesBS = detailed_recipes_bs_json_1.default;
14
+ this.currentLocale = locale;
15
+ }
16
+ setLocale(locale) {
17
+ this.currentLocale = locale;
18
+ }
19
+ getCurrentRecipes() {
20
+ return this.currentLocale === 'bs' ? this.recipesBS : this.recipes;
21
+ }
22
+ getAllRecipes() {
23
+ return this.getCurrentRecipes();
24
+ }
25
+ getRecipeById(id) {
26
+ return this.getCurrentRecipes().find(recipe => recipe.id === id);
27
+ }
28
+ getRecipesByCategory(category) {
29
+ return this.getCurrentRecipes().filter(recipe => recipe.category === category);
30
+ }
31
+ filterRecipes(filter) {
32
+ return this.getCurrentRecipes().filter(recipe => {
33
+ if (filter.category && recipe.category !== filter.category) {
34
+ return false;
35
+ }
36
+ if (filter.tags && filter.tags.length > 0) {
37
+ const hasMatchingTag = filter.tags.some(tag => recipe.tags.includes(tag));
38
+ if (!hasMatchingTag) {
39
+ return false;
40
+ }
41
+ }
42
+ if (filter.maxPrepTime && recipe.prepTime > filter.maxPrepTime) {
43
+ return false;
44
+ }
45
+ if (filter.maxCookTime && recipe.cookTime > filter.maxCookTime) {
46
+ return false;
47
+ }
48
+ if (filter.difficulty && recipe.difficulty !== filter.difficulty) {
49
+ return false;
50
+ }
51
+ if (filter.maxCalories && recipe.nutrition.calories > filter.maxCalories) {
52
+ return false;
53
+ }
54
+ if (filter.minProtein && recipe.nutrition.protein < filter.minProtein) {
55
+ return false;
56
+ }
57
+ return true;
58
+ });
59
+ }
60
+ getRecipesByTags(tags) {
61
+ return this.filterRecipes({ tags });
62
+ }
63
+ getRecipesForHealthGoals(healthGoals) {
64
+ const relevantTags = healthGoals.map(goal => {
65
+ switch (goal) {
66
+ case 'weight_loss':
67
+ return ['low-carb', 'high-protein', 'low-fat'];
68
+ case 'muscle_gain':
69
+ return ['high-protein'];
70
+ case 'heart_health':
71
+ return ['heart-healthy', 'omega-3', 'cholesterol'];
72
+ case 'diabetes':
73
+ return ['diabetes', 'low-carb'];
74
+ case 'cholesterol':
75
+ return ['cholesterol', 'heart-healthy'];
76
+ case 'fatty_liver':
77
+ return ['fatty_liver', 'low-fat'];
78
+ case 'triglycerides':
79
+ return ['triglycerides', 'omega-3'];
80
+ default:
81
+ return [];
82
+ }
83
+ }).flat();
84
+ return this.filterRecipes({ tags: relevantTags });
85
+ }
86
+ getRecipesForDietaryRestrictions(restrictions) {
87
+ return this.getCurrentRecipes().filter(recipe => {
88
+ if (restrictions.includes('vegetarian')) {
89
+ return recipe.tags.includes('vegetarian') || recipe.tags.includes('vegan');
90
+ }
91
+ if (restrictions.includes('vegan')) {
92
+ return recipe.tags.includes('vegan');
93
+ }
94
+ if (restrictions.includes('gluten-free')) {
95
+ return recipe.tags.includes('gluten-free');
96
+ }
97
+ return true;
98
+ });
99
+ }
100
+ getRandomRecipe(category) {
101
+ const filteredRecipes = category
102
+ ? this.getRecipesByCategory(category)
103
+ : this.getCurrentRecipes();
104
+ const randomIndex = Math.floor(Math.random() * filteredRecipes.length);
105
+ return filteredRecipes[randomIndex];
106
+ }
107
+ getWeeklyRecipeSuggestions(healthGoals, dietaryRestrictions) {
108
+ let availableRecipes = this.getCurrentRecipes();
109
+ if (dietaryRestrictions.length > 0) {
110
+ availableRecipes = this.getRecipesForDietaryRestrictions(dietaryRestrictions);
111
+ }
112
+ if (healthGoals.length > 0) {
113
+ const healthRecipes = this.getRecipesForHealthGoals(healthGoals);
114
+ availableRecipes = availableRecipes.filter(recipe => healthRecipes.some(hr => hr.id === recipe.id));
115
+ }
116
+ const breakfast = availableRecipes.filter(r => r.category === 'breakfast').slice(0, 7);
117
+ const lunch = availableRecipes.filter(r => r.category === 'lunch').slice(0, 7);
118
+ const dinner = availableRecipes.filter(r => r.category === 'dinner').slice(0, 7);
119
+ const snack = availableRecipes.filter(r => r.category === 'snack').slice(0, 7);
120
+ return { breakfast, lunch, dinner, snack };
121
+ }
122
+ searchRecipes(query) {
123
+ const lowerQuery = query.toLowerCase();
124
+ return this.getCurrentRecipes().filter(recipe => recipe.name.toLowerCase().includes(lowerQuery) ||
125
+ recipe.ingredients.some(ing => ing.name.toLowerCase().includes(lowerQuery)) ||
126
+ recipe.tags.some(tag => tag.toLowerCase().includes(lowerQuery)));
127
+ }
128
+ getTotalTime(recipe) {
129
+ return recipe.prepTime + recipe.cookTime;
130
+ }
131
+ getRecipesByTotalTime(maxMinutes) {
132
+ return this.recipes.filter(recipe => this.getTotalTime(recipe) <= maxMinutes);
133
+ }
134
+ }
135
+ exports.RecipeService = RecipeService;
136
+ exports.recipeService = new RecipeService();
@@ -0,0 +1,2 @@
1
+ import { Recipe } from '../types';
2
+ export declare function filterCholesterol(recipes: Recipe[]): Recipe[];
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.filterCholesterol = void 0;
4
+ function filterCholesterol(recipes) {
5
+ return recipes.filter(r => r.tags.includes('cholesterol'));
6
+ }
7
+ exports.filterCholesterol = filterCholesterol;
@@ -0,0 +1,2 @@
1
+ import { Recipe } from '../types';
2
+ export declare function filterDiabetes(recipes: Recipe[]): Recipe[];
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.filterDiabetes = void 0;
4
+ function filterDiabetes(recipes) {
5
+ return recipes.filter(r => r.tags.includes('diabetes'));
6
+ }
7
+ exports.filterDiabetes = filterDiabetes;
@@ -0,0 +1,2 @@
1
+ import { Recipe } from '../types';
2
+ export declare function filterFattyLiver(recipes: Recipe[]): Recipe[];
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.filterFattyLiver = void 0;
4
+ function filterFattyLiver(recipes) {
5
+ return recipes.filter(r => r.tags.includes('fatty_liver'));
6
+ }
7
+ exports.filterFattyLiver = filterFattyLiver;
@@ -0,0 +1,7 @@
1
+ import { Recipe, HealthCondition } from '../types';
2
+ export declare function applyHealthRules(recipes: Recipe[], conditions: HealthCondition[]): Recipe[];
3
+ export * from './cholesterol';
4
+ export * from './triglycerides';
5
+ export * from './fattyLiver';
6
+ export * from './diabetes';
7
+ export * from './lowCarb';
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.applyHealthRules = void 0;
18
+ const cholesterol_1 = require("./cholesterol");
19
+ const triglycerides_1 = require("./triglycerides");
20
+ const fattyLiver_1 = require("./fattyLiver");
21
+ const diabetes_1 = require("./diabetes");
22
+ const lowCarb_1 = require("./lowCarb");
23
+ function applyHealthRules(recipes, conditions) {
24
+ let result = recipes;
25
+ if (conditions.includes('cholesterol')) {
26
+ result = (0, cholesterol_1.filterCholesterol)(result);
27
+ }
28
+ if (conditions.includes('triglycerides')) {
29
+ result = (0, triglycerides_1.filterTriglycerides)(result);
30
+ }
31
+ if (conditions.includes('fatty_liver')) {
32
+ result = (0, fattyLiver_1.filterFattyLiver)(result);
33
+ }
34
+ if (conditions.includes('diabetes')) {
35
+ result = (0, diabetes_1.filterDiabetes)(result);
36
+ }
37
+ if (conditions.includes('low_carb')) {
38
+ result = (0, lowCarb_1.filterLowCarb)(result);
39
+ }
40
+ return result;
41
+ }
42
+ exports.applyHealthRules = applyHealthRules;
43
+ __exportStar(require("./cholesterol"), exports);
44
+ __exportStar(require("./triglycerides"), exports);
45
+ __exportStar(require("./fattyLiver"), exports);
46
+ __exportStar(require("./diabetes"), exports);
47
+ __exportStar(require("./lowCarb"), exports);
@@ -0,0 +1,2 @@
1
+ import { Recipe } from '../types';
2
+ export declare function filterLowCarb(recipes: Recipe[]): Recipe[];
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.filterLowCarb = void 0;
4
+ function filterLowCarb(recipes) {
5
+ return recipes.filter(r => r.tags.includes('low_carb'));
6
+ }
7
+ exports.filterLowCarb = filterLowCarb;
@@ -0,0 +1,2 @@
1
+ import { Recipe } from '../types';
2
+ export declare function filterTriglycerides(recipes: Recipe[]): Recipe[];
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.filterTriglycerides = void 0;
4
+ function filterTriglycerides(recipes) {
5
+ return recipes.filter(r => r.tags.includes('triglycerides'));
6
+ }
7
+ exports.filterTriglycerides = filterTriglycerides;
@@ -0,0 +1,3 @@
1
+ import { UserProfile } from './types';
2
+ export declare function calculateBMR(profile: UserProfile): number;
3
+ export declare function calculateTDEE(profile: UserProfile): number;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateBMR = calculateBMR;
4
+ exports.calculateTDEE = calculateTDEE;
5
+ function calculateBMR(profile) {
6
+ const { weightKg, heightCm, age, gender } = profile;
7
+ return gender === 'male'
8
+ ? 10 * weightKg + 6.25 * heightCm - 5 * age + 5
9
+ : 10 * weightKg + 6.25 * heightCm - 5 * age - 161;
10
+ }
11
+ function calculateTDEE(profile) {
12
+ return calculateBMR(profile) * profile.activityLevel;
13
+ }
@@ -0,0 +1,3 @@
1
+ import { UserProfile } from './types/firestore';
2
+ import { MealPlan } from './types/firestore';
3
+ export declare function generateDailyMealPlan(profile: UserProfile, userId: string): MealPlan;
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateDailyMealPlan = generateDailyMealPlan;
4
+ const foodConversion_1 = require("./foodConversion");
5
+ // Mock food data - in a real app, this would come from Open Food Facts search
6
+ const mockFoods = {
7
+ // Breakfast foods
8
+ oatmeal: {
9
+ id: 'oatmeal',
10
+ name: 'Oatmeal',
11
+ brand: 'Generic',
12
+ nutritionPer100g: { calories: 379, protein: 13.2, carbs: 66.3, fat: 6.9 },
13
+ servingSize: 40,
14
+ unit: 'g'
15
+ },
16
+ banana: {
17
+ id: 'banana',
18
+ name: 'Banana',
19
+ brand: 'Generic',
20
+ nutritionPer100g: { calories: 89, protein: 1.1, carbs: 22.8, fat: 0.3 },
21
+ servingSize: 118,
22
+ unit: 'g'
23
+ },
24
+ milk: {
25
+ id: 'milk',
26
+ name: 'Whole Milk',
27
+ brand: 'Generic',
28
+ nutritionPer100g: { calories: 61, protein: 3.2, carbs: 4.8, fat: 3.3 },
29
+ servingSize: 244,
30
+ unit: 'ml'
31
+ },
32
+ // Lunch/Dinner proteins
33
+ chicken: {
34
+ id: 'chicken',
35
+ name: 'Chicken Breast',
36
+ brand: 'Generic',
37
+ nutritionPer100g: { calories: 165, protein: 31, carbs: 0, fat: 3.6 },
38
+ servingSize: 100,
39
+ unit: 'g'
40
+ },
41
+ salmon: {
42
+ id: 'salmon',
43
+ name: 'Salmon',
44
+ brand: 'Generic',
45
+ nutritionPer100g: { calories: 206, protein: 22, carbs: 0, fat: 13 },
46
+ servingSize: 100,
47
+ unit: 'g'
48
+ },
49
+ // Carbs
50
+ rice: {
51
+ id: 'rice',
52
+ name: 'White Rice',
53
+ brand: 'Generic',
54
+ nutritionPer100g: { calories: 130, protein: 2.7, carbs: 28, fat: 0.3 },
55
+ servingSize: 185,
56
+ unit: 'g'
57
+ },
58
+ bread: {
59
+ id: 'bread',
60
+ name: 'Whole Wheat Bread',
61
+ brand: 'Generic',
62
+ nutritionPer100g: { calories: 247, protein: 13, carbs: 41, fat: 3.5 },
63
+ servingSize: 45,
64
+ unit: 'g'
65
+ },
66
+ // Veggies
67
+ broccoli: {
68
+ id: 'broccoli',
69
+ name: 'Broccoli',
70
+ brand: 'Generic',
71
+ nutritionPer100g: { calories: 34, protein: 2.8, carbs: 7, fat: 0.4 },
72
+ servingSize: 91,
73
+ unit: 'g'
74
+ },
75
+ spinach: {
76
+ id: 'spinach',
77
+ name: 'Spinach',
78
+ brand: 'Generic',
79
+ nutritionPer100g: { calories: 23, protein: 2.9, carbs: 3.6, fat: 0.4 },
80
+ servingSize: 30,
81
+ unit: 'g'
82
+ },
83
+ // Snacks
84
+ apple: {
85
+ id: 'apple',
86
+ name: 'Apple',
87
+ brand: 'Generic',
88
+ nutritionPer100g: { calories: 52, protein: 0.3, carbs: 13.8, fat: 0.2 },
89
+ servingSize: 182,
90
+ unit: 'g'
91
+ },
92
+ almonds: {
93
+ id: 'almonds',
94
+ name: 'Almonds',
95
+ brand: 'Generic',
96
+ nutritionPer100g: { calories: 579, protein: 21.2, carbs: 21.6, fat: 49.9 },
97
+ servingSize: 28,
98
+ unit: 'g'
99
+ }
100
+ };
101
+ function calculateDailyNeeds(profile) {
102
+ // Provide defaults for missing profile data
103
+ const age = profile.age || 30;
104
+ const height = profile.height || 170; // cm
105
+ const weight = profile.weight || 70; // kg
106
+ const gender = profile.gender || 'male';
107
+ const activityLevel = profile.activityLevel || 'moderately_active';
108
+ // Basic BMR calculation (simplified)
109
+ const bmr = gender === 'male'
110
+ ? 88.362 + (13.397 * weight) + (4.799 * height) - (5.677 * age)
111
+ : 447.593 + (9.247 * weight) + (3.098 * height) - (4.330 * age);
112
+ // Activity multiplier
113
+ const activityMultipliers = {
114
+ sedentary: 1.2,
115
+ lightly_active: 1.375,
116
+ moderately_active: 1.55,
117
+ very_active: 1.725,
118
+ extremely_active: 1.9
119
+ };
120
+ const tdee = bmr * (activityMultipliers[activityLevel] || 1.2);
121
+ // Adjust based on goals
122
+ let dailyCalories = tdee;
123
+ if (profile.healthGoals?.includes('weight_loss')) {
124
+ dailyCalories -= 500;
125
+ }
126
+ else if (profile.healthGoals?.includes('weight_gain')) {
127
+ dailyCalories += 500;
128
+ }
129
+ return {
130
+ calories: Math.round(Math.max(dailyCalories, 1200)), // Minimum 1200 calories
131
+ protein: Math.round(Math.max(dailyCalories * 0.3 / 4, 50)), // Minimum 50g protein
132
+ carbs: Math.round(Math.max(dailyCalories * 0.4 / 4, 100)), // Minimum 100g carbs
133
+ fat: Math.round(Math.max(dailyCalories * 0.3 / 9, 30)) // Minimum 30g fat
134
+ };
135
+ }
136
+ function createMeal(name, type, foods) {
137
+ const ingredients = foods.map(({ food, amount, unit }) => (0, foodConversion_1.convertFoodItemToIngredient)(food, amount, unit));
138
+ const meal = (0, foodConversion_1.createMealFromFoodItems)(name, type, foods.map(({ food, amount, unit }, index) => ({
139
+ food: food,
140
+ amount,
141
+ unit
142
+ })));
143
+ return {
144
+ ...meal,
145
+ instructions: [`Prepare ${name} according to recipe`],
146
+ };
147
+ }
148
+ function generateDailyMealPlan(profile, userId) {
149
+ const needs = calculateDailyNeeds(profile);
150
+ // Check dietary restrictions
151
+ const isVegetarian = profile.dietaryRestrictions?.includes('vegetarian');
152
+ const isVegan = profile.dietaryRestrictions?.includes('vegan');
153
+ // Breakfast: Oatmeal with fruit
154
+ const breakfast = createMeal('Healthy Oatmeal Breakfast', 'breakfast', [
155
+ { food: mockFoods.oatmeal, amount: 50, unit: 'g' },
156
+ { food: mockFoods.banana, amount: 100, unit: 'g' },
157
+ { food: mockFoods.milk, amount: 200, unit: 'ml' }
158
+ ]);
159
+ // Lunch: Chicken salad (or vegetarian alternative)
160
+ const lunchProtein = isVegan ? mockFoods.broccoli : (isVegetarian ? mockFoods.broccoli : mockFoods.chicken);
161
+ const lunch = createMeal('Nutritious Lunch Salad', 'lunch', [
162
+ { food: lunchProtein, amount: lunchProtein === mockFoods.chicken ? 150 : 200, unit: 'g' },
163
+ { food: mockFoods.spinach, amount: 100, unit: 'g' },
164
+ { food: mockFoods.broccoli, amount: 150, unit: 'g' },
165
+ { food: mockFoods.bread, amount: 90, unit: 'g' }
166
+ ]);
167
+ // Dinner: Salmon with rice and veggies (or vegetarian alternative)
168
+ const dinnerProtein = isVegan ? mockFoods.broccoli : (isVegetarian ? mockFoods.broccoli : mockFoods.salmon);
169
+ const dinner = createMeal('Balanced Dinner', 'dinner', [
170
+ { food: dinnerProtein, amount: dinnerProtein === mockFoods.salmon ? 150 : 200, unit: 'g' },
171
+ { food: mockFoods.rice, amount: 150, unit: 'g' },
172
+ { food: mockFoods.broccoli, amount: 100, unit: 'g' }
173
+ ]);
174
+ // Snack: Apple and almonds
175
+ const snack = createMeal('Healthy Snack', 'snack', [
176
+ { food: mockFoods.apple, amount: 150, unit: 'g' },
177
+ { food: mockFoods.almonds, amount: 20, unit: 'g' }
178
+ ]);
179
+ const meals = [breakfast, lunch, dinner, snack];
180
+ const totalNutrition = meals.reduce((total, meal) => ({
181
+ calories: total.calories + (meal.nutrition?.calories || 0),
182
+ protein: Math.round((total.protein + (meal.nutrition?.protein || 0)) * 10) / 10,
183
+ carbs: total.carbs + (meal.nutrition?.carbs || 0),
184
+ fat: total.fat + (meal.nutrition?.fat || 0)
185
+ }), { calories: 0, protein: 0, carbs: 0, fat: 0 });
186
+ const today = new Date();
187
+ return {
188
+ id: `daily-plan-${Date.now()}`,
189
+ userId: userId,
190
+ name: `Daily Meal Plan - ${today.toLocaleDateString()}`,
191
+ description: `Personalized daily meal plan based on your profile (${Math.round(totalNutrition.calories)} cal)`,
192
+ startDate: today.toISOString().split('T')[0],
193
+ endDate: today.toISOString().split('T')[0],
194
+ dailyPlans: [],
195
+ meals,
196
+ totalCalories: totalNutrition.calories,
197
+ totalProtein: totalNutrition.protein,
198
+ totalCarbs: totalNutrition.carbs,
199
+ totalFat: totalNutrition.fat,
200
+ uid: userId,
201
+ goals: {
202
+ dailyCalories: Math.round(totalNutrition.calories),
203
+ proteinPercentage: 25,
204
+ carbsPercentage: 45,
205
+ fatPercentage: 30,
206
+ },
207
+ createdAt: new Date(),
208
+ updatedAt: new Date()
209
+ };
210
+ }
@@ -0,0 +1,55 @@
1
+ import { NormalizedFoodItem } from './types/openfoodfacts';
2
+ import { Meal, Ingredient } from './types/firestore';
3
+ export interface ExtendedIngredient extends Ingredient {
4
+ barcode?: string;
5
+ brand?: string;
6
+ nutritionGrade?: string;
7
+ ecoScore?: string;
8
+ allergens?: string[];
9
+ }
10
+ /**
11
+ * Convert Open Food Facts item to Ingredient for meal planning
12
+ */
13
+ export declare function convertFoodItemToIngredient(foodItem: NormalizedFoodItem, amount?: number, unit?: string): Ingredient;
14
+ /**
15
+ * Calculate total nutrition for a list of ingredients
16
+ */
17
+ export declare function calculateTotalNutrition(ingredients: Ingredient[]): {
18
+ calories: number;
19
+ protein: number;
20
+ carbs: number;
21
+ fat: number;
22
+ fiber: number;
23
+ sugar: number;
24
+ sodium: number;
25
+ };
26
+ /**
27
+ * Create a meal from selected food items
28
+ */
29
+ export declare function createMealFromFoodItems(name: string, type: 'breakfast' | 'lunch' | 'dinner' | 'snack', foodItems: Array<{
30
+ food: NormalizedFoodItem;
31
+ amount: number;
32
+ unit: string;
33
+ }>): Meal;
34
+ /**
35
+ * Get nutrition density score (protein per calorie ratio)
36
+ */
37
+ export declare function getNutritionDensityScore(foodItem: NormalizedFoodItem): number;
38
+ /**
39
+ * Check if food item meets dietary restrictions
40
+ */
41
+ export declare function checkDietaryRestrictions(foodItem: NormalizedFoodItem, restrictions: string[]): {
42
+ meets: boolean;
43
+ violations: string[];
44
+ };
45
+ /**
46
+ * Get recommended serving size based on meal type and nutrition goals
47
+ */
48
+ export declare function getRecommendedServingSize(foodItem: NormalizedFoodItem, mealType: 'breakfast' | 'lunch' | 'dinner' | 'snack', targetCalories?: number): {
49
+ amount: number;
50
+ unit: string;
51
+ };
52
+ /**
53
+ * Filter foods by health goals
54
+ */
55
+ export declare function filterFoodsByHealthGoals(foods: NormalizedFoodItem[], healthGoals: string[]): NormalizedFoodItem[];