add basic cart
This commit is contained in:
239
controllers/cartItemController.go
Normal file
239
controllers/cartItemController.go
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
"example.com/gin/test/models"
|
||||||
|
//"example.com/gin/test/services"
|
||||||
|
"example.com/gin/test/repositories"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CartItemController interface {
|
||||||
|
//CRUDController
|
||||||
|
CartItemView(*gin.Context)
|
||||||
|
AddItemHandler(*gin.Context)
|
||||||
|
//EditCartItemHandler(*gin.Context)
|
||||||
|
//DeleteCartItemHandler(*gin.Context)
|
||||||
|
}
|
||||||
|
|
||||||
|
type cartItemController struct {}
|
||||||
|
|
||||||
|
func NewCartItemController() CartItemController {
|
||||||
|
return &cartItemController{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateSessionId() string {
|
||||||
|
bytes := make([]byte, 16) // 16 bytes = 128 bits
|
||||||
|
_, err := rand.Read(bytes)
|
||||||
|
if err != nil {
|
||||||
|
panic("failed to generate session ID")
|
||||||
|
}
|
||||||
|
return hex.EncodeToString(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSessionId(ctx *gin.Context) string {
|
||||||
|
sessionId, err := ctx.Cookie("session_id")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
sessionId = generateSessionId()
|
||||||
|
ctx.SetCookie("session_id", sessionId, 3600, "/", "", false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessionId
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *cartItemController) NewCartItemFromForm(ctx *gin.Context) (models.CartItem, error) {
|
||||||
|
fmt.Println("NEWITEM")
|
||||||
|
sessionId := GetSessionId(ctx)
|
||||||
|
|
||||||
|
shopItemId, err := strconv.Atoi(ctx.PostForm("ShopItemId"))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return models.CartItem{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
quantity := 1
|
||||||
|
//quantity, err := strconv.Atoi(ctx.PostForm("quantity"))
|
||||||
|
|
||||||
|
//if err != nil {
|
||||||
|
// return models.CartItem{}, err
|
||||||
|
//}
|
||||||
|
|
||||||
|
cartItem := models.CartItem{
|
||||||
|
SessionId: sessionId,
|
||||||
|
ShopItemId: shopItemId,
|
||||||
|
Quantity: quantity,
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("NEWITEM")
|
||||||
|
return cartItem, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (rc *cartItemController) Create(c *gin.Context) {
|
||||||
|
cartItem, err := rc.NewCartItemFromForm(c)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
ReplyError(c, fmt.Errorf("cartItem creation failed: %s", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = repositories.CartItems.Create(cartItem)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
ReplyError(c, fmt.Errorf("cartItem creation failed: %s", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ReplyOK(c, "cartItem was created")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (rc *cartItemController) Update(c *gin.Context) {
|
||||||
|
cartItem, err := rc.NewCartItemFromForm(c)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
ReplyError(c, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = repositories.CartItems.Update(cartItem)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
ReplyError(c, fmt.Errorf("cartItem creation failed: %s", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ReplyOK(c, "cartItem was updated")
|
||||||
|
}
|
||||||
|
|
||||||
|
//func (rc *cartItemController) Delete(c *gin.Context) {
|
||||||
|
// err := repositories.CartItems.DeleteBySessionId(c.Param("id"))
|
||||||
|
//
|
||||||
|
// if err != nil {
|
||||||
|
// ReplyError(c, fmt.Errorf("cartItem deletion failed: %s", err))
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ReplyOK(c, "cartItem was deleted")
|
||||||
|
//}
|
||||||
|
|
||||||
|
func (rc *cartItemController) CartItemView(c *gin.Context) {
|
||||||
|
sessionId := GetSessionId(c)
|
||||||
|
|
||||||
|
cartItems, err := repositories.CartItems.GetAllBySession(sessionId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.HTML(http.StatusBadRequest, "cart.html", gin.H{ "data": gin.H{ "error": err } })
|
||||||
|
}
|
||||||
|
|
||||||
|
data := CreateSessionData(c, gin.H{
|
||||||
|
"cartItems": cartItems,
|
||||||
|
})
|
||||||
|
|
||||||
|
c.HTML(http.StatusOK, "cart.html", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *cartItemController) AddItemHandler(c *gin.Context) {
|
||||||
|
cartItem, err := rc.NewCartItemFromForm(c)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
c.HTML(http.StatusBadRequest, "cart.html", gin.H{ "error": err })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = repositories.CartItems.Create(cartItem)
|
||||||
|
if err != nil {
|
||||||
|
data := CreateSessionData(c, gin.H{
|
||||||
|
"error": err,
|
||||||
|
"success": "",
|
||||||
|
})
|
||||||
|
|
||||||
|
c.HTML(http.StatusOK, "cart.html", data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rc.CartItemView(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//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)
|
||||||
|
//}
|
||||||
|
|
||||||
|
//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)
|
||||||
|
//}
|
||||||
4
main.go
4
main.go
@@ -17,6 +17,7 @@ import(
|
|||||||
var(
|
var(
|
||||||
shopItemController controllers.ShopItemController = controllers.NewShopItemController()
|
shopItemController controllers.ShopItemController = controllers.NewShopItemController()
|
||||||
userController controllers.UserController = controllers.UserController{}
|
userController controllers.UserController = controllers.UserController{}
|
||||||
|
cartItemController controllers.CartItemController = controllers.NewCartItemController()
|
||||||
authValidator middlewares.AuthValidator = middlewares.AuthValidator{}
|
authValidator middlewares.AuthValidator = middlewares.AuthValidator{}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -84,6 +85,9 @@ func main() {
|
|||||||
viewRoutes.GET("/tags", authValidator.RequireAuth, shopItemController.TagView)
|
viewRoutes.GET("/tags", authValidator.RequireAuth, shopItemController.TagView)
|
||||||
viewRoutes.POST("/tags/:id", authValidator.RequireAuth, shopItemController.TagHandler)
|
viewRoutes.POST("/tags/:id", authValidator.RequireAuth, shopItemController.TagHandler)
|
||||||
viewRoutes.POST("/tags", authValidator.RequireAuth, shopItemController.AddTagHandler)
|
viewRoutes.POST("/tags", authValidator.RequireAuth, shopItemController.AddTagHandler)
|
||||||
|
viewRoutes.GET("/cart", cartItemController.CartItemView)
|
||||||
|
viewRoutes.POST("/cart", cartItemController.AddItemHandler)
|
||||||
|
|
||||||
//write middleware that redirects to homescreen on register/login/reset for logged in users
|
//write middleware that redirects to homescreen on register/login/reset for logged in users
|
||||||
viewRoutes.GET("/login", userController.LoginView)
|
viewRoutes.GET("/login", userController.LoginView)
|
||||||
viewRoutes.GET("/logout", userController.Logout)
|
viewRoutes.GET("/logout", userController.Logout)
|
||||||
|
|||||||
12
models/cart.go
Normal file
12
models/cart.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CartItem struct {
|
||||||
|
gorm.Model
|
||||||
|
SessionId string `gorm:"index"`
|
||||||
|
ShopItemId int `gorm:"index"`
|
||||||
|
Quantity int
|
||||||
|
}
|
||||||
57
repositories/cartItemRepository.go
Normal file
57
repositories/cartItemRepository.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package repositories
|
||||||
|
|
||||||
|
import(
|
||||||
|
"gorm.io/gorm"
|
||||||
|
|
||||||
|
"example.com/gin/test/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CartItemRepository interface {
|
||||||
|
Create(models.CartItem) (models.CartItem, error)
|
||||||
|
GetAll() ([]models.CartItem, error)
|
||||||
|
GetAllBySession(string) ([]models.CartItem, error)
|
||||||
|
Update(models.CartItem) (models.CartItem, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type GORMCartItemRepository struct {
|
||||||
|
DB *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGORMCartItemRepository(db *gorm.DB) CartItemRepository {
|
||||||
|
return &GORMCartItemRepository{
|
||||||
|
DB: db,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *GORMCartItemRepository) Create(cartItem models.CartItem) (models.CartItem, error) {
|
||||||
|
result := r.DB.Create(&cartItem)
|
||||||
|
if result.Error != nil {
|
||||||
|
return models.CartItem{}, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return cartItem, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *GORMCartItemRepository) GetAll() ([]models.CartItem, error) {
|
||||||
|
var cartItems []models.CartItem
|
||||||
|
result := r.DB.Find(&cartItems)
|
||||||
|
|
||||||
|
return cartItems, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *GORMCartItemRepository) GetAllBySession(sessionId string) ([]models.CartItem, error) {
|
||||||
|
var cartItems []models.CartItem
|
||||||
|
result := r.DB.Where("session_id = ?", sessionId).Find(&cartItems)
|
||||||
|
|
||||||
|
return cartItems, result.Error
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *GORMCartItemRepository) Update(cartItem models.CartItem) (models.CartItem, error) {
|
||||||
|
result := r.DB.Save(&cartItem)
|
||||||
|
if result.Error != nil {
|
||||||
|
return models.CartItem{}, result.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return cartItem, nil
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ var(
|
|||||||
ShopItems ShopItemRepository
|
ShopItems ShopItemRepository
|
||||||
Users UserRepository
|
Users UserRepository
|
||||||
Tags TagRepository
|
Tags TagRepository
|
||||||
|
CartItems CartItemRepository
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitRepositories() {
|
func InitRepositories() {
|
||||||
@@ -20,7 +21,7 @@ func InitRepositories() {
|
|||||||
panic("failed to connect to database")
|
panic("failed to connect to database")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = db.AutoMigrate(&models.ShopItem{}, &models.User{}, &models.Tag{})
|
err = db.AutoMigrate(&models.ShopItem{}, &models.User{}, &models.Tag{}, &models.CartItem{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("failed to migrate database")
|
panic("failed to migrate database")
|
||||||
}
|
}
|
||||||
@@ -28,4 +29,5 @@ func InitRepositories() {
|
|||||||
ShopItems = NewGORMShopItemRepository(db)
|
ShopItems = NewGORMShopItemRepository(db)
|
||||||
Users = NewGORMUserRepository(db)
|
Users = NewGORMUserRepository(db)
|
||||||
Tags = NewGORMTagRepository(db)
|
Tags = NewGORMTagRepository(db)
|
||||||
|
CartItems = NewGORMCartItemRepository(db)
|
||||||
}
|
}
|
||||||
|
|||||||
35
views/addtag.html
Normal file
35
views/addtag.html
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{{ template "header.html" . }}
|
||||||
|
|
||||||
|
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
|
||||||
|
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
|
||||||
|
<img class="mx-auto h-10 w-auto" src="/static/img/circlea.png" alt="Your Company">
|
||||||
|
<h2 class="mt-10 text-center text-2xl/9 font-bold tracking-tight text-gray-900">Add Tag</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||||
|
<form class="space-y-6" action="#" method="POST" enctype="multipart/form-data">
|
||||||
|
<div>
|
||||||
|
<label for="name" class="block text-sm/6 font-medium text-gray-900">Name</label>
|
||||||
|
<div class="mt-2">
|
||||||
|
<input type="text" name="name" id="name" required class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mt-10 text-center text-sm/6 text-red-500">
|
||||||
|
{{ .data.error }}
|
||||||
|
</p>
|
||||||
|
<p class="mt-10 text-center text-sm/6 text-green-500">
|
||||||
|
{{ .data.success }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button type="submit" class="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm/6 font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Add Tag</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{ template "footer.html" . }}
|
||||||
18
views/cart.html
Normal file
18
views/cart.html
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{{ template "header.html" . }}
|
||||||
|
|
||||||
|
{{ range .data.cartItems }}
|
||||||
|
|
||||||
|
<div class="group relative">
|
||||||
|
<div class="mt-4 flex justify-between">
|
||||||
|
<div>
|
||||||
|
<h3 class="text-sm text-gray-700">
|
||||||
|
{{ .ShopItemId }}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<p class="text-sm font-medium text-gray-900">{{ .Quantity }} pieces</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ template "footer.html" . }}
|
||||||
@@ -33,8 +33,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0 px-4 sm:px-8">
|
<div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0 px-4 sm:px-8">
|
||||||
<a href="/login" class="rounded-md bg-gray-900 m-2 px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700 hover:text-white">Login</a>
|
<a href="/cart" class="rounded-md bg-gray-900 m-2 px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700 hover:text-white">🛒 Cart</a>
|
||||||
<a href="/register" class="rounded-md bg-gray-900 m-2 px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700 hover:text-white">Register</a>
|
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,9 +8,12 @@
|
|||||||
<img class="w-full h-full object-cover" src="/{{ .data.shopItem.Image}}" alt="Product Image">
|
<img class="w-full h-full object-cover" src="/{{ .data.shopItem.Image}}" alt="Product Image">
|
||||||
</div>
|
</div>
|
||||||
<div class="flex -mx-2 mb-4">
|
<div class="flex -mx-2 mb-4">
|
||||||
|
<form action="/cart" method="POST">
|
||||||
|
<input type="hidden" id="{{ .data.shopItem.ID}}" name="ShopItemId" value="{{ .data.shopItem.ID }}">
|
||||||
<div class="w-1/3 px-2">
|
<div class="w-1/3 px-2">
|
||||||
<button class="w-full bg-gray-900 dark:bg-gray-600 text-white py-2 px-4 rounded-full font-bold hover:bg-gray-800 dark:hover:bg-gray-700">Add to Cart</button>
|
<button type="submit" class="w-full bg-gray-900 dark:bg-gray-600 text-white py-2 px-4 rounded-full font-bold hover:bg-gray-800 dark:hover:bg-gray-700">Add to Cart</button>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
{{ if .loggedIn }}
|
{{ if .loggedIn }}
|
||||||
<div class="w-1/3 px-2">
|
<div class="w-1/3 px-2">
|
||||||
|
|||||||
Reference in New Issue
Block a user