Producte show
Producte werden nun angezeigt .
This commit is contained in:
@@ -160,6 +160,9 @@ func (server *Server) routeInit() {
|
|||||||
server.Router.HandleFunc("/register", server.DoRegister).Methods("POST")
|
server.Router.HandleFunc("/register", server.DoRegister).Methods("POST")
|
||||||
server.Router.HandleFunc("/logout", server.Logout).Methods("GET")
|
server.Router.HandleFunc("/logout", server.Logout).Methods("GET")
|
||||||
|
|
||||||
|
server.Router.HandleFunc("/products", server.Products).Methods("GET")
|
||||||
|
server.Router.HandleFunc("/products/{slug}", server.GetProductByID).Methods("GET")
|
||||||
|
|
||||||
staticFileDirectory := http.Dir("./assets/")
|
staticFileDirectory := http.Dir("./assets/")
|
||||||
staticFileHandler := http.StripPrefix("/public/", http.FileServer(staticFileDirectory))
|
staticFileHandler := http.StripPrefix("/public/", http.FileServer(staticFileDirectory))
|
||||||
server.Router.PathPrefix("/public/").Handler(staticFileHandler).Methods("GET")
|
server.Router.PathPrefix("/public/").Handler(staticFileHandler).Methods("GET")
|
||||||
|
|||||||
62
app/controllers/product_controller.go
Normal file
62
app/controllers/product_controller.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/unrolled/render"
|
||||||
|
"moretcgshop/app/models"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (server *Server) Products(w http.ResponseWriter, r *http.Request) {
|
||||||
|
renderer := render.New(render.Options{
|
||||||
|
Layout: "layout",
|
||||||
|
Extensions: []string{".html", ".tmpl"},
|
||||||
|
})
|
||||||
|
|
||||||
|
q := r.URL.Query()
|
||||||
|
|
||||||
|
page, _ := strconv.Atoi(q.Get("page"))
|
||||||
|
if page <= 0 {
|
||||||
|
page = 1
|
||||||
|
}
|
||||||
|
perPage := 9
|
||||||
|
|
||||||
|
productModel := models.Product{}
|
||||||
|
products, totalRows, err := productModel.GetProducts(server.DB, perPage, page)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = totalRows
|
||||||
|
|
||||||
|
_ = renderer.HTML(w, http.StatusOK, "products", map[string]interface{}{
|
||||||
|
"products": products,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) GetProductByID(w http.ResponseWriter, r *http.Request) {
|
||||||
|
renderer := render.New(render.Options{
|
||||||
|
Layout: "layout",
|
||||||
|
Extensions: []string{".html", ".tmpl"},
|
||||||
|
})
|
||||||
|
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
|
||||||
|
if vars["slug"] == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
productModel := models.Product{}
|
||||||
|
product, err := productModel.FindByID(server.DB, vars["slug"])
|
||||||
|
if err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = renderer.HTML(w, http.StatusOK, "product", map[string]interface{}{
|
||||||
|
"product": product,
|
||||||
|
"success": GetFlash(w, r, "success"),
|
||||||
|
"error": GetFlash(w, r, "error"),
|
||||||
|
})
|
||||||
|
}
|
||||||
16
app/models/ProductImage.go
Normal file
16
app/models/ProductImage.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type ProductImage struct {
|
||||||
|
ID string `gorm:"size:36;not null;uniqueIndex;primary_key"`
|
||||||
|
Product Product
|
||||||
|
ProductID string `gorm:"size:36;index"`
|
||||||
|
Path string `gorm:"type:text"`
|
||||||
|
ExtraLarge string `gorm:"type:text"`
|
||||||
|
Large string `gorm:"type:text"`
|
||||||
|
Medium string `gorm:"type:text"`
|
||||||
|
Small string `gorm:"type:text"`
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
}
|
||||||
@@ -10,5 +10,6 @@ func RegisterModels() []Model {
|
|||||||
{Model: Product{}},
|
{Model: Product{}},
|
||||||
{Model: Category{}},
|
{Model: Category{}},
|
||||||
{Model: Section{}},
|
{Model: Section{}},
|
||||||
|
{Model: ProductImage{}},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,55 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Product struct {
|
type Product struct {
|
||||||
ID string
|
ID string `gorm:"size:36;not null;uniqueIndex;primary_key"`
|
||||||
ParentID string
|
ParentID string `gorm:"size:36;index"`
|
||||||
Name string
|
Name string `gorm:"size:255"`
|
||||||
Categories []Category `gorm:"many2many:product_categories;"`
|
Slug string `gorm:"size:255"`
|
||||||
CreatedAt time.Time
|
ProductImages []ProductImage
|
||||||
UpdatedAt time.Time
|
Price decimal.Decimal `gorm:"type:decimal(16,2);"`
|
||||||
DeletedAt gorm.DeletedAt
|
Categories []Category `gorm:"many2many:product_categories;"`
|
||||||
|
ShortDescription string `gorm:"type:text"`
|
||||||
|
Description string `gorm:"type:text"`
|
||||||
|
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
DeletedAt gorm.DeletedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Product) GetProducts(db *gorm.DB, perPage int, page int) (*[]Product, int64, error) {
|
||||||
|
|
||||||
|
var count int64
|
||||||
|
var products []Product
|
||||||
|
|
||||||
|
err := db.Debug().Model(&Product{}).Count(&count).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := (page - 1) * perPage
|
||||||
|
|
||||||
|
err = db.Debug().Model(&Product{}).Order("created_at desc").Limit(perPage).Offset(offset).Find(&products).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
return &products, count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Product) FindByID(db *gorm.DB, productID string) (*Product, error) {
|
||||||
|
var err error
|
||||||
|
var product Product
|
||||||
|
|
||||||
|
err = db.Debug().Preload("ProductImages").Model(&Product{}).Where("id = ?", productID).First(&product).Error
|
||||||
|
//err = db.Debug().Model(&Product{}).Where("id = ?", productID).First(&product).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &product, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,29 +31,17 @@ services:
|
|||||||
labels:
|
labels:
|
||||||
# Frontend
|
# Frontend
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.hochzeit.entrypoints=http"
|
- "traefik.http.routers.moretcg-shop.entrypoints=http"
|
||||||
- "traefik.http.routers.hochzeit.rule=Host(`drone.cosysda.de`)"
|
- "traefik.http.routers.moretcg-shop.rule=Host(`drone.cosysda.de`)"
|
||||||
- "traefik.http.middlewares.hochzeit-https-redirect.redirectscheme.scheme=https"
|
- "traefik.http.middlewares.moretcg-shop-https-redirect.redirectscheme.scheme=https"
|
||||||
- "traefik.http.routers.hochzeit.middlewares=hochzeit-https-redirect"
|
- "traefik.http.routers.moretcg-shop.middlewares=moretcg-shop-https-redirect"
|
||||||
- "traefik.http.routers.hochzeit-secure.entrypoints=https"
|
- "traefik.http.routers.moretcg-shop-secure.entrypoints=https"
|
||||||
- "traefik.http.routers.hochzeit-secure.rule=Host(`drone.cosysda.de`)"
|
- "traefik.http.routers.moretcg-shop-secure.rule=Host(`drone.cosysda.de`)"
|
||||||
- "traefik.http.routers.hochzeit-secure.tls=true"
|
- "traefik.http.routers.moretcg-shop-secure.tls=true"
|
||||||
- "traefik.http.routers.hochzeit-secure.tls.certresolver=http"
|
- "traefik.http.routers.moretcg-shop-secure.tls.certresolver=http"
|
||||||
- "traefik.http.routers.hochzeit-secure.service=hochzeit"
|
- "traefik.http.routers.moretcg-shop-secure.service=moretcg-shop"
|
||||||
- "traefik.http.services.hochzeit.loadbalancer.server.port=9000"
|
- "traefik.http.services.moretcg-shop.loadbalancer.server.port=9000"
|
||||||
- "traefik.docker.network=http_network"
|
- "traefik.docker.network=http_network"
|
||||||
#- "traefik.http.routers.frontend.entrypoints=websecure"
|
|
||||||
#- "traefik.http.services.frontend.loadbalancer.server.port=9000"
|
|
||||||
#- "traefik.http.routers.frontend.service=frontend"
|
|
||||||
#- "traefik.http.routers.frontend.tls.certresolver=leresolver"
|
|
||||||
# Edge
|
|
||||||
#- "traefik.http.routers.edge.rule=Host:edge.cosysda.de"
|
|
||||||
#- "traefik.http.routers.edge.entrypoints=websecure"
|
|
||||||
#- "traefik.http.services.edge.loadbalancer.server.port=8000"
|
|
||||||
#- "traefik.http.routers.edge.service=edge"
|
|
||||||
#- "traefik.http.routers.edge.tls.certresolver=leresolver"
|
|
||||||
networks:
|
networks:
|
||||||
- http_network
|
- http_network
|
||||||
- moretcg
|
- moretcg
|
||||||
#volumes:
|
|
||||||
#portainer_data:
|
|
||||||
|
|||||||
1
go.mod
1
go.mod
@@ -7,6 +7,7 @@ require (
|
|||||||
github.com/gorilla/mux v1.8.1
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/gorilla/sessions v1.2.2
|
github.com/gorilla/sessions v1.2.2
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
|
github.com/shopspring/decimal v1.3.1
|
||||||
github.com/unrolled/render v1.6.1
|
github.com/unrolled/render v1.6.1
|
||||||
golang.org/x/crypto v0.14.0
|
golang.org/x/crypto v0.14.0
|
||||||
gorm.io/driver/postgres v1.5.4
|
gorm.io/driver/postgres v1.5.4
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -25,6 +25,8 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
|||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||||
|
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
|||||||
27
templates/pages/pagination.html
Normal file
27
templates/pages/pagination.html
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{{ define "pagination" }}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<ul class="pagination">
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ .pagination.PrevPage }}" tabindex="-1">
|
||||||
|
<i class="fa fa-angle-left"></i>
|
||||||
|
<span class="sr-only">Previous</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{{ range $i, $link := .pagination.Links }}
|
||||||
|
{{ $active := "" }}
|
||||||
|
{{ if $link.IsCurrentPage }}
|
||||||
|
{{ $active = "active" }}
|
||||||
|
{{ end }}
|
||||||
|
<li class="page-item {{ $active }}"><a class="page-link" href="{{ $link.Url }}">{{ $link.Page }}</a></li>
|
||||||
|
{{ end }}
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="{{ .pagination.NextPage }}">
|
||||||
|
<i class="fa fa-angle-right"></i>
|
||||||
|
<span class="sr-only">Next</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
170
templates/pages/product.html
Normal file
170
templates/pages/product.html
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
{{ define "product" }}
|
||||||
|
<section class="breadcrumb-section pb-3 pt-3">
|
||||||
|
<div class="container">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item"><a href="/">Home</a></li>
|
||||||
|
<li class="breadcrumb-item"><a href="/products">Products</a></li>
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">{{ .product.Name}}</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="product-page pb-4 pt-4">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row product-detail-inner">
|
||||||
|
<div class="col-lg-6 col-md-6 col-12">
|
||||||
|
<div id="product-images" class="carousel slide" data-ride="carousel">
|
||||||
|
<!-- slides -->
|
||||||
|
<div class="carousel-inner">
|
||||||
|
{{ range $i, $productImage := .product.ProductImages }}
|
||||||
|
{{ if eq $i 0 }}
|
||||||
|
<div class="carousel-item active"><img src="{{ $productImage.Path }}" alt="Product 1">
|
||||||
|
</div>
|
||||||
|
{{ else }}
|
||||||
|
<<div class="carousel-item"><img src="{{ $productImage.Path }}" alt="Product 2"></div>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</div> <!-- Left right -->
|
||||||
|
<a class="carousel-control-prev" href="#product-images" data-slide="prev"> <span
|
||||||
|
class="carousel-control-prev-icon"></span> </a> <a class="carousel-control-next"
|
||||||
|
href="#product-images" data-slide="next">
|
||||||
|
<span class="carousel-control-next-icon"></span> </a><!-- Thumbnails -->
|
||||||
|
<ol class="carousel-indicators list-inline">
|
||||||
|
{{ range $i, $productImage := .product.ProductImages }}
|
||||||
|
{{ if eq $i 0 }}
|
||||||
|
<li class="list-inline-item active"><a id="carousel-selector-{{ $i }}" class="selected"
|
||||||
|
data-slide-to="{{ $i }}" data-target="#product-images">
|
||||||
|
<img src="{{ $productImage.Path }}" class="img-fluid"> </a></li>
|
||||||
|
{{ else }}
|
||||||
|
<li class="list-inline-item"><a id="carousel-selector-{{ $i }}" data-slide-to="{{ $i }}"
|
||||||
|
data-target="#product-images"> <img
|
||||||
|
src="{{ $productImage.Path }}" class="img-fluid"> </a></li>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 col-md-6 col-12">
|
||||||
|
<div class="product-detail">
|
||||||
|
<h2 class="product-name">{{ .product.Name }}</h2>
|
||||||
|
<div class="product-price">
|
||||||
|
<span class="price">IDR {{ .product.Price }}</span>
|
||||||
|
</div>
|
||||||
|
{{ if .success }}
|
||||||
|
<div class="alert alert-success">
|
||||||
|
{{ range $i, $msg := .success }}
|
||||||
|
{{ $msg }}<br/>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ if .error }}
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
{{ range $i, $msg := .error }}
|
||||||
|
{{ $msg }}<br/>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
<div class="product-short-desc">
|
||||||
|
<p>{{ .product.ShortDescription }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="product-select">
|
||||||
|
<form method="POST" action="/carts">
|
||||||
|
<input type="hidden" name="product_id" value="{{ .product.ID }}"/>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<input type="number" name="qty" class="form-control" value="1"/>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-5">
|
||||||
|
<button type="submit" class="btn btn-primary btn-block">Add to Cart</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<a href="#" class="btn btn-secondary"><i class="fa fa-heart-o"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<!--
|
||||||
|
<div class="product-categories">
|
||||||
|
<ul>
|
||||||
|
<li class="categories-title">Categories :</li>
|
||||||
|
<li><a href="#">fashion</a></li>
|
||||||
|
<li><a href="#">electronics</a></li>
|
||||||
|
<li><a href="#">toys</a></li>
|
||||||
|
<li><a href="#">food</a></li>
|
||||||
|
<li><a href="#">jewellery</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
<!--<div class="product-tags">
|
||||||
|
<ul>
|
||||||
|
<li class="categories-title">Tags :</li>
|
||||||
|
<li><a href="#">fashion</a></li>
|
||||||
|
<li><a href="#">electronics</a></li>
|
||||||
|
<li><a href="#">toys</a></li>
|
||||||
|
<li><a href="#">food</a></li>
|
||||||
|
<li><a href="#">jewellery</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
<div class="product-share">
|
||||||
|
<ul>
|
||||||
|
<li class="categories-title">Share :</li>
|
||||||
|
<li><a href="#"><i class="fa fa-facebook"></i></a></li>
|
||||||
|
<li><a href="#"><i class="fa fa-twitter"></i></a></li>
|
||||||
|
<li><a href="#"><i class="fa fa-pinterest"></i></a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="product-details">
|
||||||
|
<div class="nav-wrapper">
|
||||||
|
<ul class="nav nav-pills nav-fill flex-column flex-md-row" id="tabs-icons-text" role="tablist">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link mb-sm-3 mb-md-0 active" id="tabs-icons-text-1-tab" data-toggle="tab"
|
||||||
|
href="#tabs-icons-text-1" role="tab" aria-controls="tabs-icons-text-1"
|
||||||
|
aria-selected="true">Beschreibung</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link mb-sm-3 mb-md-0" id="tabs-icons-text-2-tab" data-toggle="tab"
|
||||||
|
href="#tabs-icons-text-2" role="tab" aria-controls="tabs-icons-text-2"
|
||||||
|
aria-selected="false">Reviews</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="tab-content" id="myTabContent">
|
||||||
|
<div class="tab-pane fade show active" id="tabs-icons-text-1" role="tabpanel"
|
||||||
|
aria-labelledby="tabs-icons-text-1-tab">
|
||||||
|
<p>{{ .product.Description }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane fade" id="tabs-icons-text-2" role="tabpanel"
|
||||||
|
aria-labelledby="tabs-icons-text-2-tab">
|
||||||
|
<div class="review-form">
|
||||||
|
<h3>Write a review</h3>
|
||||||
|
<form>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Your Name</label>
|
||||||
|
<input type="text" class="form-control"/>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Your Review</label>
|
||||||
|
<textarea cols="4" class="form-control"></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Submit</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{{ end }}
|
||||||
120
templates/pages/products.html
Normal file
120
templates/pages/products.html
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
{{ define "products" }}
|
||||||
|
<section class="breadcrumb-section pb-3 pt-3">
|
||||||
|
<div class="container">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item"><a href="#">Home</a></li>
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">Products</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="products-grid pb-4 pt-4">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 col-12">
|
||||||
|
<div class="sidebar">
|
||||||
|
<!--<div class="sidebar-widget">
|
||||||
|
<div class="widget-title">
|
||||||
|
<h3>Shop by Price</h3>
|
||||||
|
</div>
|
||||||
|
<div class="widget-content shop-by-price">
|
||||||
|
<form method="get" action="/tesas">
|
||||||
|
<div class="price-filter">
|
||||||
|
<div class="price-filter-inner">
|
||||||
|
<div id="slider-range"></div>
|
||||||
|
<div class="price_slider_amount">
|
||||||
|
<div class="label-input">
|
||||||
|
<input type="text" id="amount" name="price"
|
||||||
|
placeholder="Add Your Price" />
|
||||||
|
<button type="submit">Filter</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>-->
|
||||||
|
<div class="sidebar-widget">
|
||||||
|
<div class="widget-title">
|
||||||
|
<h3>Categories</h3>
|
||||||
|
</div>
|
||||||
|
<div class="widget-content widget-categories">
|
||||||
|
<ul>
|
||||||
|
<li><a href="#">Fashions</a></li>
|
||||||
|
<li><a href="#">Electronics</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#">Hand Phone</a></li>
|
||||||
|
<li><a href="#">Laptops</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="#">Home and Kitchen</a></li>
|
||||||
|
<li><a href="#">Baby and Toys</a></li>
|
||||||
|
<li><a href="#">Sports</a></li>
|
||||||
|
<li><a href="#">Digital Goods</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--
|
||||||
|
<div class="sidebar-widget">
|
||||||
|
<div class="widget-title">
|
||||||
|
<h3>Brands</h3>
|
||||||
|
</div>
|
||||||
|
<div class="widget-content widget-brands">
|
||||||
|
<ul>
|
||||||
|
<li><a href="#">Apple</a></li>
|
||||||
|
<li><a href="#">Samsung</a></li>
|
||||||
|
<li><a href="#">Lenovo</a></li>
|
||||||
|
<li><a href="#">Asus</a></li>
|
||||||
|
<li><a href="#">Xiaomi</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-9 col-md-8 col-12">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="products-top">
|
||||||
|
<div class="products-top-inner">
|
||||||
|
<div class="products-found">
|
||||||
|
<p><span>25</span> products found of <span>1.342</span></p>
|
||||||
|
</div>
|
||||||
|
<!--
|
||||||
|
<div class="products-sort">
|
||||||
|
<span>Sort By : </span>
|
||||||
|
<select>
|
||||||
|
<option>Default</option>
|
||||||
|
<option>Price</option>
|
||||||
|
<option>Recent</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
{{ range $i, $product := .products }}
|
||||||
|
<div class="col-lg-4 col-md-6 col-12">
|
||||||
|
<div class="single-product">
|
||||||
|
<div class="product-img">
|
||||||
|
<a href="/products/{{ $product.Slug }}">
|
||||||
|
<img src="https://placehold.jp/300x400.png" class="img-fluid" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="product-content">
|
||||||
|
<h3><a href="/products/{{ $product.Slug }}">{{ $product.Name }}</a></h3>
|
||||||
|
<div class="product-price">
|
||||||
|
<span>{{ $product.Price }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ template "pagination" . }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{{ end }}
|
||||||
Reference in New Issue
Block a user