Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Netlify Frontend for sample app #5

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
3 changes: 3 additions & 0 deletions netlify-functions-ecommerce/.config/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const api = 'http:localhost:8888/.netlify/functions';

module.exports = api;
6 changes: 3 additions & 3 deletions netlify-functions-ecommerce/.config/development.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module.exports = Object.freeze({
mongodbUri: 'mongodb://localhost:27017/ecommerce',
stripeSecretKey: 'YOUR STRIPE KEY HERE',
stripeSuccessUrl: 'localhost:3000/success',
stripeCancelUrl: 'localhost:3000/cancel'
stripeSecretKey: '',
stripeSuccessUrl: 'http://localhost:5000/Confirmation/confirmation',
stripeCancelUrl: 'http://localhost:5000/Confirmation/confirmation'
});
51 changes: 51 additions & 0 deletions netlify-functions-ecommerce/frontend/Cart/cart.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.cart {
display: block;
padding: 0 25px;
height: 200px;
font-size: 64px;
line-height: 200px;
border-radius: 100px;
background-color: #f1f1f1;
}

.cart img {
float: left;
margin: 0 10px 0 -25px;
height: 200px;
width: 200px;
border-radius: 50%;
}

.cart-quantity {
float: right;
padding-right:50px;
}

.plus-minus {
padding-right: 10px;
padding-left: 10px;
margin-right: 10px;
margin-left: 10px;
background-color: grey;
cursor: pointer;
}
.remove-button {
position: relative;
top: 50px;
font-size: X-large;
right: 50%;
cursor: pointer;
background-color: red;
padding: 10px;
}

