Commit 88b9f764 authored by Kyle Muldoon's avatar Kyle Muldoon

merged Dev into master for deployment. Backend now looking into cloud services...

merged Dev into master for deployment. Backend now looking into cloud services instead of local servers. Bugfixes (lots)
parent cc6a4363
package com.nisum.ecomservice.config;
public class AppConfig {
private static final String orderManagementUrl = "http://localhost:8084";
private static final String productsManagementUrl = "http://localhost:8083";
private static final String promoManagementUrl = "http://localhost:8082";
public static String getOrderManagementUrl() {
return orderManagementUrl;
}
public static String getProductsManagementUrl() {
return productsManagementUrl;
}
public static String getPromoManagementUrl() {
return promoManagementUrl;
}
}
......@@ -18,8 +18,8 @@ public class CartController {
@Autowired
private CartService cartService;
@Autowired
private CartRepository cartRepository;
// @Autowired
// private CartRepository cartRepository;
@GetMapping("/api/carts")
public ResponseEntity<Flux<CartDTO>>getAllUserCarts(){
......
......@@ -6,11 +6,9 @@ import com.nisum.ecomservice.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api")
......@@ -38,4 +36,11 @@ public class ProductsController {
return ResponseEntity.ok(productService.getAllPromotions());
}
@GetMapping("/products/{sku}")
public ResponseEntity<Mono<Product>> getProductBySku(@PathVariable String sku) {
return ResponseEntity.ok(productService.getProductBySku(sku));
}
}
package com.nisum.ecomservice.service;
import com.nisum.ecomservice.config.AppConfig;
import com.nisum.ecomservice.dto.*;
import com.nisum.ecomservice.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
......@@ -20,6 +19,8 @@ public class OrderService {
@Autowired
ProductService productService;
@Value("${orders.apiUrl}")
private String orderManagementUrl;
public Mono<Order> postOrder(OrderRequest orderRequest) {
......@@ -93,7 +94,7 @@ public class OrderService {
}
public Mono<Order> postOrderToAPI(OrderSubmission orderSubmission){
return WebClient.create(String.format("%s/api/orders", AppConfig.getOrderManagementUrl()))
return WebClient.create(String.format("%s/api/orders", orderManagementUrl))
.post()
.bodyValue(orderSubmission)
.retrieve()
......@@ -101,7 +102,7 @@ public class OrderService {
}
public Flux<Order> getOrderFromOmsAPI(String userId){
return WebClient.create(String.format("%s/api/orders/byCustomer/%s", AppConfig.getOrderManagementUrl(),userId))
return WebClient.create(String.format("%s/api/orders/byCustomer/%s", orderManagementUrl,userId))
.get()
.retrieve()
.bodyToFlux(Order.class);
......
package com.nisum.ecomservice.service;
import com.nisum.ecomservice.config.AppConfig;
import com.nisum.ecomservice.model.Product;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
......@@ -13,8 +13,15 @@ import java.util.List;
@Service
public class ProductService {
@Value("${products.apiUrl}")
private String productsManagementUrl;
@Value("${promos.apiUrl}")
private String promoManagementUrl;
public Mono<Product> getProductBySku(String sku){
return WebClient.create(String.format("%s/api/products/%s", AppConfig.getProductsManagementUrl(),sku))
return WebClient.create(String.format("%s/api/products/%s", productsManagementUrl,sku))
.get()
.retrieve()
.bodyToMono(Product.class);
......@@ -23,7 +30,7 @@ public class ProductService {
public Flux<Product> getAllProducts() {
return WebClient
.builder()
.baseUrl(AppConfig.getProductsManagementUrl())
.baseUrl(productsManagementUrl)
.build()
.get()
.uri("/api/products")
......@@ -34,7 +41,7 @@ public class ProductService {
public Flux<Promotion> getAllPromotions() {
return WebClient
.builder()
.baseUrl(AppConfig.getPromoManagementUrl())
.baseUrl(promoManagementUrl)
.build()
.get()
.uri("/api/promos")
......@@ -43,7 +50,7 @@ public class ProductService {
}
public Flux<Promotion> getPromotionBySkus(List<String> listOfSkus){
return WebClient.create(String.format("%s/api/promos/bulkSearch",AppConfig.getPromoManagementUrl()))
return WebClient.create(String.format("%s/api/promos/bulkSearch",promoManagementUrl))
.post()
.bodyValue(listOfSkus)
.retrieve()
......
spring.data.mongodb.uri=${MONGOCONNECTION}
# UNCOMMENT FOR PRODUCTION DEPLOYMENT
#spring.data.mongodb.uri=${MONGOCONNECTION}
# UNCOMMENT FOR LOCAL TESTING
spring.data.mongodb.uri=mongodb+srv://ecom:ecom@e-commerce-db-cluster.va815.mongodb.net/e-commerce-db?retryWrites=true&w=majority
spring.data.mongodb.database=e-commerce-db
security.enable-csrf=false
server.port=8080
products.apiUrl=http://13.64.175.185:8080
promos.apiUrl=http://40.118.215.99:8082
orders.apiUrl=http://138.91.251.222:8086
#products.apiUrl=http://localhost:8083
#promos.apiUrl=http://localhost:8082
#orders.apiUrl=http://localhost:8084
\ No newline at end of file
......@@ -4047,7 +4047,8 @@
"node_modules/babel-runtime/node_modules/core-js": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
"hasInstallScript": true
},
"node_modules/babel-runtime/node_modules/regenerator-runtime": {
"version": "0.11.1",
......@@ -5075,7 +5076,8 @@
"node_modules/core-js": {
"version": "3.11.2",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.11.2.tgz",
"integrity": "sha512-3tfrrO1JpJSYGKnd9LKTBPqgUES/UYiCzMKeqwR1+jF16q4kD1BY2NvqkfuzXwQ6+CIWm55V9cjD7PQd+hijdw=="
"integrity": "sha512-3tfrrO1JpJSYGKnd9LKTBPqgUES/UYiCzMKeqwR1+jF16q4kD1BY2NvqkfuzXwQ6+CIWm55V9cjD7PQd+hijdw==",
"hasInstallScript": true
},
"node_modules/core-js-compat": {
"version": "3.11.2",
......@@ -5097,7 +5099,8 @@
"node_modules/core-js-pure": {
"version": "3.11.2",
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.11.2.tgz",
"integrity": "sha512-DQxdEKm+zFsnON7ZGOgUAQXBt1UJJ01tOzN/HgQ7cNf0oEHW1tcBLfCQQd1q6otdLu5gAdvKYxKHAoXGwE/kiQ=="
"integrity": "sha512-DQxdEKm+zFsnON7ZGOgUAQXBt1UJJ01tOzN/HgQ7cNf0oEHW1tcBLfCQQd1q6otdLu5gAdvKYxKHAoXGwE/kiQ==",
"hasInstallScript": true
},
"node_modules/core-util-is": {
"version": "1.0.2",
......@@ -6201,6 +6204,7 @@
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
"hasInstallScript": true,
"engines": {
"node": ">=0.10.0"
}
......@@ -18734,6 +18738,7 @@
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
......@@ -19179,6 +19184,7 @@
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
......@@ -3,6 +3,7 @@ import * as ApiUtil from '../util/cart_api_util';
export const RECEIVE_USER_CART = "RECEIVE_USER_CART";
export const CLEAR_USER_CART = "CLEAR_USER_CART";
const receiveUserCart = cart => ({
type: RECEIVE_USER_CART,
cart
......@@ -12,6 +13,7 @@ export const clearUserCart = () => ({
type: CLEAR_USER_CART
})
export const fetchUserCart = userEmail => dispatch => ApiUtil.fetchUserCart(userEmail)
.then(cart => dispatch(receiveUserCart(cart)));
......@@ -20,3 +22,4 @@ export const updateUserCart = (updatedCart, userEmail) => dispatch => ApiUtil.up
export const createUserCart = newCart => dispatch => ApiUtil.createCart(newCart)
.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
......@@ -4,7 +4,7 @@ import { sendOrderPost } from './../util/order-api';
export const SEND_USER_ORDER = "SEND_USER_ORDER"
const sendUserOrder = (orderConfirmationResponse) => ({
export const sendUserOrder = (orderConfirmationResponse) => ({
type: SEND_USER_ORDER,
payload: orderConfirmationResponse
})
......
import React, { useState, useEffect } from 'react'
import {useSelector} from 'react-redux';
export default function SubmitOrder(props) {
const {currentUser} = useSelector(state => state);
let handleSubmitClick = (e) => {
let handleSubmitClick = () => {
console.log("Submit Button Clicked")
props.setSubmitButtonActive(1)
......@@ -16,9 +19,12 @@ export default function SubmitOrder(props) {
<p>Step 4 - Checkout</p>
</div>
<div id="SubmitButtonContainer">
<p className="errorMessage">{(props.errorWhileValidating === 1 && props.allFieldsValidated[0] === 0)? 'One or more fields is missing a value' : ''}</p>
<button id="SubmitButtonInput" onClick={handleSubmitClick} >Submit Order</button>
<div id="SubmitButtonContainer">
<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>
</div>
</div>
......
main {
margin: 0 auto;
max-width: 1080px;
}
#order-confirmation-header {
font-size: 40px;
text-align: center;
padding: 10px;
}
#return-to-martket {
margin-top: 50px;
display: flex;
justify-content: center;
width: 100%;
}
\ No newline at end of file
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Redirect } from 'react-router';
import {NavLink} from 'react-router-dom';
import {sendUserOrder} from '../../actions/checkout_actions'
import Order from '../order-history/Order';
import './order-confirmation.css'
const OrderConfirmation = () => {
const dispatch = useDispatch();
const {orderResponse} = useSelector(state => state.orderStatus);
useEffect(()=>{
return () => dispatch(sendUserOrder({}));
},[])
const orderPlaced = new Date(orderResponse.orderCreatedAt);
if (!orderResponse.id) return (<Redirect to="/product-market" />) //once we have flow from place order page, this can be uncommented
return (
<main>
<h1 id="order-confirmation-header">Thanks for your order!</h1>
<Order order={orderResponse} alt={0}/>
<div id="return-to-market">
<NavLink to="/product-market"> Return To Market</NavLink>
</div>
</main>
);
}
export default OrderConfirmation;
\ No newline at end of file
......@@ -5,28 +5,15 @@ import OrderItem from './OrderItem';
const Order = (props) => {
const {order} = props;
const {order, alt} = props;
const {orderItems, customerAddress} = order;
const orderTotalPrice = totalPrice(orderItems);
const orderPlaced = new Date(order.orderCreatedAt);
return (
<div className="order">
<p><span className="order-field">Order ID:</span> {order.id}</p>
<p><span className="order-field">Order Status:</span> {order.orderStatus}</p>
<p><span className="order-field">Order Placed:</span> {orderPlaced.getUTCMonth()}
/{orderPlaced.getUTCDay()}
/{orderPlaced.getUTCFullYear()}
</p>
<p>
<span className="order-field">Delivery Address:</span> {`
${customerAddress.street},
${customerAddress.city},
${customerAddress.state} ${customerAddress.zip}
`}
</p>
<p><span className="order-field">Items Ordered:</span></p>
<div className={`order order-${alt%2}`}>
<p className="order-number">Order #: {order.id}</p>
<div className="products-ordered">
{orderItems.map((orderItem, ind) => {
return (
......@@ -34,8 +21,27 @@ const Order = (props) => {
)
})}
</div>
<div className="total-price">
<p><span className="order-field">Total Price:</span> ${orderTotalPrice}</p>
</div>
<div className="order-details">
<div className="order-description">
<p className="order-status-header">Status</p>
<p><span className="order-field">Order Placed:</span> {orderPlaced.getUTCMonth()}
/{orderPlaced.getUTCDay()}
/{orderPlaced.getUTCFullYear()}
</p>
<p><span className="order-field">Order Status:</span> {order.orderStatus}</p>
</div>
<div className="shipping-details">
<p className="shipping-details-header">Shipping Address</p>
<span>{customerAddress.street},</span>
<p>{`${customerAddress.city},
${customerAddress.state} ${customerAddress.zip}
`}
</p>
</div>
</div>
</div>
)
}
......
import React from 'react';
import React, { useEffect,useState } from 'react';
import { fetchProductBySku } from '../../util/product_api_util';
const OrderItem = (props) => {
const {orderItem} = props;
const {itemName, itemPrice, itemQuantity} = orderItem;
const {itemName, itemPrice, itemQuantity, itemSku} = orderItem;
const subTotal = itemQuantity * itemPrice;
const [fullItemDetails, setFullItemDetails] = useState({});
useEffect(async ()=>{
const item = await fetchProductBySku(itemSku);
setFullItemDetails(item.data);
}, []);
return (
<div className="order-item">
<p>Item: {itemName}</p>
<p>Quantity: {itemQuantity}</p>
<p>Price Per Unit: ${itemPrice.toFixed(2)}</p>
<p>Subtotal: ${subTotal.toFixed(2)}</p>
<div className="pic-container">
<img className="order-item-pic" src={fullItemDetails.productImageUrl} />
</div>
<div className="item-details-container">
<p className="order-item-name">{itemName}</p>
<p className="order-item-quantity">QTY: {itemQuantity}</p>
</div>
<div className="item-price-container">
<p>Price Per Unit: ${itemPrice.toFixed(2)}</p>
<p className="order-subtotal">Subtotal: ${subTotal.toFixed(2)}</p>
</div>
</div>
)
}
......
......@@ -6,8 +6,8 @@ main {
.order {
display: flex;
flex-direction: column;
border: 1px solid black;
padding: 20px;
margin-bottom: 10px;
}
.products-ordered {
......@@ -16,12 +16,16 @@ main {
}
.order-item {
border: 1px solid gray;
padding: 5px;
display: grid;
grid-template-columns: 1fr 4fr 1fr;
grid-template-rows: auto;
border-bottom: 1px solid lightgray;
width: 100%;
}
.order-field {
.order-number {
font-weight: 600;
border-bottom: 1px solid black;
}
#order-history-header {
......@@ -29,3 +33,72 @@ main {
text-align: center;
padding: 10px;
}
.order-item-pic {
width: 200px;
height: 200px;
padding: 25px;
}
.item-details-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.order-item-name {
font-size: 24px;
}
.order-item-quantity {
color: gray;
}
.item-price-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.order-subtotal {
font-weight: 600;
}
.order-details {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto;
}
.total-price {
display: flex;
justify-content: flex-end;
border-bottom: 1px solid lightgray;
padding: 20px;
font-weight: 600;
font-size: 20px;
}
.order-status-header, .shipping-details-header {
font-weight: 600;
border-bottom: 1px solid black ;
width: fit-content;
margin-bottom: 10px;
font-size: 16px;
margin-top: 10px;
}
.shipping-details, .order-description {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.order-1 {
background-color: #f0f0f0;
}
\ No newline at end of file
......@@ -25,12 +25,12 @@ const OrderHistory = () => {
return (
<main>
<h1 id="order-history-header">Order History</h1>
{user === null ? (
{user === null || user.currentUser === null ? (
<div>Please login to place orders!</div>
) : null}
<div id="orders">
{orderHistory.map(order => {
return <Order order={order}/>;
{orderHistory.map((order, ind) => {
return <Order order={order} key={ind} alt={ind}/>;
})}
</div>
</main>
......
......@@ -7,6 +7,7 @@ import ShoppingCartContainer from './shopping-cart/shopping-cart-container';
import CheckoutContianer from './checkout/checkout-container';
import Header from './Header/header-container'
import OrderHistory from './order-history/order-history';
import OrderConfirmation from './order-confirmation/order-confirmation';
const Root = ({ store }) => (
<Provider store={ store }>
......@@ -24,6 +25,7 @@ const Root = ({ store }) => (
<Route path="/cart" component={ ShoppingCartContainer } />
<Route path="/checkout" component={ CheckoutContianer } />
<Route path="/orders" component={ OrderHistory } />
<Route path="/order-confirmation" component= {OrderConfirmation} />
</Switch>
</BrowserRouter>
</Provider>
......
......@@ -22,9 +22,19 @@ export default function CartItem(props) {
<div id="productName">{props.productInfo.productName}</div>
<div id="productStock">{props.productInfo.availableStock} left in stock</div>
<div id="quantityControls">
<select id="productQuantitySelect"><option>{props.productInfo.quantity}</option></select>
<button>Delete</button>
<div className="quantityControls">
<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>
......
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>
{
cartItems.length > 0 ? (
<Link id="checkoutButtonContainer" to="/checkout">
<button id="checkoutButton">Proceed To Checkout</button>
</Link>
) : (
<div>Add more items to your cart!</div>
)
}
</div>
)
}
class Config {
static baseApiUrl = "13.93.237.130:8084"; //env file
// static baseApiUrl = "http://13.93.237.130:8084"; //env file
static baseApiUrl = "http://localhost:8080"; //env file
static orderHistoryApiUrlMethod = (userId) => `${this.baseApiUrl}/api/orders/byUser/${userId}`;
......
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';
import orderReducer from './order_reducer'
import userReducer from './user_reducer'
import cartReducer from './cart_reducer';
import cartProcessingReducer from './cart_processing_reducer'
const rootReducer = combineReducers({
market: productsReducer,
user: userReducer,
cart: cartReducer,
orderStatus: orderReducer
orderStatus: orderReducer,
cartProcessing: cartProcessingReducer
});
export default rootReducer;
\ No newline at end of file
import axios from 'axios';
import Config from '../config';
export const fetchUserCart = userEmail => {
return axios.get(`13.93.237.130:8084/api/carts/${userEmail}`)
return axios.get(`${Config.baseApiUrl}/api/carts/${userEmail}`)
}
export const createCart = newCart => {
return axios.post(`13.93.237.130:8084/api/carts`, newCart)
return axios.post(`${Config.baseApiUrl}/api/carts`, newCart)
}
export const updateCart = (updatedCart, userEmail) => {
// debugger
return axios.put(`13.93.237.130:8084/api/carts/${userEmail}`, updatedCart)
}
\ No newline at end of file
return axios.put(`${Config.baseApiUrl}/api/carts/${userEmail}`, updatedCart)
}
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
}
import Config from './../config'
import axios from 'axios'
export const sendOrderPost = (order) => {
return axios.post("13.93.237.130:8084/api/orders", order)
return axios.post(`${Config.baseApiUrl}/api/orders`, order)
}
\ No newline at end of file
......@@ -11,4 +11,8 @@ export const fetchPromotions = () => {
export const fetchProductsAndPromotions = () => {
return axios.get(`${Config.baseApiUrl}/api/products-and-promos`)
}
export const fetchProductBySku = (sku) => {
return axios.get(`${Config.baseApiUrl}/api/products/${sku}`)
}
\ No newline at end of file
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