Compare commits

..

No commits in common. "429540ddd53884e9308c4675130e83bdf0331502" and "a91e28c9bd724ba40bc1efeea71cac3ca852df12" have entirely different histories.

11 changed files with 214 additions and 422 deletions

View File

@ -1,9 +1,7 @@
package handlers package handlers
import ( import (
"fmt"
"net/http" "net/http"
"strconv"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
domain "github.com/haydenhargreaves/Potion/internal/domain/server" domain "github.com/haydenhargreaves/Potion/internal/domain/server"
@ -69,38 +67,9 @@ func ListPage(ctx *gin.Context) {
ctx.HTML(200, "", layouts.AppLayout(title, page)) ctx.HTML(200, "", layouts.AppLayout(title, page))
} }
// TODO: Figure out how to handle errors, think we just need a simple display.
func RecipePage(ctx *gin.Context) { func RecipePage(ctx *gin.Context) {
// Call recipe service to get via ID
deps := ctx.MustGet("deps").(*domain.InjectedDependencies)
id := ctx.Param("id")
// Parse ID
parsed, err := strconv.Atoi(id)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
ctx.JSON(400, err.Error())
return
}
// Get recipe
recipe, err := deps.RecipeService.GetRecipe(parsed)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
ctx.JSON(400, err.Error())
return
}
// Get user
user, err := deps.UserService.GetUser(recipe.UserId)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
ctx.JSON(400, err.Error())
return
}
title := "Potion - View Recipe" title := "Potion - View Recipe"
page := pages.RecipePage(*recipe, *user) page := pages.RecipePage()
ctx.HTML(200, "", layouts.AppLayout(title, page)) ctx.HTML(200, "", layouts.AppLayout(title, page))
} }

View File

