Skip to content

Commit

Permalink
upgrade dependencies and method
Browse files Browse the repository at this point in the history
  • Loading branch information
FACorreiaa committed Jan 25, 2025
1 parent 9011645 commit c1050df
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 73 deletions.
1 change: 0 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ func InitConfig() (Config, error) {
if err != nil {
fmt.Printf("Warning: Failed to find file-based config: %s. Falling back to embedded config.\n", err)

// Fallback to embedded config
if err = v.ReadConfig(bytes.NewReader(embeddedConfig)); err != nil {
return Config{}, fmt.Errorf("failed to read embedded config: %s", err)
}
Expand Down
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/FACorreiaa/fitme-grpc
go 1.23.5

require (
github.com/FACorreiaa/fitme-protos v0.0.0-20250119183157-03cd1940aa6a
github.com/FACorreiaa/fitme-protos v0.0.0-20250125155034-0a10eaeedd91
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/google/uuid v1.6.0
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
Expand All @@ -25,8 +25,8 @@ require (
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.32.0
golang.org/x/time v0.9.0
google.golang.org/grpc v1.69.4
google.golang.org/protobuf v1.36.3
google.golang.org/grpc v1.70.0
google.golang.org/protobuf v1.36.4
)

require (
Expand All @@ -38,7 +38,7 @@ require (
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
Expand Down Expand Up @@ -68,8 +68,8 @@ require (
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/text v0.21.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250124145028-65684f501c47 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
24 changes: 12 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/FACorreiaa/fitme-protos v0.0.0-20250119183157-03cd1940aa6a h1:3xhxiorbsS3XrxnyJsj8cJF7HMVh2+DlvWpS473VMag=
github.com/FACorreiaa/fitme-protos v0.0.0-20250119183157-03cd1940aa6a/go.mod h1:qnRoGd2MO/82ZpUO0nhSlIEYR7BTNxneHpXFTIxgx30=
github.com/FACorreiaa/fitme-protos v0.0.0-20250125155034-0a10eaeedd91 h1:0ePUdX65hLMgYqg8LKWf9fxYAmwaGCw/Cl7wScxoBU0=
github.com/FACorreiaa/fitme-protos v0.0.0-20250125155034-0a10eaeedd91/go.mod h1:P9kbr7QqDwk6WTwnFndC+uGnhcbS0GMMqH7aOB20U8w=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
Expand Down Expand Up @@ -60,8 +60,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpS
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.2.0 h1:kQ0NI7W1B3HwiN5gAYtY+XFItDPbLBwYRxAqbFTyDes=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.2.0/go.mod h1:zrT2dxOAjNFPRGjTUe2Xmb4q4YdUwVvQFV6xiCSf+z0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 h1:VD1gqscl4nYs1YxVuSdemTrSgTKrwOWDK0FVFMqm+Cg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0/go.mod h1:4EgsQoS4TOhJizV+JTFg40qx1Ofh3XmXEQNBpgvNT40=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
Expand Down Expand Up @@ -241,19 +241,19 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA=
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
google.golang.org/genproto/googleapis/api v0.0.0-20250124145028-65684f501c47 h1:5iw9XJTD4thFidQmFVvx0wi4g5yOHk76rNRUxz1ZG5g=
google.golang.org/genproto/googleapis/api v0.0.0-20250124145028-65684f501c47/go.mod h1:AfA77qWLcidQWywD0YgqfpJzf50w2VjzBml3TybHeJU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47 h1:91mG8dNTpkC0uChJUQ9zCiRqx3GEEFOWaRZ0mI6Oj2I=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
Expand Down
10 changes: 5 additions & 5 deletions internal/domain/calculator/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ type Macros struct {
}

type CaloriesInfo struct {
CaloriesDistribution CaloriesDistribution `json:"carbDistribution"`
CaloriesDistribution pb.CaloriesDistribution `json:"carbDistribution"`
CaloriesDistributionDescription CaloriesDistributionDescription `json:"carbDistributionDescription"`
}
type MacrosInfo struct {
Expand Down Expand Up @@ -220,8 +220,8 @@ var objectiveDescriptionMap = map[pb.Objective]ObjectiveDescription{
pb.Objective_CUTTING: cuttingDescription,
}

var carbsDistribution = map[CaloriesDistribution]CaloriesDistributionDescription{
HighCarbRatios: highCarbs,
LowCarbRatios: lowCarbs,
ModerateCarbRatios: moderateCarbs,
var carbsDistribution = map[pb.CaloriesDistribution]CaloriesDistributionDescription{
pb.CaloriesDistribution_HIGH_CALORIE: highCarbs,
pb.CaloriesDistribution_LOW_CALORIE: lowCarbs,
pb.CaloriesDistribution_MODERATE_CALORIE: moderateCarbs,
}
87 changes: 57 additions & 30 deletions internal/domain/calculator/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"log"
"time"

pbc "github.com/FACorreiaa/fitme-protos/modules/calculator/generated"
Expand Down Expand Up @@ -119,44 +118,72 @@ func (c *CalculatorRepository) GetUserMacros(ctx context.Context, req *pbc.GetUs
return &pbc.GetUserMacroResponse{UserMacro: &macroDistribution}, nil
}

func (c *CalculatorRepository) CreateUserMacro(ctx context.Context, req *pbc.UserMacroDistribution) (*pbc.UserMacroDistribution, error) {
query := `INSERT INTO user_macro_distribution (user_id, age, height, weight,
gender, system, activity, activity_description, objective,
objective_description, calories_distribution, calories_distribution_description,
protein, fats, carbs, bmr, tdee, goal, created_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)
RETURNING *`
func (c *CalculatorRepository) CreateUserMacro(ctx context.Context, req *pbc.CreateUserMacroRequest) (*pbc.UserMacroDistribution, error) {
// Start a transaction if you want to ensure atomic update
tx, err := c.pgpool.BeginTx(ctx, pgx.TxOptions{})
if err != nil {
return nil, fmt.Errorf("failed to start transaction: %w", err)
}
defer func() {
if err != nil {
_ = tx.Rollback(ctx)
}
}()

// If the incoming macro should be "current," set all other macros for this user to false
if req.IsCurrent {
_, err = tx.Exec(ctx, `
UPDATE user_macro_distribution
SET is_current = false
WHERE user_id = $1
`, req.UserMacro.UserId)
if err != nil {
return nil, fmt.Errorf("failed to reset is_current: %w", err)
}
}

// Then insert the new macro
query := `
INSERT INTO user_macro_distribution (
user_id, age, height, weight, gender, system, activity, activity_description,
objective, objective_description, calories_distribution, calories_distribution_description,
protein, fats, carbs, bmr, tdee, goal, created_at, is_current
)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,now(),$19)
RETURNING
id, user_id, age, height, weight, gender, system, activity, activity_description,
objective, objective_description, calories_distribution, calories_distribution_description,
protein, fats, carbs, bmr, tdee, goal, created_at, is_current
`

var macro pbc.UserMacroDistribution
var createdAt time.Time

rows, err := c.pgpool.Query(ctx, query,
req.UserId, req.Age, req.Height, req.Weight, req.Gender, req.System, req.Activity,
req.ActivityDescription, req.Objective, req.ObjectiveDescription, req.CaloriesDistribution,
req.CaloriesDistributionDescription, req.Protein, req.Fats, req.Carbs, req.Bmr, req.Tdee,
req.Goal, createdAt,
var isCurrent bool
userMacro := req.UserMacro
row := tx.QueryRow(ctx, query,
userMacro.UserId, userMacro.Age, userMacro.Height, userMacro.Weight, userMacro.Gender, userMacro.System, userMacro.Activity,
userMacro.ActivityDescription, userMacro.Objective, userMacro.ObjectiveDescription,
userMacro.CaloriesDistribution, userMacro.CaloriesDistributionDescription,
userMacro.Protein, userMacro.Fats, userMacro.Carbs, userMacro.Bmr, userMacro.Tdee, userMacro.Goal, req.IsCurrent,
)

err = row.Scan(
&macro.Id, &macro.UserId, &macro.Age, &macro.Height, &macro.Weight, &macro.Gender,
&macro.System, &macro.Activity, &macro.ActivityDescription, &macro.Objective,
&macro.ObjectiveDescription, &macro.CaloriesDistribution,
&macro.CaloriesDistributionDescription, &macro.Protein,
&macro.Fats, &macro.Carbs, &macro.Bmr, &macro.Tdee,
&macro.Goal, &createdAt, &isCurrent,
)
if err != nil {
log.Printf("Query execution error: %v", err) // Log detailed error
return nil, fmt.Errorf("failed to execute query: %w", err)
return nil, fmt.Errorf("failed to scan row: %w", err)
}
defer rows.Close()

if rows.Next() {
err = rows.Scan(
&macro.Id, &macro.UserId, &macro.Age, &macro.Height, &macro.Weight, &macro.Gender, &macro.System,
&macro.Activity, &macro.ActivityDescription, &macro.Objective, &macro.ObjectiveDescription,
&macro.CaloriesDistribution, &macro.CaloriesDistributionDescription, &macro.Protein,
&macro.Fats, &macro.Carbs, &macro.Bmr, &macro.Tdee, &macro.Goal, &createdAt,
)

if err != nil {
return nil, fmt.Errorf("failed to scan row: %w", err)
}
macro.CreatedAt = timestamppb.New(createdAt)
req.IsCurrent = isCurrent

// Convert `createdAt` (Go time.Time) to Protobuf Timestamp
macro.CreatedAt = timestamppb.New(createdAt)
if err = tx.Commit(ctx); err != nil {
return nil, fmt.Errorf("failed to commit transaction: %w", err)
}

return &macro, nil
Expand Down
38 changes: 31 additions & 7 deletions internal/domain/calculator/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func mapObjective(ctx context.Context, objective pb.Objective) (*ObjectiveList,
}, nil
}

func mapDistribution(ctx context.Context, distribution CaloriesDistribution) (*CaloriesInfo, error) {
func mapDistribution(ctx context.Context, distribution pb.CaloriesDistribution) (*CaloriesInfo, error) {
// Check for context cancellation
select {
case <-ctx.Done():
Expand Down Expand Up @@ -244,7 +244,7 @@ func calculateUserPersonalMacros(ctx context.Context, params UserParams) (UserIn
return UserInfo{}, err
}

d, err := mapDistribution(ctx, CaloriesDistribution(params.CaloriesDist))
d, err := mapDistribution(ctx, parseCaloriesDistribution(params.CaloriesDist))
if err != nil {
return UserInfo{}, err
}
Expand Down Expand Up @@ -331,7 +331,7 @@ func (s *CalculatorService) CreateUserMacro(ctx context.Context, req *pb.CreateU
//ActivityDesc: req.UserMacro.ActivityDescription,
Objective: req.UserMacro.Objective.String(),
//ObjectiveDesc: req.UserMacro.ObjectiveDescription,
CaloriesDist: req.UserMacro.CaloriesDistribution,
CaloriesDist: string(req.UserMacro.CaloriesDistribution),
//CaloriesDistDesc: req.UserMacro.CaloriesDistributionDescription,
}

Expand Down Expand Up @@ -367,7 +367,7 @@ func (s *CalculatorService) CreateUserMacro(ctx context.Context, req *pb.CreateU
ActivityDescription: string(userInfo.ActivityInfo.Description),
Objective: objective,
ObjectiveDescription: string(userInfo.ObjectiveInfo.Description),
CaloriesDistribution: string(userInfo.MacrosInfo.CaloriesInfo.CaloriesDistribution),
CaloriesDistribution: userInfo.MacrosInfo.CaloriesInfo.CaloriesDistribution,
CaloriesDistributionDescription: string(userInfo.MacrosInfo.CaloriesInfo.CaloriesDistributionDescription),
Protein: uint32(userInfo.MacrosInfo.Macros.Protein),
Fats: uint32(userInfo.MacrosInfo.Macros.Fats),
Expand All @@ -378,7 +378,11 @@ func (s *CalculatorService) CreateUserMacro(ctx context.Context, req *pb.CreateU
CreatedAt: createdAt,
}

savedMacro, err := s.repo.CreateUserMacro(ctx, macroDistribution)
req = &pb.CreateUserMacroRequest{
UserMacro: macroDistribution,
}

savedMacro, err := s.repo.CreateUserMacro(ctx, req)
if err != nil {
span.RecordError(err)
span.SetAttributes(attribute.String("error.type", fmt.Sprintf("%T", err)))
Expand Down Expand Up @@ -470,7 +474,7 @@ func (s *CalculatorService) CreateOfflineUserMacro(ctx context.Context, req *pb.
System: req.UserMacro.System,
Activity: req.UserMacro.Activity,
Objective: req.UserMacro.Objective,
CaloriesDist: req.UserMacro.CaloriesDistribution,
CaloriesDist: string(req.UserMacro.CaloriesDistribution),
}

// Perform the offline calculations
Expand All @@ -491,7 +495,7 @@ func (s *CalculatorService) CreateOfflineUserMacro(ctx context.Context, req *pb.
ActivityDescription: string(userInfo.ActivityInfo.Description),
Objective: userInfo.ObjectiveInfo.Objective,
ObjectiveDescription: string(userInfo.ObjectiveInfo.Description),
CaloriesDistribution: string(userInfo.MacrosInfo.CaloriesInfo.CaloriesDistribution),
CaloriesDistribution: userInfo.MacrosInfo.CaloriesInfo.CaloriesDistribution,
CaloriesDistributionDescription: string(userInfo.MacrosInfo.CaloriesInfo.CaloriesDistributionDescription),
Protein: uint32(userInfo.MacrosInfo.Macros.Protein),
Fats: uint32(userInfo.MacrosInfo.Macros.Fats),
Expand Down Expand Up @@ -560,3 +564,23 @@ func StringToActivityEnum(s string) (pb.Activity, error) {
return pb.Activity_ACTIVITY_UNSPECIFIED, fmt.Errorf("invalid Activity: %s", s)
}
}

func (s *CalculatorService) SetActiveUserMacro(ctx context.Context, req *pb.SetActiveUserMacroRequest) (*pb.SetActiveUserMacroResponse, error) {
return nil, nil
}

func parseCaloriesDistribution(s string) pb.CaloriesDistribution {
switch s {
case "CD_UNSPECIFIED":
return pb.CaloriesDistribution_CD_UNSPECIFIED
case "HIGH_CALORIE":
return pb.CaloriesDistribution_HIGH_CALORIE
case "MODERATE_CALORIE":
return pb.CaloriesDistribution_MODERATE_CALORIE
case "LOW_CALORIE":
return pb.CaloriesDistribution_LOW_CALORIE
default:
// Return a default if the string is unknown
return pb.CaloriesDistribution_CD_UNSPECIFIED
}
}
19 changes: 19 additions & 0 deletions internal/domain/meals/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,22 @@ func Listen[T any](ctx context.Context, mb *Broadcaster) <-chan T {
}()
return ch
}

//func validateMealPlanCalories(mealPlan *XMealPlan, objectiveCalories int) error {
// totalCalories := calculateTotalCalories(mealPlan)
// if totalCalories > objectiveCalories {
// return fmt.Errorf("meal plan exceeds your calorie goal by %d kcal", totalCalories-objectiveCalories)
// }
// return nil
//}
//
//func createMealPlan(ctx context.Context, mealPlan *XMealPlan, userObjective *UserMacroDistribution) (*XMealPlan, error) {
// // Check if the meal plan exceeds the calorie goal for the user objective
// err := validateMealPlanCalories(mealPlan, userObjective.goal)
// if err != nil {
// return nil, err
// }
//
// // Proceed with saving the meal plan
// // Save the meal plan logic here...
//}
Loading

0 comments on commit c1050df

Please sign in to comment.