Merge pull request '(UI/STYLE): Implemented the first rendition of the profile page.' (#17) from feature/profile into master
Reviewed-on: #17
This commit is contained in:
commit
db447b3a7d
@ -213,6 +213,35 @@ creation process will take place here
|
||||
|
||||
|
||||
|
||||
##### UI Requirements
|
||||
|
||||
- [ ] User details section
|
||||
- [ ] Google details: profile picture, full name and email
|
||||
|
||||
- [ ] User recipe section
|
||||
- [ ] List of all the recipes created by the user
|
||||
- [ ] Paginated? **Maybe a max size and a button for seeing them all***
|
||||
- [ ] Short and sweet, not much data displayed, no image and no description
|
||||
- [ ] Different layout then used elsewhere, spanned across the entire page
|
||||
|
||||
- [ ] User saved recipe section
|
||||
- [ ] List of all the recipes liked/saved by the user
|
||||
- [ ] Max size of **x*** amount, a see all button will take the user to their favorites page
|
||||
- [ ] Should look the like section above
|
||||
|
||||
- [ ] User activity section
|
||||
- [ ] List of all recent "engagement" the user has created
|
||||
- [ ] Just a message and a date
|
||||
|
||||
|
||||
'*': Not sure yet, still under consideration
|
||||
|
||||
|
||||
##### API Requirements
|
||||
|
||||
|
||||
|
||||
|
||||
## Database Requirements
|
||||
|
||||
This section outlines the specific technical requirements for the database store for
|
||||
|
||||
@ -58,9 +58,18 @@ func ProfilePage(ctx *gin.Context) {
|
||||
// Else, get the user data
|
||||
deps := ctx.MustGet("deps").(*domainServer.InjectedDependencies)
|
||||
user := deps.UserService.GetAuthenicatedUser(ctx)
|
||||
recipes, err := deps.RecipeService.GetUserRecipes(user.Id)
|
||||
if err != nil {
|
||||
fmt.Printf("Error getting recipes. %s\n", err.Error())
|
||||
ctx.JSON(http.StatusInternalServerError, gin.H{
|
||||
"status": http.StatusInternalServerError,
|
||||
"message": fmt.Sprintf("Error getting recipes. %s\n", err.Error()),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
title := "Potion - Profile"
|
||||
page := pages.ProfilePage(user)
|
||||
page := pages.ProfilePage(user, recipes)
|
||||
|
||||
ctx.HTML(http.StatusOK, "", layouts.AppLayout(title, page))
|
||||
}
|
||||
|
||||
@ -1 +1,49 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
domain "github.com/haydenhargreaves/Potion/internal/domain/server"
|
||||
)
|
||||
|
||||
func GetUserRecipes(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.GetUserRecipes(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,
|
||||
})
|
||||
}
|
||||
|
||||
@ -181,6 +181,7 @@ func (s *Server) Setup() *Server {
|
||||
// Recipe endpoints
|
||||
router_api.POST("/recipe", handlers.CreateRecipe)
|
||||
router_api.POST("/recipe/search", handlers.SearchRecipes)
|
||||
router_api.GET("/user/recipes", handlers.GetUserRecipes)
|
||||
|
||||
// Catch un-routed URLS
|
||||
s.Router.NoRoute(func(ctx *gin.Context) {
|
||||
|
||||
@ -150,3 +150,7 @@ func (s *RecipeService) GetRecipe(id int) (*domain.Recipe, error) {
|
||||
func (s *RecipeService) SearchRecipes(filters domain.SearchFilters) ([]domain.Recipe, error) {
|
||||
return s.recipeRepository.SearchRecipes(filters)
|
||||
}
|
||||
|
||||
func (s *RecipeService) GetUserRecipes(id int) ([]domain.Recipe, error) {
|
||||
return s.recipeRepository.GetUserRecipes(id)
|
||||
}
|
||||
|
||||
@ -5,4 +5,6 @@ type RecipeRepository interface {
|
||||
GetRecipe(id int) (*Recipe, error)
|
||||
SearchRecipes(filters SearchFilters) ([]Recipe, error)
|
||||
CreateRecipeTags(recipe Recipe, tags []string) error
|
||||
GetUserRecipes(id int) ([]Recipe, error)
|
||||
GetRecipeTags(recipe *Recipe) error
|
||||
}
|
||||
|
||||
@ -6,4 +6,5 @@ type RecipeService interface {
|
||||
CreateRecipe(ctx *gin.Context) (*Recipe, error)
|
||||
GetRecipe(id int) (*Recipe, error)
|
||||
SearchRecipes(filters SearchFilters) ([]Recipe, error)
|
||||
GetUserRecipes(id int) ([]Recipe, error)
|
||||
}
|
||||
|
||||
@ -128,34 +128,6 @@ func (r *RecipeRepository) GetRecipe(id int) (*domain.Recipe, error) {
|
||||
return nil, fmt.Errorf("Failed to location recipe in database: %s", err.Error())
|
||||
}
|
||||
|
||||
// Get tags from external tables
|
||||
query = `
|
||||
SELECT t.* FROM tags t
|
||||
JOIN recipetags rt ON rt.tagid = t.id
|
||||
WHERE rt.recipeid = $1;
|
||||
`
|
||||
rows, err := tx.Query(query, recipe.Id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to get tags for recipe. %s\n", err.Error())
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var tag domain.Tag
|
||||
|
||||
err := rows.Scan(&tag.Id, &tag.Name, &tag.Created)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to scan tag onto domain model. %s\n", err.Error())
|
||||
}
|
||||
|
||||
recipe.Tags = append(recipe.Tags, tag)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
tx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Parse duration
|
||||
if len(durationBytes) > 0 {
|
||||
var duration domain.RecipeDuration
|
||||
@ -180,6 +152,14 @@ func (r *RecipeRepository) GetRecipe(id int) (*domain.Recipe, error) {
|
||||
recipe.Ingredients = []domain.RecipeIngredient{}
|
||||
}
|
||||
|
||||
// Add tags
|
||||
r.GetRecipeTags(&recipe)
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
tx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &recipe, nil
|
||||
}
|
||||
|
||||
@ -387,6 +367,9 @@ func (r *RecipeRepository) SearchRecipes(filters domain.SearchFilters) ([]domain
|
||||
recipe.Ingredients = []domain.RecipeIngredient{}
|
||||
}
|
||||
|
||||
// Add tags
|
||||
r.GetRecipeTags(&recipe)
|
||||
|
||||
recipes = append(recipes, recipe)
|
||||
}
|
||||
|
||||
@ -456,3 +439,135 @@ func (r *RecipeRepository) CreateRecipeTags(recipe domain.Recipe, tags []string)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetUserRecipes gets a list of a users owned recipes. This function does not ensure the user is
|
||||
// authenticated or exists. If nothing is found, a blank slice will be returned. The resulting list
|
||||
// is sorted by the created dates, newest first. Any errors will be bubbled to the caller.
|
||||
func (r *RecipeRepository) GetUserRecipes(id int) ([]domain.Recipe, error) {
|
||||
tx, err := r.db.Begin()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := `
|
||||
SELECT id, title, description, instructions, serves, difficulty, duration, category, ingredients,
|
||||
userid, modified, created
|
||||
FROM recipes
|
||||
WHERE userid = $1
|
||||
ORDER BY 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()
|
||||
|
||||
// Prepare statement for tag query
|
||||
// tagQuery := `
|
||||
// `
|
||||
|
||||
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
|
||||
r.GetRecipeTags(&recipe)
|
||||
|
||||
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.
|
||||
func (r *RecipeRepository) GetRecipeTags(recipe *domain.Recipe) error {
|
||||
tx, err := r.db.Begin()
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
recipe.Tags = []domain.Tag{}
|
||||
|
||||
query := `
|
||||
SELECT t.* FROM tags t
|
||||
JOIN recipetags rt ON rt.tagid = t.id
|
||||
WHERE rt.recipeid = $1;
|
||||
`
|
||||
rows, err := tx.Query(query, recipe.Id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to get tags for recipe. %s\n", err.Error())
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var tag domain.Tag
|
||||
|
||||
err := rows.Scan(&tag.Id, &tag.Name, &tag.Created)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to scan tag onto domain model. %s\n", err.Error())
|
||||
}
|
||||
|
||||
recipe.Tags = append(recipe.Tags, tag)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1,28 +1,167 @@
|
||||
package templates
|
||||
|
||||
import "github.com/haydenhargreaves/Potion/internal/templates/components"
|
||||
import "fmt"
|
||||
import "strings"
|
||||
import domain "github.com/haydenhargreaves/Potion/internal/domain/server"
|
||||
import domain_user"github.com/haydenhargreaves/Potion/internal/domain/user"
|
||||
import domainRecipe "github.com/haydenhargreaves/Potion/internal/domain/recipe"
|
||||
import domainUser "github.com/haydenhargreaves/Potion/internal/domain/user"
|
||||
|
||||
templ userDetailsSection(user domain_user.User) {
|
||||
func displayDifficulty(diff int) string {
|
||||
switch diff {
|
||||
case 1:
|
||||
return "Beginner"
|
||||
case 2:
|
||||
return "Easy"
|
||||
case 3:
|
||||
return "Intermediate"
|
||||
case 4:
|
||||
return "Challenging"
|
||||
case 5:
|
||||
return "Extreme"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func displayTags(tags []domainRecipe.Tag) string {
|
||||
names := make([]string, 0, len(tags))
|
||||
for _, tag := range tags {
|
||||
names = append(names, tag.Name)
|
||||
}
|
||||
return strings.Join(names, ", ")
|
||||
}
|
||||
|
||||
templ userDetailsSection(user domainUser.User, recipeCount int) {
|
||||
<section class="w-full flex flex-col justify-center my-8 py-4 border-b border-gray-300">
|
||||
<div class="w-full p-4 md:p-8 flex items-center gap-x-8">
|
||||
if user.ImageUrl != "" {
|
||||
<img
|
||||
class="w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none"
|
||||
src={ user.ImageUrl }
|
||||
/>
|
||||
<div class="">
|
||||
<h1 class="text-md md:text-2xl font-semibold">{ user.Name }</h1>
|
||||
<p class="text-xs md:text-sm">{ user.Email }</p>
|
||||
} else {
|
||||
<img
|
||||
class="w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none"
|
||||
src={ fmt.Sprintf("https://ui-avatars.com/api/?name=%s+%s&size=150", strings.Split(user.Name, " ")[0], strings.Split(user.Name, " ")[1])}
|
||||
/>
|
||||
|
||||
}
|
||||
<div class="flex flex-col gap-y-4">
|
||||
<div class="">
|
||||
<h1 class="text-md md:text-2xl font-semibold">{ user.Name }</h1>
|
||||
<p class="text-xs md:text-sm">{ user.Email }</p>
|
||||
</div>
|
||||
<div class="flex gap-x-4">
|
||||
<p class="text-xs md:text-sm"><span class="font-bold">{ recipeCount }</span> recipes</p>
|
||||
<p class="text-xs md:text-sm"><span class="font-bold">0</span> favorites</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
|
||||
templ recipesSection(recipes []domainRecipe.Recipe) {
|
||||
<section class="p-8">
|
||||
<h2 class="text-2xl font-semibold text-gray-800">My Recipes</h2>
|
||||
<ul class="w-full my-2">
|
||||
if len(recipes) <= 4 {
|
||||
for _, recipe :=range recipes {
|
||||
@recipeListItem(recipe)
|
||||
}
|
||||
} else {
|
||||
for _, recipe := range recipes[:4] {
|
||||
@recipeListItem(recipe)
|
||||
}
|
||||
}
|
||||
<a href="/" class="bg-red-500">
|
||||
<li
|
||||
class="w-full border-b border-gray-300 px-2 py-4 even:bg-gray-50 hover:bg-gray-100 hover:text-blue-600 duration-150 text-center"
|
||||
>
|
||||
See all...
|
||||
</li>
|
||||
</a>
|
||||
</ul>
|
||||
</section>
|
||||
}
|
||||
|
||||
templ favoritesSection(recipes []domainRecipe.Recipe) {
|
||||
<section class="p-8">
|
||||
<h2 class="text-2xl font-semibold text-gray-800">My Favorites</h2>
|
||||
<p class="text-sm my-2">Favorites section is under construction!</p>
|
||||
</section>
|
||||
}
|
||||
|
||||
templ activitySection() {
|
||||
<section class="p-8">
|
||||
<h2 class="text-2xl font-semibold text-gray-800">Recent Activity</h2>
|
||||
<p class="text-sm my-2">Activity section is under construction!</p>
|
||||
<!--
|
||||
<ul class="w-full my-2">
|
||||
@activityListItem()
|
||||
@activityListItem()
|
||||
@activityListItem()
|
||||
@activityListItem()
|
||||
@activityListItem()
|
||||
@activityListItem()
|
||||
<a href="/" class="bg-red-500">
|
||||
<li
|
||||
class="w-full border-b border-gray-300 px-2 py-4 even:bg-gray-50 hover:bg-gray-100 hover:text-blue-600 duration-150 text-center"
|
||||
>
|
||||
See all...
|
||||
</li>
|
||||
</a>
|
||||
</ul>
|
||||
-->
|
||||
</section>
|
||||
}
|
||||
|
||||
templ recipeListItem(recipe domainRecipe.Recipe) {
|
||||
<li class="w-full border-b border-gray-300 px-2 py-4 even:bg-gray-50 hover:bg-gray-100 duration-150">
|
||||
<p class="text-base md:text-lg">
|
||||
<a href={ templ.SafeURL(fmt.Sprintf(domain.WEB_RECIPE, recipe.Id)) } class="hover:text-blue-600 duration-100">
|
||||
{ recipe.Title }
|
||||
</a>
|
||||
</p>
|
||||
<p class="hidden md:block text-sm text-gray-700 my-1.5">
|
||||
Difficulty: <span class="font-semibold">{ displayDifficulty(recipe.Difficulty) }</span>
|
||||
| Duration: <span class="font-semibold">{ recipe.Duration.Total } min</span>
|
||||
| Category: <span class="font-semibold">{ recipe.Category }</span>
|
||||
</p>
|
||||
<p class="md:hidden text-xs md:text-sm text-gray-700 my-1">
|
||||
Difficulty: <span class="font-semibold">{ displayDifficulty(recipe.Difficulty) }</span>
|
||||
</p>
|
||||
<p class="md:hidden text-xs md:text-sm text-gray-700 my-1">
|
||||
Duration: <span class="font-semibold">{ recipe.Duration.Total } min</span>
|
||||
</p>
|
||||
<p class="md:hidden text-xs md:text-sm text-gray-700 my-1">
|
||||
Category: <span class="font-semibold">{ recipe.Category }</span>
|
||||
</p>
|
||||
if len(recipe.Tags) > 0 {
|
||||
<p class="text-xs italic text-gray-500">
|
||||
Tags: { displayTags(recipe.Tags) }
|
||||
</p>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
|
||||
templ activityListItem() {
|
||||
<li
|
||||
class="w-full border-b border-gray-300 px-2 py-4 even:bg-gray-50 hover:bg-gray-100 duration-150 flex justify-between items-center"
|
||||
>
|
||||
<p class="text-sm md:text-base text-gray-800">
|
||||
Rated "Spicy Chicken Wings"
|
||||
</p>
|
||||
<p class="text-xs md:text-sm text-gray-600 w-fit shrink-0">
|
||||
2 days ago
|
||||
</p>
|
||||
</li>
|
||||
}
|
||||
|
||||
templ logoutSection() {
|
||||
<section class="w-full flex flex-col justify-center items-center py-8 border-t border-gray-300">
|
||||
<section class="w-full flex flex-col justify-center items-center py-8 border-t border-gray-300 mt-auto">
|
||||
<a
|
||||
href={domain.API_AUTH_LOGOUT}
|
||||
href={ domain.API_AUTH_LOGOUT }
|
||||
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
|
||||
@ -30,13 +169,14 @@ templ logoutSection() {
|
||||
</section>
|
||||
}
|
||||
|
||||
templ ProfilePage(user domain_user.User) {
|
||||
templ ProfilePage(user domainUser.User, recipes []domainRecipe.Recipe) {
|
||||
@components.Navbar(" profile")
|
||||
<div class="w-full h-screen flex justify-center">
|
||||
<div
|
||||
class="mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 border-l border-r border-gray-300 bg-white flex flex-col justify-between"
|
||||
>
|
||||
@userDetailsSection(user)
|
||||
<div class="w-full h-fit flex justify-center">
|
||||
<div class="mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 border-l border-r border-gray-300 bg-white flex flex-col">
|
||||
@userDetailsSection(user, len(recipes))
|
||||
@recipesSection(recipes)
|
||||
@favoritesSection(recipes)
|
||||
@activitySection()
|
||||
@logoutSection()
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -9,10 +9,38 @@ import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import "github.com/haydenhargreaves/Potion/internal/templates/components"
|
||||
import "fmt"
|
||||
import "strings"
|
||||
import domain "github.com/haydenhargreaves/Potion/internal/domain/server"
|
||||
import domain_user "github.com/haydenhargreaves/Potion/internal/domain/user"
|
||||
import domainRecipe "github.com/haydenhargreaves/Potion/internal/domain/recipe"
|
||||
import domainUser "github.com/haydenhargreaves/Potion/internal/domain/user"
|
||||
|
||||
func userDetailsSection(user domain_user.User) templ.Component {
|
||||
func displayDifficulty(diff int) string {
|
||||
switch diff {
|
||||
case 1:
|
||||
return "Beginner"
|
||||
case 2:
|
||||
return "Easy"
|
||||
case 3:
|
||||
return "Intermediate"
|
||||
case 4:
|
||||
return "Challenging"
|
||||
case 5:
|
||||
return "Extreme"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func displayTags(tags []domainRecipe.Tag) string {
|
||||
names := make([]string, 0, len(tags))
|
||||
for _, tag := range tags {
|
||||
names = append(names, tag.Name)
|
||||
}
|
||||
return strings.Join(names, ", ")
|
||||
}
|
||||
|
||||
func userDetailsSection(user domainUser.User, recipeCount int) 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 {
|
||||
@ -33,46 +61,374 @@ func userDetailsSection(user domain_user.User) templ.Component {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<section class=\"w-full flex flex-col justify-center my-8 py-4 border-b border-gray-300\"><div class=\"w-full p-4 md:p-8 flex items-center gap-x-8\"><img class=\"w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none\" src=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<section class=\"w-full flex flex-col justify-center my-8 py-4 border-b border-gray-300\"><div class=\"w-full p-4 md:p-8 flex items-center gap-x-8\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(user.ImageUrl)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 12, Col: 23}
|
||||
if user.ImageUrl != "" {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<img class=\"w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none\" src=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(user.ImageUrl)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 41, Col: 23}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<img class=\"w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none\" src=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
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: 46, Col: 140}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"><div class=\"\"><h1 class=\"text-md md:text-2xl font-semibold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(user.Name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 15, Col: 61}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h1><p class=\"text-xs md:text-sm\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"flex flex-col gap-y-4\"><div class=\"\"><h1 class=\"text-md md:text-2xl font-semibold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(user.Email)
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(user.Name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 16, Col: 46}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 52, Col: 62}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p></div></div></section>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</h1><p class=\"text-xs md:text-sm\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(user.Email)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 53, Col: 47}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</p></div><div class=\"flex gap-x-4\"><p class=\"text-xs md:text-sm\"><span class=\"font-bold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(recipeCount)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 56, Col: 72}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</span> recipes</p><p class=\"text-xs md:text-sm\"><span class=\"font-bold\">0</span> favorites</p></div></div></div></section>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func recipesSection(recipes []domainRecipe.Recipe) 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 {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var7 == nil {
|
||||
templ_7745c5c3_Var7 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<section class=\"p-8\"><h2 class=\"text-2xl font-semibold text-gray-800\">My Recipes</h2><ul class=\"w-full my-2\">")
|
||||
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, 11, "<a href=\"/\" class=\"bg-red-500\"><li class=\"w-full border-b border-gray-300 px-2 py-4 even:bg-gray-50 hover:bg-gray-100 hover:text-blue-600 duration-150 text-center\">See all...</li></a></ul></section>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func favoritesSection(recipes []domainRecipe.Recipe) 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 {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var8 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var8 == nil {
|
||||
templ_7745c5c3_Var8 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<section class=\"p-8\"><h2 class=\"text-2xl font-semibold text-gray-800\">My Favorites</h2><p class=\"text-sm my-2\">Favorites section is under construction!</p></section>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func activitySection() 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 {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var9 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var9 == nil {
|
||||
templ_7745c5c3_Var9 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<section class=\"p-8\"><h2 class=\"text-2xl font-semibold text-gray-800\">Recent Activity</h2><p class=\"text-sm my-2\">Activity section is under construction!</p><!--\n\t\t<ul class=\"w-full my-2\">\n\t\t\t@activityListItem()\n\t\t\t@activityListItem()\n\t\t\t@activityListItem()\n\t\t\t@activityListItem()\n\t\t\t@activityListItem()\n\t\t\t@activityListItem()\n\t\t\t<a href=\"/\" class=\"bg-red-500\">\n\t\t\t\t<li\n\t\t\t\t\tclass=\"w-full border-b border-gray-300 px-2 py-4 even:bg-gray-50 hover:bg-gray-100 hover:text-blue-600 duration-150 text-center\"\n\t\t\t\t>\n\t\t\t\t\tSee all...\n\t\t\t\t</li>\n\t\t\t</a>\n\t\t</ul>\n --></section>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func recipeListItem(recipe domainRecipe.Recipe) 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 {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var10 == nil {
|
||||
templ_7745c5c3_Var10 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<li class=\"w-full border-b border-gray-300 px-2 py-4 even:bg-gray-50 hover:bg-gray-100 duration-150\"><p class=\"text-base md:text-lg\"><a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var11 templ.SafeURL = templ.SafeURL(fmt.Sprintf(domain.WEB_RECIPE, recipe.Id))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var11)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "\" class=\"hover:text-blue-600 duration-100\">")
|
||||
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: 123, Col: 18}
|
||||
}
|
||||
_, 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, 16, "</a></p><p class=\"hidden md:block text-sm text-gray-700 my-1.5\">Difficulty: <span class=\"font-semibold\">")
|
||||
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: 127, 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, 17, "</span> | Duration: <span class=\"font-semibold\">")
|
||||
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: 128, 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, 18, " min</span> | Category: <span class=\"font-semibold\">")
|
||||
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: 129, 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, 19, "</span></p><p class=\"md:hidden text-xs md:text-sm text-gray-700 my-1\">Difficulty: <span class=\"font-semibold\">")
|
||||
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: 132, 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, 20, "</span></p><p class=\"md:hidden text-xs md:text-sm text-gray-700 my-1\">Duration: <span class=\"font-semibold\">")
|
||||
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: 135, 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, 21, " min</span></p><p class=\"md:hidden text-xs md:text-sm text-gray-700 my-1\">Category: <span class=\"font-semibold\">")
|
||||
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: 138, 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, 22, "</span></p>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if len(recipe.Tags) > 0 {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<p class=\"text-xs italic text-gray-500\">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: 142, 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, 24, "</p>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func activityListItem() 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 {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var20 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var20 == nil {
|
||||
templ_7745c5c3_Var20 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<li class=\"w-full border-b border-gray-300 px-2 py-4 even:bg-gray-50 hover:bg-gray-100 duration-150 flex justify-between items-center\"><p class=\"text-sm md:text-base text-gray-800\">Rated \"Spicy Chicken Wings\"</p><p class=\"text-xs md:text-sm text-gray-600 w-fit shrink-0\">2 days ago</p></li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -96,21 +452,21 @@ func logoutSection() templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
templ_7745c5c3_Var21 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var21 == nil {
|
||||
templ_7745c5c3_Var21 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<section class=\"w-full flex flex-col justify-center items-center py-8 border-t border-gray-300\"><a href=\"")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "<section class=\"w-full flex flex-col justify-center items-center py-8 border-t border-gray-300 mt-auto\"><a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 templ.SafeURL = domain.API_AUTH_LOGOUT
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6)))
|
||||
var templ_7745c5c3_Var22 templ.SafeURL = domain.API_AUTH_LOGOUT
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var22)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" 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</a></section>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "\" 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</a></section>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -118,7 +474,7 @@ func logoutSection() templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
func ProfilePage(user domain_user.User) templ.Component {
|
||||
func ProfilePage(user domainUser.User, recipes []domainRecipe.Recipe) 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 {
|
||||
@ -134,20 +490,32 @@ func ProfilePage(user domain_user.User) templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var7 == nil {
|
||||
templ_7745c5c3_Var7 = templ.NopComponent
|
||||
templ_7745c5c3_Var23 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var23 == nil {
|
||||
templ_7745c5c3_Var23 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = components.Navbar(" profile").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<div class=\"w-full h-screen flex justify-center\"><div class=\"mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 border-l border-r border-gray-300 bg-white flex flex-col justify-between\">")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "<div class=\"w-full h-fit flex justify-center\"><div class=\"mx-2 md:mx-0 w-full md:w-1/2 md:pt-14 border-l border-r border-gray-300 bg-white flex flex-col\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = userDetailsSection(user).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = userDetailsSection(user, len(recipes)).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = recipesSection(recipes).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = favoritesSection(recipes).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = activitySection().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -155,7 +523,7 @@ func ProfilePage(user domain_user.User) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
--color-blue-500: oklch(62.3% 0.214 259.815);
|
||||
--color-blue-600: oklch(54.6% 0.245 262.881);
|
||||
--color-blue-700: oklch(48.8% 0.243 264.376);
|
||||
--color-blue-800: oklch(42.4% 0.199 265.638);
|
||||
--color-purple-100: oklch(94.6% 0.033 307.174);
|
||||
--color-purple-200: oklch(90.2% 0.063 306.703);
|
||||
--color-gray-50: oklch(98.5% 0.002 247.839);
|
||||
@ -29,6 +28,7 @@
|
||||
--color-gray-600: oklch(44.6% 0.03 256.802);
|
||||
--color-gray-700: oklch(37.3% 0.034 259.733);
|
||||
--color-gray-800: oklch(27.8% 0.033 256.848);
|
||||
--color-gray-900: oklch(21% 0.034 264.665);
|
||||
--color-black: #000;
|
||||
--color-white: #fff;
|
||||
--spacing: 0.25rem;
|
||||
@ -49,8 +49,6 @@
|
||||
--text-3xl--line-height: calc(2.25 / 1.875);
|
||||
--text-4xl: 2.25rem;
|
||||
--text-4xl--line-height: calc(2.5 / 2.25);
|
||||
--text-5xl: 3rem;
|
||||
--text-5xl--line-height: 1;
|
||||
--text-6xl: 3.75rem;
|
||||
--text-6xl--line-height: 1;
|
||||
--text-8xl: 6rem;
|
||||
@ -240,6 +238,9 @@
|
||||
.static {
|
||||
position: static;
|
||||
}
|
||||
.top-1 {
|
||||
top: calc(var(--spacing) * 1);
|
||||
}
|
||||
.top-1\/2 {
|
||||
top: calc(1/2 * 100%);
|
||||
}
|
||||
@ -249,6 +250,9 @@
|
||||
.left-0 {
|
||||
left: calc(var(--spacing) * 0);
|
||||
}
|
||||
.left-1 {
|
||||
left: calc(var(--spacing) * 1);
|
||||
}
|
||||
.left-1\/2 {
|
||||
left: calc(1/2 * 100%);
|
||||
}
|
||||
@ -273,6 +277,9 @@
|
||||
.my-1 {
|
||||
margin-block: calc(var(--spacing) * 1);
|
||||
}
|
||||
.my-1\.5 {
|
||||
margin-block: calc(var(--spacing) * 1.5);
|
||||
}
|
||||
.my-2 {
|
||||
margin-block: calc(var(--spacing) * 2);
|
||||
}
|
||||
@ -300,6 +307,9 @@
|
||||
.mt-16 {
|
||||
margin-top: calc(var(--spacing) * 16);
|
||||
}
|
||||
.mt-auto {
|
||||
margin-top: auto;
|
||||
}
|
||||
.mr-2 {
|
||||
margin-right: calc(var(--spacing) * 2);
|
||||
}
|
||||
@ -410,12 +420,18 @@
|
||||
.min-h-screen {
|
||||
min-height: 100vh;
|
||||
}
|
||||
.w-1 {
|
||||
width: calc(var(--spacing) * 1);
|
||||
}
|
||||
.w-1\/3 {
|
||||
width: calc(1/3 * 100%);
|
||||
}
|
||||
.w-1\/4 {
|
||||
width: calc(1/4 * 100%);
|
||||
}
|
||||
.w-3 {
|
||||
width: calc(var(--spacing) * 3);
|
||||
}
|
||||
.w-3\/4 {
|
||||
width: calc(3/4 * 100%);
|
||||
}
|
||||
@ -428,6 +444,9 @@
|
||||
.w-5 {
|
||||
width: calc(var(--spacing) * 5);
|
||||
}
|
||||
.w-9 {
|
||||
width: calc(var(--spacing) * 9);
|
||||
}
|
||||
.w-9\/10 {
|
||||
width: calc(9/10 * 100%);
|
||||
}
|
||||
@ -446,16 +465,33 @@
|
||||
.max-w-2xl {
|
||||
max-width: var(--container-2xl);
|
||||
}
|
||||
.flex-shrink {
|
||||
flex-shrink: 1;
|
||||
}
|
||||
.flex-shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.flex-grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.border-collapse {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.-translate-x-1 {
|
||||
--tw-translate-x: calc(var(--spacing) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.-translate-x-1\/2 {
|
||||
--tw-translate-x: calc(calc(1/2 * 100%) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.-translate-y-1 {
|
||||
--tw-translate-y: calc(var(--spacing) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.-translate-y-1\/2 {
|
||||
--tw-translate-y: calc(calc(1/2 * 100%) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
@ -468,9 +504,15 @@
|
||||
--tw-scale-y: 50%;
|
||||
scale: var(--tw-scale-x) var(--tw-scale-y);
|
||||
}
|
||||
.transform {
|
||||
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
|
||||
}
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
.resize {
|
||||
resize: both;
|
||||
}
|
||||
.resize-none {
|
||||
resize: none;
|
||||
}
|
||||
@ -645,6 +687,9 @@
|
||||
.bg-red-100 {
|
||||
background-color: var(--color-red-100);
|
||||
}
|
||||
.bg-red-500 {
|
||||
background-color: var(--color-red-500);
|
||||
}
|
||||
.bg-white {
|
||||
background-color: var(--color-white);
|
||||
}
|
||||
@ -656,6 +701,9 @@
|
||||
--tw-gradient-position: to right in oklab;
|
||||
background-image: linear-gradient(var(--tw-gradient-stops));
|
||||
}
|
||||
.bg-none {
|
||||
background-image: none;
|
||||
}
|
||||
.from-blue-100 {
|
||||
--tw-gradient-from: var(--color-blue-100);
|
||||
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
|
||||
@ -686,6 +734,9 @@
|
||||
.p-4 {
|
||||
padding: calc(var(--spacing) * 4);
|
||||
}
|
||||
.p-8 {
|
||||
padding: calc(var(--spacing) * 8);
|
||||
}
|
||||
.px-1 {
|
||||
padding-inline: calc(var(--spacing) * 1);
|
||||
}
|
||||
@ -858,6 +909,9 @@
|
||||
.uppercase {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
.underline {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
@ -920,6 +974,10 @@
|
||||
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
||||
}
|
||||
.duration-100 {
|
||||
--tw-duration: 100ms;
|
||||
transition-duration: 100ms;
|
||||
}
|
||||
.duration-150 {
|
||||
--tw-duration: 150ms;
|
||||
transition-duration: 150ms;
|
||||
@ -1008,6 +1066,11 @@
|
||||
color: var(--color-blue-700);
|
||||
}
|
||||
}
|
||||
.even\:bg-gray-50 {
|
||||
&:nth-child(even) {
|
||||
background-color: var(--color-gray-50);
|
||||
}
|
||||
}
|
||||
.valid\:my-2 {
|
||||
&:valid {
|
||||
margin-block: calc(var(--spacing) * 2);
|
||||
@ -1079,6 +1142,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.hover\:text-blue-600 {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
color: var(--color-blue-600);
|
||||
}
|
||||
}
|
||||
}
|
||||
.hover\:shadow {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
@ -1189,6 +1259,11 @@
|
||||
margin-top: calc(var(--spacing) * -2);
|
||||
}
|
||||
}
|
||||
.md\:block {
|
||||
@media (width >= 48rem) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.md\:flex {
|
||||
@media (width >= 48rem) {
|
||||
display: flex;
|
||||
@ -1408,6 +1483,26 @@
|
||||
inherits: false;
|
||||
initial-value: 1;
|
||||
}
|
||||
@property --tw-rotate-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-rotate-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-rotate-z {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-skew-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-skew-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-border-style {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
@ -1617,6 +1712,11 @@
|
||||
--tw-scale-x: 1;
|
||||
--tw-scale-y: 1;
|
||||
--tw-scale-z: 1;
|
||||
--tw-rotate-x: initial;
|
||||
--tw-rotate-y: initial;
|
||||
--tw-rotate-z: initial;
|
||||
--tw-skew-x: initial;
|
||||
--tw-skew-y: initial;
|
||||
--tw-border-style: solid;
|
||||
--tw-gradient-position: initial;
|
||||
--tw-gradient-from: #0000;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user