diff --git a/internal/app/server/recipe_handler_v2.go b/internal/app/server/recipe_handler_v2.go index 7c1a9fb..6792ea2 100644 --- a/internal/app/server/recipe_handler_v2.go +++ b/internal/app/server/recipe_handler_v2.go @@ -96,6 +96,15 @@ func (s *Server) SearchRecipeHandlerV2(ctx *gin.Context) { } func (s *Server) CreateRecipeHandlerV2(ctx *gin.Context) { + userId := getUserId(ctx) + if userId == nil { + ctx.JSON(http.StatusBadRequest, gin.H{ + "status": http.StatusBadRequest, + "message": "[ERROR] User must be logged in to create a recipe.", + }) + return + } + recipe, err := s.deps.RecipeService.CreateRecipe(ctx) if err != nil { ctx.JSON(http.StatusBadRequest, gin.H{ @@ -105,6 +114,15 @@ func (s *Server) CreateRecipeHandlerV2(ctx *gin.Context) { return } + _, err = s.deps.EngagementService.UserCreateRecipe(*userId, recipe.Id) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{ + "status": http.StatusBadRequest, + "message": fmt.Sprintf("[ERROR] Failed to create recipe engagement. %s", err.Error()), + }) + return + } + ctx.JSON(http.StatusOK, gin.H{ "status": http.StatusOK, "message": "[OK] Successfully created new recipe.", diff --git a/internal/app/service/engagement_service.go b/internal/app/service/engagement_service.go index 54ec6a9..fa89e00 100644 --- a/internal/app/service/engagement_service.go +++ b/internal/app/service/engagement_service.go @@ -122,6 +122,34 @@ func (s *EngagementService) UserShareRecipe(userId, recipeId int) (domain.Engage return s.engagementRepository.AddUserEntityEngagement(userId, recipeId, message, domain.EngagementShared) } +// UserCreateRecipe requires a user ID and a recipe ID to create an engagement record in the database. +// A message will be generated using the recipe data and then used to add a make engagement to the +// database. +func (s *EngagementService) UserCreateRecipe(userId, recipeId int) (domain.Engagement, error) { + recipe, err := s.recipeRepository.GetRecipe(recipeId, &userId) + if err != nil { + return domain.Engagement{}, err + } + + message := fmt.Sprintf("Created \"%s\"", recipe.Title) + + return s.engagementRepository.AddUserEntityEngagement(userId, recipeId, message, domain.EngagementCreated) +} + +// UserDeleteRecipe requires a user ID and a recipe ID to create an engagement record in the database. +// A message will be generated using the recipe data and then used to add a make engagement to the +// database. +func (s *EngagementService) UserDeleteRecipe(userId, recipeId int) (domain.Engagement, error) { + recipe, err := s.recipeRepository.GetRecipe(recipeId, &userId) + if err != nil { + return domain.Engagement{}, err + } + + message := fmt.Sprintf("Deleted \"%s\"", recipe.Title) + + return s.engagementRepository.AddUserEntityEngagement(userId, recipeId, message, domain.EngagementDeleted) +} + // GetUserEngagement returns a list of the users most recent engagement entries. The number of records // is determined by the limit passed into this function. The results are sorted, newest-to-oldest. func (s *EngagementService) GetUserEngagement(userId, limit int) ([]domain.Engagement, error) { diff --git a/internal/domain/engagement/engagement.go b/internal/domain/engagement/engagement.go index 92ca859..7be27ce 100644 --- a/internal/domain/engagement/engagement.go +++ b/internal/domain/engagement/engagement.go @@ -14,6 +14,8 @@ const ( EngagementShared EngagementType = "shared" EngagementReviewed EngagementType = "reviewed" EngagementRated EngagementType = "rated" + EngagementCreated EngagementType = "created" + EngagementDeleted EngagementType = "deleted" ) // Engagement is the database model of a user engagement. There is no need to map to a different diff --git a/internal/domain/engagement/service.go b/internal/domain/engagement/service.go index 4c3a0ff..bbf4492 100644 --- a/internal/domain/engagement/service.go +++ b/internal/domain/engagement/service.go @@ -7,5 +7,7 @@ type EngagementService interface { UserFavoriteRecipe(userId, recipeId int) (Engagement, error) UserMakeRecipe(userId, recipeId int) (Engagement, error) UserShareRecipe(userId, recipeId int) (Engagement, error) + UserCreateRecipe(userId, recipeId int) (Engagement, error) + UserDeleteRecipe(userId, recipeId int) (Engagement, error) GetUserEngagement(userId, limit int) ([]Engagement, error) } diff --git a/internal/infrastructure/database/migrations/011_update_engagement_enum.sql b/internal/infrastructure/database/migrations/011_update_engagement_enum.sql new file mode 100644 index 0000000..62baf3e --- /dev/null +++ b/internal/infrastructure/database/migrations/011_update_engagement_enum.sql @@ -0,0 +1,14 @@ + +-- Author: Hayden Hargreaves (hhargreaves2006@gmail.com) +-- Desc: Updated the E_ENGAGEMENT enum to contain created and deleted. +-- Date: 01/10/2026 + +BEGIN; + +ALTER TYPE E_ENGAGEMENT + ADD VALUE IF NOT EXISTS 'created'; -- created recipe + +ALTER TYPE E_ENGAGEMENT + ADD VALUE IF NOT EXISTS 'deleted'; -- deleted recipe + +COMMIT; diff --git a/internal/infrastructure/database/migrations/100_init_database.sh b/internal/infrastructure/database/migrations/100_init_database.sh index 94f8559..203d3fb 100755 --- a/internal/infrastructure/database/migrations/100_init_database.sh +++ b/internal/infrastructure/database/migrations/100_init_database.sh @@ -10,4 +10,5 @@ psql -h "$PSQL_HOST" -U "$PSQL_USERNAME" -d "$PSQL_DATABASE" -f ./internal/infra psql -h "$PSQL_HOST" -U "$PSQL_USERNAME" -d "$PSQL_DATABASE" -f ./internal/infrastructure/database/migrations/008_create_favorites_table.sql psql -h "$PSQL_HOST" -U "$PSQL_USERNAME" -d "$PSQL_DATABASE" -f ./internal/infrastructure/database/migrations/009_create_recipe_of_the_week_table.sql psql -h "$PSQL_HOST" -U "$PSQL_USERNAME" -d "$PSQL_DATABASE" -f ./internal/infrastructure/database/migrations/010_create_recipe_of_the_week_procedure.sql +psql -h "$PSQL_HOST" -U "$PSQL_USERNAME" -d "$PSQL_DATABASE" -f ./internal/infrastructure/database/migrations/011_update_engagement_enum.sql