Products
- {products.map(product => (
+ {Object.values(products.byId).map(product => (
))}
diff --git a/src/client/redux/actions/index.js b/src/client/redux/actions/index.js
index 771fd14..89bb2ad 100644
--- a/src/client/redux/actions/index.js
+++ b/src/client/redux/actions/index.js
@@ -1,16 +1,18 @@
import * as actionTypes from "../actionTypes";
+import { transformProductsApi } from "../transformers/transformProductsApi";
+import { transformGetCartItemsApi } from "../transformers/transformGetCartItemsApi";
export const getProducts = productId => {
return dispatch => {
dispatch({ type: actionTypes.GET_PRODUCTS_REQUEST });
const apiUrl = productId ? `/api/products/${productId}` : "/api/products";
- console.log(apiUrl);
return fetch(apiUrl).then(async response => {
const responseData = await response.json();
if (response.ok) {
+ const data = transformProductsApi(responseData);
dispatch({
type: actionTypes.GET_PRODUCTS_SUCCESS,
- payload: responseData
+ payload: data
});
} else {
dispatch({
@@ -28,9 +30,10 @@ export const getCartItems = () => {
return fetch("/api/cart-items").then(async response => {
const responseData = await response.json();
if (response.ok) {
+ const data = transformGetCartItemsApi(responseData);
dispatch({
type: actionTypes.GET_CART_ITEMS_SUCCESS,
- payload: responseData
+ payload: data
});
} else {
dispatch({
diff --git a/src/client/redux/reducers/cartItems.js b/src/client/redux/reducers/cartItems.js
index 40cbb43..4f9dcf8 100644
--- a/src/client/redux/reducers/cartItems.js
+++ b/src/client/redux/reducers/cartItems.js
@@ -1,12 +1,39 @@
import * as actionTypes from "../actionTypes";
-export default function cartItemsReducer(state = [], action) {
+const initialState = {
+ byId: {},
+ ids: [],
+ isLoading: false,
+ isError: false,
+ errorMsg: ""
+};
+
+export default function cartItemsReducer(state = initialState, action) {
switch (action.type) {
+ case actionTypes.ADD_ITEMS_TO_CART_REQUEST:
+ case actionTypes.GET_CART_ITEMS_REQUEST:
+ return {
+ ...state,
+ isLoading: true
+ };
+
case actionTypes.GET_CART_ITEMS_SUCCESS:
- return [...state, ...action.payload];
+ return {
+ ...state,
+ ...action.payload,
+ isLoading: false
+ };
case actionTypes.ADD_ITEMS_TO_CART_SUCCESS:
- return [...state, action.payload];
+ return {
+ ...state,
+ byId: {
+ ...state.byId,
+ [action.payload.id]: action.payload
+ },
+ ids: [...state.ids, action.payload.id],
+ isLoading: false
+ };
default:
return state;
diff --git a/src/client/redux/reducers/products.js b/src/client/redux/reducers/products.js
index 61ce489..2ba4410 100644
--- a/src/client/redux/reducers/products.js
+++ b/src/client/redux/reducers/products.js
@@ -1,9 +1,40 @@
import * as actionTypes from "../actionTypes";
+import merge from "lodash/merge";
-export default function productsReducer(state = [], action) {
+const initialState = {
+ byId: {},
+ ids: [],
+ isLoading: false,
+ isError: false,
+ errorMsg: ""
+};
+
+export default function productsReducer(state = initialState, action) {
switch (action.type) {
+ case actionTypes.GET_PRODUCTS_REQUEST:
+ return {
+ ...state,
+ byId: {},
+ ids: [],
+ isLoading: true
+ };
+
case actionTypes.GET_PRODUCTS_SUCCESS:
- return action.payload;
+ return {
+ ...state,
+ byId: merge({}, state.byId, action.payload.byId),
+ ids: [...state.ids, action.payload.ids],
+ isLoading: false
+ };
+
+ case actionTypes.GET_PRODUCTS_FAILURE:
+ return {
+ ...state,
+ isLoading: false,
+ isError: true,
+ errorMsg: action.payload
+ };
+
default:
return state;
}
diff --git a/src/client/redux/transformers/transformGetCartItemsApi.js b/src/client/redux/transformers/transformGetCartItemsApi.js
new file mode 100644
index 0000000..03647f6
--- /dev/null
+++ b/src/client/redux/transformers/transformGetCartItemsApi.js
@@ -0,0 +1,10 @@
+export const transformGetCartItemsApi = data => ({
+ byId: data.reduce(
+ (obj, cartItem) => ({
+ ...obj,
+ [cartItem.id]: cartItem
+ }),
+ {}
+ ),
+ ids: data.map(cartItem => cartItem.id)
+});
diff --git a/src/client/redux/transformers/transformProductsApi.js b/src/client/redux/transformers/transformProductsApi.js
new file mode 100644
index 0000000..0e3980e
--- /dev/null
+++ b/src/client/redux/transformers/transformProductsApi.js
@@ -0,0 +1,10 @@
+export const transformProductsApi = data => ({
+ byId: data.reduce(
+ (obj, product) => ({
+ ...obj,
+ [product.id]: product
+ }),
+ {}
+ ),
+ ids: data.map(product => product.id)
+});
diff --git a/src/server/connectors/index.js b/src/server/connectors/index.js
index 580c78a..d342667 100644
--- a/src/server/connectors/index.js
+++ b/src/server/connectors/index.js
@@ -2,6 +2,7 @@ let products = [
{
id: 1,
name: "Macbook",
+ brand: "Apple",
description: "Latest Macbook with 16GB ram and Quad core processor",
price: 65000,
url: "/img/macbook.jpeg"
@@ -9,6 +10,15 @@ let products = [
{
id: 2,
name: "Keyboard",
+ brand: "Apple",
+ description: "Ergonomic keyboard",
+ price: 3000,
+ url: "/img/keyboard.jpeg"
+ },
+ {
+ id: 3,
+ name: "Keyboard",
+ brand: "Samsung",
description: "Ergonomic keyboard",
price: 3000,
url: "/img/keyboard.jpeg"
@@ -29,11 +39,16 @@ export function getProducts() {
return products;
}
-export function getProduct(id) {
- console.log("productId", id);
+export function getProductById(id) {
return [products.find(product => product.id === id)];
}
+export function getProductsByBrand(brand) {
+ return products.filter(
+ product => product.brand.toLowerCase() === brand.toLowerCase()
+ );
+}
+
export function getCartItem(id) {
return cartItems.find(c => c.id === id);
}
@@ -51,7 +66,11 @@ export function addToCart({ productId }) {
product: products.find(p => p.id === productId)
};
cartItems.push(newCartItem);
- return newCartItem;
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ resolve(newCartItem);
+ }, 5000);
+ });
}
export function deleteCartItem(args) {
diff --git a/src/server/index.js b/src/server/index.js
index 1b44b11..7c32686 100644
--- a/src/server/index.js
+++ b/src/server/index.js
@@ -4,7 +4,8 @@ import morgan from "morgan";
import {
getUser,
getProducts,
- getProduct,
+ getProductById,
+ getProductsByBrand,
getCartItems,
getCartItem,
addToCart,
@@ -43,10 +44,13 @@ app.get("/api/products", function(req, res) {
res.json(getProducts());
});
-app.get("/api/products/:id", function(req, res) {
+app.get("/api/products/:id(\\d+)/", function(req, res) {
const id = parseInt(req.params.id, 10);
- console.log("product id", id);
- res.json(getProduct(id));
+ res.json(getProductById(id));
+});
+
+app.get("/api/products/:brand(\\w+)/", function(req, res) {
+ res.json(getProductsByBrand(req.params.brand));
});
app.get("/api/cart-items", function(req, res) {
@@ -59,7 +63,7 @@ app.get("/api/cart-items/:id", function(req, res) {
});
app.post("/api/cart-items", function(req, res) {
- res.json(addToCart(req.body));
+ addToCart(req.body).then(response => res.json(response));
});
app.post("/api/cart-items/:id", function(req, res) {
diff --git a/yarn.lock b/yarn.lock
index 78c06ea..efd3fa1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4969,6 +4969,10 @@ lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
+lodash@4.17.10:
+ version "4.17.10"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
+
"lodash@>=3.5 <5", lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0:
version "4.17.5"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"