diff --git a/public/cart.js b/public/cart.js new file mode 100644 index 00000000..52af8985 --- /dev/null +++ b/public/cart.js @@ -0,0 +1,180 @@ +function getCartFetch(cartId){ + fetch(`https://acastore.herokuapp.com/carts/${cartId}`) + .then(response => response.json()) + .then(data => { + asyncLocalStorage.setItem("cart", JSON.stringify(data)) + .then(function(){ + return asyncLocalStorage.getItem('cart'); + }) + }) +} + +function addToCart(prodId){ + timeOutFunction(); + + class CartItem{ + constructor(id, price, quantity, imgUrl, name, description) { + this.id = id; + this.price = price; + this.quantity = quantity; + this.imgUrl = imgUrl; + this.name = name; + this.description = description; + } + } + + let userStorage = JSON.parse(localStorage.getItem('user')) + let foundProd = products.find(p => p.id === prodId); + + if(!userStorage.cartId){ + let cart = []; + let foundProd = products.find(p => p.id === prodId); + let product = new CartItem(foundProd.id, foundProd.price, 1, foundProd.imgUrl, foundProd.name, foundProd.description) + cart.push(product); + + fetch("https://acastore.herokuapp.com/carts",{ + method: "POST", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify({userId: userStorage.id, products: cart}) + }) + .then(response => response.json()) + .then(data => { + asyncLocalStorage.setItem("cart", JSON.stringify(data)) + .then(function(){ + return asyncLocalStorage.getItem("cart"); + }) + fetch(`https://acastore.herokuapp.com/users/${userStorage.id}`,{ + method: "PUT", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify({email: userStorage.email, password: userStorage.password, cartId: data.id}) + }) + .then(response => response.json()) + .then(data =>{ + asyncLocalStorage.setItem("user", JSON.stringify(data)) + .then(function(){ + listProducts(products); + }) + }) + }) + } + else{ + let cartStorage = JSON.parse(localStorage.getItem('cart')) + let cartProducts = cartStorage.products; + let foundInCart = cartProducts.find(p => p.id === prodId); + if (!foundInCart){ + let cartItem = new CartItem(foundProd.id, foundProd.price, 1, foundProd.imgUrl, foundProd.name, foundProd.description) + cartProducts.push(cartItem); + } + else{ + let quantity = Number(foundInCart.quantity); + foundInCart.quantity = quantity + 1; + } + fetch(`https://acastore.herokuapp.com/carts/${cartStorage.id}`,{ + method: "PUT", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify({ userId: userStorage.id, products: cartProducts}) + }) + .then(response =>response.json()) + .then(data => { + asyncLocalStorage.setItem("cart", JSON.stringify(data)) + .then(function(){ + listProducts(products); + }) + }) + } +} + +function viewCart(){ + let cartStorage = localStorage.getItem("cart"); + if(cartStorage){ + cartStorage = JSON.parse(cartStorage) + cartProducts = cartStorage.products; + } + else{ + cartProducts = []; + } + listProducts(cartProducts); + //variable declaration for total cost + let subtotal = 0; + //variable declaration for total item count + let itemCounter = 0; + //maps through items in cart + cartProducts.map(product => { + //changes functionality of the cart button to remove from cart + let cartButton = document.getElementById(`cartButton${product.id}`); + cartButton.setAttribute('onClick', `removeCartItem(${product.id});`); + cartButton.innerHTML = "REMOVE ITEM" + //more info div to contain drop down for quantity of a particular item + moreInfoDiv = document.getElementById(`moreInfo${product.id}`) + moreInfoDiv.innerHTML = ` + + `; + //sets default selected value in drop down menu to the current quantity + document.getElementById(`qty${product.id}`).options[product.quantity - 1].selected = true; + //variable stores the price as a float + let priceFloat = Number(product.price.slice(1, product.price.length)); + //updates total item count variable + itemCounter += Number(product.quantity); + //updates subtotal variable + subtotal += priceFloat * Number(product.quantity); + }); + //make sure subtotal is displayed in correct $ format + subtotal = subtotal.toFixed(2); + //changes style of subtotal div to display current total + let subtotalDiv = document.getElementById('subtotal'); + subtotalDiv.style.border = '1px solid black'; + subtotalDiv.style.height = '100px' + subtotalDiv.style.width = '250px' + subtotalDiv.innerHTML = `subtotal (${itemCounter} items): $${subtotal} +
+ `; +} + +function changeQuantity(prodId, qty){ + let cartStorage = JSON.parse(localStorage.getItem("cart")); + let cartItems = cartStorage.products + let product = cartItems.find(p => p.id === prodId); + product.quantity = Number(qty); + fetch(`https://acastore.herokuapp.com/carts/${cartStorage.id}`,{ + method: "PUT", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify({ userId: cartStorage.userId, products: cartItems}) + }) + .then(response => response.json()) + .then(data => { + asyncLocalStorage.setItem("cart", JSON.stringify(data)) + .then(function(){ + viewCart(); + }) + }) +} + +function removeCartItem(prodId){ + let cartStorage = JSON.parse(localStorage.getItem("cart")); + let cartProducts = cartStorage.products + let productIdx = cartProducts.map(p => p.id).indexOf(prodId); + cartProducts.splice(productIdx, 1); + fetch(`https://acastore.herokuapp.com/carts/${cartStorage.id}`,{ + method: "PUT", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify({ userId: cartStorage.userId, products: cartProducts}) + }) + .then(response => response.json()) + .then(data => { + asyncLocalStorage.setItem("cart", JSON.stringify(data)) + .then(function(){ + viewCart(); + }) + }) +} diff --git a/public/cart.png b/public/cart.png new file mode 100644 index 00000000..026f3d76 Binary files /dev/null and b/public/cart.png differ diff --git a/public/index.html b/public/index.html index 138da963..005c9419 100644 --- a/public/index.html +++ b/public/index.html @@ -5,10 +5,43 @@ My Store + - - +
+
+
+

ACA Store

+

+
+
+

search

+
+
+ +
+
+
+
+
+
+ Email
+ Password
+ + +
+
+ + + + + + \ No newline at end of file diff --git a/public/index.js b/public/index.js index 034dbd5e..12749665 100644 --- a/public/index.js +++ b/public/index.js @@ -1 +1,300 @@ -//stuff \ No newline at end of file +let products = []; +let loggedIn; + +function alertFunc(){ + alert("are you still there?") +} + +function clearStorage(){ + localStorage.clear(); +} + +if(loggedIn != 'undefined'){ + loggedIn = true; +} + +function loggedInView(){ + let user = JSON.parse(localStorage.getItem('user')); + let welcomeDiv = document.getElementById('welcome'); + let signUpDiv = document.getElementById('signUp'); + let name = user.email.split('@')[0]; + name = name.toUpperCase() + welcomeDiv.innerHTML = `Hello, ${name}` + signUpDiv.style.display = 'none'; +} + +const asyncLocalStorage = { + setItem: async function (key, value) { + await null; + return localStorage.setItem(key, value); + }, + getItem: async function (key) { + await null; + return localStorage.getItem(key); + } +}; + +function getUserFetch(email){ + fetch("https://acastore.herokuapp.com/users") + .then(response => response.json()) + .then(data => user = data.find(user => user.email == email)) + .then(user => { + asyncLocalStorage.setItem("user", JSON.stringify(user)) + .then(function(){ + return asyncLocalStorage.getItem('user'); + }) + }) +} + +function getProductsFetch(){ + fetch("https://acastore.herokuapp.com/products") + .then(response => response.json()) + .then(data => products = data) + .then(products => listProducts(products)) +} + +window.onload = function(){ + timeOutFunction(); + getProductsFetch() + if(localStorage.getItem('user') && loggedIn == true){ + loggedInView(); + } +} + +function listProducts(products){ + timeOutFunction(); + let productsDiv = document.getElementById("products"); + let cartDiv = document.getElementById("cart"); + let newProd = ''; + //maps through products and creates a div for each product + products.map(product =>{ + newProd += `
+
+

${product.name}

+

+
${product.description}
+
${product.price}
+
+ rating: ${product.rating} +
+
+
+
+
`; + }) + productsDiv.innerHTML = newProd + '
' + + if(localStorage.getItem("user") != null){ + userStorage = JSON.parse(localStorage.getItem("user")) + if(userStorage.cartId != null){ + getCartFetch(userStorage.cartId) + let cartStorage = JSON.parse(localStorage.getItem("cart")); + let itemsCounter = 0; + cartStorage.products.map(p => itemsCounter = itemsCounter + Number(p.quantity)); + cartDiv.innerHTML = itemsCounter + } + } + else{ + cartDiv.innerHTML = 0; + } +} + +function filterCategory(cat){ + //if all is selected, displays all products + if (cat === 'all'){ + listProducts(products); + return products; + } + //filters products depending on category selected + else{ + let filteredProducts = products.filter(prod => + prod.category === cat); + listProducts(filteredProducts); + return filteredProducts; + } +} + +function searchFunc(){ + let category = document.getElementById('categories').value; + + //assigns search text to variable + let searchText = document.getElementById("searchText").value; + searchText.toLowerCase(); + //shows only products matching search + let filteredProducts = filterCategory(category).filter(prod => + prod.name.toLowerCase().includes(searchText) || prod.description.toLowerCase().includes(searchText)); + //lists only filtered products + listProducts(filteredProducts) +} + +function timeOutFunction(){ + var hours = 1; // Reset when storage is more than 24hours + var minutes = 1; + var now = new Date().getTime(); + var setupTime = localStorage.getItem('setupTime'); + if (setupTime == null) { + localStorage.setItem('setupTime', now) + } + else { + if(now-setupTime > minutes*60*1000) { + localStorage.clear() + alert("your session timed out"); + } + if(now-setupTime < minutes*60*1000){ + localStorage.setItem('setupTime', now) + } + } +} + +function logIn(){ + let txtEmail = document.getElementById("email"); + let txtPassword = document.getElementById("password"); + + timeOutFunction(); + + fetch("https://acastore.herokuapp.com/users") + .then(response => response.json()) + .then(data => user = data.find(user => user.email === txtEmail.value)) + .then(user => { + if(user.password == txtPassword.value){ + asyncLocalStorage.setItem("user", JSON.stringify(user)) + .then(function(){ + loggedInView(); + }) + if(user.cartId){ + getCartFetch(user.cartId) + } + } + else{ + alert("try again"); + } + }) + if(localStorage.getItem('user')){ + return loggedIn = true; + } +} + +class User { + constructor(email, password, cartId) { + this.email = email; + this.password = password; + this.cartId = cartId; + } +} + +function signUp(){ + let txtPassword = document.getElementById("password"); + let txtEmail = document.getElementById("email"); + + fetch("https://acastore.herokuapp.com/users") + .then(response => response.json()) + .then(data => user = data.find(user => user.email == txtEmail.value)) + .then(user => { + if(user){ + alert("that email address already has an account") + } + else{ + let newUser = new User(txtEmail.value, txtPassword.value, null); + fetch("https://acastore.herokuapp.com/users", { + method: "POST", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify(newUser) + }) + .then(response => response.json()) + .then(data => { + asyncLocalStorage.setItem("user", JSON.stringify(data)) + .then(function(){ + loggedInView(); + listProducts(products); + }) + }) + return loggedIn = true; + } + }) +} + +function moreInfo(prodId){ + //assigns empty string + let moreInfoDiv = ''; + //filters array to only the product requested + let viewProd = products.filter(prod =>prod.id === prodId) + listProducts(viewProd); + //allows access to the moreInfo div to display all reviews and ratings + let productDiv = document.getElementById(`moreInfo${prodId}`); + viewProd[0].reviews.map(review => + moreInfoDiv += `
${review.description}
+
${review.rating}
+
` + ) + productDiv.innerHTML = moreInfoDiv; +} + +function displayReviews(prodId){ + product = products.find(p => p.id === prodId); + let reviewDiv = document.getElementById(`hiddenReviews ${prodId}`); + let newRev = ''; + for(i=0; i<3; i++){ + if(product.reviews[i]){ + newRev += `
${product.reviews[i].description}
+
${product.reviews[i].rating}
+
` + } + } + reviewDiv.innerHTML = newRev; +} + +function hideReviews(prodId){ + let reviewDiv = document.getElementById(`hiddenReviews ${prodId}`); + let newRev = `
`; + reviewDiv.innerHTML = newRev; +} + +class ItemOrder{ + constructor(quantity, prodId) { + this.quantity = quantity; + this.prodId = prodId; + } +} + +class Order{ + constructor(userId, items) { + this.userId = userId; + this.items = items; + } +} + +function submitFunc(){ + let cartStorage = JSON.parse(localStorage.getItem('cart')); + let cartProducts = cartStorage.products + let items = []; + items.push(cartProducts.map(p => { + new ItemOrder(p.quantity, p.id) + })) + alert(items); + let order = new Order(cartStorage.userId, items); + + fetch("https://acastore.herokuapp.com/orders", { + method: "POST", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify(order) + }) +} + +//function called when customer clicks checkout button +//displays form for data entry +function checkoutForm(){ + let productsDiv = document.getElementById("products"); + let form = `
+ First name:
+ +
+ Last name:
+ +
+ Email:
+ +
+ +
` + productsDiv.innerHTML = form; +} \ No newline at end of file diff --git a/public/index2.js b/public/index2.js new file mode 100644 index 00000000..49396a4e --- /dev/null +++ b/public/index2.js @@ -0,0 +1,243 @@ +let products = []; +let loggedIn; +if(loggedIn != 'undefined'){ + loggedIn = true; +} + +function loggedInView(){ + let user = JSON.parse(localStorage.getItem('user')); + let welcomeDiv = document.getElementById('welcome'); + let signUpDiv = document.getElementById('signUp'); + let name = user.email.split('@')[0]; + name = name.toUpperCase() + welcomeDiv.innerHTML = `Hello, ${name}` + signUpDiv.style.display = 'none'; +} + + +const asyncLocalStorage = { + setItem: async function (key, value) { + await null; + return localStorage.setItem(key, value); + }, + getItem: async function (key) { + await null; + return localStorage.getItem(key); + } +}; + +function getUserFetch(email){ + fetch("https://acastore.herokuapp.com/users") + .then(response => response.json()) + .then(data => user = data.find(user => user.email == email)) + .then(user => { + asyncLocalStorage.setItem("user", JSON.stringify(user)) + .then(function(){ + return asyncLocalStorage.getItem('user'); + }) + }) +} + +function getProductsFetch(){ + fetch("https://acastore.herokuapp.com/products") + .then(response => response.json()) + .then(data => products = data) + .then(products => listProducts(products)) +} + +window.onload = function(){ + getProductsFetch() + if(localStorage.getItem('user') && loggedIn == true){ + loggedInView(); + } +} + +function listProducts(products){ + let productsDiv = document.getElementById("products"); + let cartDiv = document.getElementById("cart"); + let newProd = ''; + //maps through products and creates a div for each product + products.map(product =>{ + newProd += `
+
+

${product.name}

+

+
${product.description}
+
${product.price}
+
+ rating: ${product.rating} +
+
+
+
+
`; + }) + productsDiv.innerHTML = newProd + '
' + + if(localStorage.getItem("user") != null){ + userStorage = JSON.parse(localStorage.getItem("user")) + if(userStorage.cartId != null){ + getCartFetch(userStorage.id) + let cartStorage = JSON.parse(localStorage.getItem("cart")); + let itemsCounter = 0; + cartStorage.products.map(p => itemsCounter = itemsCounter + Number(p.quantity)); + cartDiv.innerHTML = itemsCounter + } + + } + else{ + cartDiv.innerHTML = 0; + } +} + +function filterCategory(cat){ + //if all is selected, displays all products + if (cat === 'all'){ + listProducts(products); + return products; + } + //filters products depending on category selected + else{ + let filteredProducts = products.filter(prod => + prod.category === cat); + listProducts(filteredProducts); + return filteredProducts; + } +} + +function searchFunc(){ + let category = document.getElementById('categories').value; + + //assigns search text to variable + let searchText = document.getElementById("searchText").value; + searchText.toLowerCase(); + //shows only products matching search + let filteredProducts = filterCategory(category).filter(prod => + prod.name.toLowerCase().includes(searchText) || prod.description.toLowerCase().includes(searchText)); + //lists only filtered products + listProducts(filteredProducts) +} + +function logIn(){ + let txtEmail = document.getElementById("email"); + let txtPassword = document.getElementById("password"); + + fetch("https://acastore.herokuapp.com/users") + .then(response => response.json()) + .then(data => user = data.find(user => user.email === txtEmail.value)) + .then(user => { + if(user.password == txtPassword.value){ + asyncLocalStorage.setItem("user", JSON.stringify(user)) + .then(function(){ + loggedInView(); + }) + if(user.cartId){ + getCartFetch(user.cartId) + } + } + else{ + alert("try again"); + } + }) + if(localStorage.getItem('user')){ + return loggedIn = true; + } +} + +class User { + constructor(email, password, cartId) { + this.email = email; + this.password = password; + this.cartId = cartId; + } +} + +function signUp(){ + let txtPassword = document.getElementById("password"); + let txtEmail = document.getElementById("email"); + + fetch("https://acastore.herokuapp.com/users") + .then(response => response.json()) + .then(data => user = data.find(user => user.email == txtEmail.value)) + .then(user => { + if(user){ + alert("that email address already has an account") + } + else{ + let newUser = new User(txtEmail.value, txtPassword.value, null); + fetch("https://acastore.herokuapp.com/users", { + method: "POST", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify(newUser) + }) + .then(response => response.json()) + .then(data => { + asyncLocalStorage.setItem("user", JSON.stringify(data)) + .then(function(){ + loggedInView(); + listProducts(products); + }) + }) + return loggedIn = true; + } + }) +} + +function moreInfo(prodId){ + //assigns empty string + let moreInfoDiv = ''; + //filters array to only the product requested + let viewProd = products.filter(prod =>prod.id === prodId) + listProducts(viewProd); + //allows access to the moreInfo div to display all reviews and ratings + let productDiv = document.getElementById(`moreInfo${prodId}`); + viewProd[0].reviews.map(review => + moreInfoDiv += `
${review.description}
+
${review.rating}
+
` + ) + productDiv.innerHTML = moreInfoDiv; +} + +function displayReviews(prodId){ + product = products.find(p => p.id === prodId); + let reviewDiv = document.getElementById(`hiddenReviews ${prodId}`); + let newRev = ''; + for(i=0; i<3; i++){ + if(product.reviews[i]){ + newRev += `
${product.reviews[i].description}
+
${product.reviews[i].rating}
+
` + } + } + reviewDiv.innerHTML = newRev; +} + +function hideReviews(prodId){ + let reviewDiv = document.getElementById(`hiddenReviews ${prodId}`); + let newRev = `
`; + reviewDiv.innerHTML = newRev; +} + +function submitFunc(){ + alert("We have received your order!"); +} + +//function called when customer clicks checkout button +//displays form for data entry +function checkoutForm(){ + let productsDiv = document.getElementById("products"); + let form = `
+ First name:
+ +
+ Last name:
+ +
+ Email:
+ +
+ +
` + productsDiv.innerHTML = form; +} \ No newline at end of file diff --git a/public/styles.css b/public/styles.css new file mode 100644 index 00000000..c8d6fbb5 --- /dev/null +++ b/public/styles.css @@ -0,0 +1,146 @@ +*{ + box-sizing: border-box; +} +#products{ + background-color: rgb(238, 223, 228); +} + +header{ + background-color: #b3759e; + height:85px; +} + +.title:hover{ + cursor: pointer; +} + +.title h1{ + margin: 7px auto; +} + +.title h4{ + margin: auto; +} + +.header{ + text-align: center; + height:85px; + display:flex; + flex-direction:row; + justify-content: space-between; + align-items: stretch; +} + +.centerHeader{ + display:flex; + justify-content: space-around; + align-items: center; +} + +.centerHeader div{ + align-items: center; +} + +input{ + width: 500px; +} + +#signUp{ + text-Align:center; + height:200px; + display:flex; + flex-direction: column; + align-items: center; +} + + +#products{ + display: flex; + flex-wrap:wrap; + +} + +#products > #product{ + border: 1px solid rgb(148, 148, 148); + width: 250px; + height: auto; + text-align:center; +} + +#product a div{ + height: 250px; +} + +div.review{ + height: auto; + border: 1px solid rgb(148, 148, 148); + background-color:white; +} + +.cart{ + margin:0px 30px; + display:flex; + align-items: center; +} + +.cart img{ + border: 1px solid #b3759e; +} + +.cart img:hover{ + opacity: .6; + cursor: pointer; +} + +/* #product a:hover{ + opacity: .1; +} */ + +#categories{ + margin: 0 10px; + width: 150px; +} + +#cart{ + position: absolute; + font-family: 'Times New Roman', Times, serif; + font-size:20px; + background-color: rgb(192, 161, 190); + border-radius: 100%; + padding: 0 5px; + top:25px; + right:30px; +} + +.cartButton { + background-color:#6b2f5c; + border: 1px solid #a04288; + border-radius:12px; + cursor:pointer; + color:#ffffff; + font-family:Verdana; + font-size:12px; + padding:3px 25px; +} +.cartButton:hover { + background-color:#7e4d71; +} + +.hiddenReviews{ + position: absolute; + margin: 0px 0px 600px 200px; + max-height:300px; +} + +#subtotal{ + float: right; + font-family: 'Times New Roman', Times, serif; + font-size: 20px; + text-align: center; +} + +#checkoutButton{ + width: 200px; + text-align: center; + margin: 20px 0px; +}