Commit c192bbc3 authored by Shaphen Pangburn's avatar Shaphen Pangburn

Resolve merge conflicts

parents d08a6cb4 91cbb5a3
...@@ -16,11 +16,17 @@ ...@@ -16,11 +16,17 @@
"bootstrap": "^5.0.0", "bootstrap": "^5.0.0",
"jquery": "^3.6.0", "jquery": "^3.6.0",
"react": "^17.0.2", "react": "^17.0.2",
<<<<<<< HEAD
"react-animate-on-change": "^2.2.0", "react-animate-on-change": "^2.2.0",
"react-bootstrap": "^1.5.2", "react-bootstrap": "^1.5.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-google-login": "^5.2.2", "react-google-login": "^5.2.2",
"react-icons": "^4.2.0", "react-icons": "^4.2.0",
=======
"react-bootstrap": "^1.5.2",
"react-dom": "^17.0.2",
"react-google-login": "^5.2.2",
>>>>>>> 91cbb5a38fbec945bfec3a7e84e02d6710c9ccaf
"react-modal": "^3.13.1", "react-modal": "^3.13.1",
"react-redux": "^7.2.4", "react-redux": "^7.2.4",
"react-router-bootstrap": "^0.25.0", "react-router-bootstrap": "^0.25.0",
...@@ -4050,7 +4056,12 @@ ...@@ -4050,7 +4056,12 @@
"node_modules/babel-runtime/node_modules/core-js": { "node_modules/babel-runtime/node_modules/core-js": {
"version": "2.6.12", "version": "2.6.12",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
<<<<<<< HEAD
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
=======
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
"hasInstallScript": true
>>>>>>> 91cbb5a38fbec945bfec3a7e84e02d6710c9ccaf
}, },
"node_modules/babel-runtime/node_modules/regenerator-runtime": { "node_modules/babel-runtime/node_modules/regenerator-runtime": {
"version": "0.11.1", "version": "0.11.1",
...@@ -5078,7 +5089,12 @@ ...@@ -5078,7 +5089,12 @@
"node_modules/core-js": { "node_modules/core-js": {
"version": "3.11.2", "version": "3.11.2",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.11.2.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.11.2.tgz",
<<<<<<< HEAD
"integrity": "sha512-3tfrrO1JpJSYGKnd9LKTBPqgUES/UYiCzMKeqwR1+jF16q4kD1BY2NvqkfuzXwQ6+CIWm55V9cjD7PQd+hijdw==" "integrity": "sha512-3tfrrO1JpJSYGKnd9LKTBPqgUES/UYiCzMKeqwR1+jF16q4kD1BY2NvqkfuzXwQ6+CIWm55V9cjD7PQd+hijdw=="
=======
"integrity": "sha512-3tfrrO1JpJSYGKnd9LKTBPqgUES/UYiCzMKeqwR1+jF16q4kD1BY2NvqkfuzXwQ6+CIWm55V9cjD7PQd+hijdw==",
"hasInstallScript": true
>>>>>>> 91cbb5a38fbec945bfec3a7e84e02d6710c9ccaf
}, },
"node_modules/core-js-compat": { "node_modules/core-js-compat": {
"version": "3.11.2", "version": "3.11.2",
...@@ -5100,7 +5116,12 @@ ...@@ -5100,7 +5116,12 @@
"node_modules/core-js-pure": { "node_modules/core-js-pure": {
"version": "3.11.2", "version": "3.11.2",
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.11.2.tgz", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.11.2.tgz",
<<<<<<< HEAD
"integrity": "sha512-DQxdEKm+zFsnON7ZGOgUAQXBt1UJJ01tOzN/HgQ7cNf0oEHW1tcBLfCQQd1q6otdLu5gAdvKYxKHAoXGwE/kiQ==" "integrity": "sha512-DQxdEKm+zFsnON7ZGOgUAQXBt1UJJ01tOzN/HgQ7cNf0oEHW1tcBLfCQQd1q6otdLu5gAdvKYxKHAoXGwE/kiQ=="
=======
"integrity": "sha512-DQxdEKm+zFsnON7ZGOgUAQXBt1UJJ01tOzN/HgQ7cNf0oEHW1tcBLfCQQd1q6otdLu5gAdvKYxKHAoXGwE/kiQ==",
"hasInstallScript": true
>>>>>>> 91cbb5a38fbec945bfec3a7e84e02d6710c9ccaf
}, },
"node_modules/core-util-is": { "node_modules/core-util-is": {
"version": "1.0.2", "version": "1.0.2",
...@@ -6204,6 +6225,10 @@ ...@@ -6204,6 +6225,10 @@
"version": "2.7.4", "version": "2.7.4",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==", "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
<<<<<<< HEAD
=======
"hasInstallScript": true,
>>>>>>> 91cbb5a38fbec945bfec3a7e84e02d6710c9ccaf
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
...@@ -14894,6 +14919,7 @@ ...@@ -14894,6 +14919,7 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
<<<<<<< HEAD
"node_modules/react-animate-on-change": { "node_modules/react-animate-on-change": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/react-animate-on-change/-/react-animate-on-change-2.2.0.tgz", "resolved": "https://registry.npmjs.org/react-animate-on-change/-/react-animate-on-change-2.2.0.tgz",
...@@ -14902,6 +14928,8 @@ ...@@ -14902,6 +14928,8 @@
"react": ">15.0.0" "react": ">15.0.0"
} }
}, },
=======
>>>>>>> 91cbb5a38fbec945bfec3a7e84e02d6710c9ccaf
"node_modules/react-app-polyfill": { "node_modules/react-app-polyfill": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-2.0.0.tgz", "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-2.0.0.tgz",
...@@ -15117,6 +15145,7 @@ ...@@ -15117,6 +15145,7 @@
"prop-types": "^15.6.0" "prop-types": "^15.6.0"
} }
}, },
<<<<<<< HEAD
"node_modules/react-icons": { "node_modules/react-icons": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.2.0.tgz", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.2.0.tgz",
...@@ -15125,6 +15154,8 @@ ...@@ -15125,6 +15154,8 @@
"react": "*" "react": "*"
} }
}, },
=======
>>>>>>> 91cbb5a38fbec945bfec3a7e84e02d6710c9ccaf
"node_modules/react-is": { "node_modules/react-is": {
"version": "17.0.2", "version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
...@@ -15213,10 +15244,13 @@ ...@@ -15213,10 +15244,13 @@
"integrity": "sha512-/22eqxjn6Zv5fvY2rZHn57SKmjmJfK7xzJ6/G1OgxAjLtKVfWgV5sn41W2yiqzbtV5eE4/i4LeDLBGYTqx7jbA==", "integrity": "sha512-/22eqxjn6Zv5fvY2rZHn57SKmjmJfK7xzJ6/G1OgxAjLtKVfWgV5sn41W2yiqzbtV5eE4/i4LeDLBGYTqx7jbA==",
"dependencies": { "dependencies": {
"prop-types": "^15.5.10" "prop-types": "^15.5.10"
<<<<<<< HEAD
}, },
"peerDependencies": { "peerDependencies": {
"react": ">=0.14.0", "react": ">=0.14.0",
"react-router-dom": ">=4.0.0" "react-router-dom": ">=4.0.0"
=======
>>>>>>> 91cbb5a38fbec945bfec3a7e84e02d6710c9ccaf
} }
}, },
"node_modules/react-router-dom": { "node_modules/react-router-dom": {
...@@ -18765,6 +18799,10 @@ ...@@ -18765,6 +18799,10 @@
"version": "1.2.13", "version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
<<<<<<< HEAD
=======
"hasInstallScript": true,
>>>>>>> 91cbb5a38fbec945bfec3a7e84e02d6710c9ccaf
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
...@@ -19210,6 +19248,10 @@ ...@@ -19210,6 +19248,10 @@
"version": "1.2.13", "version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
<<<<<<< HEAD
=======
"hasInstallScript": true,
>>>>>>> 91cbb5a38fbec945bfec3a7e84e02d6710c9ccaf
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
...@@ -3,6 +3,7 @@ import * as ApiUtil from '../util/cart_api_util'; ...@@ -3,6 +3,7 @@ import * as ApiUtil from '../util/cart_api_util';
export const RECEIVE_USER_CART = "RECEIVE_USER_CART"; export const RECEIVE_USER_CART = "RECEIVE_USER_CART";
export const CLEAR_USER_CART = "CLEAR_USER_CART"; export const CLEAR_USER_CART = "CLEAR_USER_CART";
const receiveUserCart = cart => ({ const receiveUserCart = cart => ({
type: RECEIVE_USER_CART, type: RECEIVE_USER_CART,
cart cart
...@@ -12,6 +13,7 @@ export const clearUserCart = () => ({ ...@@ -12,6 +13,7 @@ export const clearUserCart = () => ({
type: CLEAR_USER_CART type: CLEAR_USER_CART
}) })
export const fetchUserCart = userEmail => dispatch => ApiUtil.fetchUserCart(userEmail) export const fetchUserCart = userEmail => dispatch => ApiUtil.fetchUserCart(userEmail)
.then(cart => dispatch(receiveUserCart(cart))); .then(cart => dispatch(receiveUserCart(cart)));
...@@ -20,3 +22,4 @@ export const updateUserCart = (updatedCart, userEmail) => dispatch => ApiUtil.up ...@@ -20,3 +22,4 @@ export const updateUserCart = (updatedCart, userEmail) => dispatch => ApiUtil.up
export const createUserCart = newCart => dispatch => ApiUtil.createCart(newCart) export const createUserCart = newCart => dispatch => ApiUtil.createCart(newCart)
.then(res => res.json) .then(res => res.json)
import {priceCalcUtil, numItemsCalcUtil} from '../util/cart_processing_util'
export const GET_TOTAL_PRICE = "GET_TOTAL_PRICE"
export const GET_NUM_ITEMS = "GET_NUM_ITEMS"
export const GET_CART_PRODUCTS = "GET_CART_PRODUCTS"
export const getTotalPrice = (totalPrice) => ({
type: GET_TOTAL_PRICE,
payload: totalPrice
})
export const getNumItems = (numItems) => ({
type: GET_NUM_ITEMS,
payload: numItems
})
export const getCartProducts = (cartProducts) => ({
type: GET_CART_PRODUCTS,
payload: cartProducts
})
export const calcTotalPrice = (productList) => {
return (dispatch) => {
return dispatch(getTotalPrice(priceCalcUtil(productList)))
}
}
export const calcNumItems = (productList) => {
return (dispatch) => {
return dispatch(getNumItems(numItemsCalcUtil(productList)))
}
}
export const storeCartItemsInProcessing = (productList) => {
return (dispatch) => {
return dispatch(getCartProducts(productList))
}
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react' ...@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'
export default function SubmitOrder(props) { export default function SubmitOrder(props) {
let handleSubmitClick = (e) => { let handleSubmitClick = () => {
console.log("Submit Button Clicked") console.log("Submit Button Clicked")
props.setSubmitButtonActive(1) props.setSubmitButtonActive(1)
...@@ -17,8 +17,8 @@ export default function SubmitOrder(props) { ...@@ -17,8 +17,8 @@ export default function SubmitOrder(props) {
</div> </div>
<div id="SubmitButtonContainer"> <div id="SubmitButtonContainer">
<p className="errorMessage">{(props.errorWhileValidating === 1 && props.allFieldsValidated[0] === 0)? 'One or more fields is missing a value' : ''}</p> <p className="errorMessage">{(props.errorWhileValidating === 1 && props.allFieldsValidated === 0)? 'One or more fields is missing a value' : ''}</p>
<button id="SubmitButtonInput" onClick={handleSubmitClick} >Submit Order</button> <button id="SubmitButtonInput" onClick={() => {handleSubmitClick()}} >Submit Order</button>
</div> </div>
</div> </div>
......
import React, {useState, useEffect} from 'react' import React, { useState, useEffect } from 'react'
import {useSelector, useDispatch} from 'react-redux' import { useSelector, useDispatch } from 'react-redux'
import ShippingAddress from './ShippingAddress.js' import ShippingAddress from './ShippingAddress.js'
import PaymentMethod from './PaymentMethod.js' import PaymentMethod from './PaymentMethod.js'
...@@ -7,34 +7,42 @@ import ReviewOrder from './ReviewOrder.js' ...@@ -7,34 +7,42 @@ import ReviewOrder from './ReviewOrder.js'
import SubmitOrder from './SubmitOrder.js' import SubmitOrder from './SubmitOrder.js'
import './checkout.css' import './checkout.css'
import {dispatchOrderInfo} from './../../actions/checkout_actions' import { dispatchOrderInfo } from './../../actions/checkout_actions'
import { updateUserCart } from './../../actions/cart_actions'
import { calcTotalPrice, calcNumItems, storeCartItemsInProcessing } from './../../actions/cart_processing_actions'
export default function Checkout() { export default function Checkout() {
///////////////////////
// REDUX Global State const dispatch = useDispatch()
///////////////////////
// const {currentUser} = useSelector(state => state)
// const {cart} = useSelector(state => state)
/////////////////////// ///////////////////////
// Shipping Info State // Shipping Info State
/////////////////////// ///////////////////////
const [firstName, setFirstName] = useState([]) // const [firstName, setFirstName] = useState("Guy")
const [lastName, setLastName] = useState([]) // const [lastName, setLastName] = useState("Fieri")
const [shippingAddress, setShippingAddress] = useState([]) // const [shippingAddress, setShippingAddress] = useState("1234 Flavortown Dr")
const [aptSuiteNo, setAptSuiteNo] = useState([]) // const [aptSuiteNo, setAptSuiteNo] = useState("Apt 317")
const [city, setCity] = useState([]) // const [city, setCity] = useState("Santa Rosa")
const [state, setState] = useState([]) // const [state, setState] = useState("California")
const [zipCode, setZipCode] = useState([]) // const [zipCode, setZipCode] = useState("90210")
const [firstName, setFirstName] = useState("")
const [lastName, setLastName] = useState("")
const [shippingAddress, setShippingAddress] = useState("")
const [aptSuiteNo, setAptSuiteNo] = useState("")
const [city, setCity] = useState("")
const [state, setState] = useState("")
const [zipCode, setZipCode] = useState("")
/////////////////////// ///////////////////////
// Billing Info State // Billing Info State
/////////////////////// ///////////////////////
const [cardNumber, setCardNumber] = useState(["123456789"]) const [cardNumber, setCardNumber] = useState(["123456789"])
const [cardHolderName, setCardHolderName] = useState(["Jane Doe"]) const [cardHolderName, setCardHolderName] = useState(["Guy Fieri"])
const [expirationDate, setExpirationDate] = useState(["05/20206"]) const [expirationDate, setExpirationDate] = useState(["05/20206"])
const [cvv, setCVV] = useState(["123"]) const [cvv, setCVV] = useState(["123"])
...@@ -42,90 +50,70 @@ export default function Checkout() { ...@@ -42,90 +50,70 @@ export default function Checkout() {
/////////////////////// ///////////////////////
// Order Review / Summary State // Order Review / Summary State
/////////////////////// ///////////////////////
const [numCartItems, setNumCartItems] = useState([3])
const [itemsTotal, setItemsTotal] = useState([87.65]) // arbitrary cart total const numCartItems = useSelector(state => state.cartProcessing.numItems)
const [shippingHandling, setShippingHandling] = useState([8.00]) // arbitraty shipping and handling amount const itemsTotal = useSelector(state => state.cartProcessing.totalPrice)
const [taxRate, setTaxRate] = useState([0.0725]) // california tax rate const taxRate = 0.0725
const shippingHandling = 9.00
/////////////////////// ///////////////////////
// Submit Button State // Submit Button State
/////////////////////// ///////////////////////
const [submitButtonActive, setSubmitButtonActive] = useState([0]) const [submitButtonActive, setSubmitButtonActive] = useState(0)
const [allFieldsValidated, setAllFieldsValidated] = useState([0]) const [allFieldsValidated, setAllFieldsValidated] = useState(0)
const [errorWhileValidating, setErrorWhileValidating] = useState([0]) const [errorWhileValidating, setErrorWhileValidating] = useState(0)
/////////////////////// ///////////////////////
// Submit Action State // Form Submission State
/////////////////////// ///////////////////////
const user = useSelector(state => state.user.currentUser)
const dispatch = useDispatch() const cart = useSelector(state => state.cart)
useEffect(() => {
if (firstName && lastName && shippingAddress && city && state && zipCode) {
console.log("All Fields Validated!")
setAllFieldsValidated(1)
}
}, [firstName, lastName, shippingAddress, city, state, zipCode])
// This effect listens for the submit button to be clicked useEffect(() => {
// It then checks each of the required fields to make sure they are non null
useEffect( () => {
// when submit button clicked after being inactive
if (submitButtonActive === 1) { if (submitButtonActive === 1) {
if (allFieldsValidated) {
// fields to make sure are non-empty setErrorWhileValidating(0)
let fieldsToCheck = [ handleSubmit()
firstName, console.log("Successful submission request")
lastName, setSubmitButtonActive(0)
shippingAddress,
city,
state, const cartUpdateObj = {
zipCode, userId: user.email,
// cardNumber, cartItems: []
// cardHolderName,
// expirationDate,
// cvv
]
// initially validated, gets flipped if required field is empty
let validated = 1
for (let i in fieldsToCheck) {
if (fieldsToCheck[i].length === 0) {
console.log("a required Field Value was empty")
validated = 0
break
} }
}
// if validated, propogate to component state that all fields were validated
if (validated === 1) {
setAllFieldsValidated(1)
}
// if invalid, propogate to component state // clear user cart now that order has been placed
dispatch(updateUserCart(cartUpdateObj, cartUpdateObj.userId))
dispatch(storeCartItemsInProcessing([]))
dispatch(calcTotalPrice([]))
dispatch(calcNumItems([]))
}
else { else {
console.log("Failed to validate")
setErrorWhileValidating(1) setErrorWhileValidating(1)
setSubmitButtonActive(0) setSubmitButtonActive(0)
} }
} }
else { ; }
// when submit button gets reset from active to inactive
else if (submitButtonActive === 0) {
;
}
}, [submitButtonActive]) }, [submitButtonActive])
// This effect looks for the allFieldsValidated signal and fires off the order submission when complete
useEffect( () => {
handleSubmit()
console.log("Successful submission request")
}, [allFieldsValidated])
let handleSubmit = () => { let handleSubmit = () => {
console.log("Submitting Order!") console.log("Submitting Order!")
// let order = {} // let order = {}
...@@ -142,36 +130,29 @@ export default function Checkout() { ...@@ -142,36 +130,29 @@ export default function Checkout() {
// order["cvv"] = cvv // order["cvv"] = cvv
// console.log(order) // console.log(order)
let chrisSpec = { let orderInfo = {
"user": { "user": {
"userId": "e-com-test-id", "userId": user.userId,
"email": "test@test.test", "email": user.email,
"firstName":"ecom", "firstName": user.firstName,
"lastName":"test" "lastName": user.lastName,
"accessToken": user.accessToken
}, },
"address": { "address": {
"state": "IL", "state": state,
"city": "chicago", "city": city,
"zip": "90210", "zip": zipCode,
"street": "Grand" "street": shippingAddress
}, },
"cart": { "cart": {
"id": "something", "id": "something",
"userId": "e-com-test-id", "userId": user.userId,
"cartItems":[ "cartItems": cart
{ }
"quantity": 2,
"productRef": {
"id": "something",
"sku": "AFP-1",
"upc": "00002"
}
}
]
}
} }
dispatch(dispatchOrderInfo(chrisSpec)) console.log(orderInfo)
dispatch(dispatchOrderInfo(orderInfo))
} }
...@@ -205,7 +186,7 @@ export default function Checkout() { ...@@ -205,7 +186,7 @@ export default function Checkout() {
<div id="checkout-container"> <div id="checkout-container">
{/* Collects User's shipping info */} {/* Collects User's shipping info */}
<ShippingAddress <ShippingAddress
captureFirstName={setFirstName} captureFirstName={setFirstName}
captureLastName={setLastName} captureLastName={setLastName}
captureShippingAddress={setShippingAddress} captureShippingAddress={setShippingAddress}
...@@ -220,7 +201,7 @@ export default function Checkout() { ...@@ -220,7 +201,7 @@ export default function Checkout() {
cardNumber={cardNumber} cardNumber={cardNumber}
cardHolderName={cardHolderName} cardHolderName={cardHolderName}
expirationDate={expirationDate} expirationDate={expirationDate}
cvv={cvv} cvv={cvv}
captureCardNumber={setCardNumber} captureCardNumber={setCardNumber}
captureCardHolderName={setCardHolderName} captureCardHolderName={setCardHolderName}
captureExpirationDate={setExpirationDate} captureExpirationDate={setExpirationDate}
...@@ -242,7 +223,7 @@ export default function Checkout() { ...@@ -242,7 +223,7 @@ export default function Checkout() {
errorWhileValidating={errorWhileValidating} errorWhileValidating={errorWhileValidating}
allFieldsValidated={allFieldsValidated} allFieldsValidated={allFieldsValidated}
/> />
</div> </div>
) )
} }
......
...@@ -22,9 +22,19 @@ export default function CartItem(props) { ...@@ -22,9 +22,19 @@ export default function CartItem(props) {
<div id="productName">{props.productInfo.productName}</div> <div id="productName">{props.productInfo.productName}</div>
<div id="productStock">{props.productInfo.availableStock} left in stock</div> <div id="productStock">{props.productInfo.availableStock} left in stock</div>
<div id="quantityControls"> <div className="quantityControls">
<select id="productQuantitySelect"><option>{props.productInfo.quantity}</option></select>
<button>Delete</button> <input
className="productQuantitySelect"
type="number"
value={props.quantity}
min="1"
max="99"
onChange={(e) => {props.handleQuantityUpdate(props.productInfo.sku, parseInt( e.target.value) )}}
/>
<button onClick={() => { props.handleDelete(props.productInfo.sku) }}>Delete</button>
</div> </div>
</div> </div>
......
import React, { useState, useEffect } from 'react'
import CartItem from './CartItem.js'
import './shopping-cart.css'
import { useSelector, useDispatch } from 'react-redux'
import { Link, Redirect } from 'react-router-dom'
import { updateUserCart} from './../../actions/cart_actions'
import { calcTotalPrice, calcNumItems, storeCartItemsInProcessing } from './../../actions/cart_processing_actions'
export default function ShoppingCart() {
const dispatch = useDispatch()
const userSession = useSelector(state => state.user.currentUser)
const allProducts = useSelector(state => state.market.products)
const [cartRefs, setCartRefs] = useState(useSelector(state => state.cart))
const [cartItems, setCartItems] = useState([])
////////////////////////////////////////////////////////////////
// Map Product Refs to Products that exist in redux global state
////////////////////////////////////////////////////////////////
useEffect(() => {
const productsFromRefs = []
cartRefs.map((cartRef) => {
productsFromRefs.push((
{
product: allProducts.filter((currProduct) => (currProduct.sku === cartRef.productRef.sku))[0],
quantity: cartRef.quantity
}))
})
console.log("NEW PRODUCTS FROM REFS YO")
console.log(productsFromRefs)
setCartItems(productsFromRefs)
}, [cartRefs])
////////////////////////////////
// Delete Item from Cart
////////////////////////////////
let handleDelete = (skuToBeDeleted) => {
const newCartRefs = cartRefs.filter((cartRef) => !(cartRef.productRef.sku === skuToBeDeleted))
setCartRefs(newCartRefs)
}
////////////////////////////////
// Update Quantity of an item
////////////////////////////////
let handleQuantityUpdate = (skuToBeUpdated, newQuantity) => {
const newCartRefs = []
cartRefs.map( (cartRef) => {
if (cartRef.productRef.sku === skuToBeUpdated) {
let temp = cartRef
temp.quantity = newQuantity
newCartRefs.push(temp)
}
else {
newCartRefs.push(cartRef)
}
})
setCartRefs(newCartRefs)
}
////////////////////////////////////////////////////////////////
// Sync Cart with backend and redux global state
////////////////////////////////////////////////////////////////
useEffect(() => {
if (!userSession) return;
const cartUpdateObj = {
userId: userSession.email,
cartItems: cartRefs
}
dispatch(updateUserCart(cartUpdateObj, cartUpdateObj.userId))
dispatch(storeCartItemsInProcessing(cartItems))
dispatch(calcTotalPrice(cartItems))
dispatch(calcNumItems(cartItems))
}, [cartItems])
if (!userSession) return <Redirect to="/product-market" />
return (
<div id="shoppingCartContainer">
{/* map each cart item into CartItem component */}
<div id="cartItemList">
{cartItems.map((currItem) => {
return (
<CartItem
productInfo={currItem.product}
quantity={currItem.quantity}
handleDelete={handleDelete}
handleQuantityUpdate={handleQuantityUpdate}
key={currItem.product.sku}
/>
)
})}
</div>
<Link id="checkoutButtonContainer" to="/checkout">
<button id="checkoutButton">Proceed To Checkout</button>
</Link>
</div>
)
}
import {GET_TOTAL_PRICE, GET_NUM_ITEMS, GET_CART_PRODUCTS} from './../actions/cart_processing_actions'
const initialState = {
cartProducts: [],
numItems: 0,
totalPrice: 0
}
const cartProcessingReducer = (prevState = initialState, action) => {
Object.freeze(prevState)
const nextState = {...prevState}
switch (action.type) {
case GET_TOTAL_PRICE:
nextState.totalPrice = action.payload
return nextState
case GET_NUM_ITEMS:
nextState.numItems = action.payload
return nextState
case GET_CART_PRODUCTS:
nextState.cartProducts = action.payload
return nextState
default:
return nextState
}
}
export default cartProcessingReducer
\ No newline at end of file
...@@ -3,14 +3,15 @@ import productsReducer from './products_reducer'; ...@@ -3,14 +3,15 @@ import productsReducer from './products_reducer';
import orderReducer from './order_reducer' import orderReducer from './order_reducer'
import userReducer from './user_reducer' import userReducer from './user_reducer'
import cartReducer from './cart_reducer'; import cartReducer from './cart_reducer';
import cartProcessingReducer from './cart_processing_reducer'
const rootReducer = combineReducers({ const rootReducer = combineReducers({
market: productsReducer, market: productsReducer,
user: userReducer, user: userReducer,
cart: cartReducer, cart: cartReducer,
orderStatus: orderReducer orderStatus: orderReducer,
cartProcessing: cartProcessingReducer
}); });
export default rootReducer; export default rootReducer;
\ No newline at end of file
...@@ -10,6 +10,5 @@ export const createCart = newCart => { ...@@ -10,6 +10,5 @@ export const createCart = newCart => {
} }
export const updateCart = (updatedCart, userEmail) => { export const updateCart = (updatedCart, userEmail) => {
// debugger
return axios.put(`${Config.baseApiUrl}/api/carts/${userEmail}`, updatedCart) return axios.put(`${Config.baseApiUrl}/api/carts/${userEmail}`, updatedCart)
} }
\ No newline at end of file
export const priceCalcUtil = (productList) => {
const totalPrice = productList.reduce((acc, curr) => {return parseFloat(acc) + (parseFloat(curr.product.price) * parseFloat(curr.quantity))}, 0)
console.log("PRICE IN CART: " + totalPrice)
return totalPrice
}
export const numItemsCalcUtil = (productList) => {
const totalItems = productList.reduce((acc, curr) => {return parseInt(acc) + parseInt(curr.quantity)}, 0)
console.log("ITEMS IN CART: " + totalItems)
return totalItems
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment