Commit 5b775c46 authored by Kristian Freeman's avatar Kristian Freeman

2018-04-25T17:59:30

parent 07f7fd91
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# testing
/coverage
# production
/build
# misc
.DS_Store
.env
npm-debug.log*
yarn-debug.log*
yarn-error.log*
This is The Widget Company--we create widgets.
This React and Redux project is part of the free [_Redux manufacturing_ course][manu], created by [Bytesized][bytesized].
**Bytesized helps software teams go from unfamiliarity to fluency, through world-class technical training.**
[manu]: https://bytesized.xyz/redux-manufacturing/
[bytesized]: https://bytesized.xyz
This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app).
---
## Available (and useful scripts)
A variety of scripts are included with `creat-react-app`. For The Widget Company, the important and useful ones are:
### `npm start`
Runs the app in the development mode.<br>
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.<br>
You will also see any lint errors in the console.
### `npm run build`
Builds the app for production to the `build` folder.<br>
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.<br>
Your app is ready to be deployed!
{
"name": "thewidgetcompany",
"version": "0.1.0",
"private": true,
"devDependencies": {
"react-scripts": "0.9.5"
},
"dependencies": {
"history": "^4.7.2",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-redux": "^5.0.6",
"react-router-dom": "^4.2.2",
"react-router-redux": "^5.0.0-alpha.9",
"redux": "^3.7.2",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.2.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tag above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start`.
To create a production bundle, use `npm run build`.
-->
</body>
</html>
import React, {Component} from 'react';
import './index.css';
import './normalize.css';
import Header from './Header';
// Add the children prop underneath Header
const App = ({children}) => (
<div>
<Header />
</div>
);
// Set the default export for this file to be the App component.
import React from 'react';
import {connect} from 'react-redux';
const Header = ({warehouse: {error}}) => (
<div>
<img className="logo" src="/logo.png" />
<div style={{margin: '2em'}}>
{error && (
<span style={{background: 'red', color: 'white', padding: '1em'}}>
{error}
</span>
)}
</div>
</div>
);
export default connect(state => state)(Header);
import React from 'react';
import './index.css';
import './normalize.css';
const Home = () => (
<div>
<h1>
Factory status: <span style={{color: 'green'}}>NORMAL</span>
</h1>
</div>
);
export default Home;
import React, {Component} from 'react';
// Import two named functions from './actions':
// - attemptWidgetCreation
// - orderMaterials
//
// Remember that named functions are imported in the format
// import { namedFunction } from './module'
// Import the named function connect from 'react-redux'
class Inventory extends Component {
render() {
const {
attemptWidgetCreation,
orderMaterials,
warehouse: {materials: {dowel, screw, wheel}, widgets},
} = this.props;
return (
<div>
<h2>Inventory</h2>
<h4>{widgets.length} widgets in inventory</h4>
<button onClick={attemptWidgetCreation}>Manufacture widget</button>
<h2>Materials</h2>
<ul>
<li>Dowel: {dowel.count}</li>
<li>Screw: {screw.count}</li>
<li>Wheel: {wheel.count}</li>
</ul>
<button onClick={orderMaterials}>Order raw materials</button>
</div>
);
}
}
// Set component to the response of the connect function, with two arguments:
// 1) a function with an argument state, that simply returns state
// 2) an object with:
// key attemptWidgetCreation set to attemptWidgetCreation
// key orderMaterials set to orderMaterials
//
// This response should itself be called as a function, with the argument Inventory
// e.g. connect(1, 2)(3)
const component = null;
export default component;
import React, {Component} from 'react';
// Import the named function 'generateOrder' from './actions':
//
// Remember that named functions are imported in the format
// import { namedFunction } from './module'
// Import the named function connect from 'react-redux'
class Orders extends Component {
render() {
const {generateOrder, warehouse: {orders}} = this.props;
return (
<div>
<h2>Orders</h2>
<h3>{orders.length} orders</h3>
<ul>
{orders.map(order => (
<li key={order.created}>Order for {order.widgets} widgets</li>
))}
</ul>
<button onClick={generateOrder}>Generate order</button>
</div>
);
}
}
// Set component to the response of the connect function, with two arguments:
// 1) a function with an argument state, that simply returns state
// 2) an object with:
// key generateOrder set to generateOrder
//
// This response should itself be called as a function, with the argument Orders
// e.g. connect(1, 2)(3)
const component = null;
export default component;
import React, {Component} from 'react';
// Import the named function 'checkOrderForPackaging' from './actions':
//
// Remember that named functions are imported in the format
// import { namedFunction } from './module'
// Import the named function connect from 'react-redux'
class Packaging extends Component {
render() {
const {warehouse: {orders, packaged}, checkOrderForPackaging} = this.props;
return (
<div>
<h2>Packaging</h2>
<h4>{packaged} orders packaged</h4>
{orders.length ? (
<button onClick={checkOrderForPackaging}>Package order</button>
) : (
<h4>No orders to package</h4>
)}
</div>
);
}
}
// Set component to the response of the connect function, with two arguments:
// 1) a function with an argument state, that simply returns state
// 2) an object with:
// key checkOrderForPackaging set to checkOrderForPackaging
//
// This response should itself be called as a function, with the argument Orders
// e.g. connect(1, 2)(3)
const component = null;
export default component;
import React, {Component} from 'react';
import {connect} from 'react-redux';
class QA extends Component {
render() {
// Set the variable failed to this.props.warehouse.failed.
return (
<div>
<h2>QA</h2>
<h4>{failed} widgets failed QA</h4>
</div>
);
}
}
export default connect(state => state)(QA);
// Import the following named constants from './constants':
// - ADD_WIDGET
// - GENERATE_ORDER
// - ORDER_MATERIALS
// - PACKAGE_ORDER
// - PRESENT_ERROR
// - SHIP_ORDER
// - DOWELS_NEEDED
// - SCREWS_NEEDED
// - WHEELS_NEEDED
export function attemptWidgetCreation() {
return (dispatch, getState) => {
const {warehouse: {materials}} = getState();
const {dowel, screw, wheel} = materials;
if (
dowel.count >= DOWELS_NEEDED &&
screw.count >= SCREWS_NEEDED &&
wheel.count >= WHEELS_NEEDED
) {
dispatch(addWidget());
} else {
dispatch(presentError('Not enough materials to create a widget'));
}
};
}
// Define the function addWidget, which returns an object:
// - the key "date" should be set to Date.now()
// - the key "type" should be the constant ADD_WIDGET
// Define the function generateOrder, which returns an object:
// - the key "date" should be set to Date.now()
// - the key "type" should be the constant GENERATE_ORDER
// Define the function orderMaterials, which returns an object:
// - the key "type" should be the constant ORDER_MATERIALS
export function checkOrderForPackaging() {
return (dispatch, getState) => {
const {warehouse: {orders, widgets}} = getState();
const order = orders[0];
if (order.widgets <= widgets.length) {
dispatch(packageOrder(order));
} else {
dispatch(presentError('Not enough widgets to fill order!'));
}
};
}
// Define the function packageOrder, which takes an argument "order" and returns an object:
// - the key "type" should be the constant PACKAGE_ORDER
// - the key "order" should be set to the argument order
// Define the function shipOrder, which and returns an object:
// - the key "type" should be the constant SHIP_ORDER
export function presentError(message) {
return {
type: PRESENT_ERROR,
message,
};
}
export default {
attemptWidgetCreation,
generateOrder,
orderMaterials,
packageOrder,
presentError,
shipOrder,
};
export const ADD_WIDGET = 'ADD_WIDGET'
export const GENERATE_ORDER = 'GENERATE_ORDER'
export const ORDER_MATERIALS = 'ORDER_MATERIALS'
export const PACKAGE_ORDER = 'PACKAGE_ORDER'
export const PRESENT_ERROR = 'PRESENT_ERROR'
export const SHIP_ORDER = 'SHIP_ORDER'
export const DOWELS_NEEDED = 1
export const SCREWS_NEEDED = 2
export const WHEELS_NEEDED = 2
html, body {
font-family: sans-serif;
padding: 0.5em 1em;
}
img.logo {
width: 300px;
}
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import {Provider} from 'react-redux';
import {createStore, combineReducers, applyMiddleware} from 'redux';
import {
ConnectedRouter,
routerReducer,
routerMiddleware,
} from 'react-router-redux';
import {Link} from 'react-router-dom';
import {Route} from 'react-router';
import reduxLogger from 'redux-logger';
import thunk from 'redux-thunk';
import createHistory from 'history/createBrowserHistory';
import reducer from './reducer';
import routes from './routes';
const history = createHistory();
const linkList = (
<ul>
{routes.map(route => (
<li key={route.path}>
<Link to={route.path}>{route.title}</Link>
</li>
))}
</ul>
);
const routeList = routes.map(route => (
<Route
exact={route.exact || false}
path={route.path}
component={route.component}
/>
));
// Set the variable store as the result of the function createStore, with two arguments:
// 1) the response of the combineReducers function, with a hash passed in as the argument:
// - set the key router to routerReducer
// - set the key warehouse to reducer
// 2) the response of the applyMiddleware function, with the arguments:
// - the response of the routerMiddleware function, with history passed as an argument
// - reduxLogger
// - thunk
const store = null;
// First, we need to set up our application and wrap it in the
// correct Redux/React Router components. Define the app variable as:
//
// A Provider component with the prop "store" passed in (with the value of the variable store)
// A child ConnectedRouter component with the prop "history" passed in (with the value of the variable history)
// A child <App> component
// With child linkList and routeList variables
const app = null;
ReactDOM.render(app, document.getElementById('root'));
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in
* IE on Windows Phone and in iOS.
*/
html {
line-height: 1.15; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers (opinionated).
*/
body {
margin: 0;
}
/**
* Add the correct display in IE 9-.
*/
article,
aside,
footer,
header,
nav,
section {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in IE.
*/
figcaption,
figure,
main { /* 1 */
display: block;
}
/**
* Add the correct margin in IE 8.
*/
figure {
margin: 1em 40px;
}
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* 1. Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/
a {
background-color: transparent; /* 1 */
-webkit-text-decoration-skip: objects; /* 2 */
}
/**
* 1. Remove the bottom border in Chrome 57- and Firefox 39-.
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Add the correct background and color in IE 9-.
*/
mark {
background-color: #ff0;
color: #000;
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
audio,
video {
display: inline-block;
}
/**
* Add the correct display in iOS 4-7.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Remove the border on images inside links in IE 10-.
*/
img {
border-style: none;
}
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers (opinionated).
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: sans-serif; /* 1 */
font-size: 100%; /* 1 */