work on checkout
This commit is contained in:
@@ -21,6 +21,7 @@ type CartItemController interface {
|
|||||||
DeleteItemHandler(*gin.Context)
|
DeleteItemHandler(*gin.Context)
|
||||||
EditItemHandler(*gin.Context)
|
EditItemHandler(*gin.Context)
|
||||||
CheckoutView(*gin.Context)
|
CheckoutView(*gin.Context)
|
||||||
|
CheckoutHandler(*gin.Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
type cartItemController struct {}
|
type cartItemController struct {}
|
||||||
@@ -29,6 +30,15 @@ func NewCartItemController() CartItemController {
|
|||||||
return &cartItemController{}
|
return &cartItemController{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func GetShippingMethods() []models.Shipping {
|
||||||
|
return []models.Shipping{
|
||||||
|
{ Id: "germany", Name: "Germany (DHL)", Price: 3.99 },
|
||||||
|
{ Id: "international", Name: "International (DHL)", Price: 5.99 },
|
||||||
|
{ Id: "pickup", Name: "Pickup", Price: 0.00 },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func generateSessionId() string {
|
func generateSessionId() string {
|
||||||
bytes := make([]byte, 16) // 16 bytes = 128 bits
|
bytes := make([]byte, 16) // 16 bytes = 128 bits
|
||||||
_, err := rand.Read(bytes)
|
_, err := rand.Read(bytes)
|
||||||
@@ -151,6 +161,7 @@ func (rc *cartItemController) CartItemView(c *gin.Context) {
|
|||||||
data := CreateSessionData(c, gin.H{
|
data := CreateSessionData(c, gin.H{
|
||||||
"cartItems": cartItems,
|
"cartItems": cartItems,
|
||||||
"priceTotal": fmt.Sprintf("%.2f", priceTotal), //round 2 decimals
|
"priceTotal": fmt.Sprintf("%.2f", priceTotal), //round 2 decimals
|
||||||
|
"shipping": GetShippingMethods(),
|
||||||
})
|
})
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "cart.html", data)
|
c.HTML(http.StatusOK, "cart.html", data)
|
||||||
@@ -229,5 +240,14 @@ func (rc *cartItemController) EditItemHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rc *cartItemController) CheckoutView(c *gin.Context) {
|
func (rc *cartItemController) CheckoutView(c *gin.Context) {
|
||||||
c.HTML(http.StatusOK, "checkout.html", gin.H{})
|
shippingMethod := c.Query("shippingMethod")
|
||||||
|
|
||||||
|
c.HTML(http.StatusOK, "checkout.html", gin.H{
|
||||||
|
"askAddress": (shippingMethod != "pickup"),
|
||||||
|
"shippingMethod": shippingMethod,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *cartItemController) CheckoutHandler(*gin.Context) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,8 +126,6 @@ func (rc *shopItemController) NewShopItemFromForm(ctx *gin.Context) (models.Shop
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the price string to float64
|
|
||||||
|
|
||||||
shopItem := models.ShopItem{
|
shopItem := models.ShopItem{
|
||||||
Name: name,
|
Name: name,
|
||||||
Abstract: abstract,
|
Abstract: abstract,
|
||||||
@@ -151,7 +149,6 @@ func (rc *shopItemController) NewShopItemFromForm(ctx *gin.Context) (models.Shop
|
|||||||
}
|
}
|
||||||
|
|
||||||
return shopItem, nil
|
return shopItem, nil
|
||||||
//return services.ShopItems.NewShopItem(name, abstract, description, price, tagIds)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *shopItemController) GetBasePrice(variants []models.ItemVariant) float64 {
|
func (rc *shopItemController) GetBasePrice(variants []models.ItemVariant) float64 {
|
||||||
|
|||||||
1
main.go
1
main.go
@@ -90,6 +90,7 @@ func main() {
|
|||||||
viewRoutes.POST("/cart/delete", cartItemController.DeleteItemHandler)
|
viewRoutes.POST("/cart/delete", cartItemController.DeleteItemHandler)
|
||||||
viewRoutes.POST("/cart/edit", cartItemController.EditItemHandler)
|
viewRoutes.POST("/cart/edit", cartItemController.EditItemHandler)
|
||||||
viewRoutes.GET("/checkout", cartItemController.CheckoutView)
|
viewRoutes.GET("/checkout", cartItemController.CheckoutView)
|
||||||
|
viewRoutes.POST("/checkout", cartItemController.CheckoutHandler)
|
||||||
|
|
||||||
//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)
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ type AddressInfo struct {
|
|||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Shipping struct {
|
||||||
|
Id string `json:"name"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Price float64 `json:"price"`
|
||||||
|
}
|
||||||
|
|
||||||
type Order struct {
|
type Order struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Status OrderStatus `json:"status"`
|
Status OrderStatus `json:"status"`
|
||||||
@@ -31,6 +37,7 @@ type Order struct {
|
|||||||
CartItems []CartItem `json:"cartitems"`
|
CartItems []CartItem `json:"cartitems"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Comment string `json:"comment"`
|
Comment string `json:"comment"`
|
||||||
|
Shipping
|
||||||
}
|
}
|
||||||
|
|
||||||
type CartItem struct {
|
type CartItem struct {
|
||||||
|
|||||||
@@ -1128,6 +1128,11 @@ video {
|
|||||||
line-height: 1rem;
|
line-height: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-sm\/8 {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.font-bold {
|
.font-bold {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,20 +64,34 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="flex flex-col md:flex-row items-center md:items-center justify-between lg:px-6 pb-6 max-lg:max-w-lg max-lg:mx-auto">
|
||||||
<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>
|
<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>
|
||||||
|
|
||||||
<div class="flex items-center justify-between gap-5 ">
|
<div class="flex items-center justify-between gap-5 ">
|
||||||
<h6 class="font-manrope font-bold text-3xl lead-10 text-indigo-600">{{ .data.priceTotal }}€</h6>
|
<h6 class="font-manrope font-bold text-3xl lead-10 text-indigo-600">{{ .data.priceTotal }}€</h6>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<form action="/checkout" method="GET">
|
||||||
|
<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">
|
||||||
|
<h2 class="text-gray-900 font-manrope font-semibold leading-9 w-full max-md:text-center max-md:mb-4">Select shipping method</h2>
|
||||||
|
<select name="shippingMethod" id="shippingMethod" required class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||||
|
<option selected value="">Shipping</option>
|
||||||
|
{{ range .data.shipping }}
|
||||||
|
<option value="{{ .Id }}">{{ .Name }} - {{ .Price }}€</option>
|
||||||
|
{{ end }}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="max-lg:max-w-lg max-lg:mx-auto">
|
<div class="max-lg:max-w-lg max-lg:mx-auto">
|
||||||
<p class="font-normal text-base leading-7 text-gray-500 text-center mb-5 mt-6">Shipping calculated at checkout</p>
|
<p class="font-normal text-base leading-7 text-gray-500 text-center mb-5 mt-6">Shipping calculated at checkout</p>
|
||||||
<a href="/checkout"
|
<button type="submit"
|
||||||
class="rounded-full py-4 px-6 bg-indigo-600 text-white font-semibold text-lg w-full text-center transition-all duration-500 hover:bg-indigo-700 ">Checkout</a>
|
class="rounded-full py-4 px-6 bg-indigo-600 text-white font-semibold text-lg w-full text-center transition-all duration-500 hover:bg-indigo-700 ">Checkout</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
<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">
|
<form class="space-y-6" action="#" method="POST" enctype="multipart/form-data">
|
||||||
|
<input type="hidden" name="shippingMethod" value="{{ .shippingMethod }}" required>
|
||||||
|
{{ if .askAddress }}
|
||||||
<div>
|
<div>
|
||||||
<label for="name" class="block text-sm/6 font-medium text-gray-900">First Name</label>
|
<label for="name" class="block text-sm/6 font-medium text-gray-900">First Name</label>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
@@ -54,11 +56,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label for="lastname" class="block text-sm/6 font-medium text-gray-900">E-Mail</label>
|
<label for="lastname" class="block text-sm/6 font-medium text-gray-900">E-Mail</label>
|
||||||
|
<p class="text-sm/8 font-small text-gray-600">Without E-Mail you wont receive an order confirmation.</p>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<input type="text" name="lastname" id="lastname" 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">
|
<input type="email" name="lastname" id="lastname" 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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -68,17 +73,6 @@
|
|||||||
<textarea id="description" name="description" type="textarea" class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"></textarea>
|
<textarea id="description" name="description" type="textarea" class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="flex mb-4">
|
|
||||||
<label for="DeliveryMethod" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"></label>
|
|
||||||
<select name="DeliveryMethod" id="DeliveryMethod" required class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
|
||||||
<option selected value="">Shipping</option>
|
|
||||||
<option value="germany">germany (DHL) 3.99€</option>
|
|
||||||
<option value="international">international (DHL) 5.99€</option>
|
|
||||||
<option value="pickup">pickup 0.00€</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="mt-10 text-center text-sm/6 text-red-500">
|
<p class="mt-10 text-center text-sm/6 text-red-500">
|
||||||
{{ .data.error }}
|
{{ .data.error }}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user