Skip to content
film-camera.jpg,CC0 Public Domain,https://pxhere.com/en/photo/829555
camera-lens.jpg,CC0 Public Domain,https://pxhere.com/en/photo/670041
air-plant.jpg,,https://unsplash.com/photos/uUwEAW5jFLE
camp-mug.jpg,,https://unsplash.com/photos/h9VhRlMfVkg
record-player.jpg,,https://unsplash.com/photos/pEEHFSX1vak
city-bike.jpg,,https://unsplash.com/photos/Lpe9u9etwMU
typewriter.jpg,,https://unsplash.com/photos/mk7D-4UCfmg
barista-kit.jpg,,https://unsplash.com/photos/ZiRyGGIpRCw
terrarium.jpg,,https://unsplash.com/photos/E9QYLj0724Y
.cart-bg {
background: #f0f0f0;
}
.cart .form-control {
border: none;
border-radius: 0;
-webkit-appearance: none;
}
.cart h3 {
font-size: 36px;
}
.cart form label {
color: #707070;
}
.empty-btn {
margin-right: 20px;
}
.btn {
border-radius: 0;
color: #111111;
background: #e9ecef;
border: 1px solid #d1d7dc;
font-size: 18px;
padding: 10px 15px;
text-transform: uppercase;
letter-spacing: 1.8px;
}
.btn-info {
border: none;
background: #4cc8c6;
}
.center-contents > * {
margin: auto;
}
.product-item {
max-width: 540px;
margin: auto;
margin-bottom: 30px;
}
.product-item .image {
max-width: 180px;
padding: 0;
}
.product-item .image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.product-item .text {
background: white;
padding: 25px 30px;
}
.product-item .text h4 {
font-size: 24px;
letter-spacing: 4.8px;
margin-bottom: 0;
}
.product-item .text p {
margin-bottom: 20px;
}
.product-item .text small {
font-size: 18px;
}
.product-item .text .details {
font-size: 18px;
}
.order-summary {
font-size: 24px;
color: #000000;
margin-bottom: 30px;
}
.order-summary p {
font-size: 18px;
}
.checkout h3 {
font-size: 36px;
margin-bottom: 30px;
}
.last-row {
margin-top: 30px;
}
\ No newline at end of file
.order {
background: #f0f0f0;
}
.order .container {
border-top: 1px solid #b4b2bb;
}
.order-logo {
height: 100px;
margin-bottom: 35px;
}
.order h3 {
font-size: 36px;
margin-bottom: 40px;
}
.order p {
font-size: 24px;
margin-bottom: 0;
color: #707070;
}
.order .mg-bt {
color: #111111;
margin-bottom: 35px;
}
.order .btn {
margin: auto;
}
\ No newline at end of file
/* general */
html, body {
height: 100%;
}
body {
color: #111111;
font-family: 'Roboto', sans-serif;
display: flex;
flex-direction: column;
}
hr {
border-top: 1px solid #b4b2bb;
}
.text-muted {
color: #707070;
}
.badge {
display: inline-block !important;
width: 18px;
height: 18px;
color: #111111;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
border-radius: 50%;
padding-left: 3px;
}
.badge.badge-blue {
background-color: #4bc7c7;
padding-top: 5px;
}
/*header*/
header .badge.badge-blue {
transform: translateY(-3px);
}
header .navbar {
height: 38px;
}
header .h-free-shipping {
font-size: 15px;
}
header .h-free-shipping span:first-child {
font-weight: bold;
}
header .h-free-shipping span:last-child {
font-size: 12px;
cursor: pointer;
text-decoration: underline;
}
header .h-controls {
display: flex;
justify-content: flex-end;
}
header .h-control {
display: flex;
align-items: center;
font-size: 12px;
position: relative;
margin-left: 40px;
color: #605f64;
}
header .h-control:first-child {
margin-left: 0;
}
header .h-control img {
width: 20px;
height: 20px;
margin-right: 8px;
}
header .h-control input {
border: none;
padding: 0 31px 0 31px;
width: 250px;
height: 24px;
flex-shrink: 0;
background-color: #f2f2f2;
display: flex;
align-items: center;
}
header .h-control input:focus {
outline: 0;
border: 0;
box-shadow: 0;
}
header .icon {
width: 20px;
height: 20px;
}
header .icon.arrow {
position: absolute;
right: 4px;
width: 11px;
height: 7px;
}
header .icon.search-icon {
width: 12px;
height: 13px;
position: absolute;
left: 10px;
}
header .h-control select {
background: transparent;
border-radius: 0;
border: 1px solid #acacac;
width: 100px;
height: 20px;
flex-shrink: 0;
padding: 0 7px;
display: flex;
align-items: center;
}
header .h-control::-webkit-input-placeholder {
/* Chrome/Opera/Safari */
font-size: 12px;
color: #605f64;
}
header .h-control::-moz-placeholder {
/* Firefox 19+ */
font-size: 12px;
color: #605f64;
}
header .h-control :-ms-input-placeholder {
/* IE 10+ */
font-size: 12px;
color: #605f64;
}
header .h-control :-moz-placeholder {
/* Firefox 18- */
font-size: 12px;
color: #605f64;
}
header .navbar.sub-navbar {
height: 60px;
background-color: #111111;
font-size: 15px;
color: #b4b2bb;
padding-top: 0;
padding-bottom: 0;
}
header .navbar.sub-navbar .logo {
width: 209px;
height: 40px;
}
header .navbar.sub-navbar .navbar-brand {
padding: 0;
}
header .navbar.sub-navbar a {
color: #b4b2bb;
}
header .navbar.sub-navbar nav a {
margin: 0 10px;
}
header .navbar.sub-navbar .controls {
display: flex;
height: 60px;
}
header .navbar.sub-navbar .controls a {
display: block;
width: 120px;
border-left: 1px solid #b4b2bb;
display: flex;
flex-flow: column;
align-items: center;
justify-content: center;
}
header .navbar.sub-navbar .controls a img {
width: 20px;
height: 20px;
margin-bottom: 3px;
}
header .navbar.sub-navbar .controls a:last-child {
border-right: 1px solid #b4b2bb;
}
/*footer*/
footer.py-5 {
flex-shrink: 0;
padding: 0 !important;
}
footer .footer-top {
background-color: #f0f0f0;
}
footer .footer-top .footer-social,
footer .footer-top .footer-app,
footer .footer-links,
footer .footer-top .social,
footer .footer-top .app {
display: flex;
align-items: center;
}
footer .footer-top .footer-social {
padding: 31px;
}
footer .footer-top .footer-social h4 {
margin-bottom: 0;
}
footer .footer-top .footer-social div {
width: 50%;
}
.footer-top .social {
border-right: 1px solid #b4b2bb;
}
.footer-top .social h4 {
font-size: 24px;
color: #111111;
font-weight: bold;
text-transform: uppercase;
margin-right: 37px;
line-height: 0.92;
}
.footer-top .social img {
margin-right: 16px;
width: 48px;
height: 48px;
}
.footer-top .app {
justify-content: flex-end;
}
.footer-top .app h4 {
font-size: 24px;
font-weight: bold;
color: #111111;
line-height: 0.92;
}
.footer-top .app h4 span {
color: #707070;
font-style: italic;
}
.footer-top .app img {
width: 136px;
height: 41px;
margin-left: 42px;
}
footer .footer-links {
padding-top: 37px;
justify-content: space-between;
align-items: flex-start;
}
footer .links-group {
width: 164px;
flex-shrink: 0;
list-style: none;
color: #707070;
padding: 0;
}
footer .links-group .group-header {
font-size: 16px;
text-transform: uppercase;
color: #111111;
font-weight: bold;
margin-bottom: 12px;
}
footer .links-group li {
margin-bottom: 10px;
cursor: pointer;
}
footer .links-group li:hover {
text-decoration: underline;
}
footer .footer-bottom {
background-color: #111111;
font-size: 16px;
height: 80px;
padding: 23px 0;
display: flex;
justify-content: center;
flex-flow: column;
}
footer .footer-bottom p {
text-align: center;
color: #b4b2bb;
padding: 0;
margin: 0;
}
footer .footer-bottom p:first-child {
color: white;
}
/*Home*/
main {
flex: 1 0 auto;
}
main.home {
background-color: white;
}
.h-jumbotron {
border-radius: 0;
background: url(/static/images/HeroBannerImage2.png) no-repeat top center;
background-size: cover;
}
.h-jumbotron .container img {
width: 280px;
height: 210px;
}
.h-row {
display: flex;
justify-content: center;
align-items: center;
}
.h-row img {
width: 156px;
height: 100px;
margin-bottom: 45px;
}
.h-grid .bg-light {
background-color: white;
}
.card-title.h-card-title {
width: 100%;
font-size: 22px;
letter-spacing: 4.8px;
text-align: center;
color: #111111;
text-transform: uppercase;
margin-bottom: 0;
}
.card-body.h-card-body {
padding: 1.25rem 0.75rem;
}
.h-card-body .text-muted {
font-size: 18px;
}
.ad-row {
padding-left: 68px;
height: 400px;
display: flex;
align-items: center;
background: url(/static/images/AdvertBannerImage.png) no-repeat top center;
background-size: cover;
}
.ad-row-2 {
background: url(/static/images/Advert2BannerImage.png) no-repeat top center;
}
.ad-row img {
width: 292px;
height: 280px;
}
/*Product*/
.h-product {
background-color: #f0f0f0;
padding: 65px 16.96428571%;
color: #707070;
font-size: 18px;
}
.h-product .col {
height: 540px;
}
.h-product .col img {
width: 540px;
}
.h-product .product-info {
width: calc(100% - 540px);
}
.h-product .product-info .product-wrapper {
border-top: 1px solid #b4b2bb;
border-bottom: 1px solid #b4b2bb;
height: 100%;
margin-left: 15px;
display: flex;
flex-flow: column;
justify-content: center;
}
.h-product .text-muted {
color: #707070 !important;
margin: 20px 0;
}
.h-product .product-info h2 {
font-size: 48px;
line-height: 1.1;
letter-spacing: 9.6px;
color: #111111;
}
.h-product .product-info h6 {
font-size: 18px;
color: #111111;
text-transform: uppercase;
margin: 0 0 3px 0;
}
.h-product .product-info form {
margin-top: 100px;
}
.h-product .input-group-text,
.h-product .btn.btn-info {
font-size: 18px;
line-height: 1.89;
letter-spacing: 3.6px;
text-align: center;
color: #111111;
text-transform: uppercase;
border-radius: 0;
}
.h-product .input-group-text {
width: 150px;
height: 49px;
border: solid 1px #d1d7dc;
background-color: #e9ecef;
}
.h-product select.form-control-lg.custom-select {
height: 49px;
}
.h-product .btn.btn-info {
width: 178px;
height: 49px;
padding-left: 0.75rem;
padding-right: 0.75rem;
background-color: #4cc8c6;
margin-left: 30px;
}
.h-product .btn.btn-info:hover {
color: #fff;
background-color: #138496;
border-color: #117a8b;
}
.other-products-img {
width: 234px !important;
height: 80px !important;
}
/*recommendations*/
.h-card.card {
border: none;
border-radius: 0 !important;
position: relative;
cursor: pointer;
}
.h-card.card a {
position: relative;
}
.h-card.card a .card-hover {
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
background-color: transparent;
}
.h-card.card:hover a .card-hover {
background-color: rgba(0, 0, 0, 0.3);
}
/*platform banner*/
.aws-platform,
.onprem-platform,
.azure-platform,
.gcp-platform {
position: fixed;
top: 0;
left: 0;
width: 10px;
height: 100vh;
color: white;
font-size: 24px;
z-index: 999;
}
.aws-platform,
.aws-platform .platform-flag {
background-color: #ff9900;
}
.onprem-platform,
.onprem-platform .platform-flag {
background-color: #34A853;
}
.gcp-platform,
.gcp-platform .platform-flag {
background-color: #4285f4;
}
.azure-platform,
.azure-platform .platform-flag {
background-color: #f35426;
}
.platform-flag {
position: absolute;
top: 98px;
left: 0;
width: 190px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
}
@media (min-width: 1679px) {
header .navbar,
header .navbar.sub-navbar,
footer .footer-top {
padding: 0 16.96428571%;
}
}
.recommendations {
background: white;
}
.recommendations .container .image {
text-align: center;
}
.recommendations .container .image>img {
height: 80px;
margin: 50px 0;
}
.recommendations .prods {
padding-bottom: 50px;
}
.recommendations .card-img-top {
border-radius: 0;
}
select {
-webkit-appearance: none;
-webkit-border-radius: 0px;
}
\ No newline at end of file
{{ define "text_ad" }}
<div class="container">
<div class="alert alert-dark" role="alert">
<strong>Advertisement:</strong>
<a href="{{.RedirectUrl}}" rel="nofollow" target="_blank" class="alert-link">
{{.Text}}
</a>
</div>
</div>
{{ end }}
\ No newline at end of file
{{ define "cart" }}
{{ template "header" . }}
<div {{ with $.platform_css }} class="{{.}}" {{ end }}>
<span class="platform-flag">
{{$.platform_name}}
</span>
</div>
<main role="main" class="cart">
<div class="cart-bg">
<div class="container 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-info" href="/" role="button">Browse Products &rarr; </a>
{{ else }}
<div class="row mb-3 py-2">
<div class="col">
<h3>{{ $.cart_size }} item
{{- if gt ($.cart_size) 1}}s{{end}}
in your cart</h3>
</div>
<div class="col text-right">
<form method="POST" action="/cart/empty">
<button class="btn btn-secondary empty-btn" type="submit">Empty cart</button>
<a class="btn btn-info" href="/" role="button">Keep browsing</a>
</form>
</div>
</div>
{{ range $.items }}
<div class="product-item">
<div class="row pt-2 mb-2">
<div class="col text-right image">
<a href="/product/{{.Item.Id}}"><img class="img-fluid"
src="{{.Item.Picture}}" /></a>
</div>
<div class="col text-left text">
<h4>{{ .Item.Name }}</h4>
<p><small class="text-muted">SKU: #{{ .Item.Id }}</small></p>
<div class="details">
Quantity: {{ .Quantity }}<br/>
<strong>
{{ renderMoney .Price }}
</strong>
</div>
</div>
</div>
</div>
{{ end }}
<div class="row pt-2 my-3">
<div class="col text-center order-summary">
<p class="text-muted my-0">Shipping Cost: <strong>{{ renderMoney .shipping_cost }}</strong></p>
Total Cost: <strong>{{ renderMoney .total_cost }}</strong>
</div>
</div>
<div class="row py-3 my-2 checkout">
<div class="col-12 col-lg-8 offset-lg-2">
<h3 class="text-center">Checkout</h3>
<form action="/cart/checkout" method="POST">
<div class="form-row">
<div class="col-md-5 mb-3">
<label for="email">E-mail Address</label>
<input type="email" class="form-control" id="email"
name="email" value="someone@example.com" required>
</div>
<div class="col-md-5 mb-3">
<label for="street_address">Street Address</label>
<input type="text" class="form-control" name="street_address"
id="street_address" value="1600 Amphitheatre Parkway" required>
</div>
<div class="col-md-2 mb-3">
<label for="zip_code">Zip Code</label>
<input type="text" class="form-control"
name="zip_code" id="zip_code" value="94043" required pattern="\d{4,5}">
</div>
</div>
<div class="form-row">
<div class="col-md-5 mb-3">
<label for="city">City</label>
<input type="text" class="form-control" name="city" id="city"
value="Mountain View" required>
</div>
<div class="col-md-2 mb-3">
<label for="state">State</label>
<input type="text" class="form-control" name="state" id="state"
value="CA" required>
</div>
<div class="col-md-5 mb-3">
<label for="country">Country</label>
<input type="text" class="form-control" id="country"
placeholder="Country Name"
name="country" value="United States" required>
</div>
</div>
<div class="form-row">
<div class="col-md-6 mb-3">
<label for="credit_card_number">Credit Card Number</label>
<input type="text" class="form-control" id="credit_card_number"
name="credit_card_number"
placeholder="0000-0000-0000-0000"
value="4432-8015-6152-0454"
required pattern="\d{4}-\d{4}-\d{4}-\d{4}">
</div>
<div class="col-md-2 mb-3">
<label for="credit_card_expiration_month">Month</label>
<select name="credit_card_expiration_month" id="credit_card_expiration_month"
class="form-control">
<option value="1">January</option>
<option value="2">February</option>
<option value="3">March</option>
<option value="4">April</option>
<option value="5">May</option>
<option value="6">June</option>
<option value="7">July</option>
<option value="8">August</option>
<option value="9">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">January</option>
</select>
</div>
<div class="col-md-2 mb-3">
<label for="credit_card_expiration_year">Year</label>
<select name="credit_card_expiration_year" id="credit_card_expiration_year"
class="form-control">
{{ range $i, $y := $.expiration_years}}<option value="{{$y}}"
{{if eq $i 1 -}}
selected="selected"
{{- end}}
>{{$y}}</option>{{end}}
</select>
</div>
<div class="col-md-2 mb-3">
<label for="credit_card_cvv">CVV</label>
<input type="password" class="form-control" id="credit_card_cvv"
name="credit_card_cvv" value="672" required pattern="\d{3}">
</div>
</div>
<div class="form-row center-contents last-row">
<button class="btn btn-info" type="submit">Place order</button>
</div>
</form>
</div>
</div>
{{ end }} <!-- end if $.items -->
</div>
{{ if $.recommendations}}
{{ template "recommendations" $.recommendations }}
{{ end }}
</div>
</main>
{{ template "footer" . }}
{{ end }}
{{ define "error" }}
{{ template "header" . }}
<div {{ with $.platform_css }} class="{{.}}" {{ end }}>
<span class="platform-flag">
{{$.platform_name}}
</span>
</div>
<main role="main">
<div class="py-5">
<div class="container bg-light py-3 px-lg-5 py-lg-5">
<h1>Uh, oh!</h1>
<p>Something has failed. Below are some details for debugging.</p>
<p><strong>HTTP Status:</strong> {{.status_code}} {{.status}}</p>
<pre class="border border-danger p-3"
style="white-space: pre-wrap; word-break: keep-all;">
{{- .error -}}
</pre>
</div>
</div>
</main>
{{ template "footer" . }}
{{ end }}
\ No newline at end of file
{{ define "footer" }}
<footer class="py-5">
<div class="footer-top">
<div class="container footer-social">
<p class="footer-text">© 2020 Google Inc (<a href="https://github.com/GoogleCloudPlatform/microservices-demo">Source Code</a>) — </p>
<p class="footer-text"> This website is hosted for demo purposes only. It is not an actual shop. This is not a Google product.</p>
</div>
</div>
</footer>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"
integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous">
</script>
</body>
</html>
{{ end }}
\ No newline at end of file
{{ define "header" }}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Online Boutique</title>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB"
crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/static/styles/styles.css">
<link rel="stylesheet" type="text/css" href="/static/styles/cart.css">
<link rel="stylesheet" type="text/css" href="/static/styles/order.css">
<link rel='shortcut icon' type='image/x-icon' href='/static/favicon.ico' />
</head>
<body>
<header>
<div class="navbar">
<div class="container d-flex justify-content-between">
<div class="h-free-shipping">Free shipping with $75 purchase! &nbsp;&nbsp;</div>
{{ if $.show_currency }}
<div class="h-controls">
<div class="h-control">
<img src="/static/icons/Hipster_CurrencyIcon.svg" alt="icon" class="icon" />
<form method="POST" class="controls-form" action="/setCurrency" id="currency_form" >
<select name="currency_code" onchange="document.getElementById('currency_form').submit();">
{{range $.currencies}}
<option value="{{.}}" {{if eq . $.user_currency}}selected="selected"{{end}}>{{.}}</option>
{{end}}
</select>
</form>
<img src="/static/icons/Hipster_DownArrow.svg" alt="icon" class="icon arrow" />
</div>
</div>
{{ end }}
</div>
</div>
<div class="navbar sub-navbar">
<div class="container d-flex justify-content-between">
<a href="/" class="navbar-brand d-flex align-items-center">
<img src="/static/icons/Hipster_NavLogo.svg" alt="logo" class="logo" />
</a>
<div class="controls">
<a href="/cart">
<img src="/static/icons/Hipster_CartIcon.svg" alt="cart-icon" class="logo" />
<span>Cart
{{ if $.cart_size }}
<span class="badge badge-blue">{{$.cart_size}}</span>
{{ end }}
</span>
</a>
</div>
</div>
</div>
</header>
{{end}}
\ No newline at end of file