Hozifa Elgharbawy commited on
Commit
bb3dc70
·
1 Parent(s): adcab3a
src/common/enums/meal-type.enum.ts CHANGED
@@ -3,7 +3,5 @@ export enum MealType {
3
  DINNER = "dinner",
4
  SNACKS = "snacks",
5
  DRINKS_BEVERAGES = 'drinks beverages',
6
- CUSINES = 'cusines',
7
  LUNCH = "lunch",
8
- BREAKFAST_DINNER= "breakfast, dinner"
9
  }
 
3
  DINNER = "dinner",
4
  SNACKS = "snacks",
5
  DRINKS_BEVERAGES = 'drinks beverages',
 
6
  LUNCH = "lunch",
 
7
  }
src/common/serializers/meal-plan.serialization.ts CHANGED
@@ -15,8 +15,8 @@ class MealPlanDays {
15
 
16
  class MealPlanKeyFeatures {
17
  @Expose()
18
- @SwaggerResponseProperty({ type: "number" })
19
- day_number: number;
20
 
21
  @Expose({ name: "description" })
22
  @SwaggerResponseProperty({ type: "string" })
 
15
 
16
  class MealPlanKeyFeatures {
17
  @Expose()
18
+ @SwaggerResponseProperty({ type: "string" })
19
+ title: string;
20
 
21
  @Expose({ name: "description" })
22
  @SwaggerResponseProperty({ type: "string" })
src/common/serializers/meal-planPopulate.serialization.ts CHANGED
@@ -16,8 +16,8 @@ class MealPlanDaysPopulate {
16
 
17
  class MealPlanKeyFeaturesPopulate {
18
  @Expose()
19
- @SwaggerResponseProperty({ type: "number" })
20
- day_number: number;
21
 
22
  @Expose({ name: "description" })
23
  @SwaggerResponseProperty({ type: "string" })
@@ -63,4 +63,38 @@ export class MealPlanPopulateSerialization {
63
  )
64
  days: any;
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
 
16
 
17
  class MealPlanKeyFeaturesPopulate {
18
  @Expose()
19
+ @SwaggerResponseProperty({ type: "string" })
20
+ title: string;
21
 
22
  @Expose({ name: "description" })
23
  @SwaggerResponseProperty({ type: "string" })
 
63
  )
64
  days: any;
65
 
66
+ }
67
+
68
+ export class ListMealPlanSerialization {
69
+ @Expose({ name: "_id" })
70
+ @SwaggerResponseProperty({ type: "string" })
71
+ id: string;
72
+
73
+ @Expose()
74
+ @SwaggerResponseProperty({ type: "string" })
75
+ image: string;
76
+
77
+ @Expose()
78
+ @SwaggerResponseProperty({ type: "string" })
79
+ description: string;
80
+
81
+ @Expose()
82
+ @SwaggerResponseProperty({ type: "string" })
83
+ duration: string;
84
+
85
+ @Expose()
86
+ @SwaggerResponseProperty({ type: "string" })
87
+ level: string;
88
+
89
+ @Expose()
90
+ @SwaggerResponseProperty({ type: "string" })
91
+ your_journey: string;
92
+
93
+ @Expose({ name: "key_features" })
94
+ @SwaggerResponseProperty({ type: [MealPlanKeyFeaturesPopulate] })
95
+ @Transform(
96
+ ({ value }) => serialize(value, MealPlanKeyFeaturesPopulate)
97
+ )
98
+ key_features: any;
99
+
100
  }
src/common/serializers/user-registered-meal-planPopulate.serialization.ts CHANGED
@@ -1,6 +1,7 @@
1
  import { Expose, Transform } from "class-transformer";
2
  import { serialize } from "@helpers/serialize";
3
  import { SwaggerResponseProperty } from "@lib/decorators/swagger-response-property.decorator";
 
4
  import { MealSerialization } from "./meal.serialization";
5
  import { MealPlanSerialization } from "./meal-plan.serialization";
6
 
@@ -13,6 +14,9 @@ class MealDaysPopulate {
13
 
14
  @Expose({ name: "meals" })
15
  @SwaggerResponseProperty({ type: [MealSerialization] })
 
 
 
16
  meals: any;
17
 
18
  @Expose()
@@ -32,6 +36,35 @@ export class UserRegisteredMealPlansPopulateSerialization {
32
 
33
  @Expose()
34
  @SwaggerResponseProperty({ type: MealPlanSerialization })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  meal_plan: string;
36
 
37
  @Expose()
 
1
  import { Expose, Transform } from "class-transformer";
2
  import { serialize } from "@helpers/serialize";
3
  import { SwaggerResponseProperty } from "@lib/decorators/swagger-response-property.decorator";
4
+ import { ListMealPlanSerialization } from "./meal-planPopulate.serialization";
5
  import { MealSerialization } from "./meal.serialization";
6
  import { MealPlanSerialization } from "./meal-plan.serialization";
7
 
 
14
 
15
  @Expose({ name: "meals" })
16
  @SwaggerResponseProperty({ type: [MealSerialization] })
17
+ @Transform(
18
+ ({ value }) => serialize(value, MealSerialization)
19
+ )
20
  meals: any;
21
 
22
  @Expose()
 
36
 
37
  @Expose()
38
  @SwaggerResponseProperty({ type: MealPlanSerialization })
39
+ @Transform(
40
+ ({ value }) => serialize(value, MealPlanSerialization)
41
+ )
42
+ meal_plan: string;
43
+
44
+ @Expose()
45
+ @SwaggerResponseProperty({ type: "boolean" })
46
+ isActive: boolean;
47
+
48
+ @Expose({ name: "days" })
49
+ @SwaggerResponseProperty({ type: [MealDaysPopulate] })
50
+ @Transform(
51
+ ({ value }) => serialize(value, MealDaysPopulate)
52
+ )
53
+ days: any;
54
+
55
+ }
56
+
57
+ export class GetMyMealPlanSerialization {
58
+ @Expose({ name: "_id" })
59
+ @SwaggerResponseProperty({ type: "string" })
60
+ id: string;
61
+
62
+ @Expose()
63
+ @SwaggerResponseProperty({ type: "string" })
64
+ user: string;
65
+
66
+ @Expose()
67
+ @SwaggerResponseProperty({ type: ListMealPlanSerialization })
68
  meal_plan: string;
69
 
70
  @Expose()
src/modules/users/modules/home/controllers/home-nutriguide.controller.ts CHANGED
@@ -6,26 +6,97 @@ import { Controller } from "@lib/decorators/controller.decorator";
6
  import { serialize } from "@helpers/serialize";
7
  import { ControllerMiddleware } from "@lib/decorators/controller-middleware.decorator";
8
  import { UsersGuardMiddleware } from "modules/users/common/guards/users.guard";
9
- import { SwaggerGet } from "@lib/decorators/swagger-routes.decorator";
10
  import { SwaggerSummary } from "@lib/decorators/swagger-summary.decorator";
11
  import { SwaggerDescription } from "@lib/decorators/swagger-description.decorator";
12
  import { SwaggerResponse } from "@lib/decorators/swagger-response.decorator";
 
13
  import { UserHomeService } from "../services/user-home.service";
14
  import { IUserRequest } from "@common/interfaces/user-request.interface";
15
  import { UserHomeYourDailyIntakeSerialization } from "../responses/user-home-your-daily-intake.serialization";
16
  import { UserNutriHomeDailyGoalsSerialization } from "../responses/user-nutri-home-daily-goals.serialization";
 
 
 
17
 
18
 
19
  @Controller("/user/nutri-guide")
20
  @ControllerMiddleware(UsersGuardMiddleware())
21
  export class homeNutriGuideController extends BaseController {
22
  private userHomeService = new UserHomeService();
 
23
 
24
  setRoutes(): void {
25
  this.router.get("/todays-intake", asyncHandler(this.getHomePageYourDailyIntake));
26
  this.router.get("/daily-goals", asyncHandler(this.getHomePageDailyGoals));
 
 
 
 
 
27
  }
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  @SwaggerGet('/todays-intake')
31
  @SwaggerResponse(UserHomeYourDailyIntakeSerialization)
 
6
  import { serialize } from "@helpers/serialize";
7
  import { ControllerMiddleware } from "@lib/decorators/controller-middleware.decorator";
8
  import { UsersGuardMiddleware } from "modules/users/common/guards/users.guard";
9
+ import { SwaggerGet, SwaggerPatch } from "@lib/decorators/swagger-routes.decorator";
10
  import { SwaggerSummary } from "@lib/decorators/swagger-summary.decorator";
11
  import { SwaggerDescription } from "@lib/decorators/swagger-description.decorator";
12
  import { SwaggerResponse } from "@lib/decorators/swagger-response.decorator";
13
+ import { SwaggerQuery } from "@lib/decorators/swagger-query.decorator";
14
  import { UserHomeService } from "../services/user-home.service";
15
  import { IUserRequest } from "@common/interfaces/user-request.interface";
16
  import { UserHomeYourDailyIntakeSerialization } from "../responses/user-home-your-daily-intake.serialization";
17
  import { UserNutriHomeDailyGoalsSerialization } from "../responses/user-nutri-home-daily-goals.serialization";
18
+ import { UserRegisteredMealPlansPopulateSerialization } from "@common/serializers/user-registered-meal-planPopulate.serialization";
19
+ import { UserRegisteredMealPlansService } from "../../user-registered-meal-plans/services/user-registered-meal-plans.service";
20
+ import { SwaggerRequest } from "@lib/decorators/swagger-request.decorator";
21
 
22
 
23
  @Controller("/user/nutri-guide")
24
  @ControllerMiddleware(UsersGuardMiddleware())
25
  export class homeNutriGuideController extends BaseController {
26
  private userHomeService = new UserHomeService();
27
+ private userRegisteredMealPlansService = new UserRegisteredMealPlansService();
28
 
29
  setRoutes(): void {
30
  this.router.get("/todays-intake", asyncHandler(this.getHomePageYourDailyIntake));
31
  this.router.get("/daily-goals", asyncHandler(this.getHomePageDailyGoals));
32
+ this.router.get("/today-meals", asyncHandler(this.getTodayMeals));
33
+ this.router.patch(
34
+ "/:id/progress/:day",
35
+ asyncHandler(this.updateProgress)
36
+ );
37
  }
38
 
39
+ @SwaggerGet("/today-meals")
40
+ @SwaggerResponse(UserRegisteredMealPlansPopulateSerialization)
41
+ @SwaggerSummary("Get today's meals")
42
+ @SwaggerDescription("Get today's meals for the user.")
43
+ getTodayMeals = async (req: IUserRequest, res: Response): Promise<Response> => {
44
+ try {
45
+ const data = await this.userRegisteredMealPlansService.findOneOrFail(
46
+ {
47
+ user: req.jwtPayload.id, isActive: true},
48
+ {
49
+ populateArray: [
50
+ { path: "meal_plan", select: "-days" },
51
+ { path: "days.meals" }
52
+ ],
53
+ }
54
+ );
55
+ console.log(data);
56
+
57
+
58
+ const dayToEat = data.days.find(day => day.is_eaten === false);
59
+
60
+ if (dayToEat) {
61
+ data.days = [dayToEat];
62
+ return JsonResponse.success(
63
+ {
64
+ data: serialize(data, UserRegisteredMealPlansPopulateSerialization),
65
+ },
66
+ res
67
+ );
68
+ } else {
69
+ return JsonResponse.success(
70
+ {
71
+ message: "All planned meals have been eaten.",
72
+ },
73
+ res
74
+ );
75
+ }
76
+ } catch (error) {
77
+ console.error(error);
78
+ return res.status(500).json({ error: "An error occurred." });
79
+ }
80
+ };
81
+
82
+ @SwaggerPatch('/:id/progress/:day')
83
+ @SwaggerResponse({})
84
+ @SwaggerSummary("Update MyMealPlan Progress")
85
+ @SwaggerDescription("Update the progress of a MyMealPlan")
86
+ updateProgress = async (req: IUserRequest, res: Response) => {
87
+ const urwId: string = req.params.id;
88
+ const dayNumber: number = Number(req.params.day);
89
+ await this.userRegisteredMealPlansService.updateForUser({
90
+ urwId, dayNumber
91
+ }, req.body, req.jwtPayload.id);
92
+ return JsonResponse.success(
93
+ {
94
+ message: "mealPlan updated successfully",
95
+ },
96
+ res
97
+ );
98
+ };
99
+
100
 
101
  @SwaggerGet('/todays-intake')
102
  @SwaggerResponse(UserHomeYourDailyIntakeSerialization)
src/modules/users/modules/meal-plans/controller/meal-plans.controller.ts CHANGED
@@ -1,5 +1,5 @@
1
  import { MealPlansService } from "../services/meal-plans.service";
2
- import { MealPlanPopulateSerialization } from "@common/serializers/meal-planPopulate.serialization";
3
  import { Request, Response } from "express";
4
  import { JsonResponse } from "@lib/responses/json-response";
5
  import { parsePaginationQuery } from "@helpers/pagination";
@@ -26,7 +26,7 @@ export class UsersMealPlansController extends BaseController {
26
  }
27
 
28
  @SwaggerGet()
29
- @SwaggerResponse([MealPlanPopulateSerialization])
30
  @SwaggerSummary("list meal plans")
31
  @SwaggerDescription("List all meal plans")
32
  @SwaggerQuery({
@@ -37,17 +37,12 @@ export class UsersMealPlansController extends BaseController {
37
  const paginationQuery = parsePaginationQuery(req.query);
38
  const { docs, paginationData } = await this.mealPlansService.list(
39
  {},
40
- paginationQuery,
41
- {
42
- populateArray: [
43
- { path: "days.meals" }
44
- ],
45
- }
46
  );
47
 
48
  return JsonResponse.success(
49
  {
50
- data: serialize(docs, MealPlanPopulateSerialization),
51
  meta: paginationData,
52
  },
53
  res
 
1
  import { MealPlansService } from "../services/meal-plans.service";
2
+ import { ListMealPlanSerialization } from "@common/serializers/meal-planPopulate.serialization";
3
  import { Request, Response } from "express";
4
  import { JsonResponse } from "@lib/responses/json-response";
5
  import { parsePaginationQuery } from "@helpers/pagination";
 
26
  }
27
 
28
  @SwaggerGet()
29
+ @SwaggerResponse([ListMealPlanSerialization])
30
  @SwaggerSummary("list meal plans")
31
  @SwaggerDescription("List all meal plans")
32
  @SwaggerQuery({
 
37
  const paginationQuery = parsePaginationQuery(req.query);
38
  const { docs, paginationData } = await this.mealPlansService.list(
39
  {},
40
+ paginationQuery
 
 
 
 
 
41
  );
42
 
43
  return JsonResponse.success(
44
  {
45
+ data: serialize(docs, ListMealPlanSerialization),
46
  meta: paginationData,
47
  },
48
  res
src/modules/users/modules/user-registered-meal-plans/controller/user-registered-meal-plans.controller.ts CHANGED
@@ -5,7 +5,7 @@ import { asyncHandler } from "@helpers/async-handler";
5
  import { BaseController } from "@lib/controllers/controller.base";
6
  import { Controller } from "@lib/decorators/controller.decorator";
7
  import { serialize } from "@helpers/serialize";
8
- import { UserRegisteredMealPlansPopulateSerialization } from "@common/serializers/user-registered-meal-planPopulate.serialization";
9
  import { ControllerMiddleware } from "@lib/decorators/controller-middleware.decorator";
10
  import { UsersGuardMiddleware } from "modules/users/common/guards/users.guard";
11
  import { SwaggerGet } from "@lib/decorators/swagger-routes.decorator";
@@ -26,22 +26,22 @@ export class UsersRegisteredMealPlansController extends BaseController {
26
  }
27
 
28
  @SwaggerGet()
29
- @SwaggerResponse(UserRegisteredMealPlansPopulateSerialization)
30
  @SwaggerSummary("get my meal plan")
31
  @SwaggerDescription("Get the meal plan that the user is currently using")
32
  get = async (req: userRequest, res: Response): Promise<Response> => {
33
  const data = await this.userRegisteredMealPlansService.findOneOrFail(
34
- { user: req.jwtPayload._id, isActive: true },
35
  {
36
  populateArray: [
37
- { path: "meal_plan" },
38
  { path: "days.meals"}
39
  ],
40
  });
41
 
42
  return JsonResponse.success(
43
  {
44
- data: serialize(data, UserRegisteredMealPlansPopulateSerialization),
45
  },
46
  res
47
  );
 
5
  import { BaseController } from "@lib/controllers/controller.base";
6
  import { Controller } from "@lib/decorators/controller.decorator";
7
  import { serialize } from "@helpers/serialize";
8
+ import { GetMyMealPlanSerialization } from "@common/serializers/user-registered-meal-planPopulate.serialization";
9
  import { ControllerMiddleware } from "@lib/decorators/controller-middleware.decorator";
10
  import { UsersGuardMiddleware } from "modules/users/common/guards/users.guard";
11
  import { SwaggerGet } from "@lib/decorators/swagger-routes.decorator";
 
26
  }
27
 
28
  @SwaggerGet()
29
+ @SwaggerResponse(GetMyMealPlanSerialization)
30
  @SwaggerSummary("get my meal plan")
31
  @SwaggerDescription("Get the meal plan that the user is currently using")
32
  get = async (req: userRequest, res: Response): Promise<Response> => {
33
  const data = await this.userRegisteredMealPlansService.findOneOrFail(
34
+ { user: req.jwtPayload.id, isActive: true },
35
  {
36
  populateArray: [
37
+ { path: "meal_plan", select: "-days"},
38
  { path: "days.meals"}
39
  ],
40
  });
41
 
42
  return JsonResponse.success(
43
  {
44
+ data: serialize(data, GetMyMealPlanSerialization),
45
  },
46
  res
47
  );
src/modules/users/modules/user-registered-meal-plans/services/user-registered-meal-plans.service.ts CHANGED
@@ -1,4 +1,29 @@
1
  import { UserRegisteredMealPlan } from "@common/models/user-registered-meal-plan.model";
2
  import { CrudService } from "@lib/services/crud.service";
 
 
3
 
4
- export class UserRegisteredMealPlansService extends CrudService(UserRegisteredMealPlan) {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import { UserRegisteredMealPlan } from "@common/models/user-registered-meal-plan.model";
2
  import { CrudService } from "@lib/services/crud.service";
3
+ import { IUpdateUserRegisteredMealPlan } from "../validations/update-user-registered-meal-plan.validation";
4
+ import { HttpError } from "@lib/error-handling/http-error";
5
 
6
+
7
+ export class UserRegisteredMealPlansService extends CrudService(UserRegisteredMealPlan) {
8
+ async updateForUser(mealPlanProps: {urwId: string; dayNumber: number}, data: any, userId: string) {
9
+ // find workout
10
+ const mealPlan = await this.findOneOrFail({
11
+ _id: mealPlanProps.urwId,
12
+ user: userId,
13
+ });
14
+
15
+
16
+ // find day
17
+ const day = mealPlan.days.find(d => d.day_number === mealPlanProps.dayNumber);
18
+ if(!day) throw new HttpError(404, 'Workout Day Not Found');
19
+ const dayIndex = mealPlan.days.indexOf(day)
20
+
21
+ // update day and week
22
+ day.is_eaten = true;
23
+ mealPlan.days[dayIndex] = day;
24
+
25
+ // save changes
26
+ mealPlan.markModified('days');
27
+ return mealPlan.save()
28
+ }
29
+ }
src/resources/meals.json CHANGED
The diff for this file is too large to render. See raw diff
 
src/resources/meals1.json ADDED
The diff for this file is too large to render. See raw diff
 
src/resources/meals2.json ADDED
The diff for this file is too large to render. See raw diff
 
src/seeder/seeders/10-mealPlan.seeder.ts CHANGED
@@ -6,7 +6,30 @@ import { FitnessLevel } from "@common/enums/fitness-level.enum";
6
  export default seederWrapper(MealPlan, async () => {
7
  // 10 mealPlans
8
  await Promise.all(Array.from({ length: 10 }, (_, i) => i).map(async function (i) {
9
- const meals = await Meal.find().limit(35).lean();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  let o = {
12
  image: `https://placehold.co/300x400`,
@@ -20,10 +43,15 @@ export default seederWrapper(MealPlan, async () => {
20
  ],
21
  days: Array.from({ length: 7 }, (_, i) => ({
22
  day_number: i + 1,
23
- meals: meals.slice(i * 5, i * 5 + 5),
 
 
 
 
 
24
  })),
25
  }
26
 
27
  await MealPlan.create(o);
28
- }))
29
- })
 
6
  export default seederWrapper(MealPlan, async () => {
7
  // 10 mealPlans
8
  await Promise.all(Array.from({ length: 10 }, (_, i) => i).map(async function (i) {
9
+ // Fetch all meals
10
+ const meals = await Meal.find().lean();
11
+
12
+ // Categorize meals by type
13
+ const categorizedMeals = {
14
+ 'breakfast': [],
15
+ 'dinner': [],
16
+ 'snacks': [],
17
+ 'lunch': [],
18
+ };
19
+
20
+
21
+ meals.forEach(meal => {
22
+ if (meal.type in categorizedMeals) {
23
+ categorizedMeals[meal.type].push(meal);
24
+ }
25
+ });
26
+
27
+ // Check if we have enough meals of each type
28
+ for (const type in categorizedMeals) {
29
+ if (categorizedMeals[type].length < 7) {
30
+ throw new Error(`Not enough meals of type ${type}`);
31
+ }
32
+ }
33
 
34
  let o = {
35
  image: `https://placehold.co/300x400`,
 
43
  ],
44
  days: Array.from({ length: 7 }, (_, i) => ({
45
  day_number: i + 1,
46
+ meals: [
47
+ categorizedMeals['breakfast'][i],
48
+ categorizedMeals['lunch'][i],
49
+ categorizedMeals['dinner'][i],
50
+ categorizedMeals['snacks'][i],
51
+ ],
52
  })),
53
  }
54
 
55
  await MealPlan.create(o);
56
+ }));
57
+ });