frontend: checkout form
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
parent
75135e6c7f
commit
e9826f5f69
5 changed files with 111 additions and 36 deletions
|
@ -233,6 +233,28 @@ func (fe *frontendServer) viewCartHandler(w http.ResponseWriter, r *http.Request
|
|||
}
|
||||
}
|
||||
|
||||
func (fe *frontendServer) prepareCheckoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
streetAddress1 := r.FormValue("street_address_1")
|
||||
streetAddress2 := r.FormValue("street_address_2")
|
||||
city := r.FormValue("city")
|
||||
country := r.FormValue("country")
|
||||
zipCode, _ := strconv.ParseInt(r.FormValue("country"), 10, 32)
|
||||
|
||||
log.Printf("[prepareCheckout] session_id=%+v", sessionID(r))
|
||||
_, _ = pb.NewCheckoutServiceClient(fe.checkoutSvcConn).CreateOrder(r.Context(),
|
||||
&pb.CreateOrderRequest{
|
||||
UserId: sessionID(r),
|
||||
UserCurrency: currentCurrency(r),
|
||||
Address: &pb.Address{
|
||||
StreetAddress_1: streetAddress1,
|
||||
StreetAddress_2: streetAddress2,
|
||||
City: city,
|
||||
ZipCode: int32(zipCode),
|
||||
Country: country,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (fe *frontendServer) logoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("[home] session_id=%+v", sessionID(r))
|
||||
for _, c := range r.Cookies() {
|
||||
|
|
|
@ -40,6 +40,9 @@ type frontendServer struct {
|
|||
|
||||
recommendationSvcAddr string
|
||||
recommendationSvcConn *grpc.ClientConn
|
||||
|
||||
checkoutSvcAddr string
|
||||
checkoutSvcConn *grpc.ClientConn
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
@ -55,6 +58,7 @@ func main() {
|
|||
mustMapEnv(&svc.currencySvcAddr, "CURRENCY_SERVICE_ADDR")
|
||||
mustMapEnv(&svc.cartSvcAddr, "CART_SERVICE_ADDR")
|
||||
mustMapEnv(&svc.recommendationSvcAddr, "RECOMMENDATION_SERVICE_ADDR")
|
||||
mustMapEnv(&svc.checkoutSvcAddr, "CHECKOUT_SERVICE_ADDR")
|
||||
|
||||
var err error
|
||||
svc.currencySvcConn, err = grpc.DialContext(ctx, svc.currencySvcAddr, grpc.WithInsecure())
|
||||
|
@ -82,6 +86,7 @@ func main() {
|
|||
r.HandleFunc("/cart/empty", ensureSessionID(svc.emptyCartHandler)).Methods(http.MethodPost)
|
||||
r.HandleFunc("/setCurrency", ensureSessionID(svc.setCurrencyHandler)).Methods(http.MethodPost)
|
||||
r.HandleFunc("/logout", svc.logoutHandler).Methods(http.MethodGet)
|
||||
r.HandleFunc("/checkout", ensureSessionID(svc.prepareCheckoutHandler)).Methods(http.MethodGet, http.MethodHead)
|
||||
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static/"))))
|
||||
log.Printf("starting server on :" + srvPort)
|
||||
log.Fatal(http.ListenAndServe("localhost:"+srvPort, r))
|
||||
|
|
13
src/frontend/port-forward-dependencies.sh
Executable file
13
src/frontend/port-forward-dependencies.sh
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
kubectl port-forward $(kubectl get pods -l app=currencyservice -o=name) 7000:31337 &
|
||||
kubectl port-forward $(kubectl get pods -l app=recommendationservice -o=name) 8081:8080 &
|
||||
kubectl port-forward $(kubectl get pods -l app=cartservice -o=name) 7070:7070 &
|
||||
kubectl port-forward $(kubectl get pods -l app=productcatalogservice -o=name) 3550:3550 &
|
||||
kubectl port-forward $(kubectl get pods -l app=checkoutservice -o=name) 5050:5050 &
|
||||
|
||||
set +x
|
||||
trap "exit" INT TERM ERR
|
||||
trap "kill 0" EXIT
|
||||
wait
|
|
@ -5,45 +5,80 @@
|
|||
<div class="py-5">
|
||||
<div class="container bg-light py-3 px-lg-5 py-lg-5">
|
||||
{{ if eq (len $.items) 0 }}
|
||||
<h3>Your shopping cart is empty!</h3>
|
||||
<p>Items you add to your shopping cart will appear here.</p>
|
||||
<a class="btn btn-primary" href="/" role="button">Browse Products → </a>
|
||||
<h3>Your shopping cart is empty!</h3>
|
||||
<p>Items you add to your shopping cart will appear here.</p>
|
||||
<a class="btn btn-primary" href="/" role="button">Browse Products → </a>
|
||||
{{ else }}
|
||||
<h3>{{ len $.items }} item {{- if gt (len $.items) 0}}s{{end}}
|
||||
in your Shopping Cart</h3>
|
||||
{{ end }}
|
||||
|
||||
{{ range $.items }}
|
||||
<div class="row pt-2 mb-2">
|
||||
<div class="col text-right">
|
||||
<a href="/product/{{.Item.Id}}"><img class="img-fluid" style="width: auto; max-height: 60px;"
|
||||
src="{{.Item.Picture}}" /></a>
|
||||
</div>
|
||||
<div class="col align-middle">
|
||||
<strong>{{.Item.Name}}</strong><br/>
|
||||
<small class="text-muted">SKU: #{{.Item.Id}}</small>
|
||||
</div>
|
||||
<div class="col text-left">
|
||||
Qty: {{.Quantity}}<br/>
|
||||
<strong>
|
||||
{{ renderMoney .Price}}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if $.items }}
|
||||
<div class="row mt-5">
|
||||
<div class="col-8 offset-2">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<form method="POST" action="/cart/empty">
|
||||
<button class="btn btn-secondary" type="submit">Empty Cart</button>
|
||||
</form>
|
||||
<a class="btn btn-primary" href="/checkout" role="button">Proceed to Checkout →</a>
|
||||
<h3>{{ len $.items }} item {{- if gt (len $.items) 1}}s{{end}}
|
||||
in your Shopping Cart</h3>
|
||||
|
||||
{{ range $.items }}
|
||||
<div class="row pt-2 mb-2">
|
||||
<div class="col text-right">
|
||||
<a href="/product/{{.Item.Id}}"><img class="img-fluid" style="width: auto; max-height: 60px;"
|
||||
src="{{.Item.Picture}}" /></a>
|
||||
</div>
|
||||
<div class="col align-middle">
|
||||
<strong>{{.Item.Name}}</strong><br/>
|
||||
<small class="text-muted">SKU: #{{.Item.Id}}</small>
|
||||
</div>
|
||||
<div class="col text-left">
|
||||
Qty: {{.Quantity}}<br/>
|
||||
<strong>
|
||||
{{ renderMoney .Price}}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }} <!-- range $.items-->
|
||||
|
||||
<hr/>
|
||||
<div class="row py-3 my-2">
|
||||
<div class="col-12 col-lg-8 offset-lg-2">
|
||||
<h3>Prepare to checkout</h3>
|
||||
<form class="needs-validation">
|
||||
<div class="form-row">
|
||||
<div class="col-md-5 mb-3">
|
||||
<label for="street_address_1">Street Address</label>
|
||||
<input type="text" class="form-control" id="street_address_1"
|
||||
value="1600 Amphitheatre Parkway" required>
|
||||
</div>
|
||||
<div class="col-md-5 mb-3">
|
||||
<label for="street_address_2">Street Address (cont.)</label>
|
||||
<input type="text" class="form-control" id="street_address_2" placeholder="...your address here">
|
||||
</div>
|
||||
<div class="col-md-2 mb-3">
|
||||
<label for="zip_code">Zip Code</label>
|
||||
<input type="text" class="form-control" id="zip_code" value="94043" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="city">City</label>
|
||||
<input type="text" class="form-control" id="city" placeholder="City" value="Mountain View" required>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<label for="state">State</label>
|
||||
<input type="text" class="form-control" id="state" placeholder="State" value="CA" required>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<label for="country">Country</label>
|
||||
<input type="text" class="form-control" id="country" placeholder="Country Name"
|
||||
value="United States" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-12 d-flex justify-content-between align-items-center">
|
||||
<form method="POST" action="/cart/empty">
|
||||
<button class="btn btn-secondary" type="submit">Empty Cart</button>
|
||||
</form>
|
||||
<a class="btn btn-primary" href="/checkout" role="button">Proceed to Checkout →</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }} <!-- end if $.items -->
|
||||
|
||||
{{ if $.recommendations}}
|
||||
<hr/>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{ define "recommendations" }}
|
||||
<h5 class="text-muted">Products you might like</h5>
|
||||
<div class="row mt-2">
|
||||
<div class="row my-2 py-3">
|
||||
{{range . }}
|
||||
<div class="col-3">
|
||||
<div class="card mb-3 box-shadow">
|
||||
|
|
Loading…
Reference in a new issue