diff --git a/src/__tests__/App.test.js b/src/__tests__/App.test.js index ec3cd12..e506e07 100644 --- a/src/__tests__/App.test.js +++ b/src/__tests__/App.test.js @@ -1,6 +1,11 @@ +import React from 'react' import { customRender } from '../test-utils' import App from '../App' +jest.mock('../components/ItemTimer', () => { + return () => MockedTime +}) + describe('', () => { it('Should render the component.', () => { const container = customRender({ component: App }) diff --git a/src/__tests__/__snapshots__/App.test.js.snap b/src/__tests__/__snapshots__/App.test.js.snap index 2b79610..9951797 100644 --- a/src/__tests__/__snapshots__/App.test.js.snap +++ b/src/__tests__/__snapshots__/App.test.js.snap @@ -11,7 +11,7 @@ exports[` Should render the component. 1`] = ` Hermes - 10 minutes 0 seconds + MockedTime
Should render the component. 1`] = `

Cargo

+
+ + Volume Remaining: + + + 5 + +

Location:

diff --git a/src/__tests__/components/ItemTimer.test.js b/src/__tests__/components/ItemTimer.test.js index aa3f230..00359e2 100644 --- a/src/__tests__/components/ItemTimer.test.js +++ b/src/__tests__/components/ItemTimer.test.js @@ -1,6 +1,14 @@ import { customRender } from '../../test-utils' import ItemTimer from '../../components/ItemTimer' +jest.mock('../../util', () => { + const moment = require('moment') + const mockCreateDuration = () => moment.duration({ minutes: 60, seconds: 0 }) + return { + createDuration: mockCreateDuration + } +}) + describe('', () => { it('Should render the component.', () => { const container = customRender({ component: ItemTimer }) diff --git a/src/__tests__/components/__snapshots__/ItemTimer.test.js.snap b/src/__tests__/components/__snapshots__/ItemTimer.test.js.snap index 8a8665e..776afe6 100644 --- a/src/__tests__/components/__snapshots__/ItemTimer.test.js.snap +++ b/src/__tests__/components/__snapshots__/ItemTimer.test.js.snap @@ -3,7 +3,7 @@ exports[` Should render the component. 1`] = ` - 10 minutes 0 seconds + 0 minutes 0 seconds `; diff --git a/src/__tests__/views/__snapshots__/planets.js.snap b/src/__tests__/views/__snapshots__/planets.js.snap index b8fc0eb..9e3e64e 100644 --- a/src/__tests__/views/__snapshots__/planets.js.snap +++ b/src/__tests__/views/__snapshots__/planets.js.snap @@ -28,6 +28,15 @@ exports[` Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -59,8 +68,9 @@ exports[` Should render the component. 1`] = ` class="StyledBox-sc-13pk1d4-0 hroMnY" > +
+ +
+
Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -121,8 +158,9 @@ exports[` Should render the component. 1`] = ` class="StyledBox-sc-13pk1d4-0 hroMnY" > +
+ +
+
Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -183,8 +248,9 @@ exports[` Should render the component. 1`] = ` class="StyledBox-sc-13pk1d4-0 hroMnY" > +
+ +
+
Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -245,8 +338,9 @@ exports[` Should render the component. 1`] = ` class="StyledBox-sc-13pk1d4-0 hroMnY" > +
+ +
+
Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -307,8 +428,9 @@ exports[` Should render the component. 1`] = ` class="StyledBox-sc-13pk1d4-0 hroMnY" > +
+ +
+
@@ -373,6 +513,15 @@ exports[` Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -413,6 +562,15 @@ exports[` Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -453,6 +611,15 @@ exports[` Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -493,6 +660,15 @@ exports[` Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -533,6 +709,15 @@ exports[` Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -608,6 +793,15 @@ exports[` Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -648,6 +842,15 @@ exports[` Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -688,6 +891,15 @@ exports[` Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -728,6 +940,15 @@ exports[` Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
@@ -768,6 +989,15 @@ exports[` Should render the component. 1`] = ` Name: Test Item
+
+ + Quantity: + +
diff --git a/src/__tests__/views/__snapshots__/ship.js.snap b/src/__tests__/views/__snapshots__/ship.js.snap index c64b0ec..af80e3f 100644 --- a/src/__tests__/views/__snapshots__/ship.js.snap +++ b/src/__tests__/views/__snapshots__/ship.js.snap @@ -9,6 +9,20 @@ exports[` Should render the component. 1`] = `

Cargo

+
+ + Volume Remaining: + + + 4 + +
@@ -36,6 +50,22 @@ exports[` Should render the component. 1`] = `
+ + Quantity: + +
+ + 1 + +
+ ) +} + +PlanetDisplay.propTypes = { + handleShipTravel: PropTypes.func.isRequired, + planet: PropTypes.object.isRequired, + shipCargo: PropTypes.object.isRequired, + shipLocationValue: PropTypes.number.isRequired +} + +const mapStateToProps = ({ ship }) => ({ + shipCargo: ship.cargo, + shipLocationValue: ship.location.value +}) + +const mapDispatchToProps = dispatch => ({ + handleShipTravel: (destination, shipCargo) => { + const sellableItems = shipCargo.items.filter( + item => item.destination.value === destination.value + ) + + let profit = 0 + + sellableItems.forEach(item => { + const { quantity, value } = item + const itemProfit = quantity * value + profit += itemProfit + }) + + dispatch(addCash(profit)) + + sellableItems.forEach(item => { + // * Remove the item from the ship cargo + dispatch(removeCargo(item)) + }) + + dispatch(setShipLocationName(destination.name)) + dispatch(setShipLocationValue(destination.value)) + } +}) + +export default connect( + mapStateToProps, + mapDispatchToProps +)(PlanetDisplay) diff --git a/src/fixtures.js b/src/fixtures.js index 40d625e..a02fa42 100644 --- a/src/fixtures.js +++ b/src/fixtures.js @@ -1,6 +1,9 @@ export const defaultState = { ship: { - cargo: [], + cargo: { + items: [], + volumeRemaining: 5 + }, location: { name: null, value: null diff --git a/src/redux/actions/ship.js b/src/redux/actions/ship.js index af6c7dd..9176fbd 100644 --- a/src/redux/actions/ship.js +++ b/src/redux/actions/ship.js @@ -22,10 +22,11 @@ export const setShipLocationValue = value => ({ payload: { value } }) -export const storeCargo = item => ({ +export const storeCargo = (item, quantity) => ({ type: STORE_CARGO, payload: { - item + item, + quantity } }) diff --git a/src/redux/actions/world.js b/src/redux/actions/world.js index dfbaab4..410cef1 100644 --- a/src/redux/actions/world.js +++ b/src/redux/actions/world.js @@ -10,10 +10,11 @@ export const clearItems = () => ({ type: CLEAR_ITEMS }) export const refreshItems = () => ({ type: REFRESH_ITEMS }) -export const removeItem = item => ({ +export const removeItem = (item, quantity) => ({ type: REMOVE_ITEM, payload: { - item + item, + quantity } }) diff --git a/src/redux/reducers/ship.js b/src/redux/reducers/ship.js index 423af2d..3b8c82c 100644 --- a/src/redux/reducers/ship.js +++ b/src/redux/reducers/ship.js @@ -1,5 +1,8 @@ const shipDefaultState = { - cargo: [], + cargo: { + items: [], + volumeRemaining: 5 + }, location: { name: null, value: null @@ -11,7 +14,14 @@ export default (state = shipDefaultState, action) => { case 'REMOVE_CARGO': return { ...state, - cargo: state.cargo.filter(item => item.id !== action.payload.item.id) + cargo: { + ...state.cargo, + items: state.cargo.items.filter( + item => item.id !== action.payload.item.id + ), + volumeRemaining: + state.cargo.volumeRemaining + action.payload.item.quantity + } } case 'SET_SHIP_LOCATION_NAME': return { @@ -24,7 +34,38 @@ export default (state = shipDefaultState, action) => { location: { ...state.location, value: action.payload.value } } case 'STORE_CARGO': - return { ...state, cargo: [...state.cargo, action.payload.item] } + let updatedItems = state.cargo.items.map(currentItem => { + if (action.payload.item.id === currentItem.id) { + // * This item is the same, and you should just add the quantity + return { + ...currentItem, + quantity: currentItem.quantity + action.payload.quantity + } + } else { + // * This currentItem is different, and you should return the currentItem + return currentItem + } + }) + + if ( + !updatedItems.find( + currentItem => currentItem.id === action.payload.item.id + ) + ) { + updatedItems.push({ + ...action.payload.item, + quantity: action.payload.quantity + }) + } + + return { + ...state, + cargo: { + ...state.cargo, + items: updatedItems, + volumeRemaining: state.cargo.volumeRemaining - action.payload.quantity + } + } default: return state } diff --git a/src/redux/reducers/world.js b/src/redux/reducers/world.js index baf8179..7561595 100644 --- a/src/redux/reducers/world.js +++ b/src/redux/reducers/world.js @@ -21,17 +21,43 @@ export default (state = worldDefaultState, action) => { })) } case 'REMOVE_ITEM': - const { item } = action.payload + const { item, quantity } = action.payload const updatedPlanets = state.planets.map(planet => { const { isHomePlanet, items, location, name } = planet if (planet.items.includes(item)) { - return { - isHomePlanet, - items: items.filter(currentItem => item !== currentItem), - location, - name + // * This plaanet has the item in question + // * Figure out if all of the quantity needs to be removed + + if (quantity === item.quantity) { + // * All of the item should be removed + return { + isHomePlanet, + items: items.filter(currentItem => item !== currentItem), + location, + name + } + } else { + // * Only some of the item quantity should be removed + const updatedItems = items.map(currentItem => { + if (item.id === currentItem.id) { + // * figure out quantity + return { + ...currentItem, + quantity: currentItem.quantity - quantity + } + } else { + return currentItem + } + }) + + return { + isHomePlanet, + items: updatedItems, + location, + name + } } } else { return planet diff --git a/src/util.js b/src/util.js index 7a156b9..42b3ec8 100644 --- a/src/util.js +++ b/src/util.js @@ -24,7 +24,8 @@ export const generateItems = possibleDestinations => { destination: { name: destinationPlanet.name, value: destinationPlanet.location - } + }, + quantity: 10 } ) items.push(item) diff --git a/src/views/planets.js b/src/views/planets.js index e7a0ff0..dfbf424 100644 --- a/src/views/planets.js +++ b/src/views/planets.js @@ -1,139 +1,24 @@ import React from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' -import { Box, Text, Button, Heading } from 'grommet' -import { Add, Target } from 'grommet-icons' -import useLocalStorage from '../hooks/useLocalStorage' -import { - storeCargo, - setShipLocationName, - setShipLocationValue, - removeCargo -} from '../redux/actions/ship' -import { addCash } from '../redux/actions/user' -import { removeItem } from '../redux/actions/world' - -const PlanetsView = ({ - handleShipTravel, - handleStoreCargo, - planets, - shipCargo, - shipCargoLength, - shipLocationValue -}) => { - const [storagePlanets, setStoragePlanets] = useLocalStorage('planets', []) +import PlanetDisplay from '../components/PlanetDisplay' +const PlanetsView = ({ planets }) => { return (
- {planets.map(({ items, isHomePlanet, location, name }) => ( -
- - - {isHomePlanet ? name + ' - Home Planet' : name} - - {shipLocationValue !== location && ( -
+ {planets.map((planet, i) => ( + ))}
) } PlanetsView.propTypes = { - handleShipTravel: PropTypes.func.isRequired, - handleStoreCargo: PropTypes.func.isRequired, - planets: PropTypes.array.isRequired, - shipCargo: PropTypes.array.isRequired, - shipCargoLength: PropTypes.number.isRequired, - shipLocationValue: PropTypes.number.isRequired + planets: PropTypes.array.isRequired } -const mapStateToProps = ({ ship, world }) => ({ - planets: world.planets, - shipCargo: ship.cargo, - shipCargoLength: ship.cargo.length, - shipLocationValue: ship.location.value -}) - -const mapDispatchToProps = dispatch => ({ - handleStoreCargo: (item, currentPlanets, setStoragePlanets) => { - // * dispatch an action to store the item in ship cargo - dispatch(storeCargo(item)) - // * dispatch an action to remove the item from the list of stored items on this planet - dispatch(removeItem(item)) - }, - handleShipTravel: (destination, shipCargo) => { - const sellableItems = shipCargo.filter( - item => item.destination.value === destination.value - ) - - sellableItems.forEach(item => { - // * Add the value of this item to the user's cash - dispatch(addCash(item.value)) - // * Remove the item from the ship cargo - dispatch(removeCargo(item)) - }) - dispatch(setShipLocationName(destination.name)) - dispatch(setShipLocationValue(destination.value)) - } +const mapStateToProps = ({ world }) => ({ + planets: world.planets }) -export default connect( - mapStateToProps, - mapDispatchToProps -)(PlanetsView) +export default connect(mapStateToProps)(PlanetsView) diff --git a/src/views/ship.js b/src/views/ship.js index f605026..5db0113 100644 --- a/src/views/ship.js +++ b/src/views/ship.js @@ -5,16 +5,22 @@ import { Box, Text, Button } from 'grommet' import { Subtract } from 'grommet-icons' import { removeCargo } from '../redux/actions/ship' -const ShipView = ({ cargo, handleRemoveCargo, location }) => { +const ShipView = ({ items, handleRemoveCargo, location, volumeRemaining }) => { return (

Your Ship

Cargo

- {cargo.map(item => ( + + Volume Remaining: + {volumeRemaining} + + {items.map(item => ( {item.name} Destination: {item.destination.name} + Quantity: + {item.quantity}