Created
December 15, 2015 16:03
-
-
Save kaaloo/b3f48488434403c543a9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var React = require('react'); | |
var ReactDOM = require('react-dom'); | |
var CSSTransitionGroup = require('react-addons-css-transition-group'); | |
var ReactRouter = require('react-router'); | |
var Router = ReactRouter.Router; | |
var Route = ReactRouter.Route; | |
var Navigation = ReactRouter.Navigation; | |
var History = ReactRouter.History; | |
var createBrowserHistory = require('history/lib/createBrowserHistory'); | |
var h = require('./helpers'); | |
// Firebase | |
var Rebase = require('re-base'); | |
var base = Rebase.createClass('https://xxxxxxxx.firebaseio.com/'); | |
var Catalyst = require('react-catalyst'); | |
/* | |
App | |
*/ | |
var App = React.createClass({ | |
mixins: [Catalyst.LinkedStateMixin], | |
getInitialState: function() { | |
return { | |
fishes: {}, | |
order: {} | |
} | |
}, | |
componentDidMount: function() { | |
var localStorageRef = localStorage.getItem('order-' + this.props.params.storeId); | |
base.syncState(this.props.params.storeId + '/fishes', { | |
context: this, | |
state: 'fishes', | |
then() { | |
if (localStorageRef) { | |
this.setState({ | |
order: JSON.parse(localStorageRef) | |
}); | |
} | |
} | |
}); | |
}, | |
componentWillUpdate: function(nextProps, nextState) { | |
localStorage.setItem('order-'+this.props.params.storeId, JSON.stringify(nextState.order)); | |
}, | |
addToOrder: function(key) { | |
this.state.order[key] = this.state.order[key] + 1 || 1; | |
this.setState({ order: this.state.order }); | |
}, | |
removeFromOrder: function(key) { | |
delete this.state.order[key]; | |
this.setState({ order: this.state.order }); | |
}, | |
addFish: function(fish) { | |
var timestamp = (new Date()).getTime(); | |
// update state | |
this.state.fishes['fish-' + timestamp] = fish; | |
// set the state | |
this.setState({ fishes: this.state.fishes }); | |
}, | |
removeFish: function(key) { | |
if (confirm("Are you sure you want to remove this fish?!")) { | |
this.state.fishes[key] = null; | |
this.setState({ fishes: this.state.fishes }); | |
} | |
}, | |
loadSamples: function() { | |
this.setState({ | |
fishes: require('./sample-fishes') | |
}); | |
}, | |
renderFish: function(key) { | |
return <Fish key={key} index={key} details={this.state.fishes[key]} addToOrder={this.addToOrder}/> | |
}, | |
render: function() { | |
return ( | |
<div className="catch-of-the-day"> | |
<div className="menu"> | |
<Header tagline="Fresh Seafood Market" num="5000"/> | |
<ul className="list-of-fishes"> | |
{Object.keys(this.state.fishes).map(this.renderFish)} | |
</ul> | |
</div> | |
<Order fishes={this.state.fishes} | |
order={this.state.order} | |
removeFromOrder={this.removeFromOrder}/> | |
<Inventory addFish={this.addFish} | |
removeFish={this.removeFish} | |
loadSamples={this.loadSamples} | |
fishes={this.state.fishes} | |
linkState={this.linkState}/> | |
</div> | |
) | |
} | |
}); | |
/* | |
Fish | |
*/ | |
var Fish = React.createClass({ | |
onButtonClick: function(event) { | |
console.log("Going to add the fish: " + this.props.index); | |
this.props.addToOrder(this.props.index); | |
}, | |
render: function() { | |
var details = this.props.details; | |
var isAvailable = details.status === 'available'; | |
var buttonText = isAvailable ? 'Add To Order' : 'Sold Out!'; | |
return ( | |
<li className="menu-fish"> | |
<img src={details.image} alt={details.name}/> | |
<h3 className="fish-name"> | |
{details.name} | |
<span className="price">{h.formatPrice(details.price)}</span> | |
</h3> | |
<p>{details.desc}</p> | |
<button disabled={!isAvailable} onClick={this.onButtonClick}>{buttonText}</button> | |
</li> | |
) | |
} | |
}); | |
/* | |
Add Fish Form | |
*/ | |
var AddFishForm = React.createClass({ | |
createFish: function(event) { | |
// 1. Stop the form from submitting | |
event.preventDefault(); | |
// 2. Take the date from the form and create an object | |
var fish = { | |
name: this.refs.name.value, | |
price: this.refs.price.value, | |
status: this.refs.status.value, | |
desc: this.refs.desc.value, | |
image: this.refs.image.value | |
} | |
// 3. Add the fish to the App State | |
this.props.addFish(fish); | |
this.refs.fishForm.reset(); | |
}, | |
render: function() { | |
return ( | |
<form className="fish-edit" ref="fishForm" onSubmit={this.createFish}> | |
<input type="text" ref="name" placeholder="Fish Name"/> | |
<input type="text" ref="price" placeholder="Fish Price"/> | |
<select ref="status"> | |
<option value="available">Fresh!</option> | |
<option value="unavailable">Sold Out!</option> | |
</select> | |
<textarea type="text" ref="desc" placeholder="Desc"></textarea> | |
<input type="text" ref="image" placeholder="URL to Image"/> | |
<button type="submit">+ Add Item</button> | |
</form> | |
) | |
} | |
}); | |
/* | |
Header | |
*/ | |
var Header = React.createClass({ | |
render: function() { | |
return ( | |
<header className="top"> | |
<h1>Catch | |
<span className="ofThe"> | |
<span className="of">of</span> | |
<span className="of">the</span> | |
</span> | |
Day</h1> | |
<h3 className="tagline"><span>{this.props.tagline}</span></h3> | |
</header> | |
) | |
}, | |
propTypes: { | |
tagline: React.PropTypes.string.isRequired | |
} | |
}); | |
/* | |
Order | |
*/ | |
var Order = React.createClass({ | |
propTypes: { | |
fishes: React.PropTypes.object.isRequired, | |
order: React.PropTypes.object.isRequired, | |
removeFromOrder: React.PropTypes.func.isRequired | |
}, | |
renderOrder: function(key) { | |
var fish = this.props.fishes[key]; | |
var count = this.props.order[key]; | |
var removeButton = <button onClick={this.props.removeFromOrder.bind(null, key)}>×</button>; | |
if (!fish) { | |
return <li key={key}>Sorry, fish no longer available {removeButton}</li> | |
} | |
return ( | |
<li key={key}> | |
<span> | |
<CSSTransitionGroup component="span" | |
transitionName="count" | |
transitionEnterTimeout={250} | |
transitionLeaveTimeout={250}> | |
<span key={count}>{count}</span> | |
</CSSTransitionGroup> | |
lbs {fish.name} {removeButton} | |
</span> | |
<span className="price">{h.formatPrice(count * fish.price)}</span> | |
</li>) | |
}, | |
render: function() { | |
var orderIds = Object.keys(this.props.order); | |
var total = orderIds.reduce((prevTotal, key) => { | |
var fish = this.props.fishes[key]; | |
var count = this.props.order[key]; | |
var isAvailable = fish && fish.status === 'available'; | |
if (fish && isAvailable) { | |
return prevTotal + (count * parseInt(fish.price) || 0); | |
} | |
}, 0); | |
return ( | |
<div className="order-wrap"> | |
<h2 className="order-title">Your Order</h2> | |
<CSSTransitionGroup | |
className="order" | |
component="ul" | |
transitionName="order" | |
transitionEnterTimeout={500} | |
transitionLeaveTimeout={500}> | |
{orderIds.map(this.renderOrder)} | |
<li className="total"> | |
{h.formatPrice(total)} | |
</li> | |
</CSSTransitionGroup> | |
</div> | |
) | |
} | |
}); | |
/* | |
Inventory | |
*/ | |
var Inventory = React.createClass({ | |
propTypes: { | |
addFish: React.PropTypes.func.isRequired, | |
removeFish: React.PropTypes.func.isRequired, | |
loadSamples: React.PropTypes.func.isRequired, | |
fishes: React.PropTypes.object.isRequired, | |
linkState: React.PropTypes.func.isRequired | |
}, | |
renderInventory: function(key) { | |
var linkState = this.props.linkState; | |
return ( | |
<div className="fish-edit" key={key}> | |
<input type="text" valueLink={linkState('fishes.'+key+'.name')}/> | |
<input text="text" valueLink={linkState('fishes.'+key+'.price')}/> | |
<select valueLink={linkState('fishes.'+key+'.status')}> | |
<option value="available">Fresh!</option> | |
<option value="unavailable">Sold Out!</option> | |
</select> | |
<textarea type="text" valueLink={linkState('fishes.'+key+'.desc')}></textarea> | |
<input type="text" valueLink={linkState('fishes.'+key+'.image')}/> | |
<button onClick={this.props.removeFish.bind(null, key)}>Remove Fish!</button> | |
</div> | |
) | |
}, | |
render: function() { | |
return ( | |
<div> | |
<h2>Inventory</h2> | |
{Object.keys(this.props.fishes).map(this.renderInventory)} | |
<AddFishForm {...this.props}/> | |
<button onClick={this.props.loadSamples}>Load Sample Fishes</button> | |
</div> | |
) | |
} | |
}); | |
/* | |
StorePicker | |
This will let us make <StorePicker/> | |
*/ | |
var StorePicker = React.createClass({ | |
mixins: [History], | |
goToStore: function(event) { | |
event.preventDefault(); | |
// get the data from the input | |
var storeId = this.refs.storeId.value; | |
console.log(storeId); | |
// transition from <StorePicker/> to <App/> | |
this.history.pushState(null, '/store/' + storeId); | |
}, | |
render: function() { | |
return ( | |
<form className="store-selector" onSubmit={this.goToStore}> | |
<h2>Please Enter A Store</h2> | |
{/* creating the store */} | |
<input type="text" ref="storeId" defaultValue={h.getFunName()} required /> | |
<input type="Submit"/> | |
</form> | |
) | |
} | |
}); | |
var NotFound = React.createClass({ | |
render: function() { | |
return <h1>Not Found!</h1> | |
} | |
}); | |
/* | |
Routes | |
*/ | |
var routes = ( | |
<Router history={createBrowserHistory()}> | |
<Route path="/" component={StorePicker}/> | |
<Route path="/store/:storeId" component={App}/> | |
<Route path="*" component={NotFound}/> | |
</Router> | |
) | |
ReactDOM.render(routes, document.querySelector('#main')); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment