Skip to content

Commit

Permalink
add readme
Browse files Browse the repository at this point in the history
  • Loading branch information
jbkly committed Feb 29, 2016
1 parent 76c9bbd commit 0f28cf3
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 26 deletions.
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Inventory System Demo
A simple CRUD inventory system demo using React, Hapi, Webpack, and Babel.

To try it out on your machine:
```bash
git clone https://github.com/jbkly/inventory-system.git inventory && cd $_
npm install
npm run serve
npm run launch (or open http://localhost:3000 in your browser)
```

This project is a code exercise to model an inventory system with a simple API and UI, a few basic CRUD operations, and tracking of expiring items.

I decided to use this exercise as an opportunity to get more practice with React and ES2015 and learn a few things, like server routing with [HapiJS](http://hapijs.com/), React unit testing with Mocha and [expect-jsx](https://github.com/algolia/expect-jsx), and modular React components.

I didn't want to spend too much time on database code, so items are stored in a simple JSON file. The goal is to access and remove items from the inventory by label, so rather than storing them in an array they are stored as key/value pairs for fast access. Node and Hapi provide a basic REST API for retrieving, adding, and removing items from the inventory.

The UI is handled by modular, reusable React components, and it optimistically updates before hearing back from the server to create faster feedback.

### Features
* Add items with a label, type, and expiration time. Duplicate labels are disallowed on the client side.
* Remove items from the inventory using either a dropdown or buttons on each item, and get a notification (provided by [toastr](https://github.com/CodeSeven/toastr)) that the item has been removed.
* Seed the database with a few random items by clicking a button.
* Set item expiration dates ranging from two weeks to a few seconds. When an item expires, user gets a notification and visual feedback that the item is expired.

### Dev setup
* Webpack Dev Server, Babel, and nodemon for ES2015 Javascript and live reloading.
* React unit tests via React test utilities, Mocha, Expect, and expect-jsx.
* [Swagger](https://github.com/glennjones/hapi-swagger) API documentation at http://localhost:3000/documentation.
* Test API calls with [Postman](https://www.getpostman.com/).

To start the node server in watch mode:
```
npm run serve
```
To start the Webpack dev server in live-reloading mode:
```
npm run dev
```
To have Webpack build a minified app bundle into dist:
```
npm run deploy
```
To run tests:
```
npm test
```

### Todo / wishlist
There are a few things I'd still like to add:
* Undo recently removed items. The groundwork is there: currently removed items are added to an array and stored in localStorage, so it would be simple to add an Undo button and pop them back off if the user wants to undo.
* Auto focus on item label input field after adding an item, to make adding multiple items smoother. Should be simple.
* More comprehensive tests needed (UI functionality, e2e tests, API tests, and coverage reports).
* Deploy server for online demo
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"start": "node server",
"serve": "DEV=true nodemon server --ignore public/ --ignore store/",
"dev": "webpack-dev-server --inline",
"go": "npm run serve && npm run dev",
"launch": "open 'http://localhost:3000'",
"test": "mocha './tests/**/*.spec.js' --compilers js:babel-core/register",
"testwatch": "clear && mocha './tests/**/*.spec.js' --compilers js:babel-core/register --watch",
"deploy": "NODE_ENV=production webpack -p --config webpack.prod.config.js"
Expand Down Expand Up @@ -40,7 +40,8 @@
"jsdom": "^8.0.4",
"mocha": "^2.4.5",
"mocha-jsdom": "^1.1.0",
"nodemon": "^1.9.0",
"nodemon": "^1.9.1",
"open": "0.0.5",
"react-addons-test-utils": "^0.14.7",
"webpack": "^1.12.14",
"webpack-dev-server": "^1.14.1"
Expand Down
1 change: 1 addition & 0 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const INVENTORY = Path.join(__dirname, 'store/items.json');
const server = new Hapi.Server();

server.connection({
host: 'localhost',
port: process.env.PORT || 3000
});

Expand Down
42 changes: 26 additions & 16 deletions store/items.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,37 @@
{
"cheese": {
"label": "cheese",
"type": "dairy",
"expiration": 1456766965540
"broccoli": {
"label": "broccoli",
"type": "vegetable",
"expiration": 1456728008739
},
"orange": {
"label": "orange",
"banana": {
"label": "banana",
"type": "fruit",
"expiration": 1456723885540
"expiration": 1456814348739
},
"whiskey": {
"label": "whiskey",
"type": "liquor",
"expiration": 1456771148739
},
"taco": {
"label": "taco",
"type": "mexican",
"expiration": 1456814348739
},
"pizza": {
"label": "pizza",
"type": "italian",
"expiration": 1457328565540
"parsley": {
"label": "parsley",
"type": "inedible",
"expiration": 1456814358910
},
"ham": {
"label": "ham",
"type": "meat",
"expiration": 1457328565540
"cupcake": {
"label": "cupcake",
"type": "dessert",
"expiration": 1457332758910
},
"eggplant": {
"label": "eggplant",
"type": "vegetable",
"expiration": 1456766965540
"expiration": 1456728258910
}
}
9 changes: 1 addition & 8 deletions webpack.prod.config.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
var path = require('path');
var node_modules = path.resolve(__dirname, 'node_modules');
var reactMinified = path.resolve(node_modules, 'react/dist/react.min.js');
var reactDOMMinified = path.resolve(node_modules, 'react-dom/dist/react-dom.min.js');

module.exports = {
entry: './public/js/app.jsx',
resolve: {
extensions: ['','.js','.jsx'],
// alias: {
// 'react': reactMinified,
// 'react-dom': reactDOMMinified
// }
},
output: {
path: path.resolve(__dirname, 'dist'),
Expand All @@ -27,7 +21,6 @@ module.exports = {
presets: ['react','es2015']
}
}
],
// noParse: [reactMinified]
]
}
};

0 comments on commit 0f28cf3

Please sign in to comment.