Skip to content

Instantly share code, notes, and snippets.

@Dyrits
Forked from codecademydev/App.js
Last active May 10, 2023 08:14
Show Gist options
  • Save Dyrits/3a63b5cdea780d0a294eeaf70a745940 to your computer and use it in GitHub Desktop.
Save Dyrits/3a63b5cdea780d0a294eeaf70a745940 to your computer and use it in GitHub Desktop.
Codecademy Store

Codecademy Store

In this project, you’ll build a program that mimics Codecademy’s own online store! The application should display products from the Codecademy store and allow the user to add them to their cart. In the cart, the user can adjust the quantity of each item and the running total will be displayed at the bottom. Lastly, the user can choose the currency for the entire application.

An animated gif showing a demo of the Codecademy store's features

This application has three slices of state:

  • inventory: An array of objects representing the items that are available to purchase.
  • cart: An object that maps the name of each item added to the cart to an object with the price and desired quantity for that item.
  • currencyFilter: A string that represents the currency used to calculate the prices displayed to the user: 'USD', 'CAD' or 'EUR'. An example of this application’s state might look like this:
state = {
  inventory: [
    { name: 'Hat', img: 'img/hat.png', price: 15.99 },
    { name: 'T-Shirt', img: 'img/t-shirt.png', price: 18.99 },
    { name: 'Hoodie', img: 'img/hoodie.png', price: 49.99 },
  ],
  cart: {
    'Hat': { price: 15.99, quantity: 0 },
    'T-Shirt': { price: 15.99, quantity: 2 },
    'Hoodie': { price: 18.99, quantity: 1 },
  },
  currencyFilter: 'CAD'
}

As you will see, the file structure has been organized using the recommended feature-based pattern and most of the inventory and currency features have been built for you. It will be up to you to:

  • complete the cart’s action creators and reducer logic
  • create the store using createStore() and combineReducers()
  • pass the store resources to presentational components via the top-level <App /> component
  • render the <Cart /> component using the current state data
  • dispatch actions to the store

Let’s get started!

import React from 'react';
import { Inventory } from '../features/inventory/Inventory.js';
import { CurrencyFilter } from '../features/currencyFilter/CurrencyFilter.js';
import { Cart } from '../features/cart/Cart.js';
export const App = (props) => {
const { state, dispatch } = props;
return (
<div>
<CurrencyFilter
currencyFilter={state.currencyFilter}
dispatch={dispatch}
/>
<Inventory
inventory={state.inventory}
currencyFilter={state.currencyFilter}
dispatch={dispatch}
/>
<Cart
cart={state.cart}
currencyFilter={state.currencyFilter}
dispatch={dispatch}
/>
</div>
);
};
import React from 'react';
import { calculateTotal, getCurrencySymbol } from '../../utilities/utilities.js';
import { changeItemQuantity } from "./cartSlice.js";
export const Cart = (props) => {
const { cart, currencyFilter, dispatch } = props;
const onInputChangeHandler = (name, input) => {
props.dispatch(changeItemQuantity(name, Number(input)));
};
const cartElements = Object.keys(cart).map(createCartItem);
const total = calculateTotal(cart, currencyFilter);
return (
<div id="cart-container">
<ul id="cart-items">{cartElements}</ul>
<h3 className="total">
Total{' '}
<span className="total-value">
{getCurrencySymbol(currencyFilter)}{total} {currencyFilter}
</span>
</h3>
</div>
);
function createCartItem(name) {
const item = cart[name];
if (item.quantity) {
return (
<li key={name}>
<p>{name}</p>
<select
className="item-quantity"
value={item.quantity}
onChange={(e) => {
onInputChangeHandler(name, e.target.value);
}}
>
{[...Array(100).keys()].map((_, index) => (
<option key={index} value={index}>
{index}
</option>
))}
</select>
</li>
);
}
}
};
export const addItem = (itemToAdd) => {
return {
type: 'cart/addItem',
payload: itemToAdd,
};
};
export const changeItemQuantity = (name, newQuantity) => {
return {
type: 'cart/changeItemQuantity',
payload: { name, newQuantity },
};
};
const initialCart = {};
export const cartReducer = (cart = initialCart, action) => {
switch (action.type) {
case 'cart/addItem': {
const { name, price } = action.payload;
const quantity = cart[name] ? cart[name].quantity + 1 : 1;
const newItem = { price, quantity };
return {
...cart,
[name]: newItem
};
}
case 'cart/changeItemQuantity': {
const { name, newQuantity } = action.payload;
const item = { ...cart[name] };
item.quantity = newQuantity;
return { ...cart, [name] : item };
}
default: {
return cart;
}
}
};
import React from 'react';
import ReactDOM from 'react-dom';
import { App } from './app/App.js';
import { store } from "./app/store.js";
const render = () => {
ReactDOM.render(
<App
state={store.getState()}
dispatch={store.dispatch}
/>,
document.getElementById('root')
)
};
render();
store.subscribe(render);
import { createStore, combineReducers } from "redux";
import { inventoryReducer } from '../features/inventory/inventorySlice.js';
import { cartReducer } from '../features/cart/cartSlice.js';
import { currencyFilterReducer } from '../features/currencyFilter/currencyFilterSlice.js';
export const store = createStore(combineReducers({
inventory: inventoryReducer,
cart: cartReducer,
currencyFilter: currencyFilterReducer
}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment