+ )
+ }
+})
+
+export default Comments;
diff --git a/learn-redux/client/components/Main.js b/learn-redux/client/components/Main.js
new file mode 100644
index 000000000..7d27f1516
--- /dev/null
+++ b/learn-redux/client/components/Main.js
@@ -0,0 +1,18 @@
+import React from 'react';
+import { Link } from 'react-router';
+
+const Main = React.createClass({
+ render() {
+ return (
+
+
+ Reduxstagram
+
+ {React.cloneElement(this.props.children, this.props)}
+ // Takes the props of the parent componenet, clones them and then passes them down to the child components.
+
+ )
+ }
+});
+
+export default Main;
diff --git a/learn-redux/client/components/Photo.js b/learn-redux/client/components/Photo.js
new file mode 100644
index 000000000..f44903734
--- /dev/null
+++ b/learn-redux/client/components/Photo.js
@@ -0,0 +1,39 @@
+import React from 'react';
+import { Link } from 'react-router';
+import CSSTransitionGroup from 'react-addons-css-transition-group';
+
+const Photo = React.createClass({
+ render() {
+ const { post, i, comments } = this.props;
+ return (
+
+ )
+ }
+})
+
+export default Photo
diff --git a/learn-redux/client/components/PhotoGrid.js b/learn-redux/client/components/PhotoGrid.js
new file mode 100644
index 000000000..29dd20dad
--- /dev/null
+++ b/learn-redux/client/components/PhotoGrid.js
@@ -0,0 +1,14 @@
+import React from 'react';
+import Photo from './Photo';
+
+const PhotoGrid = React.createClass({
+ render() {
+ return (
+
+ {this.props.posts.map((post, i) => )}
+
+ )
+ }
+});
+
+export default PhotoGrid;
diff --git a/learn-redux/client/components/Single.js b/learn-redux/client/components/Single.js
new file mode 100644
index 000000000..d5d98808d
--- /dev/null
+++ b/learn-redux/client/components/Single.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import { Link } from 'react-router';
+import Photo from './Photo';
+import Comments from './Comments';
+
+const Single = React.createClass({
+ render() {
+ //index of the post
+ const { postId } = this.props.params;
+ const i = this.props.posts.findIndex((post) => post.code === postId);
+ // get us the post
+ const post = this.props.posts[i];
+ const postComments = this.props.comments[postId] || [];
+
+ return (
+
+
+
+
+ )
+ }
+});
+
+export default Single;
diff --git a/learn-redux/client/components/app.js b/learn-redux/client/components/app.js
new file mode 100644
index 000000000..4b7cbe72c
--- /dev/null
+++ b/learn-redux/client/components/app.js
@@ -0,0 +1,19 @@
+import { bindActionCreators} from 'redux';
+import { connect } from 'react-redux';
+import * as actionCreators from '../actions/actionCreators';
+import Main from './Main'
+
+function mapStateToProps(state) {
+ return {
+ posts: state.posts,
+ comments: state.comments
+ }
+}
+
+function mapDispatchToProps(dispatch) {
+ return bindActionCreators(actionCreators, dispatch);
+}
+
+const App = connect(mapStateToProps, mapDispatchToProps)(Main);
+
+export default App;
diff --git a/learn-redux/client/reducers/comments.js b/learn-redux/client/reducers/comments.js
new file mode 100644
index 000000000..64d38ce19
--- /dev/null
+++ b/learn-redux/client/reducers/comments.js
@@ -0,0 +1,32 @@
+function postComments(state = [], action) {
+ switch(action.type){
+ case 'ADD_COMMENT':
+ // return the new state with the new comment
+ return [...state, {
+ user: action.author,
+ text: action.comment
+ }]
+ case 'REMOVE_COMMENT':
+ return [
+ ...state.slice(0, action.i),
+ ...state.slice(action.i + 1)
+ ]
+ default:
+ return state;
+ }
+}
+
+function comments(state = [], action) {
+ if(typeof action.postId !== 'undefined') {
+ return {
+ // take the current state
+ ...state,
+ // overwrite this post with new one
+ [action.postId]: postComments(state[action.postId], action)
+ }
+ }
+ return state;
+}
+
+
+export default comments;
diff --git a/learn-redux/client/reducers/index.js b/learn-redux/client/reducers/index.js
new file mode 100644
index 000000000..b6e2bb510
--- /dev/null
+++ b/learn-redux/client/reducers/index.js
@@ -0,0 +1,9 @@
+import { combineReducers } from 'redux';
+import { routerReducer } from 'react-router-redux';
+
+import posts from './posts';
+import comments from './comments';
+// combines all reducers from reducers folder and prepare for export
+const rootReducer = combineReducers({posts, comments, routing: routerReducer});
+
+export default rootReducer;
diff --git a/learn-redux/client/reducers/posts.js b/learn-redux/client/reducers/posts.js
new file mode 100644
index 000000000..298fbb253
--- /dev/null
+++ b/learn-redux/client/reducers/posts.js
@@ -0,0 +1,22 @@
+// A reducer's job is to take in action and store, process the action and then return the store.
+
+// A reducer takes in two things:
+// 1) the action (info about what happened)
+// 2) copy of current state
+
+function posts(state = [], action) {
+ switch(action.type) {
+ case 'INCREMENT_LIKES' :
+ const i = action.index;
+ return [
+ ...state.slice(0,i), // before the one we are updating
+ {...state[i], likes: state[i].likes + 1},
+ ...state.slice(i + 1) // after the one we are updating
+ ]
+ // always have default returning the updated state
+ default:
+ return state;
+ }
+}
+
+export default posts;
diff --git a/learn-redux/client/reduxstagram.js b/learn-redux/client/reduxstagram.js
index 598ea1874..e754338d7 100644
--- a/learn-redux/client/reduxstagram.js
+++ b/learn-redux/client/reduxstagram.js
@@ -1 +1,31 @@
-// let's go!
+import React from 'react';
+import { render } from 'react-dom';
+
+// Import css
+import css from './styles/style.styl';
+
+// Import Components
+import App from './components/App';
+import Single from './components/Single';
+import PhotoGrid from './components/PhotoGrid';
+
+// import react router dependecies
+import { Router, Route, IndexRoute, browserHistory } from 'react-router';
+import { Provider } from 'react-redux';
+import store, { history } from './store';
+
+const router = (
+
+
+ // Router componenent needs a history object, which here is browserHistory which allows you to do push state without having to reload the page.
+
+ // If the url matches "/" or a further extension of, grab the Main component.
+
+
+ // Then depending on the URL structure, either pass 'Main', 'PhotoGrid' or 'Single'.
+
+
+
+)
+
+render(router, document.getElementById('root'));
diff --git a/learn-redux/client/store.js b/learn-redux/client/store.js
new file mode 100644
index 000000000..b225d60a6
--- /dev/null
+++ b/learn-redux/client/store.js
@@ -0,0 +1,50 @@
+import { createStore, compose } from 'redux';
+import { syncHistoryWithStore } from 'react-router-redux';
+import { browserHistory } from 'react-router';
+
+//import the root reducer
+import rootReducer from './reducers/index'; // rootReducer is just a hub for importing all the individual reducers and exporting them as a whole. Syntax => const rootReducer = combineReducers({posts, comments, routing: routerReducer});
+
+import comments from './data/comments'; // importing the initial data
+import posts from './data/posts'; // importing the initial data
+
+// Passing initial data to defaultState
+const defaultState = {
+ posts: posts,
+ comments: comments
+};
+
+// ________________________________________________
+// SUGAR ------> INSTALL REDUX DEV TOOLS.
+// Install Redux dev tools into our store by using a store enhancer. This enables Redux Dev Tools in chrome to recognise your store.
+ const enhancers = compose(
+ // compose infuses our store with any of the enhancers we want.
+ window.devToolsExtension ? window.devToolsExtension() : f => f
+ // If dev tools is in the window, install it. If not just return the store.
+);
+// Then pass createStore the enhancers when creating the store below.
+// ________________________________________________
+
+
+// Create the store using collection of reducers and collection of data
+const store = createStore(rootReducer, defaultState, enhancers);
+
+export const history = syncHistoryWithStore(browserHistory, store);
+
+
+// ________________________________________________
+// SUGAR ------> HOT RELOAD REDUCERS. Done by accepting the hot reload & then re-requiring the reducer.
+if(module.hot) {
+ // First we check if the module is hot
+ module.hot.accept('./reducers/', () => {
+ // If it is hot, we accept it and run a function that is going to re-require and swap out the module for us.
+ const nextRootReducer = require('./reducers/index').default;
+ // Grab the main reducer (which is the top level index one). Use require because you cannot use an ES6 import statement inside of a function, must be done at top level.
+ store.replaceReducer(nextRootReducer)
+ // Finally we just replace the entire reducer with store.replaceReducer() and pass it the nextRootReducer.
+ });
+}
+// ________________________________________________
+
+// Export the newly created store
+export default store;