package handlers import ( "encoding/json" "fmt" "net/http" "strconv" "time" "github.com/gin-gonic/gin" domainRecipe "github.com/haydenhargreaves/Potion/internal/domain/recipe" domain "github.com/haydenhargreaves/Potion/internal/domain/server" templates "github.com/haydenhargreaves/Potion/internal/templates/pages" ) const CREATE_ERROR_HTML = `

Uh oh! Something went wrong when creating your recipe. Please try again. %s

` func CreateRecipe(ctx *gin.Context) { deps := ctx.MustGet("deps").(*domain.InjectedDependencies) recipe, err := deps.RecipeService.CreateRecipe(ctx) if err != nil { ctx.String(http.StatusOK, CREATE_ERROR_HTML, err.Error()) return } // Send HTMX redirection url := fmt.Sprintf(domain.WEB_RECIPE, recipe.Id) ctx.Header("HX-Redirect", url) ctx.Status(http.StatusCreated) } // toBits converts an array of stringified numbers into a single summed value func toBits(arr []string) (bits int) { for _, x := range arr { num, _ := strconv.Atoi(x) bits += num } return } // TODO: I don't love doing all of this here, but it seems to be the only way to get it to work... func SearchRecipes(ctx *gin.Context) { deps := ctx.MustGet("deps").(*domain.InjectedDependencies) // create filters filters := domainRecipe.SearchFilters{ Search: ctx.PostForm("search"), // string, search query for titles MealType: toBits(ctx.PostFormArray("meal")), Time: toBits(ctx.PostFormArray("time")), Difficulty: toBits(ctx.PostFormArray("difficulty")), ServingSize: toBits(ctx.PostFormArray("serving")), } // Set the filters into the cookies, so they can be reloaded if bytes, err := json.Marshal(filters); err == nil { ctx.SetCookie( "search-filters", string(bytes), int(time.Now().Add(24*time.Hour).Sub(time.Now()).Seconds()), "/", "", // TODO: Need an actual domain false, // TODO: True in prod true, ) } redirect := ctx.PostForm("redirect") if redirect == "true" { ctx.Header("HX-Redirect", domain.WEB_SEARCH) ctx.Status(http.StatusOK) return } // Get user if logged in, so we can get favorite status var userId *int = nil if domain.IsLoggedIn(ctx) { id := ctx.MustGet("userId").(int) userId = &id } // We don't care about favorite status, so use false recipes, err := deps.RecipeService.SearchRecipes(filters, userId, false) if err != nil { ctx.JSON(http.StatusOK, gin.H{"error": err.Error()}) } // Render content as the response ctx.Status(200) templates.ResultList(recipes).Render(ctx.Request.Context(), ctx.Writer) } func SearchRecipesFavorites(ctx *gin.Context) { deps := ctx.MustGet("deps").(*domain.InjectedDependencies) // create filters filters := domainRecipe.SearchFilters{ Search: ctx.PostForm("search"), // string, search query for titles MealType: toBits(ctx.PostFormArray("meal")), Time: toBits(ctx.PostFormArray("time")), Difficulty: toBits(ctx.PostFormArray("difficulty")), ServingSize: toBits(ctx.PostFormArray("serving")), } // Set the filters into the cookies, so they can be reloaded if bytes, err := json.Marshal(filters); err == nil { ctx.SetCookie( "search-filters", string(bytes), int(time.Now().Add(24*time.Hour).Sub(time.Now()).Seconds()), "/", "", // TODO: Need an actual domain false, // TODO: True in prod true, ) } // TODO: Error here if they're not logged in? // Get user data (they should be logged in) if !domain.IsLoggedIn(ctx) { ctx.JSON(http.StatusOK, gin.H{"error": "User is not logged in. User will be nil."}) } userId := ctx.MustGet("userId").(int) recipes, err := deps.RecipeService.SearchRecipes(filters, &userId, true) if err != nil { ctx.JSON(http.StatusOK, gin.H{"error": err.Error()}) } // Render content as the response ctx.Status(200) templates.FavoriteList(recipes).Render(ctx.Request.Context(), ctx.Writer) }