@ -27,13 +27,6 @@ func NewRecipeService(recipeRepository domain.RecipeRepository) domain.RecipeSer
return &RecipeService{recipeRepository: recipeRepository} return &RecipeService{recipeRepository: recipeRepository}
} }
// CreateRecipe creates a recipe in the database using the recipe repository. This function requires
// all the data to be present, though validation does not occur in this function. However, the UI
// will enforce validation, as will the database. Errors will be returned to the called when they
// occur.
//
// TODO: Implement validation in the API.
// TODO: Implement image creation and tag creation.
func (s *RecipeService) CreateRecipe(ctx *gin.Context) (*domain.Recipe, error) { func (s *RecipeService) CreateRecipe(ctx *gin.Context) (*domain.Recipe, error) {
// Ensure user is logged in // Ensure user is logged in
if !domainServer.IsLoggedIn(ctx) { if !domainServer.IsLoggedIn(ctx) {
@ -116,16 +109,3 @@ func (s *RecipeService) CreateRecipe(ctx *gin.Context) (*domain.Recipe, error) {
return &recipe, nil return &recipe, nil
} }
// GetRecipe will get a recipe via its ID. Any errors will be bubbled to the caller. Furthermore,
// if the recipe is nil, an error will be returned, so the caller does not need to check for a nil
// recipe (e.g., if the error is nil the recipe exists)
func (s *RecipeService) GetRecipe(id int) (*domain.Recipe, error) {
recipe, err := s.recipeRepository.GetRecipe(id)
if recipe == nil {
return nil, fmt.Errorf("Failed to get recipe from database. Nil result.")
}
return recipe, err
}

View File

@ -1,8 +1,6 @@
package service package service
import ( import (
"fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
domain "github.com/haydenhargreaves/Potion/internal/domain/user" domain "github.com/haydenhargreaves/Potion/internal/domain/user"
) )
@ -21,10 +19,6 @@ func NewUserService(userRepository domain.UserRepository) domain.UserService {
return &UserService{userRepository: userRepository} return &UserService{userRepository: userRepository}
} }
// GetAuthenicatedUser will return the user the is currently authenticated. This assumes that the
// user is actually logged in, if not, a blank user will be returned. To ensure success, call the
// `domain.IsLoggedIn()` function first to ensure the user is logged in. If that passes, this
// function should yield a result.
func (s *UserService) GetAuthenicatedUser(ctx *gin.Context) domain.User { func (s *UserService) GetAuthenicatedUser(ctx *gin.Context) domain.User {
val, ok := ctx.Get("userId") val, ok := ctx.Get("userId")
if !ok { if !ok {
@ -32,24 +26,10 @@ func (s *UserService) GetAuthenicatedUser(ctx *gin.Context) domain.User {
} }
id := val.(int) id := val.(int)
user, err := s.userRepository.GetUser(id) user, err := s.userRepository.GetUserById(id)
if err != nil { if err != nil {
return domain.User{} return domain.User{}
} }
return *user return *user
} }
// GetUser will get a user from the database via its ID. This is not related to the Google ID in
// any capacity. Any errors will be bubbled to the caller. Furthermore, if the user is nil, an error
// will be returned, so the caller does not need to check for a nil user (e.g., if the error is nil
// the user exists)
func (s *UserService) GetUser(id int) (*domain.User, error) {
user, err := s.userRepository.GetUser(id)
if user == nil {
return nil, fmt.Errorf("Failed to get user from database. Nil result.")
}
return user, err
}

View File

@ -1,6 +1,6 @@
package domain package domain
type RecipeRepository interface { type RecipeRepository interface {
// TODO: Not sure the input type yet
CreateRecipe(recipe *Recipe) error CreateRecipe(recipe *Recipe) error
GetRecipe(id int) (*Recipe, error)
} }

View File

@ -4,5 +4,4 @@ import "github.com/gin-gonic/gin"
type RecipeService interface { type RecipeService interface {
CreateRecipe(ctx *gin.Context) (*Recipe, error) CreateRecipe(ctx *gin.Context) (*Recipe, error)
GetRecipe(id int) (*Recipe, error)
} }

View File

@ -3,5 +3,5 @@ package domain
type UserRepository interface { type UserRepository interface {
CreateGoogleUser(googleUserInfo *GoogleUserInfo, googleRefreshToken string) (User, error) CreateGoogleUser(googleUserInfo *GoogleUserInfo, googleRefreshToken string) (User, error)
GetGoogleUser(googleId string) (*User, error) GetGoogleUser(googleId string) (*User, error)
GetUser(id int) (*User, error) GetUserById(id int) (*User, error)
} }

View File

@ -4,5 +4,4 @@ import "github.com/gin-gonic/gin"
type UserService interface { type UserService interface {
GetAuthenicatedUser(ctx *gin.Context) User GetAuthenicatedUser(ctx *gin.Context) User
GetUser(id int) (*User, error)
} }

View File

@ -3,7 +3,6 @@ package repository
import ( import (
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"fmt"
domain "github.com/haydenhargreaves/Potion/internal/domain/recipe" domain "github.com/haydenhargreaves/Potion/internal/domain/recipe"
"github.com/lib/pq" "github.com/lib/pq"
@ -23,11 +22,6 @@ func NewRecipeRepository(db *sql.DB) domain.RecipeRepository {
} }
// NOTE: This function modified the provided recipe with the new values, such as id and time stamp // NOTE: This function modified the provided recipe with the new values, such as id and time stamp
// CreateRecipe creates a recipe in the database. The recipe provided should contain all data except
// time stamps and the ID; the database will fill them when the operation succeeds. Any errors will
// be bubbled to the caller. The recipe parameter is passed by reference and will therefore be updated
// directly and the new fields (ID, created) can be accessed upon success.
func (r *RecipeRepository) CreateRecipe(recipe *domain.Recipe) error { func (r *RecipeRepository) CreateRecipe(recipe *domain.Recipe) error {
tx, err := r.db.Begin() tx, err := r.db.Begin()
if err != nil { if err != nil {
@ -87,64 +81,3 @@ func (r *RecipeRepository) CreateRecipe(recipe *domain.Recipe) error {
return nil return nil
} }
// GetRecipe gets a recipe from the database via its ID. The operation is wrapped in a transaction
// for added safety. The repository will not check for a nil result, instead the service will. Callers
// are responsible for protecting against double nil results. Any errors will be bubbled to the caller.
func (r *RecipeRepository) GetRecipe(id int) (*domain.Recipe, error) {
tx, err := r.db.Begin()
if err != nil {
tx.Rollback()
return nil, err
}
query := "SELECT * FROM recipes WHERE id = $1"
var durationBytes []byte
var ingredientBytes []byte
var recipe domain.Recipe
if err := tx.QueryRow(query, id).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 location recipe in database: %s", err.Error())
}
if err := tx.Commit(); err != nil {
tx.Rollback()
return nil, err
}
// 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
}
// 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
}
return &recipe, nil
}

View File

@ -106,20 +106,16 @@ func (r *UserRepository) GetGoogleUser(googleId string) (*domain.User, error) {
return &user, nil return &user, nil
} }
// GetUser gets a user from the database via its ID. The operation is wrapped in a transaction func (r *UserRepository) GetUserById(id int) (*domain.User, error) {
// for added safety. The repository will not check for a nil result, instead the service will.
// Callers are responsible for protecting against double nil results. Any errors will be bubbled
// to the caller.
func (r *UserRepository) GetUser(id int) (*domain.User, error) {
tx, err := r.db.Begin() tx, err := r.db.Begin()
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return nil, err return nil, err
} }
query := "SELECT * FROM users WHERE id = $1"
var user domain.User var user domain.User
query := `SELECT * FROM users WHERE id = $1`
if err := tx.QueryRow(query, id).Scan( if err := tx.QueryRow(query, id).Scan(
&user.Id, &user.Id,
&user.GoogleId, &user.GoogleId,

View File

@ -1,11 +1,6 @@
package templates package templates
import ( import "github.com/haydenhargreaves/Potion/internal/templates/components"
domain "github.com/haydenhargreaves/Potion/internal/domain/recipe"
domainUser "github.com/haydenhargreaves/Potion/internal/domain/user"
"github.com/haydenhargreaves/Potion/internal/templates/components"
"time"
)
templ servingIcon() { templ servingIcon() {
<svg <svg
@ -63,83 +58,109 @@ templ starIcon(filled bool) {
} }
} }
templ RecipePage(recipe domain.Recipe, user domainUser.User) { templ RecipePage() {
@components.Navbar("") @components.Navbar("")
<div class="w-full flex justify-center"> <div class="w-full flex justify-center">
<div class="mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 h-full border-l border-r border-gray-300 bg-white"> <div class="mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 h-full border-l border-r border-gray-300 bg-white">
<img class="bg-gray-100 w-full h-96 mx-auto mb-8" src="" alt=""/> <img class="bg-gray-100 w-full h-96 mx-auto mb-8" src="" alt=""/>
<div class="px-4 py-8 md:px-8"> <div class="px-4 py-8 md:px-8">
<h1 class="text-3xl md:text-4xl font-bold text-gray-800">{ recipe.Title }</h1> <h1 class="text-3xl md:text-4xl font-bold text-gray-800">Easy Chicken Alfredo</h1>
<p class="text-sm mt-2 mb-1 text-gray-700">Author: { user.Name }</p> <p class="text-sm mt-2 mb-1 text-gray-700">Author: Hayden Hargreaves</p>
<p class="text-sm mb-2 text-gray-700">Category: { recipe.Category }</p> <p class="text-sm mb-2 text-gray-700">Category: Dinner</p>
</div> </div>
@metadataSection(recipe) @metadataSection()
<div class="px-4 py-8 md:px-8"> <div class="px-4 py-8 md:px-8">
<h3 class="text-xl text-gray-800 font-semibold mb-2">About this recipe</h3> <h3 class="text-xl text-gray-800 font-semibold mb-2">About this recipe</h3>
<p class="text-gray-700">{ recipe.Description }</p> <p class="text-gray-700">
A rich and creamy Classic Chicken Curry that's perfect for a comforting weeknight meal.
Tender chicken pieces are simmered in a luscious, spiced sauce with a hint of coconut, making
it an irresistible dish for the whole family. This recipe is designed to be straightforward,
delivering authentic flavors without requiring extensive culinary expertise. Enjoy it with
fluffy basmati rice or warm naan bread!
</p>
</div> </div>
@ingredientList(recipe.Ingredients) @ingredientList()
@instructionList(recipe.Instructions) @instructionList()
@tagList(recipe.Created, recipe.Modified) @tagList()
</div> </div>
</div> </div>
} }
templ metadataSection(recipe domain.Recipe) { templ metadataSection() {
<div <div
class="border border-blue-300 bg-blue-50 text-gray-700 mx-4 md:mx-8 rounded-lg flex flex-col class="border border-blue-300 bg-blue-50 text-gray-700 mx-4 md:mx-8 rounded-lg flex flex-col
md:flex-row justify-center items-center py-8" md:flex-row justify-center items-center py-8"
> >
<div class="flex flex-col items-center justify-center text-sm my-4 md:my-0 mx-4 w-full md:w-1/4"> <div class="flex flex-col items-center justify-center text-sm my-4 md:my-0 mx-4 w-full md:w-1/4">
@timeIcon() @timeIcon()
<p>Prep: { recipe.Duration.Prep } min</p> <p>Prep: 20 min</p>
<p>Cook: { recipe.Duration.Cook } min</p> <p>Cook: 45 min</p>
</div> </div>
<div <div
class="flex flex-col items-center justify-center text-sm my-4 md:my-0 mx-4 border-y md:border-y-0 md:border-x border-blue-300 py-8 w-9/10 md:w-fit md:py-0 px-8" class="flex flex-col items-center justify-center text-sm my-4 md:my-0 mx-4 border-y md:border-y-0 md:border-x border-blue-300 py-8 w-9/10 md:w-fit md:py-0 px-8"
> >
<div class="flex gap-x-1 my-2"> <div class="flex gap-x-1 my-2">
for _ = range recipe.Difficulty { @starIcon(true)
@starIcon(true) @starIcon(true)
} @starIcon(true)
for _ = range (5 - recipe.Difficulty) { @starIcon(false)
@starIcon(false) @starIcon(false)
}
</div> </div>
<p>{ recipe.Difficulty }</p> <p>Intermediate</p>
</div> </div>
<div class="flex flex-col items-center justify-center text-sm my-4 md:my-0 mx-4 w-1/4"> <div class="flex flex-col items-center justify-center text-sm my-4 md:my-0 mx-4 w-1/4">
@servingIcon() @servingIcon()
<p>Serves { recipe.Serves }</p> <p>Serves 4</p>
</div> </div>
</div> </div>
} }
templ ingredientList(ingredients []domain.RecipeIngredient) { templ ingredientList() {
<div class="px-4 py-8 md:px-8"> <div class="px-4 py-8 md:px-8">
<h2 class="text-2xl text-gray-800 font-semibold mb-2">Ingredients</h2> <h2 class="text-2xl text-gray-800 font-semibold mb-2">Ingredients</h2>
<hr class="text-gray-300"/> <hr class="text-gray-300"/>
<ul class="text-lg my-4 text-gray-700"> <ul class="text-lg my-4 text-gray-700">
for i, ingredient := range ingredients { @ingredientListItem("Chicken breast", "1lb", false)
@ingredientListItem(ingredient.Name, ingredient.Quantity, i%2 == 1) @ingredientListItem("Butter", "1/2 cup", true)
} @ingredientListItem("Heavy cream", "1 cup", false)
@ingredientListItem("Garlic powder", "1/4 tsp", true)
@ingredientListItem("Chicken breast", "1lb", false)
@ingredientListItem("Butter", "1/2 cup", true)
@ingredientListItem("Heavy cream", "1 cup", false)
@ingredientListItem("Garlic powder", "1/4 tsp", true)
</ul> </ul>
</div> </div>
} }
templ instructionList(instructions []string) { templ instructionList() {
<div class="px-4 py-8 md:px-8"> <div class="px-4 py-8 md:px-8">
<h2 class="text-2xl text-gray-800 font-semibold mb-2">Instructions</h2> <h2 class="text-2xl text-gray-800 font-semibold mb-2">Instructions</h2>
<hr class="text-gray-300"/> <hr class="text-gray-300"/>
<ul class="text-lg my-4 text-gray-700"> <ul class="text-lg my-4 text-gray-700">
for i, instruction := range instructions { @instructionListItem(`
@instructionListItem(i+1, instruction) Heat vegetable oil in a large skillet or Dutch oven over medium heat. Add chopped onion
} and cook until softened, about 5 minutes.
`, 1)
@instructionListItem(`
Stir in minced garlic and grated ginger, cooking for another minute until fragrant. Add the curry paste and cook
for 2-3 minutes, stirring constantly, to toast the spices.
`, 2)
@instructionListItem(`
Add the chicken cubes to the pan and cook until lightly browned on all sides.
`, 3)
@instructionListItem(`
Pour in the coconut milk, stirring to combine everything. Bring to a gentle simmer, then reduce heat to low,
cover, and cook for 20-25 minutes, or until chicken is cooked through and tender.
`, 4)
@instructionListItem(`
Taste and adjust seasonings if necessary. Garnish with fresh cilantro before serving. Serve hot with basmati
rice or naan bread.
`, 5)
</ul> </ul>
</div> </div>
} }
templ tagList(created time.Time, modified *time.Time) { templ tagList() {
<div class="px-4 py-4 md:px-8"> <div class="px-4 py-4 md:px-8">
<h2 class="text-2xl text-gray-800 font-semibold mb-2">Tags</h2> <h2 class="text-2xl text-gray-800 font-semibold mb-2">Tags</h2>
<hr class="text-gray-300"/> <hr class="text-gray-300"/>
@ -148,10 +169,8 @@ templ tagList(created time.Time, modified *time.Time) {
@tagListItem("high-protein") @tagListItem("high-protein")
</ul> </ul>
<hr class="text-gray-300"/> <hr class="text-gray-300"/>
<p class="my-4 mb-1.5 text-sm text-gray-700">Created: { created.Format("January 2, 2006") }</p> <p class="my-4 mb-1.5 text-sm text-gray-700">Created: January 2, 2025</p>
if modified != nil { <p class="mb-4 text-sm text-gray-700">Last Modified: February 14, 2025</p>
<p class="mb-4 text-sm text-gray-700">Last Modified: { modified.Format("January 2, 2006") }</p>
}
</div> </div>
} }
@ -178,7 +197,7 @@ templ ingredientListItem(name, quantity string, odd bool) {
</li> </li>
} }
templ instructionListItem(num int, content string) { templ instructionListItem(content string, num int) {
<li if num % 2==0 { <li if num % 2==0 {
class="p-4 flex items-start gap-x-4 bg-[#f8f8f8]" class="p-4 flex items-start gap-x-4 bg-[#f8f8f8]"
} else { } else {

View File

@ -8,12 +8,7 @@ package templates
import "github.com/a-h/templ" import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime" import templruntime "github.com/a-h/templ/runtime"
import ( import "github.com/haydenhargreaves/Potion/internal/templates/components"
domain "github.com/haydenhargreaves/Potion/internal/domain/recipe"
domainUser "github.com/haydenhargreaves/Potion/internal/domain/user"
"github.com/haydenhargreaves/Potion/internal/templates/components"
"time"
)
func servingIcon() templ.Component { func servingIcon() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
@ -109,7 +104,7 @@ func starIcon(filled bool) templ.Component {
}) })
} }
func RecipePage(recipe domain.Recipe, user domainUser.User) templ.Component { func RecipePage() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 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 templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@ -134,83 +129,31 @@ func RecipePage(recipe domain.Recipe, user domainUser.User) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div class=\"w-full flex justify-center\"><div class=\"mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 h-full border-l border-r border-gray-300 bg-white\"><img class=\"bg-gray-100 w-full h-96 mx-auto mb-8\" src=\"\" alt=\"\"><div class=\"px-4 py-8 md:px-8\"><h1 class=\"text-3xl md:text-4xl font-bold text-gray-800\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div class=\"w-full flex justify-center\"><div class=\"mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 h-full border-l border-r border-gray-300 bg-white\"><img class=\"bg-gray-100 w-full h-96 mx-auto mb-8\" src=\"\" alt=\"\"><div class=\"px-4 py-8 md:px-8\"><h1 class=\"text-3xl md:text-4xl font-bold text-gray-800\">Easy Chicken Alfredo</h1><p class=\"text-sm mt-2 mb-1 text-gray-700\">Author: Hayden Hargreaves</p><p class=\"text-sm mb-2 text-gray-700\">Category: Dinner</p></div>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var5 string templ_7745c5c3_Err = metadataSection().Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(recipe.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 72, Col: 75}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</h1><p class=\"text-sm mt-2 mb-1 text-gray-700\">Author: ") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"px-4 py-8 md:px-8\"><h3 class=\"text-xl text-gray-800 font-semibold mb-2\">About this recipe</h3><p class=\"text-gray-700\">A rich and creamy Classic Chicken Curry that's perfect for a comforting weeknight meal. Tender chicken pieces are simmered in a luscious, spiced sauce with a hint of coconut, making it an irresistible dish for the whole family. This recipe is designed to be straightforward, delivering authentic flavors without requiring extensive culinary expertise. Enjoy it with fluffy basmati rice or warm naan bread!</p></div>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var6 string templ_7745c5c3_Err = ingredientList().Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(user.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 73, Col: 66}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</p><p class=\"text-sm mb-2 text-gray-700\">Category: ") templ_7745c5c3_Err = instructionList().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var7 string templ_7745c5c3_Err = tagList().Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(recipe.Category)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 74, Col: 69}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</p></div>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = metadataSection(recipe).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<div class=\"px-4 py-8 md:px-8\"><h3 class=\"text-xl text-gray-800 font-semibold mb-2\">About this recipe</h3><p class=\"text-gray-700\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(recipe.Description)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 79, Col: 49}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</p></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = ingredientList(recipe.Ingredients).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = instructionList(recipe.Instructions).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = tagList(recipe.Created, recipe.Modified).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</div></div>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -218,7 +161,7 @@ func RecipePage(recipe domain.Recipe, user domainUser.User) templ.Component {
}) })
} }
func metadataSection(recipe domain.Recipe) templ.Component { func metadataSection() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 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 templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@ -234,12 +177,12 @@ func metadataSection(recipe domain.Recipe) templ.Component {
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var9 := templ.GetChildren(ctx) templ_7745c5c3_Var5 := templ.GetChildren(ctx)
if templ_7745c5c3_Var9 == nil { if templ_7745c5c3_Var5 == nil {
templ_7745c5c3_Var9 = templ.NopComponent templ_7745c5c3_Var5 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<div class=\"border border-blue-300 bg-blue-50 text-gray-700 mx-4 md:mx-8 rounded-lg flex flex-col \n md:flex-row justify-center items-center py-8\"><div class=\"flex flex-col items-center justify-center text-sm my-4 md:my-0 mx-4 w-full md:w-1/4\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"border border-blue-300 bg-blue-50 text-gray-700 mx-4 md:mx-8 rounded-lg flex flex-col \n md:flex-row justify-center items-center py-8\"><div class=\"flex flex-col items-center justify-center text-sm my-4 md:my-0 mx-4 w-full md:w-1/4\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -247,62 +190,31 @@ func metadataSection(recipe domain.Recipe) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<p>Prep: ") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<p>Prep: 20 min</p><p>Cook: 45 min</p></div><div class=\"flex flex-col items-center justify-center text-sm my-4 md:my-0 mx-4 border-y md:border-y-0 md:border-x border-blue-300 py-8 w-9/10 md:w-fit md:py-0 px-8\"><div class=\"flex gap-x-1 my-2\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var10 string templ_7745c5c3_Err = starIcon(true).Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(recipe.Duration.Prep)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 95, Col: 34}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, " min</p><p>Cook: ") templ_7745c5c3_Err = starIcon(true).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var11 string templ_7745c5c3_Err = starIcon(true).Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(recipe.Duration.Cook)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 96, Col: 34}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, " min</p></div><div class=\"flex flex-col items-center justify-center text-sm my-4 md:my-0 mx-4 border-y md:border-y-0 md:border-x border-blue-300 py-8 w-9/10 md:w-fit md:py-0 px-8\"><div class=\"flex gap-x-1 my-2\">") templ_7745c5c3_Err = starIcon(false).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
for _ = range recipe.Difficulty { templ_7745c5c3_Err = starIcon(false).Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Err = starIcon(true).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
for _ = range 5 - recipe.Difficulty {
templ_7745c5c3_Err = starIcon(false).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</div><p>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var12 string templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div><p>Intermediate</p></div><div class=\"flex flex-col items-center justify-center text-sm my-4 md:my-0 mx-4 w-1/4\">")
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(recipe.Difficulty)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 109, Col: 25}
}
_, 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, "</p></div><div class=\"flex flex-col items-center justify-center text-sm my-4 md:my-0 mx-4 w-1/4\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -310,20 +222,7 @@ func metadataSection(recipe domain.Recipe) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<p>Serves ") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<p>Serves 4</p></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(recipe.Serves)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 113, Col: 28}
}
_, 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, 19, "</p></div></div>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -331,7 +230,7 @@ func metadataSection(recipe domain.Recipe) templ.Component {
}) })
} }
func ingredientList(ingredients []domain.RecipeIngredient) templ.Component { func ingredientList() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 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 templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@ -347,22 +246,48 @@ func ingredientList(ingredients []domain.RecipeIngredient) templ.Component {
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var14 := templ.GetChildren(ctx) templ_7745c5c3_Var6 := templ.GetChildren(ctx)
if templ_7745c5c3_Var14 == nil { if templ_7745c5c3_Var6 == nil {
templ_7745c5c3_Var14 = templ.NopComponent templ_7745c5c3_Var6 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "<div class=\"px-4 py-8 md:px-8\"><h2 class=\"text-2xl text-gray-800 font-semibold mb-2\">Ingredients</h2><hr class=\"text-gray-300\"><ul class=\"text-lg my-4 text-gray-700\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<div class=\"px-4 py-8 md:px-8\"><h2 class=\"text-2xl text-gray-800 font-semibold mb-2\">Ingredients</h2><hr class=\"text-gray-300\"><ul class=\"text-lg my-4 text-gray-700\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
for i, ingredient := range ingredients { templ_7745c5c3_Err = ingredientListItem("Chicken breast", "1lb", false).Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Err = ingredientListItem(ingredient.Name, ingredient.Quantity, i%2 == 1).Render(ctx, templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil {
if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err
return templ_7745c5c3_Err
}
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</ul></div>") templ_7745c5c3_Err = ingredientListItem("Butter", "1/2 cup", true).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = ingredientListItem("Heavy cream", "1 cup", false).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = ingredientListItem("Garlic powder", "1/4 tsp", true).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = ingredientListItem("Chicken breast", "1lb", false).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = ingredientListItem("Butter", "1/2 cup", true).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = ingredientListItem("Heavy cream", "1 cup", false).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = ingredientListItem("Garlic powder", "1/4 tsp", true).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</ul></div>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -370,7 +295,7 @@ func ingredientList(ingredients []domain.RecipeIngredient) templ.Component {
}) })
} }
func instructionList(instructions []string) templ.Component { func instructionList() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 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 templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@ -386,22 +311,50 @@ func instructionList(instructions []string) templ.Component {
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var15 := templ.GetChildren(ctx) templ_7745c5c3_Var7 := templ.GetChildren(ctx)
if templ_7745c5c3_Var15 == nil { if templ_7745c5c3_Var7 == nil {
templ_7745c5c3_Var15 = templ.NopComponent templ_7745c5c3_Var7 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<div class=\"px-4 py-8 md:px-8\"><h2 class=\"text-2xl text-gray-800 font-semibold mb-2\">Instructions</h2><hr class=\"text-gray-300\"><ul class=\"text-lg my-4 text-gray-700\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<div class=\"px-4 py-8 md:px-8\"><h2 class=\"text-2xl text-gray-800 font-semibold mb-2\">Instructions</h2><hr class=\"text-gray-300\"><ul class=\"text-lg my-4 text-gray-700\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
for i, instruction := range instructions { templ_7745c5c3_Err = instructionListItem(`
templ_7745c5c3_Err = instructionListItem(i+1, instruction).Render(ctx, templ_7745c5c3_Buffer) Heat vegetable oil in a large skillet or Dutch oven over medium heat. Add chopped onion
if templ_7745c5c3_Err != nil { and cook until softened, about 5 minutes.
return templ_7745c5c3_Err `, 1).Render(ctx, templ_7745c5c3_Buffer)
} if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</ul></div>") templ_7745c5c3_Err = instructionListItem(`
Stir in minced garlic and grated ginger, cooking for another minute until fragrant. Add the curry paste and cook
for 2-3 minutes, stirring constantly, to toast the spices.
`, 2).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = instructionListItem(`
Add the chicken cubes to the pan and cook until lightly browned on all sides.
`, 3).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = instructionListItem(`
Pour in the coconut milk, stirring to combine everything. Bring to a gentle simmer, then reduce heat to low,
cover, and cook for 20-25 minutes, or until chicken is cooked through and tender.
`, 4).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = instructionListItem(`
Taste and adjust seasonings if necessary. Garnish with fresh cilantro before serving. Serve hot with basmati
rice or naan bread.
`, 5).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</ul></div>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -409,7 +362,7 @@ func instructionList(instructions []string) templ.Component {
}) })
} }
func tagList(created time.Time, modified *time.Time) templ.Component { func tagList() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 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 templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@ -425,12 +378,12 @@ func tagList(created time.Time, modified *time.Time) templ.Component {
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var16 := templ.GetChildren(ctx) templ_7745c5c3_Var8 := templ.GetChildren(ctx)
if templ_7745c5c3_Var16 == nil { if templ_7745c5c3_Var8 == nil {
templ_7745c5c3_Var16 = templ.NopComponent templ_7745c5c3_Var8 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<div class=\"px-4 py-4 md:px-8\"><h2 class=\"text-2xl text-gray-800 font-semibold mb-2\">Tags</h2><hr class=\"text-gray-300\"><ul id=\"tag-list\" class=\"my-4 flex gap-1 flex-wrap\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<div class=\"px-4 py-4 md:px-8\"><h2 class=\"text-2xl text-gray-800 font-semibold mb-2\">Tags</h2><hr class=\"text-gray-300\"><ul id=\"tag-list\" class=\"my-4 flex gap-1 flex-wrap\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -442,43 +395,7 @@ func tagList(created time.Time, modified *time.Time) templ.Component {
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</ul><hr class=\"text-gray-300\"><p class=\"my-4 mb-1.5 text-sm text-gray-700\">Created: ") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</ul><hr class=\"text-gray-300\"><p class=\"my-4 mb-1.5 text-sm text-gray-700\">Created: January 2, 2025</p><p class=\"mb-4 text-sm text-gray-700\">Last Modified: February 14, 2025</p></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(created.Format("January 2, 2006"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 151, Col: 91}
}
_, 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, 26, "</p>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if modified != nil {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<p class=\"mb-4 text-sm text-gray-700\">Last Modified: ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var18 string
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(modified.Format("January 2, 2006"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 153, Col: 92}
}
_, 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, 28, "</p>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</div>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -502,53 +419,53 @@ func ingredientListItem(name, quantity string, odd bool) templ.Component {
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var19 := templ.GetChildren(ctx) templ_7745c5c3_Var9 := templ.GetChildren(ctx)
if templ_7745c5c3_Var19 == nil { if templ_7745c5c3_Var9 == nil {
templ_7745c5c3_Var19 = templ.NopComponent templ_7745c5c3_Var9 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<li") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "<li")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
if odd { if odd {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, " class=\"p-2 hover:bg-gray-100 transition-all duration-300 rounded-sm flex items-center justify-start bg-[#f8f8f8]\"") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, " class=\"p-2 hover:bg-gray-100 transition-all duration-300 rounded-sm flex items-center justify-start bg-[#f8f8f8]\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} else { } else {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, " class=\"p-2 hover:bg-gray-100 transition-all duration-300 rounded-sm flex items-center justify-start\"") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, " class=\"p-2 hover:bg-gray-100 transition-all duration-300 rounded-sm flex items-center justify-start\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "><span class=\"mr-4\"><svg class=\"h-4 text-gray-400\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></svg></span> <span class=\"font-semibold mr-2\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "><span class=\"mr-4\"><svg class=\"h-4 text-gray-400\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></svg></span> <span class=\"font-semibold mr-2\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var20 string var templ_7745c5c3_Var10 string
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(quantity) templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(quantity)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 177, Col: 45} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 196, Col: 45}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, ": </span> ") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, ": </span> ")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var21 string var templ_7745c5c3_Var11 string
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(name) templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(name)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 177, Col: 63} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 196, Col: 63}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</li>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "</li>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -556,7 +473,7 @@ func ingredientListItem(name, quantity string, odd bool) templ.Component {
}) })
} }
func instructionListItem(num int, content string) templ.Component { func instructionListItem(content string, num int) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 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 templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@ -572,53 +489,53 @@ func instructionListItem(num int, content string) templ.Component {
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var22 := templ.GetChildren(ctx) templ_7745c5c3_Var12 := templ.GetChildren(ctx)
if templ_7745c5c3_Var22 == nil { if templ_7745c5c3_Var12 == nil {
templ_7745c5c3_Var22 = templ.NopComponent templ_7745c5c3_Var12 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<li") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<li")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
if num%2 == 0 { if num%2 == 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, " class=\"p-4 flex items-start gap-x-4 bg-[#f8f8f8]\"") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, " class=\"p-4 flex items-start gap-x-4 bg-[#f8f8f8]\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} else { } else {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, " class=\"p-4 flex items-start gap-x-4\"") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, " class=\"p-4 flex items-start gap-x-4\"")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "><div class=\"size-10 bg-blue-50 rounded-full flex items-center justify-center flex-shrink-0\"><h3 class=\"text-blue-600 font-semibold\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "><div class=\"size-10 bg-blue-50 rounded-full flex items-center justify-center flex-shrink-0\"><h3 class=\"text-blue-600 font-semibold\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var23 string var templ_7745c5c3_Var13 string
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(num) templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(num)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 188, Col: 48} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 207, Col: 48}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "</h3></div><p class=\"\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "</h3></div><p class=\"\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var24 string var templ_7745c5c3_Var14 string
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(content) templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(content)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 190, Col: 23} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 209, Col: 23}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</p></li>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</p></li>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -642,25 +559,25 @@ func tagListItem(content string) templ.Component {
}() }()
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var25 := templ.GetChildren(ctx) templ_7745c5c3_Var15 := templ.GetChildren(ctx)
if templ_7745c5c3_Var25 == nil { if templ_7745c5c3_Var15 == nil {
templ_7745c5c3_Var25 = templ.NopComponent templ_7745c5c3_Var15 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "<li class=\"text-sm items-center bg-blue-100 text-blue-700 w-fit px-3 py-1.5 rounded-full\">") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<li class=\"text-sm items-center bg-blue-100 text-blue-700 w-fit px-3 py-1.5 rounded-full\">")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var26 string var templ_7745c5c3_Var16 string
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(content) templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(content)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 196, Col: 11} return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/recipe.templ`, Line: 215, Col: 11}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</li>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "</li>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }