allow finalizing orders
This commit is contained in:
@@ -34,14 +34,6 @@ func NewCartItemController() 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(length int) string {
|
||||
bytes := make([]byte, length) // 16 bytes = 128 bits
|
||||
_, err := rand.Read(bytes)
|
||||
@@ -63,7 +55,7 @@ func GetSessionId(ctx *gin.Context) string {
|
||||
}
|
||||
|
||||
func GenerateToken() string {
|
||||
return generateSessionId(8)
|
||||
return generateSessionId(16)
|
||||
}
|
||||
|
||||
func (rc *cartItemController) NewCartItemFromForm(ctx *gin.Context) (models.CartItem, error) {
|
||||
@@ -143,7 +135,7 @@ func (rc *cartItemController) NewAddressFromForm(ctx *gin.Context) (models.Addre
|
||||
|
||||
func (rc *cartItemController) NewOrderFromForm(ctx *gin.Context) (models.Order, error) {
|
||||
sessionId := GetSessionId(ctx)
|
||||
status := models.OrderStatus("Received")
|
||||
status := models.OrderStatus("AwaitingConfirmation")
|
||||
token := GenerateToken()
|
||||
email := ctx.PostForm("email")
|
||||
comment := ctx.PostForm("comment")
|
||||
@@ -162,14 +154,9 @@ func (rc *cartItemController) NewOrderFromForm(ctx *gin.Context) (models.Order,
|
||||
// }
|
||||
//}
|
||||
|
||||
var shipping models.Shipping
|
||||
for _, shippingMethod := range GetShippingMethods() {
|
||||
if shippingMethod.Id == shippingStr {
|
||||
shipping = shippingMethod
|
||||
}
|
||||
}
|
||||
shipping, err := models.GetShippingMethod(shippingStr)
|
||||
|
||||
if shipping == (models.Shipping{}) {
|
||||
if err != nil {
|
||||
return models.Order{}, fmt.Errorf("Invalid shipping method.")
|
||||
}
|
||||
|
||||
@@ -267,7 +254,7 @@ func (rc *cartItemController) CartItemView(c *gin.Context) {
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"cartItems": cartItems,
|
||||
"priceTotal": fmt.Sprintf("%.2f", priceTotal), //round 2 decimals
|
||||
"shipping": GetShippingMethods(),
|
||||
"shipping": models.GetShippingMethods(),
|
||||
})
|
||||
|
||||
c.HTML(http.StatusOK, "cart.html", data)
|
||||
@@ -348,6 +335,11 @@ func (rc *cartItemController) EditItemHandler(c *gin.Context) {
|
||||
func (rc *cartItemController) CheckoutView(c *gin.Context) {
|
||||
shippingMethod := c.Query("shippingMethod")
|
||||
|
||||
if shippingMethod == "" {
|
||||
rc.CartItemView(c)
|
||||
return
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "checkout.html", gin.H{
|
||||
"askAddress": (shippingMethod != "pickup"),
|
||||
"shippingMethod": shippingMethod,
|
||||
@@ -366,10 +358,8 @@ func (rc *cartItemController) CheckoutHandler(c *gin.Context) {
|
||||
existingOrder, err := repositories.Orders.GetBySession(order.SessionId)
|
||||
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
fmt.Println("CREATE")
|
||||
_, err = repositories.Orders.Create(order)
|
||||
} else if err == nil {
|
||||
fmt.Println("UPDATE")
|
||||
order.ID = existingOrder.ID
|
||||
order.CreatedAt = existingOrder.CreatedAt
|
||||
repositories.Orders.Update(order)
|
||||
@@ -385,19 +375,27 @@ func (rc *cartItemController) CheckoutHandler(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
var shipping models.Shipping
|
||||
for _, shippingMethod := range GetShippingMethods() {
|
||||
if shippingMethod.Id == order.Shipping {
|
||||
shipping = shippingMethod
|
||||
}
|
||||
shipping, err := models.GetShippingMethod(order.Shipping)
|
||||
if err != nil {
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"error": err,
|
||||
"success": "",
|
||||
})
|
||||
|
||||
c.HTML(http.StatusOK, "cart.html", data)
|
||||
return
|
||||
}
|
||||
|
||||
priceProducts := 0.0
|
||||
for _, cartItem := range order.CartItems {
|
||||
priceProducts += (float64(cartItem.Quantity) * cartItem.ItemVariant.Price)
|
||||
}
|
||||
priceProducts, priceTotal, err := order.CalculatePrices()
|
||||
if err != nil {
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"error": err,
|
||||
"success": "",
|
||||
})
|
||||
|
||||
priceTotal := priceProducts + shipping.Price
|
||||
c.HTML(http.StatusOK, "cart.html", data)
|
||||
return
|
||||
}
|
||||
|
||||
data := CreateSessionData(c, gin.H{
|
||||
"error": "",
|
||||
@@ -411,19 +409,85 @@ func (rc *cartItemController) CheckoutHandler(c *gin.Context) {
|
||||
})
|
||||
|
||||
fmt.Println(order)
|
||||
c.HTML(http.StatusOK, "order.html", data)
|
||||
c.HTML(http.StatusOK, "orderpreview.html", data)
|
||||
}
|
||||
|
||||
func (rc *cartItemController) OrderView(c *gin.Context) {
|
||||
shippingMethod := c.Query("shippingMethod")
|
||||
orderToken := c.Param("token")
|
||||
|
||||
c.HTML(http.StatusOK, "checkout.html", gin.H{
|
||||
"askAddress": (shippingMethod != "pickup"),
|
||||
"shippingMethod": shippingMethod,
|
||||
})
|
||||
order, err := repositories.Orders.GetByToken(orderToken)
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"error": "Order does not exist."})
|
||||
return
|
||||
}
|
||||
|
||||
shipping, err := models.GetShippingMethod(order.Shipping)
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"error": "Could not get shipping method"})
|
||||
return
|
||||
}
|
||||
|
||||
priceProducts, priceTotal, err := order.CalculatePrices()
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"error": "Could not calculate final prices"})
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Order: %v\n", order)
|
||||
fmt.Printf("PriceTotal: %v\n", priceTotal)
|
||||
fmt.Printf("Amount Items: %v\n", len(order.CartItems))
|
||||
|
||||
for _, item := range order.CartItems {
|
||||
fmt.Printf("Cartitem: %v", item)
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "order.html", CreateSessionData(c, gin.H{
|
||||
"error": "",
|
||||
"success": "",
|
||||
"order": order,
|
||||
"shipping": shipping,
|
||||
"priceProducts": fmt.Sprintf("%.2f", priceProducts), //round 2 decimals
|
||||
"priceTotal": fmt.Sprintf("%.2f", priceTotal), //round 2 decimals
|
||||
}))
|
||||
}
|
||||
|
||||
func (rc *cartItemController) OrderHandler(c *gin.Context) {
|
||||
//get order by session id
|
||||
//generate token, preview payment info
|
||||
confirmation := c.PostForm("confirm-order")
|
||||
|
||||
if confirmation == "" {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"error": "Something went wrong, try again later"})
|
||||
return
|
||||
}
|
||||
|
||||
if confirmation != "true" {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"error": "Order was not confirmed."})
|
||||
return
|
||||
}
|
||||
|
||||
sessionId := GetSessionId(c)
|
||||
order, err := repositories.Orders.GetBySession(sessionId)
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"error": "Something went wrong, try again later"})
|
||||
return
|
||||
}
|
||||
|
||||
order.Status = models.AwaitingPayment
|
||||
|
||||
err = order.Validate()
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
_, err = repositories.Orders.Update(order)
|
||||
|
||||
if err != nil {
|
||||
c.HTML(http.StatusBadRequest, "error.html", gin.H{"error": err})
|
||||
return
|
||||
}
|
||||
|
||||
//TODO: cartItemRepository delete all by session - otherwise items stay in cart after completing order..
|
||||
|
||||
c.Redirect(http.StatusFound, fmt.Sprintf("/order/%s", order.Token))
|
||||
}
|
||||
|
||||
2
main.go
2
main.go
@@ -90,7 +90,7 @@ func main() {
|
||||
viewRoutes.POST("/cart/edit", cartItemController.EditItemHandler)
|
||||
viewRoutes.GET("/checkout", cartItemController.CheckoutView)
|
||||
viewRoutes.POST("/checkout", cartItemController.CheckoutHandler)
|
||||
viewRoutes.GET("/order", cartItemController.OrderView)
|
||||
viewRoutes.GET("/order/:token", cartItemController.OrderView)
|
||||
viewRoutes.POST("/order", cartItemController.OrderHandler)
|
||||
|
||||
//write middleware that redirects to homescreen on register/login/reset for logged in users
|
||||
|
||||
166
models/cart.go
166
models/cart.go
@@ -1,59 +1,161 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type OrderStatus string
|
||||
|
||||
const (
|
||||
Received OrderStatus = "Received"
|
||||
AwaitingPayment OrderStatus = "AwaitingPayment"
|
||||
Payed OrderStatus = "Payed"
|
||||
ReadyForPickup OrderStatus = "ReadyForPickup"
|
||||
Shipped OrderStatus = "Shipped"
|
||||
Cancelled OrderStatus = "Cancelled"
|
||||
AwaitingConfirmation OrderStatus = "AwaitingConfirmation"
|
||||
Received OrderStatus = "Received"
|
||||
AwaitingPayment OrderStatus = "AwaitingPayment"
|
||||
Payed OrderStatus = "Payed"
|
||||
ReadyForPickup OrderStatus = "ReadyForPickup"
|
||||
Shipped OrderStatus = "Shipped"
|
||||
Cancelled OrderStatus = "Cancelled"
|
||||
)
|
||||
|
||||
type AddressInfo struct {
|
||||
FirstName string `json:"firstname"`
|
||||
LastName string `json:"lastname"`
|
||||
Address string `json:"address"`
|
||||
FirstName string `json:"firstname"`
|
||||
LastName string `json:"lastname"`
|
||||
Address string `json:"address"`
|
||||
PostalCode string `json:"postalcode"`
|
||||
City string `json:"city"`
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
Country string `json:"country"`
|
||||
}
|
||||
|
||||
type Shipping struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Price float64 `json:"price"`
|
||||
}
|
||||
|
||||
func GetShippingMethods() []Shipping {
|
||||
return []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 GetShippingMethod(id string) (Shipping, error) {
|
||||
var shipping Shipping
|
||||
found := false
|
||||
for _, shippingMethod := range GetShippingMethods() {
|
||||
if shippingMethod.Id == id {
|
||||
shipping = shippingMethod
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return Shipping{}, fmt.Errorf("Shipping method does not exist.")
|
||||
}
|
||||
|
||||
return shipping, nil
|
||||
}
|
||||
|
||||
type Order struct {
|
||||
gorm.Model
|
||||
SessionId string `json:"sessionid" binding:"required" gorm:"not null"`
|
||||
Status OrderStatus `json:"status"`
|
||||
Token string `json:"token" binding:"required" gorm:"not null"`
|
||||
Email string `json:"email"`
|
||||
Comment string `json:"comment"`
|
||||
FirstName string `json:"firstname"`
|
||||
LastName string `json:"lastname"`
|
||||
Address string `json:"address"`
|
||||
PostalCode string `json:"postalcode"`
|
||||
City string `json:"city"`
|
||||
Country string `json:"country"`
|
||||
Shipping string `json:"shipping"`
|
||||
CartItems []CartItem `json:"cartitems" gorm:"foreignKey:OrderID"`
|
||||
SessionId string `json:"sessionid" binding:"required" gorm:"not null"`
|
||||
Status OrderStatus `json:"status"`
|
||||
Token string `json:"token" binding:"required" gorm:"not null"`
|
||||
Email string `json:"email"`
|
||||
Comment string `json:"comment"`
|
||||
FirstName string `json:"firstname"`
|
||||
LastName string `json:"lastname"`
|
||||
Address string `json:"address"`
|
||||
PostalCode string `json:"postalcode"`
|
||||
City string `json:"city"`
|
||||
Country string `json:"country"`
|
||||
Shipping string `json:"shipping"`
|
||||
CartItems []CartItem `json:"cartitems" gorm:"foreignKey:OrderID"`
|
||||
}
|
||||
|
||||
func (o *Order) Validate() error {
|
||||
//TODO: validate sessionId
|
||||
if o.SessionId == "" {
|
||||
return fmt.Errorf("Invalid SessionId")
|
||||
}
|
||||
|
||||
//TODO: validate token
|
||||
if o.Token == "" {
|
||||
return fmt.Errorf("Invalid Token")
|
||||
}
|
||||
|
||||
if o.Status == AwaitingConfirmation {
|
||||
return fmt.Errorf("Order still awaiting confirmation.")
|
||||
}
|
||||
|
||||
if len(o.CartItems) == 0 {
|
||||
return fmt.Errorf("Order is empty.")
|
||||
}
|
||||
|
||||
shipping, err := GetShippingMethod(o.Shipping)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//for pickup no address validation is necessary
|
||||
if shipping.Id == "pickup" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return o.ValidateAddress()
|
||||
}
|
||||
|
||||
func (o *Order) ValidateAddress() error {
|
||||
if o.FirstName == "" {
|
||||
return fmt.Errorf("Firstname missing")
|
||||
}
|
||||
if o.LastName == "" {
|
||||
return fmt.Errorf("Lastname missing")
|
||||
}
|
||||
|
||||
if o.Address == "" {
|
||||
return fmt.Errorf("Address missing")
|
||||
}
|
||||
|
||||
if o.PostalCode == "" {
|
||||
return fmt.Errorf("Postalcode missing")
|
||||
}
|
||||
|
||||
if o.City == "" {
|
||||
return fmt.Errorf("City missing")
|
||||
}
|
||||
|
||||
if o.Country == "" {
|
||||
return fmt.Errorf("Country missing")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Order) CalculatePrices() (float64, float64, error) {
|
||||
shipping, err := GetShippingMethod(o.Shipping)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
priceProducts := 0.0
|
||||
for _, cartItem := range o.CartItems {
|
||||
priceProducts += (float64(cartItem.Quantity) * cartItem.ItemVariant.Price)
|
||||
}
|
||||
|
||||
priceTotal := priceProducts + shipping.Price
|
||||
|
||||
return priceProducts, priceTotal, nil
|
||||
}
|
||||
|
||||
type CartItem struct {
|
||||
gorm.Model
|
||||
SessionId string `json:"sessionid" binding:"required" gorm:"not null"`
|
||||
ShopItemId uint
|
||||
ShopItem ShopItem `json:"shopitem" gorm:"foreignKey:ShopItemId"` //gorm one2one
|
||||
SessionId string `json:"sessionid" binding:"required" gorm:"not null"`
|
||||
ShopItemId uint
|
||||
ShopItem ShopItem `json:"shopitem" gorm:"foreignKey:ShopItemId"` //gorm one2one
|
||||
ItemVariantId uint
|
||||
ItemVariant ItemVariant `json:"itemvariant" gorm:"foreignKey:ItemVariantId"` //gorm one2one
|
||||
Quantity int `json:"quantity" binding:"required"`
|
||||
OrderID uint
|
||||
ItemVariant ItemVariant `json:"itemvariant" gorm:"foreignKey:ItemVariantId"` //gorm one2one
|
||||
Quantity int `json:"quantity" binding:"required"`
|
||||
OrderID uint
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ type OrderRepository interface {
|
||||
GetAll() ([]models.Order, error)
|
||||
GetById(string) (models.Order, error)
|
||||
GetBySession(string) (models.Order, error)
|
||||
GetByToken(string) (models.Order, error)
|
||||
Update(models.Order) (models.Order, error)
|
||||
DeleteById(string) error
|
||||
}
|
||||
@@ -62,12 +63,19 @@ func (t *GORMOrderRepository) GetById(id string) (models.Order, error) {
|
||||
|
||||
func (r *GORMOrderRepository) GetBySession(sessionId string) (models.Order, error) {
|
||||
var orders models.Order
|
||||
result := r.DB.Preload("CartItems").Where("session_id = ?", sessionId).First(&orders)
|
||||
result := r.DB.Preload("CartItems").Preload("CartItems.ShopItem").Preload("CartItems.ItemVariant").Where("session_id = ?", sessionId).First(&orders)
|
||||
|
||||
return orders, result.Error
|
||||
|
||||
}
|
||||
|
||||
func (r *GORMOrderRepository) GetByToken(token string) (models.Order, error) {
|
||||
var orders models.Order
|
||||
result := r.DB.Preload("CartItems").Preload("CartItems.ShopItem").Preload("CartItems.ItemVariant").Where("token = ?", token).First(&orders)
|
||||
|
||||
return orders, result.Error
|
||||
}
|
||||
|
||||
func (r *GORMOrderRepository) Update(order models.Order) (models.Order, error) {
|
||||
result := r.DB.Save(&order)
|
||||
if result.Error != nil {
|
||||
|
||||
@@ -587,6 +587,22 @@ video {
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.-bottom-\[1\.75rem\] {
|
||||
bottom: -1.75rem;
|
||||
}
|
||||
|
||||
.end-0 {
|
||||
inset-inline-end: 0px;
|
||||
}
|
||||
|
||||
.left-1\/2 {
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.start-0 {
|
||||
inset-inline-start: 0px;
|
||||
}
|
||||
|
||||
.col-span-12 {
|
||||
grid-column: span 12 / span 12;
|
||||
}
|
||||
@@ -698,6 +714,16 @@ video {
|
||||
aspect-ratio: 1 / 1;
|
||||
}
|
||||
|
||||
.size-5 {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.size-6 {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
}
|
||||
|
||||
.h-10 {
|
||||
height: 2.5rem;
|
||||
}
|
||||
@@ -798,6 +824,11 @@ video {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.-translate-x-1\/2 {
|
||||
--tw-translate-x: -50%;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -810,6 +841,10 @@ video {
|
||||
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.grid-cols-3 {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.flex-col {
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -822,6 +857,14 @@ video {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.justify-start {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.justify-end {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.justify-center {
|
||||
justify-content: center;
|
||||
}
|
||||
@@ -1024,6 +1067,11 @@ video {
|
||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.bg-gray-600 {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(75 85 99 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.fill-red-50 {
|
||||
fill: #fef2f2;
|
||||
}
|
||||
@@ -1301,6 +1349,11 @@ video {
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
|
||||
}
|
||||
|
||||
.text-blue-600 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(37 99 235 / var(--tw-text-opacity, 1));
|
||||
}
|
||||
|
||||
.underline {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
@@ -1357,6 +1410,37 @@ video {
|
||||
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
|
||||
}
|
||||
|
||||
.after\:mt-4::after {
|
||||
content: var(--tw-content);
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.after\:block::after {
|
||||
content: var(--tw-content);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.after\:h-1::after {
|
||||
content: var(--tw-content);
|
||||
height: 0.25rem;
|
||||
}
|
||||
|
||||
.after\:w-full::after {
|
||||
content: var(--tw-content);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.after\:rounded-lg::after {
|
||||
content: var(--tw-content);
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.after\:bg-gray-200::after {
|
||||
content: var(--tw-content);
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.focus-within\:outline-none:focus-within {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
|
||||
@@ -1,9 +1,37 @@
|
||||
{{ template "header.html" . }}
|
||||
|
||||
<section class="bg-white py-8 antialiased dark:bg-gray-900 md:py-16">
|
||||
<form action="/checkout" method="POST" class="mx-auto max-w-screen-xl px-4 2xl:px-0">
|
||||
<div class="mx-auto max-w-screen-xl px-4 2xl:px-0">
|
||||
<div class="mx-auto max-w-3xl">
|
||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-white sm:text-2xl">Order summary</h2>
|
||||
<dd class="mt-1 text-base font-normal text-gray-500 dark:text-gray-400">
|
||||
Thanks for your order! As soon as your payment arrived we will print your Order.
|
||||
</dd>
|
||||
|
||||
<div class="mt-6 space-y-4 border-b border-t border-gray-200 py-8 dark:border-gray-700 sm:mt-8">
|
||||
<h4 class="text-lg font-semibold text-gray-900 dark:text-white">Order status: {{ .data.order.Status }}</h4>
|
||||
<dl>
|
||||
<dd class="mt-1 text-base font-normal text-gray-500 dark:text-gray-400">
|
||||
Order Code: {{ .data.order.Token }}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 space-y-4 border-b border-t border-gray-200 py-8 dark:border-gray-700 sm:mt-8">
|
||||
<h4 class="text-lg font-semibold text-gray-900 dark:text-white">Payment information</h4>
|
||||
|
||||
<dl>
|
||||
<dd class="mt-1 text-base font-normal text-gray-500 dark:text-gray-400">
|
||||
Either you transfer money to our bank account, or you come by and pay in cash.<br><br>
|
||||
|
||||
Miteinander Dresden e.V.*<br>
|
||||
IBAN: DE66500310001076201001<br>
|
||||
BIC: TRODDEF1 (Triodos Bank)<br>
|
||||
Subject: {{ .data.order.Token }}<br>
|
||||
Amount: {{ .data.priceTotal }}€
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 space-y-4 border-b border-t border-gray-200 py-8 dark:border-gray-700 sm:mt-8">
|
||||
<h4 class="text-lg font-semibold text-gray-900 dark:text-white">Delivery information</h4>
|
||||
@@ -23,8 +51,6 @@
|
||||
<p><b>Comment:</b> {{ .data.order.Comment }}</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<a href="/checkout?shippingMethod={{ .data.order.Shipping }}" data-modal-target="billingInformationModal" data-modal-toggle="billingInformationModal" class="text-base font-medium text-primary-700 hover:underline dark:text-primary-500">Edit</a>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 sm:mt-8">
|
||||
@@ -51,7 +77,6 @@
|
||||
</div>
|
||||
|
||||
<div class="mt-4 space-y-6">
|
||||
<h4 class="text-xl font-semibold text-gray-900 dark:text-white">Order summary</h4>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="space-y-2">
|
||||
@@ -72,21 +97,10 @@
|
||||
<dd class="text-lg font-bold text-gray-900 dark:text-white">{{ .data.priceTotal }}€</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="flex items-start sm:items-center">
|
||||
<input id="terms-checkbox-2" type="checkbox" value="" class="h-4 w-4 rounded border-gray-300 bg-gray-100 text-primary-600 focus:ring-2 focus:ring-primary-500 dark:border-gray-600 dark:bg-gray-700 dark:ring-offset-gray-800 dark:focus:ring-primary-600" />
|
||||
<label for="terms-checkbox-2" class="ms-2 text-sm font-medium text-gray-900 dark:text-gray-300"> I agree with the <a href="#" title="" class="text-primary-700 underline hover:no-underline dark:text-primary-500">Terms and Conditions</a> of use of the Flowbite marketplace </label>
|
||||
</div>
|
||||
|
||||
<div class="gap-4 sm:flex sm:items-center">
|
||||
<button type="button" class="w-full rounded-lg border border-gray-200 bg-white px-5 py-2.5 text-sm font-medium text-gray-900 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:outline-none focus:ring-4 focus:ring-gray-100 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white dark:focus:ring-gray-700"><a href="/">Return to Shopping</a></button>
|
||||
|
||||
<button type="submit" class="w-full bg-gray-900 dark:bg-gray-600 rounded-lg border border-gray-200 bg-white px-5 py-2.5 text-sm font-medium text-gray-900 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:outline-none focus:ring-4 focus:ring-gray-100 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white dark:focus:ring-gray-700">Place binding order</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{ template "footer.html" . }}
|
||||
|
||||
Reference in New Issue
Block a user