wip cart handling

This commit is contained in:
2025-03-04 13:00:30 +01:00
parent 23392cc5c1
commit 0c85ca5938
7 changed files with 206 additions and 253 deletions

View File

@@ -2,6 +2,7 @@ package controllers
import (
"fmt"
"strconv"
"net/http"
"crypto/rand"
"encoding/hex"
@@ -17,8 +18,8 @@ type CartItemController interface {
//CRUDController
CartItemView(*gin.Context)
AddItemHandler(*gin.Context)
//EditCartItemHandler(*gin.Context)
//DeleteCartItemHandler(*gin.Context)
DeleteItemHandler(*gin.Context)
EditItemHandler(*gin.Context)
}
type cartItemController struct {}
@@ -49,10 +50,16 @@ func GetSessionId(ctx *gin.Context) string {
func (rc *cartItemController) NewCartItemFromForm(ctx *gin.Context) (models.CartItem, error) {
sessionId := GetSessionId(ctx)
shopItemId := ctx.PostForm("ShopItemId")
shopItemIdStr := ctx.PostForm("ShopItemId")
shopItemId, err := strconv.Atoi(shopItemIdStr)
if err != nil {
return models.CartItem{}, err
}
quantity := 1
shopItem, err := repositories.ShopItems.GetById(shopItemId)
shopItem, err := repositories.ShopItems.GetById(shopItemIdStr)
if err != nil {
return models.CartItem{}, err
@@ -60,6 +67,7 @@ func (rc *cartItemController) NewCartItemFromForm(ctx *gin.Context) (models.Cart
cartItem := models.CartItem{
SessionId: sessionId,
ShopItemId: uint(shopItemId),
ShopItem: shopItem,
Quantity: quantity,
}
@@ -117,9 +125,10 @@ func (rc *cartItemController) Update(c *gin.Context) {
//}
func (rc *cartItemController) CartItemView(c *gin.Context) {
sessionId := GetSessionId(c)
//sessionId := GetSessionId(c)
cartItems, err := repositories.CartItems.GetAllBySession(sessionId)
//cartItems, err := repositories.CartItems.GetAllBySession(sessionId)
cartItems, err := repositories.CartItems.GetAll()
if err != nil {
c.HTML(http.StatusBadRequest, "cart.html", gin.H{ "data": gin.H{ "error": err } })
@@ -157,77 +166,53 @@ func (rc *cartItemController) AddItemHandler(c *gin.Context) {
rc.CartItemView(c)
}
func (rc *cartItemController) DeleteItemHandler(c *gin.Context) {
err := repositories.CartItems.DeleteById(c.PostForm("id"))
//func (rc *cartItemController) EditItemHandler(c *gin.Context) {
// cartItem, err := rc.NewCartItemFromForm(c)
//
// if err != nil {
// c.HTML(http.StatusBadRequest, "edititem.html", gin.H{ "error": err })
// return
// }
//
// newCartItem, err := repositories.ShopItems.GetById(c.Param("id"))
//
// if err != nil {
// c.HTML(http.StatusBadRequest, "edititem.html", gin.H{ "error": err })
// return
// }
//
// newCartItem.Name = cartItem.Name
// newCartItem.Abstract = cartItem.Abstract
// newCartItem.Description = cartItem.Description
// newCartItem.Price = cartItem.Price
// newCartItem.IsPublic = cartItem.IsPublic
// newCartItem.Tags = cartItem.Tags
//
// tags, err := repositories.Tags.GetAll()
// if err != nil {
// c.HTML(http.StatusBadRequest, "edititem.html", gin.H{ "error": err })
// return
// }
//
// _, err = repositories.CartItems.Update(newShopItem)
// if err != nil {
// data := CreateSessionData(c, gin.H{
// "error": err,
// "success": "",
// "tags": tags,
// })
//
// c.HTML(http.StatusOK, "edititem.html", data)
// return
// }
//
// data := CreateSessionData(c, gin.H{
// "error": "",
// "success": fmt.Sprintf("Item '%s' Updated", newCartItem.Name),
// "tags": tags,
// })
//
// c.HTML(http.StatusOK, "edititem.html", data)
//}
if err != nil {
fmt.Println(err)
data := CreateSessionData(c, gin.H{
"error": err,
"success": "",
})
//func (rc *cartItemController) DeleteItemHandler(c *gin.Context) {
// err := repositories.CartItems.DeleteById(c.Param("id"))
//
// if err != nil {
// data := CreateSessionData(c, gin.H{
// "error": err,
// "success": "",
// })
//
// c.HTML(http.StatusOK, "deleteitem.html", data)
// }
//
// cartItems, _ := repositories.CartItems.GetAll()
// fmt.Println(len(cartItems))
//
// data := CreateSessionData(c, gin.H{
// "title": "cartItem Page",
// "cartItems": shopItems,
// })
//
// fmt.Println(data)
//
// c.HTML(http.StatusOK, "index.html", data)
//}
c.HTML(http.StatusOK, "index.html", data)
}
rc.CartItemView(c)
}
func (rc *cartItemController) EditItemHandler(c *gin.Context) {
cartItemId := c.PostForm("id")
cartItem, err := repositories.CartItems.GetById(cartItemId)
if err != nil {
fmt.Println("BLAA")
fmt.Println(err)
rc.CartItemView(c)
return
}
action := c.PostForm("action")
if action == "increase" {
cartItem.Quantity += 1
}
if action == "decrease" {
cartItem.Quantity -= 1
if cartItem.Quantity == 0 {
cartItem.Quantity = 1
}
}
_, err = repositories.CartItems.Update(cartItem)
if err != nil {
fmt.Println("BLUB")
fmt.Println(err)
}
rc.CartItemView(c)
}

View File

@@ -160,6 +160,7 @@ func (rc *shopItemController) Update(c *gin.Context) {
ReplyOK(c, "shopItem was updated")
}
//TODO: delete associated cartitems
func (rc *shopItemController) Delete(c *gin.Context) {
err := repositories.ShopItems.DeleteById(c.Param("id"))

View File

@@ -87,6 +87,8 @@ func main() {
viewRoutes.POST("/tags", authValidator.RequireAuth, shopItemController.AddTagHandler)
viewRoutes.GET("/cart", cartItemController.CartItemView)
viewRoutes.POST("/cart", cartItemController.AddItemHandler)
viewRoutes.POST("/cart/delete", cartItemController.DeleteItemHandler)
viewRoutes.POST("/cart/edit", cartItemController.EditItemHandler)
//write middleware that redirects to homescreen on register/login/reset for logged in users
viewRoutes.GET("/login", userController.LoginView)

View File

@@ -7,6 +7,7 @@ import (
type CartItem struct {
gorm.Model
SessionId string `json:"sessionid" binding:"required" gorm:"not null"`
ShopItem ShopItem `json:"shopitem" gorm:"foreignKey:ID"` //gorm one2one
ShopItemId uint
ShopItem ShopItem `json:"shopitem" gorm:"foreignKey:ShopItemId"` //gorm one2one
Quantity int `json:"quantity" binding:"required"`
}

View File

@@ -1,6 +1,7 @@
package repositories
import(
"strconv"
"gorm.io/gorm"
"example.com/gin/test/models"
@@ -9,8 +10,10 @@ import(
type CartItemRepository interface {
Create(models.CartItem) (models.CartItem, error)
GetAll() ([]models.CartItem, error)
GetById(string) (models.CartItem, error)
GetAllBySession(string) ([]models.CartItem, error)
Update(models.CartItem) (models.CartItem, error)
DeleteById(string) (error)
}
type GORMCartItemRepository struct {
@@ -24,7 +27,8 @@ func NewGORMCartItemRepository(db *gorm.DB) CartItemRepository {
}
func (r *GORMCartItemRepository) Create(cartItem models.CartItem) (models.CartItem, error) {
result := r.DB.Create(&cartItem)
//Omit the shopitem so it is not created again in db leading to unique constain fails
result := r.DB.Omit("ShopItem").Create(&cartItem)
if result.Error != nil {
return models.CartItem{}, result.Error
}
@@ -39,6 +43,24 @@ func (r *GORMCartItemRepository) GetAll() ([]models.CartItem, error) {
return cartItems, result.Error
}
func (t *GORMCartItemRepository) GetById(id string) (models.CartItem, error) {
cartItemId, err := strconv.Atoi(id)
if err != nil {
return models.CartItem{}, err
}
var cartItem models.CartItem
result := t.DB.First(&cartItem, uint(cartItemId))
if result.Error != nil {
return models.CartItem{}, result.Error
}
return cartItem, nil
}
func (r *GORMCartItemRepository) GetAllBySession(sessionId string) ([]models.CartItem, error) {
var cartItems []models.CartItem
result := r.DB.Preload("ShopItem").Where("session_id = ?", sessionId).Find(&cartItems)
@@ -48,11 +70,6 @@ func (r *GORMCartItemRepository) GetAllBySession(sessionId string) ([]models.Car
}
func (r *GORMCartItemRepository) Update(cartItem models.CartItem) (models.CartItem, error) {
err := r.DB.Model(&cartItem).Association("Tags").Replace(cartItem.ShopItem)
if err != nil {
return models.CartItem{}, err
}
result := r.DB.Save(&cartItem)
if result.Error != nil {
return models.CartItem{}, result.Error
@@ -60,3 +77,14 @@ func (r *GORMCartItemRepository) Update(cartItem models.CartItem) (models.CartIt
return cartItem, nil
}
func (r *GORMCartItemRepository) DeleteById(id string) error {
cartItemId, err := strconv.Atoi(id)
if err != nil {
return err
}
result := r.DB.Omit("ShopItem").Delete(&models.CartItem{}, cartItemId)
return result.Error
}

View File

@@ -622,6 +622,18 @@ video {
margin-bottom: 1rem;
}
.mb-5 {
margin-bottom: 1.25rem;
}
.mb-6 {
margin-bottom: 1.5rem;
}
.mb-8 {
margin-bottom: 2rem;
}
.ml-2 {
margin-left: 0.5rem;
}
@@ -658,18 +670,6 @@ video {
margin-top: 1.5rem;
}
.mb-5 {
margin-bottom: 1.25rem;
}
.mb-6 {
margin-bottom: 1.5rem;
}
.mb-8 {
margin-bottom: 2rem;
}
.block {
display: block;
}
@@ -726,6 +726,10 @@ video {
width: 33.333333%;
}
.w-10 {
width: 2.5rem;
}
.w-12 {
width: 3rem;
}
@@ -742,10 +746,6 @@ video {
width: 100%;
}
.w-10 {
width: 2.5rem;
}
.max-w-2xl {
max-width: 42rem;
}
@@ -855,6 +855,14 @@ video {
border-radius: 0.25rem;
}
.rounded-3xl {
border-radius: 1.5rem;
}
.rounded-\[50px\] {
border-radius: 50px;
}
.rounded-full {
border-radius: 9999px;
}
@@ -867,14 +875,6 @@ video {
border-radius: 0.375rem;
}
.rounded-3xl {
border-radius: 1.5rem;
}
.rounded-\[50px\] {
border-radius: 50px;
}
.rounded-l-md {
border-top-left-radius: 0.375rem;
border-bottom-left-radius: 0.375rem;
@@ -896,16 +896,16 @@ video {
border-style: dashed;
}
.border-gray-300 {
--tw-border-opacity: 1;
border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));
}
.border-gray-200 {
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
}
.border-gray-300 {
--tw-border-opacity: 1;
border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));
}
.bg-blue-600 {
--tw-bg-opacity: 1;
background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1));
@@ -946,6 +946,11 @@ video {
background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));
}
.bg-indigo-50 {
--tw-bg-opacity: 1;
background-color: rgb(238 242 255 / var(--tw-bg-opacity, 1));
}
.bg-indigo-600 {
--tw-bg-opacity: 1;
background-color: rgb(79 70 229 / var(--tw-bg-opacity, 1));
@@ -966,11 +971,6 @@ video {
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
}
.bg-indigo-50 {
--tw-bg-opacity: 1;
background-color: rgb(238 242 255 / var(--tw-bg-opacity, 1));
}
.fill-red-50 {
fill: #fef2f2;
}
@@ -992,14 +992,14 @@ video {
padding: 0.5rem;
}
.p-4 {
padding: 1rem;
}
.p-2\.5 {
padding: 0.625rem;
}
.p-4 {
padding: 1rem;
}
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
@@ -1040,11 +1040,6 @@ video {
padding-bottom: 0.5rem;
}
.py-8 {
padding-top: 2rem;
padding-bottom: 2rem;
}
.py-2\.5 {
padding-top: 0.625rem;
padding-bottom: 0.625rem;
@@ -1060,6 +1055,11 @@ video {
padding-bottom: 1rem;
}
.py-8 {
padding-top: 2rem;
padding-bottom: 2rem;
}
.pb-3 {
padding-bottom: 0.75rem;
}
@@ -1102,6 +1102,16 @@ video {
line-height: 2.25rem;
}
.text-3xl {
font-size: 1.875rem;
line-height: 2.25rem;
}
.text-4xl {
font-size: 2.25rem;
line-height: 2.5rem;
}
.text-base {
font-size: 1rem;
line-height: 1.5rem;
@@ -1127,16 +1137,6 @@ video {
line-height: 1rem;
}
.text-3xl {
font-size: 1.875rem;
line-height: 2.25rem;
}
.text-4xl {
font-size: 2.25rem;
line-height: 2.5rem;
}
.font-bold {
font-weight: 700;
}
@@ -1145,14 +1145,14 @@ video {
font-weight: 500;
}
.font-semibold {
font-weight: 600;
}
.font-normal {
font-weight: 400;
}
.font-semibold {
font-weight: 600;
}
.leading-10 {
line-height: 2.5rem;
}
@@ -1169,6 +1169,11 @@ video {
letter-spacing: -0.025em;
}
.text-black {
--tw-text-opacity: 1;
color: rgb(0 0 0 / var(--tw-text-opacity, 1));
}
.text-gray-300 {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity, 1));
@@ -1224,11 +1229,6 @@ video {
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.text-black {
--tw-text-opacity: 1;
color: rgb(0 0 0 / var(--tw-text-opacity, 1));
}
.shadow-sm {
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
@@ -1240,11 +1240,6 @@ video {
--tw-shadow: var(--tw-shadow-colored);
}
.outline-none {
outline: 2px solid transparent;
outline-offset: 2px;
}
.outline {
outline-style: solid;
}
@@ -1324,6 +1319,11 @@ video {
background-color: rgb(156 163 175 / var(--tw-bg-opacity, 1));
}
.hover\:bg-gray-50:hover {
--tw-bg-opacity: 1;
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
}
.hover\:bg-gray-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));
@@ -1339,31 +1339,26 @@ video {
background-color: rgb(21 128 61 / var(--tw-bg-opacity, 1));
}
.hover\:bg-indigo-500:hover {
--tw-bg-opacity: 1;
background-color: rgb(99 102 241 / var(--tw-bg-opacity, 1));
}
.hover\:bg-red-900:hover {
--tw-bg-opacity: 1;
background-color: rgb(127 29 29 / var(--tw-bg-opacity, 1));
}
.hover\:bg-gray-50:hover {
--tw-bg-opacity: 1;
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
}
.hover\:bg-indigo-100:hover {
--tw-bg-opacity: 1;
background-color: rgb(224 231 255 / var(--tw-bg-opacity, 1));
}
.hover\:bg-indigo-500:hover {
--tw-bg-opacity: 1;
background-color: rgb(99 102 241 / var(--tw-bg-opacity, 1));
}
.hover\:bg-indigo-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(67 56 202 / var(--tw-bg-opacity, 1));
}
.hover\:bg-red-900:hover {
--tw-bg-opacity: 1;
background-color: rgb(127 29 29 / var(--tw-bg-opacity, 1));
}
.hover\:text-indigo-500:hover {
--tw-text-opacity: 1;
color: rgb(99 102 241 / var(--tw-text-opacity, 1));
@@ -1596,16 +1591,16 @@ video {
padding: 2rem;
}
.lg\:px-8 {
padding-left: 2rem;
padding-right: 2rem;
}
.lg\:px-6 {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
.lg\:px-8 {
padding-left: 2rem;
padding-right: 2rem;
}
.lg\:pl-3 {
padding-left: 0.75rem;
}

View File

@@ -2,18 +2,21 @@
<section class="py-24 relative">
<div class="w-full max-w-7xl px-4 md:px-5 lg-6 mx-auto">
<h2 class="title font-manrope font-bold text-4xl leading-10 mb-8 text-center text-black">Shopping Cart
</h2>
{{ range .data.cartItems }}
<div class="rounded-3xl border-2 border-gray-200 p-4 lg:p-8 grid grid-cols-12 mb-8 max-lg:max-w-lg max-lg:mx-auto gap-y-4 ">
<div class="col-span-12 lg:col-span-2 img box">
<img src="https://pagedone.io/asset/uploads/1701162826.png" alt="speaker image" class="max-lg:w-full lg:w-[180px] rounded-lg object-cover">
<img src="/{{ .ShopItem.Image }}" alt="speaker image" class="max-lg:w-full lg:w-[180px] rounded-lg object-cover">
</div>
<div class="col-span-12 lg:col-span-10 detail w-full lg:pl-3">
<div class="flex items-center justify-between w-full mb-4">
<h5 class="font-manrope font-bold text-2xl leading-9 text-gray-900">Round white portable
speaker</h5>
<button class="rounded-full group flex items-center justify-center focus-within:outline-red-500">
<h5 class="font-manrope font-bold text-2xl leading-9 text-gray-900">{{ .ShopItem.Name }}</h5>
<form action="/cart/delete" method="POST">
<input type="hidden" id="{{ .ID }}" name="id" value="{{ .ID }}">
<button type="submit" class="rounded-full group flex items-center justify-center focus-within:outline-red-500">
<svg width="34" height="34" viewBox="0 0 34 34" fill="none"
xmlns="http://www.w3.org/2000/svg">
<circle class="fill-red-50 transition-all duration-500 group-hover:fill-red-400"
@@ -23,14 +26,16 @@
stroke="#EF4444" stroke-width="1.6" stroke-linecap="round" />
</svg>
</button>
</form>
</div>
<p class="font-normal text-base leading-7 text-gray-500 mb-6">
Introducing our sleek round white portable speaker, the epitome of style and sound! Elevate your auditory experience with this compact yet powerful device that delivers crystal-clear audio wherever you go. <a href="javascript:;"
class="text-indigo-600">More....</a>
{{ .ShopItem.Abstract }}
</p>
<div class="flex justify-between items-center">
<div class="flex items-center gap-4">
<button
<form action="/cart/edit" method="POST">
<input type="hidden" id="{{ .ID }}" name="id" value="{{ .ID }}">
<button type="submit" name="action" value="decrease"
class="group rounded-[50px] border border-gray-200 shadow-sm shadow-transparent p-2.5 flex items-center justify-center bg-white transition-all duration-500 hover:shadow-gray-200 hover:bg-gray-50 hover:border-gray-300 focus-within:outline-gray-300">
<svg class="stroke-gray-900 transition-all duration-500 group-hover:stroke-black"
width="18" height="19" viewBox="0 0 18 19" fill="none"
@@ -39,10 +44,8 @@
stroke-linejoin="round" />
</svg>
</button>
<input type="text" id="number"
class="border border-gray-200 rounded-full w-10 aspect-square outline-none text-gray-900 font-semibold text-sm py-1.5 px-3 bg-gray-100 text-center"
placeholder="2">
<button
<p class="border border-gray-200 text-center rounded-full w-10 text-gray-900 font-semibold text-sm py-1.5 px-3 bg-gray-100 text-center">{{ .Quantity }}</p>
<button type="submit" name="action" value="increase"
class="group rounded-[50px] border border-gray-200 shadow-sm shadow-transparent p-2.5 flex items-center justify-center bg-white transition-all duration-500 hover:shadow-gray-200 hover:bg-gray-50 hover:border-gray-300 focus-within:outline-gray-300">
<svg class="stroke-gray-900 transition-all duration-500 group-hover:stroke-black"
width="18" height="19" viewBox="0 0 18 19" fill="none"
@@ -51,62 +54,17 @@
stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
</form>
</div>
<h6 class="text-indigo-600 font-manrope font-bold text-2xl leading-9 text-right">$220</h6>
</div>
</div>
</div>
<div class="rounded-3xl border-2 border-gray-200 p-4 lg:p-8 grid grid-cols-12 mb-8 max-lg:max-w-lg max-lg:mx-auto gap-y-4">
<div class="col-span-12 lg:col-span-2 img box">
<img src="https://pagedone.io/asset/uploads/1701162839.png" alt="speaker image" class="max-lg:w-full lg:w-[180px] rounded-lg object-cover">
</div>
<div class="col-span-12 lg:col-span-10 detail w-full lg:pl-3">
<div class="flex items-center justify-between w-full mb-4">
<h5 class="font-manrope font-bold text-2xl leading-9 text-gray-900">Gray round portable
speaker</h5>
<button class="rounded-full group flex items-center justify-center focus-within:outline-red-500">
<svg width="34" height="34" viewBox="0 0 34 34" fill="none"
xmlns="http://www.w3.org/2000/svg">
<circle class="fill-red-50 transition-all duration-500 group-hover:fill-red-400"
cx="17" cy="17" r="17" fill="" />
<path class="stroke-red-500 transition-all duration-500 group-hover:stroke-white"
d="M14.1673 13.5997V12.5923C14.1673 11.8968 14.7311 11.333 15.4266 11.333H18.5747C19.2702 11.333 19.834 11.8968 19.834 12.5923V13.5997M19.834 13.5997C19.834 13.5997 14.6534 13.5997 11.334 13.5997C6.90804 13.5998 27.0933 13.5998 22.6673 13.5997C21.5608 13.5997 19.834 13.5997 19.834 13.5997ZM12.4673 13.5997H21.534V18.8886C21.534 20.6695 21.534 21.5599 20.9807 22.1131C20.4275 22.6664 19.5371 22.6664 17.7562 22.6664H16.2451C14.4642 22.6664 13.5738 22.6664 13.0206 22.1131C12.4673 21.5599 12.4673 20.6695 12.4673 18.8886V13.5997Z"
stroke="#EF4444" stroke-width="1.6" stroke-linecap="round" />
</svg>
</button>
</div>
<p class="font-normal text-base leading-7 text-gray-500 mb-6">
Introducing our sleek round white portable speaker, the epitome of style and sound! Elevate your auditory experience with this compact yet powerful device that delivers crystal-clear audio wherever you go. <a href="javascript:;"
class="text-indigo-600">More....</a>
</p>
<div class="flex justify-between items-center">
<div class="flex items-center gap-4">
<button
class="group rounded-[50px] border border-gray-200 shadow-sm shadow-transparent p-2.5 flex items-center justify-center bg-white transition-all duration-500 hover:shadow-gray-200 hover:bg-gray-50 hover:border-gray-300 focus-within:outline-gray-300">
<svg class="stroke-gray-900 transition-all duration-500 group-hover:stroke-black"
width="18" height="19" viewBox="0 0 18 19" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M4.5 9.5H13.5" stroke="" stroke-width="1.6" stroke-linecap="round"
stroke-linejoin="round" />
</svg>
</button>
<input type="text" id="number"
class="border border-gray-200 rounded-full w-10 aspect-square outline-none text-gray-900 font-semibold text-sm py-1.5 px-3 bg-gray-100 text-center"
placeholder="2">
<button
class="group rounded-[50px] border border-gray-200 shadow-sm shadow-transparent p-2.5 flex items-center justify-center bg-white transition-all duration-500 hover:shadow-gray-200 hover:bg-gray-50 hover:border-gray-300 focus-within:outline-gray-300">
<svg class="stroke-gray-900 transition-all duration-500 group-hover:stroke-black"
width="18" height="19" viewBox="0 0 18 19" fill="none"
xmlns="http://www.w3.org/2000/svg">
<path d="M3.75 9.5H14.25M9 14.75V4.25" stroke="" stroke-width="1.6"
stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
</div>
<h6 class="text-indigo-600 font-manrope font-bold text-2xl leading-9 text-right">$220</h6>
<h6 class="text-indigo-600 font-manrope font-bold text-2xl leading-9 text-right">{{ .ShopItem.Price }}€</h6>
</div>
</div>
</div>
{{ end }}
<div class="flex flex-col md:flex-row items-center md:items-center justify-between lg:px-6 pb-6 border-b border-gray-200 max-lg:max-w-lg max-lg:mx-auto">
<h5 class="text-gray-900 font-manrope font-semibold text-2xl leading-9 w-full max-md:text-center max-md:mb-4">Subtotal</h5>
@@ -134,22 +92,5 @@
{{ range .data.cartItems }}
<div class="group relative">
<div class="mt-4 flex justify-between">
<div>
<h3 class="text-sm text-gray-700">
{{ .SessionId }}
</h3>
{{ .ShopItem.Name }}
{{ .ShopItem.Abstract }}
{{ .ShopItem.Price }}
</div>
<p class="text-sm font-medium text-gray-900">{{ .Quantity }} pieces</p>
</div>
</div>
{{ end }}
{{ template "footer.html" . }}