(UI/STYLE): Implemented the first rendition of the profile page. #17
@ -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
|
## Database Requirements
|
||||||
|
|
||||||
This section outlines the specific technical requirements for the database store for
|
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
|
// Else, get the user data
|
||||||
deps := ctx.MustGet("deps").(*domainServer.InjectedDependencies)
|
deps := ctx.MustGet("deps").(*domainServer.InjectedDependencies)
|
||||||
user := deps.UserService.GetAuthenicatedUser(ctx)
|
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"
|
title := "Potion - Profile"
|
||||||
page := pages.ProfilePage(user)
|
page := pages.ProfilePage(user, recipes)
|
||||||
|
|
||||||
ctx.HTML(http.StatusOK, "", layouts.AppLayout(title, page))
|
ctx.HTML(http.StatusOK, "", layouts.AppLayout(title, page))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1,49 @@
|
|||||||
package handlers
|
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
|
// Recipe endpoints
|
||||||
router_api.POST("/recipe", handlers.CreateRecipe)
|
router_api.POST("/recipe", handlers.CreateRecipe)
|
||||||
router_api.POST("/recipe/search", handlers.SearchRecipes)
|
router_api.POST("/recipe/search", handlers.SearchRecipes)
|
||||||
|
router_api.GET("/user/recipes", handlers.GetUserRecipes)
|
||||||
|
|
||||||
// Catch un-routed URLS
|
// Catch un-routed URLS
|
||||||
s.Router.NoRoute(func(ctx *gin.Context) {
|
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) {
|
func (s *RecipeService) SearchRecipes(filters domain.SearchFilters) ([]domain.Recipe, error) {
|
||||||
return s.recipeRepository.SearchRecipes(filters)
|
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)
|
GetRecipe(id int) (*Recipe, error)
|
||||||
SearchRecipes(filters SearchFilters) ([]Recipe, error)
|
SearchRecipes(filters SearchFilters) ([]Recipe, error)
|
||||||
CreateRecipeTags(recipe Recipe, tags []string) 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)
|
CreateRecipe(ctx *gin.Context) (*Recipe, error)
|
||||||
GetRecipe(id int) (*Recipe, error)
|
GetRecipe(id int) (*Recipe, error)
|
||||||
SearchRecipes(filters SearchFilters) ([]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())
|
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
|
// Parse duration
|
||||||
if len(durationBytes) > 0 {
|
if len(durationBytes) > 0 {
|
||||||
var duration domain.RecipeDuration
|
var duration domain.RecipeDuration
|
||||||
@ -180,6 +152,14 @@ func (r *RecipeRepository) GetRecipe(id int) (*domain.Recipe, error) {
|
|||||||
recipe.Ingredients = []domain.RecipeIngredient{}
|
recipe.Ingredients = []domain.RecipeIngredient{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add tags
|
||||||
|
r.GetRecipeTags(&recipe)
|
||||||
|
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &recipe, nil
|
return &recipe, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,6 +367,9 @@ func (r *RecipeRepository) SearchRecipes(filters domain.SearchFilters) ([]domain
|
|||||||
recipe.Ingredients = []domain.RecipeIngredient{}
|
recipe.Ingredients = []domain.RecipeIngredient{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add tags
|
||||||
|
r.GetRecipeTags(&recipe)
|
||||||
|
|
||||||
recipes = append(recipes, recipe)
|
recipes = append(recipes, recipe)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,3 +439,135 @@ func (r *RecipeRepository) CreateRecipeTags(recipe domain.Recipe, tags []string)
|
|||||||
|
|
||||||
return nil
|
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
|
package templates
|
||||||
|
|
||||||
import "github.com/haydenhargreaves/Potion/internal/templates/components"
|
import "github.com/haydenhargreaves/Potion/internal/templates/components"
|
||||||
|
import "fmt"
|
||||||
|
import "strings"
|
||||||
import domain "github.com/haydenhargreaves/Potion/internal/domain/server"
|
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">
|
<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">
|
<div class="w-full p-4 md:p-8 flex items-center gap-x-8">
|
||||||
|
if user.ImageUrl != "" {
|
||||||
<img
|
<img
|
||||||
class="w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none"
|
class="w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none"
|
||||||
src={ user.ImageUrl }
|
src={ user.ImageUrl }
|
||||||
/>
|
/>
|
||||||
<div class="">
|
} else {
|
||||||
<h1 class="text-md md:text-2xl font-semibold">{ user.Name }</h1>
|
<img
|
||||||
<p class="text-xs md:text-sm">{ user.Email }</p>
|
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>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</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() {
|
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
|
<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"
|
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
|
Logout
|
||||||
@ -30,13 +169,14 @@ templ logoutSection() {
|
|||||||
</section>
|
</section>
|
||||||
}
|
}
|
||||||
|
|
||||||
templ ProfilePage(user domain_user.User) {
|
templ ProfilePage(user domainUser.User, recipes []domainRecipe.Recipe) {
|
||||||
@components.Navbar(" profile")
|
@components.Navbar(" profile")
|
||||||
<div class="w-full h-screen flex justify-center">
|
<div class="w-full h-fit flex justify-center">
|
||||||
<div
|
<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">
|
||||||
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, len(recipes))
|
||||||
>
|
@recipesSection(recipes)
|
||||||
@userDetailsSection(user)
|
@favoritesSection(recipes)
|
||||||
|
@activitySection()
|
||||||
@logoutSection()
|
@logoutSection()
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,10 +9,38 @@ import "github.com/a-h/templ"
|
|||||||
import templruntime "github.com/a-h/templ/runtime"
|
import templruntime "github.com/a-h/templ/runtime"
|
||||||
|
|
||||||
import "github.com/haydenhargreaves/Potion/internal/templates/components"
|
import "github.com/haydenhargreaves/Potion/internal/templates/components"
|
||||||
|
import "fmt"
|
||||||
|
import "strings"
|
||||||
import domain "github.com/haydenhargreaves/Potion/internal/domain/server"
|
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) {
|
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 {
|
||||||
@ -33,46 +61,374 @@ func userDetailsSection(user domain_user.User) templ.Component {
|
|||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
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 {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var2 string
|
if user.ImageUrl != "" {
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(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 {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/templates/pages/profile.templ`, Line: 12, Col: 23}
|
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))
|
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
|
|
||||||
}
|
|
||||||
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\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var4 string
|
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 {
|
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))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
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, 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 {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -96,21 +452,21 @@ func logoutSection() templ.Component {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var21 := templ.GetChildren(ctx)
|
||||||
if templ_7745c5c3_Var5 == nil {
|
if templ_7745c5c3_Var21 == nil {
|
||||||
templ_7745c5c3_Var5 = templ.NopComponent
|
templ_7745c5c3_Var21 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
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 {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var6 templ.SafeURL = domain.API_AUTH_LOGOUT
|
var templ_7745c5c3_Var22 templ.SafeURL = domain.API_AUTH_LOGOUT
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6)))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var22)))
|
||||||
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, "\" 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 {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
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) {
|
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,20 +490,32 @@ func ProfilePage(user domain_user.User) templ.Component {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var23 := templ.GetChildren(ctx)
|
||||||
if templ_7745c5c3_Var7 == nil {
|
if templ_7745c5c3_Var23 == nil {
|
||||||
templ_7745c5c3_Var7 = templ.NopComponent
|
templ_7745c5c3_Var23 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = components.Navbar(" profile").Render(ctx, templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = components.Navbar(" profile").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, 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 {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
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 {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -155,7 +523,7 @@ func ProfilePage(user domain_user.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, 8, "</div></div>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "</div></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,6 @@
|
|||||||
--color-blue-500: oklch(62.3% 0.214 259.815);
|
--color-blue-500: oklch(62.3% 0.214 259.815);
|
||||||
--color-blue-600: oklch(54.6% 0.245 262.881);
|
--color-blue-600: oklch(54.6% 0.245 262.881);
|
||||||
--color-blue-700: oklch(48.8% 0.243 264.376);
|
--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-100: oklch(94.6% 0.033 307.174);
|
||||||
--color-purple-200: oklch(90.2% 0.063 306.703);
|
--color-purple-200: oklch(90.2% 0.063 306.703);
|
||||||
--color-gray-50: oklch(98.5% 0.002 247.839);
|
--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-600: oklch(44.6% 0.03 256.802);
|
||||||
--color-gray-700: oklch(37.3% 0.034 259.733);
|
--color-gray-700: oklch(37.3% 0.034 259.733);
|
||||||
--color-gray-800: oklch(27.8% 0.033 256.848);
|
--color-gray-800: oklch(27.8% 0.033 256.848);
|
||||||
|
--color-gray-900: oklch(21% 0.034 264.665);
|
||||||
--color-black: #000;
|
--color-black: #000;
|
||||||
--color-white: #fff;
|
--color-white: #fff;
|
||||||
--spacing: 0.25rem;
|
--spacing: 0.25rem;
|
||||||
@ -49,8 +49,6 @@
|
|||||||
--text-3xl--line-height: calc(2.25 / 1.875);
|
--text-3xl--line-height: calc(2.25 / 1.875);
|
||||||
--text-4xl: 2.25rem;
|
--text-4xl: 2.25rem;
|
||||||
--text-4xl--line-height: calc(2.5 / 2.25);
|
--text-4xl--line-height: calc(2.5 / 2.25);
|
||||||
--text-5xl: 3rem;
|
|
||||||
--text-5xl--line-height: 1;
|
|
||||||
--text-6xl: 3.75rem;
|
--text-6xl: 3.75rem;
|
||||||
--text-6xl--line-height: 1;
|
--text-6xl--line-height: 1;
|
||||||
--text-8xl: 6rem;
|
--text-8xl: 6rem;
|
||||||
@ -240,6 +238,9 @@
|
|||||||
.static {
|
.static {
|
||||||
position: static;
|
position: static;
|
||||||
}
|
}
|
||||||
|
.top-1 {
|
||||||
|
top: calc(var(--spacing) * 1);
|
||||||
|
}
|
||||||
.top-1\/2 {
|
.top-1\/2 {
|
||||||
top: calc(1/2 * 100%);
|
top: calc(1/2 * 100%);
|
||||||
}
|
}
|
||||||
@ -249,6 +250,9 @@
|
|||||||
.left-0 {
|
.left-0 {
|
||||||
left: calc(var(--spacing) * 0);
|
left: calc(var(--spacing) * 0);
|
||||||
}
|
}
|
||||||
|
.left-1 {
|
||||||
|
left: calc(var(--spacing) * 1);
|
||||||
|
}
|
||||||
.left-1\/2 {
|
.left-1\/2 {
|
||||||
left: calc(1/2 * 100%);
|
left: calc(1/2 * 100%);
|
||||||
}
|
}
|
||||||
@ -273,6 +277,9 @@
|
|||||||
.my-1 {
|
.my-1 {
|
||||||
margin-block: calc(var(--spacing) * 1);
|
margin-block: calc(var(--spacing) * 1);
|
||||||
}
|
}
|
||||||
|
.my-1\.5 {
|
||||||
|
margin-block: calc(var(--spacing) * 1.5);
|
||||||
|
}
|
||||||
.my-2 {
|
.my-2 {
|
||||||
margin-block: calc(var(--spacing) * 2);
|
margin-block: calc(var(--spacing) * 2);
|
||||||
}
|
}
|
||||||
@ -300,6 +307,9 @@
|
|||||||
.mt-16 {
|
.mt-16 {
|
||||||
margin-top: calc(var(--spacing) * 16);
|
margin-top: calc(var(--spacing) * 16);
|
||||||
}
|
}
|
||||||
|
.mt-auto {
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
.mr-2 {
|
.mr-2 {
|
||||||
margin-right: calc(var(--spacing) * 2);
|
margin-right: calc(var(--spacing) * 2);
|
||||||
}
|
}
|
||||||
@ -410,12 +420,18 @@
|
|||||||
.min-h-screen {
|
.min-h-screen {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
.w-1 {
|
||||||
|
width: calc(var(--spacing) * 1);
|
||||||
|
}
|
||||||
.w-1\/3 {
|
.w-1\/3 {
|
||||||
width: calc(1/3 * 100%);
|
width: calc(1/3 * 100%);
|
||||||
}
|
}
|
||||||
.w-1\/4 {
|
.w-1\/4 {
|
||||||
width: calc(1/4 * 100%);
|
width: calc(1/4 * 100%);
|
||||||
}
|
}
|
||||||
|
.w-3 {
|
||||||
|
width: calc(var(--spacing) * 3);
|
||||||
|
}
|
||||||
.w-3\/4 {
|
.w-3\/4 {
|
||||||
width: calc(3/4 * 100%);
|
width: calc(3/4 * 100%);
|
||||||
}
|
}
|
||||||
@ -428,6 +444,9 @@
|
|||||||
.w-5 {
|
.w-5 {
|
||||||
width: calc(var(--spacing) * 5);
|
width: calc(var(--spacing) * 5);
|
||||||
}
|
}
|
||||||
|
.w-9 {
|
||||||
|
width: calc(var(--spacing) * 9);
|
||||||
|
}
|
||||||
.w-9\/10 {
|
.w-9\/10 {
|
||||||
width: calc(9/10 * 100%);
|
width: calc(9/10 * 100%);
|
||||||
}
|
}
|
||||||
@ -446,16 +465,33 @@
|
|||||||
.max-w-2xl {
|
.max-w-2xl {
|
||||||
max-width: var(--container-2xl);
|
max-width: var(--container-2xl);
|
||||||
}
|
}
|
||||||
|
.flex-shrink {
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
.flex-shrink-0 {
|
.flex-shrink-0 {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
.shrink-0 {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
.flex-grow {
|
.flex-grow {
|
||||||
flex-grow: 1;
|
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 {
|
.-translate-x-1\/2 {
|
||||||
--tw-translate-x: calc(calc(1/2 * 100%) * -1);
|
--tw-translate-x: calc(calc(1/2 * 100%) * -1);
|
||||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
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 {
|
.-translate-y-1\/2 {
|
||||||
--tw-translate-y: calc(calc(1/2 * 100%) * -1);
|
--tw-translate-y: calc(calc(1/2 * 100%) * -1);
|
||||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||||
@ -468,9 +504,15 @@
|
|||||||
--tw-scale-y: 50%;
|
--tw-scale-y: 50%;
|
||||||
scale: var(--tw-scale-x) var(--tw-scale-y);
|
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 {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
.resize {
|
||||||
|
resize: both;
|
||||||
|
}
|
||||||
.resize-none {
|
.resize-none {
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
@ -645,6 +687,9 @@
|
|||||||
.bg-red-100 {
|
.bg-red-100 {
|
||||||
background-color: var(--color-red-100);
|
background-color: var(--color-red-100);
|
||||||
}
|
}
|
||||||
|
.bg-red-500 {
|
||||||
|
background-color: var(--color-red-500);
|
||||||
|
}
|
||||||
.bg-white {
|
.bg-white {
|
||||||
background-color: var(--color-white);
|
background-color: var(--color-white);
|
||||||
}
|
}
|
||||||
@ -656,6 +701,9 @@
|
|||||||
--tw-gradient-position: to right in oklab;
|
--tw-gradient-position: to right in oklab;
|
||||||
background-image: linear-gradient(var(--tw-gradient-stops));
|
background-image: linear-gradient(var(--tw-gradient-stops));
|
||||||
}
|
}
|
||||||
|
.bg-none {
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
.from-blue-100 {
|
.from-blue-100 {
|
||||||
--tw-gradient-from: var(--color-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));
|
--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 {
|
.p-4 {
|
||||||
padding: calc(var(--spacing) * 4);
|
padding: calc(var(--spacing) * 4);
|
||||||
}
|
}
|
||||||
|
.p-8 {
|
||||||
|
padding: calc(var(--spacing) * 8);
|
||||||
|
}
|
||||||
.px-1 {
|
.px-1 {
|
||||||
padding-inline: calc(var(--spacing) * 1);
|
padding-inline: calc(var(--spacing) * 1);
|
||||||
}
|
}
|
||||||
@ -858,6 +909,9 @@
|
|||||||
.uppercase {
|
.uppercase {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
.italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
.underline {
|
.underline {
|
||||||
text-decoration-line: underline;
|
text-decoration-line: underline;
|
||||||
}
|
}
|
||||||
@ -920,6 +974,10 @@
|
|||||||
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||||
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
||||||
}
|
}
|
||||||
|
.duration-100 {
|
||||||
|
--tw-duration: 100ms;
|
||||||
|
transition-duration: 100ms;
|
||||||
|
}
|
||||||
.duration-150 {
|
.duration-150 {
|
||||||
--tw-duration: 150ms;
|
--tw-duration: 150ms;
|
||||||
transition-duration: 150ms;
|
transition-duration: 150ms;
|
||||||
@ -1008,6 +1066,11 @@
|
|||||||
color: var(--color-blue-700);
|
color: var(--color-blue-700);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.even\:bg-gray-50 {
|
||||||
|
&:nth-child(even) {
|
||||||
|
background-color: var(--color-gray-50);
|
||||||
|
}
|
||||||
|
}
|
||||||
.valid\:my-2 {
|
.valid\:my-2 {
|
||||||
&:valid {
|
&:valid {
|
||||||
margin-block: calc(var(--spacing) * 2);
|
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\:shadow {
|
||||||
&:hover {
|
&:hover {
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
@ -1189,6 +1259,11 @@
|
|||||||
margin-top: calc(var(--spacing) * -2);
|
margin-top: calc(var(--spacing) * -2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.md\:block {
|
||||||
|
@media (width >= 48rem) {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
.md\:flex {
|
.md\:flex {
|
||||||
@media (width >= 48rem) {
|
@media (width >= 48rem) {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -1408,6 +1483,26 @@
|
|||||||
inherits: false;
|
inherits: false;
|
||||||
initial-value: 1;
|
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 {
|
@property --tw-border-style {
|
||||||
syntax: "*";
|
syntax: "*";
|
||||||
inherits: false;
|
inherits: false;
|
||||||
@ -1617,6 +1712,11 @@
|
|||||||
--tw-scale-x: 1;
|
--tw-scale-x: 1;
|
||||||
--tw-scale-y: 1;
|
--tw-scale-y: 1;
|
||||||
--tw-scale-z: 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-border-style: solid;
|
||||||
--tw-gradient-position: initial;
|
--tw-gradient-position: initial;
|
||||||
--tw-gradient-from: #0000;
|
--tw-gradient-from: #0000;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user