.checkout-button {
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
8 changes: 8 additions & 0 deletions netlify-functions-ecommerce/frontend/Cart/cart.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script src="https://unpkg.com/vue@3"></script>
<link rel="stylesheet" href="./cart.css" />

<div id="app"></div>
<script type="module">
import cart from './cart.js';
Vue.createApp(cart).mount('#app');
</script>
74 changes: 74 additions & 0 deletions netlify-functions-ecommerce/frontend/Cart/cart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
const serverUrl = 'http://localhost:8888/.netlify/functions';

export default {
data: function() {
return {
products: [],
cart: [],
}
},
methods: {
// a simple solution to handle the weird rendering of the number on adding and removing is pass a temp copy to the backend instead of the original.
async removeAll(item) {
const updatedCart = await fetch(serverUrl+'/removeFromCart', {
method: "POST",
body: JSON.stringify({cartId: localStorage.getItem('cartId'), item: item})
}).then((res) => res.json()).then((response) => response.items);
console.log('The updated Cart', updatedCart)
const index = updatedCart.findIndex((product) => product.productId == item.productId);
if (index < 0) {
let spot = this.cart.find((product) => product.productId == item.productId);
this.cart.splice(spot, 1);
}
},
async removeOne(item) {
item.quantity = 1;
const updatedCart = await fetch(serverUrl+'/removeFromCart', {
method: "POST",
body: JSON.stringify({cartId: localStorage.getItem('cartId'), item: item})
}).then((res) => res.json()).then((response) => response.items);
console.log(updatedCart);
const updatedItem = updatedCart.find((product) => product.productId == item.productId);
item.quantity = updatedItem.quantity;
},
async addOne(item) {
item.quantity = 1;
const updatedCart = await fetch(serverUrl+'/addToCart', {
method: "POST",
body: JSON.stringify({cartId: localStorage.getItem('cartId'), item: item})
}).then((res) => res.json()).then(response => response.items);
const updatedItem = updatedCart.find((product) => product.productId == item.productId);
item.quantity = updatedItem.quantity;
},
toCheckout() {
location.href = location.origin+'/Checkout/checkout.html';
}
},
mounted: async function() {
this.products = await fetch(serverUrl+'/getProducts').then((res) => res.json());
this.cart = await fetch(serverUrl+`/getCart?cartId=${localStorage.getItem('cartId')}`).then((res) => res.json()).then((response) => response.cart.items);
if (this.cart == null) return;
for (let i = 0; i < this.cart.length; i++) {
let product = this.products.find((item) => {
return item._id.toString() == this.cart[i].productId.toString()
});
this.cart[i].name = product.name;
this.cart[i].image = product.image;
this.cart[i].price = product.price;
}
console.log('The cart', this.cart);
},
template:
`
<div>
<h1>Your Cart</h1>
<button @click="toCheckout()" class="checkout-button">Go To Checkout</button>
<div v-for="item in cart" :key="item.productId">
<h2 class="cart">{{item.name}}
<span class="cart-quantity"><span @click="addOne(item)" class="plus-minus">+</span>{{item.quantity}}<span @click="removeOne(item)" class="plus-minus">&minus;</span><span @click="removeAll(item)" class="remove-button">Remove</span></span>
<img :src="item.image" />
</h2>
</div>
</div>
`
}
15 changes: 15 additions & 0 deletions netlify-functions-ecommerce/frontend/Checkout/checkout.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.image {
width: 50%;
height: 50%;
}

.button {
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
10 changes: 10 additions & 0 deletions netlify-functions-ecommerce/frontend/Checkout/checkout.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script src="https://js.stripe.com/v3/"></script>

<script src="https://unpkg.com/vue@3"></script>
<link rel="stylesheet" href="./checkout.css" />

<div id="app"></div>
<script type="module">
import checkout from './checkout.js';
Vue.createApp(checkout).mount('#app');
</script>
68 changes: 68 additions & 0 deletions netlify-functions-ecommerce/frontend/Checkout/checkout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const serverUrl = 'http://localhost:8888/.netlify/functions';

export default {
data: function() {
return {
cart: [],
products: [],
stripe: '',
shipping: ''
}
},
methods: {
async checkout() {
if (this.shipping == null || this.cart.length == 0) return;
await fetch(serverUrl+`/checkout`, {
method: "POST",
body: JSON.stringify({cartId: localStorage.getItem('cartId'), shippingType: this.shipping})
}).then((res) => { return res.json()}).then((response) => {
this.stripe.redirectToCheckout({sessionId: response.session.id})
});
}
},
mounted: async function() {
this.cart = await fetch(serverUrl+`/getCart?cartId=${localStorage.getItem('cartId')}`).then((res) => res.json()).then((response) => response.cart.items);
this.products = await fetch(serverUrl+'/getProducts').then((res) => res.json());
if (this.cart == null) return;
for (let i = 0; i < this.cart.length; i++) {
let product = this.products.find((item) => {
return item._id.toString() == this.cart[i].productId.toString()
});
this.cart[i].name = product.name;
this.cart[i].image = product.image;
this.cart[i].price = product.price;
this.stripe = Stripe('pk_test_51IkuAqIFSwo5WpGWudAKEeemrymI6EmICEAgkgvlq4Bo5jJ1uuMRlrBRw9kvHH7boANqjE7Y6Mb7lQmsXRQoZo3x00Ek1L6d8A');
}
},
template:
`
<div>
<head>
<title>Buy cool new product</title>
</head>
<body>
<h1 v-if="cart.length <= 0">Cannot Checkout as no items are in the cart.</h1>
<section v-else>
<div v-for="item in cart" class="product">
<img class="image" :src="item.image" alt="an iphone" />
<div class="description">
<h3>Product: {{item.name}}</h3>
<h5>Total: \${{item.price*item.quantity}}</h5>
<h5>Quantity: {{item.quantity}}</h5>
</div>
</div>
<div v-if="!shipping">Please Select a shipping type</div>
<div style="padding-bottom: 10px">
<input value="standard" type="radio" v-model="shipping" />
<label>Standard</label>
<input value="2-day" type="radio" v-model="shipping" />
<label>2-day</label>
</div>
<form @submit.prevent>
<button @click="checkout" class="button" type="submit" id="checkout-button">Checkout</button>
</form>
</section>
</body>
</div>
`
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script src="https://unpkg.com/vue@3"></script>

<div id="app"></div>
<script type="module">
import confirmation from './confirmation.js';
Vue.createApp(confirmation).mount('#app');
</script>
38 changes: 38 additions & 0 deletions netlify-functions-ecommerce/frontend/Confirmation/confirmation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const serverUrl = 'http://localhost:8888/.netlify/functions';

export default {
data: function() {
return {
order: ''
}
},
mounted: async function() {
let params = new URLSearchParams(location.search);
let sessionId = params.get('id');
const order = await fetch(serverUrl+'/createOrder', {
method: "POST",
body: JSON.stringify({ cartId: localStorage.getItem('cartId'), sessionId: sessionId})
}).then((res) => res.json());
this.order = order.order;
},
template:
`
<h1>Thank you for shopping with us!</h1>
<ul v-if="order">
<h3>Order Summary</h3>
<li>\${{order.total}}</li>
<h4>Shipping To:</h4>
<li>{{order.address1}}</li>
<li>{{order.city}}</li>
<li>{{order.state}}</li>
<li>{{order.zip}}</li>
<li>{{order.shipping}}</li>
<h4>Order Details</h4>
<li>Status: {{order.status}}</li>
<li>Order Number: {{order.orderNumber}}</li>
<h4>Customer Details</h4>
<li>Email: {{order.email}}</li>
<li>Customer Name: {{order.name}}</li>
</ul>
`
}
51 changes: 51 additions & 0 deletions netlify-functions-ecommerce/frontend/Shop/shop.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
.container{
display: flex
}

.card {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
width: 300px;
margin: 10px;
text-align: center;
font-family: arial;
}

.price {
color: grey;
font-size: 22px;
}

.image {
height: 50%;
width: 50%
}
.card button {
border: none;
outline: 0;
padding: 12px;
color: white;
background-color: #000;
text-align: center;
cursor: pointer;
width: 100%;
font-size: 18px;
}

.card button:hover {
opacity: 0.7;
}

.cart-button {
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}

.cart-link {
display:inline-block
}
8 changes: 8 additions & 0 deletions netlify-functions-ecommerce/frontend/Shop/shop.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script src="https://unpkg.com/vue@3"></script>
<link rel="stylesheet" href="./shop.css" />

<div id="app"></div>
<script type="module">
import shop from './shop.js';
Vue.createApp(shop).mount('#app');
</script>
Loading