From aacca77890bab6076d7df3f77ba6d4f741aada65 Mon Sep 17 00:00:00 2001 From: Hayden Hargreaves Date: Tue, 15 Jul 2025 22:11:25 -0700 Subject: [PATCH] (FEAT): Created backend API to get users favorite recipes. The UI is wired up and connected as well, for the profile page. Next step is to create the favorites page. --- internal/app/handlers/page_handler.go | 11 ++- internal/app/handlers/user_handler.go | 40 ++++++++ internal/app/server/server.go | 1 + internal/app/service/recipe_service.go | 8 ++ internal/domain/recipe/repository.go | 1 + internal/domain/recipe/service.go | 1 + .../database/repository/recipe_repository.go | 88 ++++++++++++++++++ internal/templates/pages/profile.templ | 41 +++++--- internal/templates/pages/profile_templ.go | 93 +++++++++++-------- web/static/css/tailwind.css | 1 - 10 files changed, 234 insertions(+), 51 deletions(-) diff --git a/internal/app/handlers/page_handler.go b/internal/app/handlers/page_handler.go index cadcee1..512d537 100644 --- a/internal/app/handlers/page_handler.go +++ b/internal/app/handlers/page_handler.go @@ -67,6 +67,15 @@ func ProfilePage(ctx *gin.Context) { return } + favorites, err := deps.RecipeService.GetUserFavoriteRecipes(user.Id) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{ + "status": http.StatusInternalServerError, + "message": fmt.Sprintf("Error getting recipes. %s\n", err.Error()), + }) + return + } + // Get the engagement data, not sure what will happen when errors occur engagements, err := deps.EngagementService.GetUserEngagement(user.Id, 6) if err != nil { @@ -78,7 +87,7 @@ func ProfilePage(ctx *gin.Context) { } title := "Potion - Profile" - page := pages.ProfilePage(user, recipes, engagements) + page := pages.ProfilePage(user, recipes, favorites, engagements) ctx.HTML(http.StatusOK, "", layouts.AppLayout(title, page)) } diff --git a/internal/app/handlers/user_handler.go b/internal/app/handlers/user_handler.go index 261e199..c5508bf 100644 --- a/internal/app/handlers/user_handler.go +++ b/internal/app/handlers/user_handler.go @@ -47,3 +47,43 @@ func GetUserRecipes(ctx *gin.Context) { "recipes": recipes, }) } + +func GetUserFavoriteRecipes(ctx *gin.Context) { + deps := ctx.MustGet("deps").(*domain.InjectedDependencies) + + // Ensure logged in + if !domain.IsLoggedIn(ctx) { + ctx.JSON(http.StatusUnauthorized, gin.H{ + "status": http.StatusUnauthorized, + "message": "User is not authorized to access this endpoint. Please login to continue.", + "recipes": nil, + }) + return + } + + userId, ok := ctx.MustGet("userId").(int) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{ + "status": http.StatusInternalServerError, + "message": "Unable to access user id from store.", + "recipes": nil, + }) + return + } + + recipes, err := deps.RecipeService.GetUserFavoriteRecipes(userId) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{ + "status": http.StatusBadRequest, + "message": fmt.Sprintf("Could not get user recipes. %s", err.Error()), + "recipes": nil, + }) + return + } + + ctx.JSON(http.StatusOK, gin.H{ + "status": http.StatusOK, + "message": "User recipes successfully retrieved.", + "recipes": recipes, + }) +} diff --git a/internal/app/server/server.go b/internal/app/server/server.go index 091e464..479ec37 100644 --- a/internal/app/server/server.go +++ b/internal/app/server/server.go @@ -185,6 +185,7 @@ func (s *Server) Setup() *Server { router_api.POST("/recipe", handlers.CreateRecipe) router_api.POST("/recipe/search", handlers.SearchRecipes) router_api.GET("/user/recipes", handlers.GetUserRecipes) + router_api.GET("/user/favorites", handlers.GetUserFavoriteRecipes) // Engagement endpoints router_api.POST("/engagement/view/:id", handlers.EngagementViewRecipe) diff --git a/internal/app/service/recipe_service.go b/internal/app/service/recipe_service.go index be4ba73..22fe6a1 100644 --- a/internal/app/service/recipe_service.go +++ b/internal/app/service/recipe_service.go @@ -155,6 +155,14 @@ func (s *RecipeService) SearchRecipes(filters domain.SearchFilters) ([]domain.Re return s.recipeRepository.SearchRecipes(filters) } +// GetUserRecipes returns a list of the recipes that the user has created. The user's +// ID should be provided. Any errors will be bubbled to the caller. func (s *RecipeService) GetUserRecipes(id int) ([]domain.Recipe, error) { return s.recipeRepository.GetUserRecipes(id) } + +// GetUserFavoriteRecipes returns a list of the recipes that the user has marked as a +// favorite. The user's ID should be provided. Any errors will be bubbled to the caller. +func (s *RecipeService) GetUserFavoriteRecipes(id int) ([]domain.Recipe, error) { + return s.recipeRepository.GetUserFavoriteRecipes(id) +} diff --git a/internal/domain/recipe/repository.go b/internal/domain/recipe/repository.go index d1a3a6e..639d21c 100644 --- a/internal/domain/recipe/repository.go +++ b/internal/domain/recipe/repository.go @@ -6,6 +6,7 @@ type RecipeRepository interface { SearchRecipes(filters SearchFilters) ([]Recipe, error) CreateRecipeTags(recipe Recipe, tags []string) error GetUserRecipes(id int) ([]Recipe, error) + GetUserFavoriteRecipes(id int) ([]Recipe, error) GetRecipeTags(recipe *Recipe) error GetRecipeFavorite(recipe *Recipe, userId int) error } diff --git a/internal/domain/recipe/service.go b/internal/domain/recipe/service.go index 33d919a..425b83e 100644 --- a/internal/domain/recipe/service.go +++ b/internal/domain/recipe/service.go @@ -7,4 +7,5 @@ type RecipeService interface { GetRecipe(id int, userId *int) (*Recipe, error) SearchRecipes(filters SearchFilters) ([]Recipe, error) GetUserRecipes(id int) ([]Recipe, error) + GetUserFavoriteRecipes(id int) ([]Recipe, error) } diff --git a/internal/infrastructure/database/repository/recipe_repository.go b/internal/infrastructure/database/repository/recipe_repository.go index a0a578d..4347ce4 100644 --- a/internal/infrastructure/database/repository/recipe_repository.go +++ b/internal/infrastructure/database/repository/recipe_repository.go @@ -548,6 +548,94 @@ func (r *RecipeRepository) GetUserRecipes(id int) ([]domain.Recipe, error) { return recipes, nil } +func (r *RecipeRepository) GetUserFavoriteRecipes(id int) ([]domain.Recipe, error) { + tx, err := r.db.Begin() + if err != nil { + tx.Rollback() + return nil, err + } + + query := ` + SELECT r.id, r.title, r.description, r.instructions, r.serves, r.difficulty, r.duration, r.category, r.ingredients, r. + userid, r.modified, r.created + FROM favorites f + JOIN recipes r ON r.id = f.recipeid + WHERE f.userid = $1 + ORDER BY f.created DESC; + ` + rows, err := tx.Query(query, id) + if err != nil { + return nil, fmt.Errorf("Failed to query DB for user recipes. %s\n", err.Error()) + } + defer rows.Close() + + var recipes []domain.Recipe + for rows.Next() { + var recipe domain.Recipe + var durationBytes []byte + var ingredientBytes []byte + + // Scan results from recipe query onto recipe object + if err := rows.Scan( + &recipe.Id, + &recipe.Title, + &recipe.Description, + pq.Array(&recipe.Instructions), + &recipe.Serves, + &recipe.Difficulty, + &durationBytes, + &recipe.Category, + &ingredientBytes, + &recipe.UserId, + &recipe.Modified, + &recipe.Created, + ); err != nil { + return nil, fmt.Errorf("Failed to scan row onto recipe object. %s\n", err.Error()) + } + + // Parse duration + if len(durationBytes) > 0 { + var duration domain.RecipeDuration + if err := json.Unmarshal(durationBytes, &duration); err != nil { + return nil, fmt.Errorf("Failed to parse duration from database: %s", err.Error()) + } + + recipe.Duration = duration + } else { + recipe.Duration = domain.RecipeDuration{} + } + + // Parse ingredient + if len(ingredientBytes) > 0 { + var ingredients []domain.RecipeIngredient + if err := json.Unmarshal(ingredientBytes, &ingredients); err != nil { + return nil, fmt.Errorf("Failed to parse ingredients from database: %s", err.Error()) + } + + recipe.Ingredients = ingredients + } else { + recipe.Ingredients = []domain.RecipeIngredient{} + } + + // Add tags + if err := r.GetRecipeTags(&recipe); err != nil { + fmt.Printf("ERROR getting recipe tags. %s\n", err.Error()) + } + + // Set favorite status (they're always true!) + recipe.Favorite = true + + recipes = append(recipes, recipe) + } + + if err := tx.Commit(); err != nil { + tx.Rollback() + return nil, err + } + + return recipes, nil +} + // GetRecipeTags requires a recipe to be filled with at least an ID. This function will use the ID // defined in the provided recipe to fill the Tags array with the recipe's tags from the database. // The recipe is modified in place and is not returned. Any errors will be bubbled to the caller. diff --git a/internal/templates/pages/profile.templ b/internal/templates/pages/profile.templ index c13d33e..c53031e 100644 --- a/internal/templates/pages/profile.templ +++ b/internal/templates/pages/profile.templ @@ -44,7 +44,7 @@ templ userDetailsSection(user domainUser.User, recipeCount int) { } else { }
@@ -74,7 +74,7 @@ templ recipesSection(recipes []domainRecipe.Recipe) { @recipeListItem(recipe) } } - +
  • @@ -88,7 +88,24 @@ templ recipesSection(recipes []domainRecipe.Recipe) { templ favoritesSection(recipes []domainRecipe.Recipe) {

    My Favorites

    -

    Favorites section is under construction!

    +
    } @@ -113,13 +130,13 @@ templ activitySection(engagement []domainEngagement.Engagement) { templ recipeListItem(recipe domainRecipe.Recipe) {
  • -

    - { recipe.Title } +

    + { recipe.Title }

    @userDetailsSection(user, len(recipes)) @recipesSection(recipes) - @favoritesSection(recipes) + @favoritesSection(favorites) @activitySection(engagement) @logoutSection()
    diff --git a/internal/templates/pages/profile_templ.go b/internal/templates/pages/profile_templ.go index 88ed43b..0a05a97 100644 --- a/internal/templates/pages/profile_templ.go +++ b/internal/templates/pages/profile_templ.go @@ -92,7 +92,7 @@ func userDetailsSection(user domainUser.User, recipeCount int) templ.Component { var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("https://ui-avatars.com/api/?name=%s+%s&size=150", strings.Split(user.Name, " ")[0], strings.Split(user.Name, " ")[1])) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 47, Col: 143} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 47, Col: 141} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -190,7 +190,7 @@ func recipesSection(recipes []domainRecipe.Recipe) templ.Component { } } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
  • See all...
  • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
  • See all...
  • ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -219,7 +219,26 @@ func favoritesSection(recipes []domainRecipe.Recipe) templ.Component { templ_7745c5c3_Var8 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "

    My Favorites

    Favorites section is under construction!

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "

    My Favorites

      ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if len(recipes) <= 4 { + for _, recipe := range recipes { + templ_7745c5c3_Err = recipeListItem(recipe).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + } else { + for _, recipe := range recipes[:4] { + templ_7745c5c3_Err = recipeListItem(recipe).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "
    • See all...
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -248,7 +267,7 @@ func activitySection(engagement []domainEngagement.Engagement) templ.Component { templ_7745c5c3_Var9 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "

    Recent Activity

    Activity section is under construction!

      ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "

      Recent Activity

      Activity section is under construction!

        ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -258,7 +277,7 @@ func activitySection(engagement []domainEngagement.Engagement) templ.Component { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
      • See all...
      ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
    • See all...
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -287,134 +306,134 @@ func recipeListItem(recipe domainRecipe.Recipe) templ.Component { templ_7745c5c3_Var10 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "
  • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\" hx-trigger=\"click\" hx-swap=\"none\" class=\"text-base md:text-lg hover:text-blue-600 duration-100 cursor-pointer\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var12 string templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(recipe.Title) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 122, Col: 18} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 139, Col: 17} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "

    Difficulty: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "

    Difficulty: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var13 string templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(displayDifficulty(recipe.Difficulty)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 125, Col: 81} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 142, Col: 81} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " | Duration: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, " | Duration: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var14 string templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(recipe.Duration.Total) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 126, Col: 66} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 143, Col: 66} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, " min | Category: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, " min | Category: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var15 string templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(recipe.Category) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 127, Col: 60} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 144, Col: 60} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "

    Difficulty: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "

    Difficulty: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var16 string templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(displayDifficulty(recipe.Difficulty)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 130, Col: 81} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 147, Col: 81} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "

    Duration: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "

    Duration: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var17 string templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(recipe.Duration.Total) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 133, Col: 64} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 150, Col: 64} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, " min

    Category: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " min

    Category: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var18 string templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(recipe.Category) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 136, Col: 58} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 153, Col: 58} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if len(recipe.Tags) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "

    Tags: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "

    Tags: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var19 string templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(displayTags(recipe.Tags)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 140, Col: 36} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 157, Col: 36} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "
  • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -443,33 +462,33 @@ func activityListItem(engagement domainEngagement.Engagement) templ.Component { templ_7745c5c3_Var20 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "
  • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "

  • ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var21 string templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(engagement.Message) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 151, Col: 23} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 168, Col: 23} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var22 string templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(engagement.Created.Format("01/02/2006")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 154, Col: 44} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 171, Col: 44} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "

  • ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "

    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -498,7 +517,7 @@ func logoutSection() templ.Component { templ_7745c5c3_Var23 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "
    Logout
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\" class=\"text-center border border-red-500 text-red-500 w-9/10 md:w-1/3 py-2 rounded-lg hover:cursor-pointer hover:bg-red-100 duration-300\">Logout") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -515,7 +534,7 @@ func logoutSection() templ.Component { }) } -func ProfilePage(user domainUser.User, recipes []domainRecipe.Recipe, engagement []domainEngagement.Engagement) templ.Component { +func ProfilePage(user domainUser.User, recipes []domainRecipe.Recipe, favorites []domainRecipe.Recipe, engagement []domainEngagement.Engagement) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -540,7 +559,7 @@ func ProfilePage(user domainUser.User, recipes []domainRecipe.Recipe, engagement if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -552,7 +571,7 @@ func ProfilePage(user domainUser.User, recipes []domainRecipe.Recipe, engagement if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = favoritesSection(recipes).Render(ctx, templ_7745c5c3_Buffer) + templ_7745c5c3_Err = favoritesSection(favorites).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -564,7 +583,7 @@ func ProfilePage(user domainUser.User, recipes []domainRecipe.Recipe, engagement if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "
    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "
    ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/web/static/css/tailwind.css b/web/static/css/tailwind.css index 14b37e1..2303839 100644 --- a/web/static/css/tailwind.css +++ b/web/static/css/tailwind.css @@ -9,7 +9,6 @@ monospace; --color-red-100: oklch(93.6% 0.032 17.717); --color-red-500: oklch(63.7% 0.237 25.331); - --color-green-300: oklch(87.1% 0.15 154.449); --color-green-500: oklch(72.3% 0.219 149.579); --color-blue-50: oklch(97% 0.014 254.604); --color-blue-100: oklch(93.2% 0.032 255.585);