├── .gitignore
├── advanced-array-methods
├── filter
│ ├── filter-exercises.js
│ ├── index.html
│ └── spec
│ │ └── filter.spec.js
├── forEach
│ ├── forEach-exercises.js
│ ├── index.html
│ └── spec
│ │ └── forEach.spec.js
├── map
│ ├── index.html
│ ├── map-exercises.js
│ └── spec
│ │ └── map.spec.js
├── reduce
│ ├── index.html
│ ├── reduce-exercises.js
│ └── spec
│ │ └── reduce.spec.js
└── some-every
│ ├── index.html
│ ├── some-every-exercises.js
│ └── spec
│ └── some-every.spec.js
├── closures-and-keyword-this
├── call-apply-bind
│ ├── call-apply-bind-exercises.js
│ ├── index.html
│ └── spec
│ │ └── call-apply-bind.spec.js
└── closures
│ ├── closures-exercises.js
│ ├── index.html
│ └── spec
│ └── closures.spec.js
├── css-project
├── 01-starter-code
│ ├── assets
│ │ ├── css
│ │ │ └── styles.css
│ │ └── img
│ │ │ ├── main.jpg
│ │ │ ├── mountain1.jpg
│ │ │ ├── mountain2.jpg
│ │ │ ├── mountain3.jpg
│ │ │ └── mountain4.jpg
│ └── index.html
├── 02-nav-and-header
│ ├── assets
│ │ ├── css
│ │ │ └── styles.css
│ │ └── img
│ │ │ ├── main.jpg
│ │ │ ├── mountain1.jpg
│ │ │ ├── mountain2.jpg
│ │ │ ├── mountain3.jpg
│ │ │ └── mountain4.jpg
│ └── index.html
├── 03-destinations-and-features
│ ├── assets
│ │ ├── css
│ │ │ └── styles.css
│ │ └── img
│ │ │ ├── main.jpg
│ │ │ ├── mountain1.jpg
│ │ │ ├── mountain2.jpg
│ │ │ ├── mountain3.jpg
│ │ │ └── mountain4.jpg
│ └── index.html
├── 04-testimonials-contact-footer
│ ├── assets
│ │ ├── css
│ │ │ └── styles.css
│ │ └── img
│ │ │ ├── main.jpg
│ │ │ ├── mountain1.jpg
│ │ │ ├── mountain2.jpg
│ │ │ ├── mountain3.jpg
│ │ │ └── mountain4.jpg
│ └── index.html
└── 05-responsive-design
│ ├── assets
│ ├── css
│ │ └── styles.css
│ └── img
│ │ ├── main.jpg
│ │ ├── mountain1.jpg
│ │ ├── mountain2.jpg
│ │ ├── mountain3.jpg
│ │ └── mountain4.jpg
│ └── index.html
├── es2015-16-17-part-1
├── arrow-functions
│ ├── arrow-functions-exercises.js
│ ├── index.html
│ └── spec
│ │ └── es2015-part1-spec.js
├── destructuring
│ ├── destructuring-exercises.js
│ ├── index.html
│ └── spec
│ │ └── es2015-part1-spec.js
└── rest-spread
│ ├── index.html
│ ├── rest-spread-exercises.js
│ └── spec
│ └── es2015-part1-spec.js
├── es2015-16-17-part-2
├── class-keyword
│ ├── class-keyword-exercises.js
│ ├── index.html
│ └── spec
│ │ └── es2015-part-2.spec.js
├── es2015-inheritance
│ ├── es2015-inheritance-exercises.js
│ ├── index.html
│ └── spec
│ │ └── es2015-part-2.spec.js
├── es2015-methods
│ ├── es2015-methods-exercises.js
│ ├── index.html
│ └── spec
│ │ └── es2015-part-2.spec.js
├── maps-sets
│ ├── index.html
│ ├── maps-sets-exercises.js
│ └── spec
│ │ └── es2015-part-2.spec.js
└── promises
│ ├── index.html
│ ├── promises-exercises.js
│ └── spec
│ └── es2015-part-2.spec.js
├── es2016-and-2017
└── async-functions
│ ├── async-functions-exercises.js
│ ├── index.html
│ └── spec
│ └── es2015-part-2.spec.js
├── object-oriented-programming
├── constructors
│ ├── constructors-exercises.js
│ ├── index.html
│ └── spec
│ │ └── oop.spec.js
├── inheritance
│ ├── index.html
│ ├── inheritance-exercises.js
│ └── spec
│ │ └── oop.spec.js
└── prototypes
│ ├── index.html
│ ├── prototypes-exercises.js
│ └── spec
│ └── oop.spec.js
├── react
├── flags
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── CountryGame.js
│ │ ├── FlagAnswer.css
│ │ ├── FlagAnswer.js
│ │ ├── FlagChoices.css
│ │ ├── FlagChoices.js
│ │ ├── FlagQuestion.css
│ │ ├── FlagQuestion.js
│ │ ├── StyledButton.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── registerServiceWorker.js
│ │ └── world.jpg
├── hacker-news
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.css
│ │ ├── index.js
│ │ └── registerServiceWorker.js
├── helloworld
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── HobbyList.js
│ │ ├── Pet.css
│ │ ├── Pet.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ └── registerServiceWorker.js
├── memory-game
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ └── index.html
│ └── src
│ │ ├── Card.css
│ │ ├── Card.js
│ │ ├── MemoryGame.js
│ │ ├── Navbar.css
│ │ ├── Navbar.js
│ │ ├── index.css
│ │ └── index.js
├── pass-state-to-props-demo
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ └── registerServiceWorker.js
├── random-boxes-solution
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.css
│ │ ├── index.js
│ │ └── registerServiceWorker.js
├── random-boxes-starter
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.css
│ │ ├── index.js
│ │ └── registerServiceWorker.js
├── react-router-senators
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── Main.js
│ │ ├── Navbar.css
│ │ ├── Navbar.js
│ │ ├── SenatorDetails.js
│ │ ├── SenatorList.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── registerServiceWorker.js
│ │ └── senators.js
├── recipe-props-solution
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── avocado_toast.jpg
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── manifest.json
│ │ ├── milkshake.jpg
│ │ └── spaghetti.jpg
│ └── src
│ │ ├── App.test.js
│ │ ├── Navbar.css
│ │ ├── Navbar.js
│ │ ├── Recipe.css
│ │ ├── Recipe.js
│ │ ├── RecipeApp.css
│ │ ├── RecipeApp.js
│ │ ├── RecipeList.css
│ │ ├── RecipeList.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ └── registerServiceWorker.js
├── recipe-props-starter
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── manifest.json
│ │ └── spaghetti.jpg
│ └── src
│ │ ├── App.test.js
│ │ ├── Recipe.css
│ │ ├── Recipe.js
│ │ ├── RecipeApp.css
│ │ ├── RecipeApp.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ └── registerServiceWorker.js
├── recipe-redux-single-folder
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── avocado_toast.jpg
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── manifest.json
│ │ ├── milkshake.jpg
│ │ └── spaghetti.jpg
│ └── src
│ │ ├── Navbar.css
│ │ ├── Navbar.js
│ │ ├── Recipe.css
│ │ ├── Recipe.js
│ │ ├── RecipeApp.css
│ │ ├── RecipeApp.js
│ │ ├── RecipeInput.css
│ │ ├── RecipeInput.js
│ │ ├── RecipeList.css
│ │ ├── RecipeList.js
│ │ ├── images
│ │ └── spaghetti.jpg
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── reducers.js
│ │ └── registerServiceWorker.js
├── recipe-with-state
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── avocado_toast.jpg
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── manifest.json
│ │ ├── milkshake.jpg
│ │ └── spaghetti.jpg
│ └── src
│ │ ├── App.test.js
│ │ ├── Navbar.css
│ │ ├── Navbar.js
│ │ ├── Recipe.css
│ │ ├── Recipe.js
│ │ ├── RecipeApp.css
│ │ ├── RecipeApp.js
│ │ ├── RecipeInput.css
│ │ ├── RecipeInput.js
│ │ ├── RecipeList.css
│ │ ├── RecipeList.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ └── registerServiceWorker.js
├── redux-async
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ └── index.html
│ └── src
│ │ ├── actions
│ │ └── index.js
│ │ ├── components
│ │ ├── Picker.js
│ │ └── Posts.js
│ │ ├── containers
│ │ └── App.js
│ │ ├── index.js
│ │ └── reducers
│ │ └── index.js
├── redux-todos
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ └── index.html
│ └── src
│ │ ├── actions
│ │ ├── index.js
│ │ └── index.spec.js
│ │ ├── components
│ │ ├── App.js
│ │ ├── Footer.js
│ │ ├── Link.js
│ │ ├── Todo.js
│ │ └── TodoList.js
│ │ ├── containers
│ │ ├── AddTodo.js
│ │ ├── FilterLink.js
│ │ └── VisibleTodoList.js
│ │ ├── index.js
│ │ └── reducers
│ │ ├── index.js
│ │ ├── todos.js
│ │ ├── todos.spec.js
│ │ └── visibilityFilter.js
├── routing-demo
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── SwitchDemo.js
│ │ ├── index.css
│ │ ├── index.js
│ │ └── registerServiceWorker.js
├── simple-todo
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.css
│ │ ├── index.js
│ │ └── registerServiceWorker.js
├── update-complex-state-solution
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ └── registerServiceWorker.js
├── update-complex-state
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ └── registerServiceWorker.js
├── warbler-solution
│ ├── .gitignore
│ ├── warbler-client
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── public
│ │ │ ├── favicon.ico
│ │ │ ├── index.html
│ │ │ └── manifest.json
│ │ └── src
│ │ │ ├── actions
│ │ │ └── index.js
│ │ │ ├── components
│ │ │ ├── AuthForm.css
│ │ │ ├── AuthForm.js
│ │ │ ├── Homepage.js
│ │ │ ├── MessageForm.js
│ │ │ ├── MessageItem.css
│ │ │ ├── MessageItem.js
│ │ │ ├── MessageList.js
│ │ │ ├── MessageTimeline.js
│ │ │ ├── Navbar.css
│ │ │ ├── Navbar.js
│ │ │ ├── PrivateRoute.js
│ │ │ ├── UserAside.css
│ │ │ └── UserAside.js
│ │ │ ├── containers
│ │ │ ├── App.js
│ │ │ ├── Main.js
│ │ │ └── Warbler.js
│ │ │ ├── images
│ │ │ ├── default-profile-image.jpg
│ │ │ ├── warbler-hero.jpg
│ │ │ └── warbler-logo.png
│ │ │ ├── index.css
│ │ │ ├── index.js
│ │ │ ├── reducers
│ │ │ ├── currentUser.js
│ │ │ ├── index.js
│ │ │ └── messages.js
│ │ │ └── registerServiceWorker.js
│ └── warbler-server
│ │ ├── .env
│ │ ├── README.md
│ │ ├── helpers
│ │ ├── auth.js
│ │ └── messages.js
│ │ ├── index.js
│ │ ├── loadData.js
│ │ ├── middleware
│ │ └── auth.js
│ │ ├── models
│ │ ├── index.js
│ │ ├── message.js
│ │ └── user.js
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ └── routes
│ │ ├── auth.js
│ │ └── messages.js
├── warbler-starter-server
│ ├── .env
│ ├── README.md
│ ├── helpers
│ │ ├── auth.js
│ │ └── messages.js
│ ├── index.js
│ ├── loadData.js
│ ├── middleware
│ │ └── auth.js
│ ├── models
│ │ ├── index.js
│ │ ├── message.js
│ │ └── user.js
│ ├── package-lock.json
│ ├── package.json
│ └── routes
│ │ ├── auth.js
│ │ └── messages.js
└── warbler
│ ├── warbler-client
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ └── registerServiceWorker.js
│ └── warbler-server
│ ├── .env
│ ├── README.md
│ ├── helpers
│ ├── auth.js
│ └── messages.js
│ ├── index.js
│ ├── loadData.js
│ ├── middleware
│ └── auth.js
│ ├── models
│ ├── index.js
│ ├── message.js
│ └── user.js
│ ├── package-lock.json
│ ├── package.json
│ └── routes
│ ├── auth.js
│ └── messages.js
├── readme.md
└── todos_api
├── helpers
└── todos.js
├── index.js
├── models
├── index.js
└── todo.js
├── package-lock.json
├── package.json
├── public
├── app.css
└── app.js
├── routes
└── todos.js
└── views
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 |
--------------------------------------------------------------------------------
/advanced-array-methods/filter/filter-exercises.js:
--------------------------------------------------------------------------------
1 | // filter
2 |
3 | function filterByValue(arr,key){
4 | return arr.filter(function(val){
5 | return val[key] !== undefined;
6 | });
7 | }
8 |
9 | function find(arr, searchValue){
10 | return arr.filter(function(val){
11 | return val === searchValue
12 | })[0];
13 | }
14 |
15 | function findInObj(arr, key, searchValue){
16 | return arr.filter(function(val){
17 | return val[key] === searchValue;
18 | })[0];
19 | }
20 |
21 | function removeVowels(str){
22 | var vowels = "aeiou"
23 | return str.toLowerCase().split("").filter(function(val){
24 | return vowels.indexOf(val) === -1;
25 | }).join('')
26 | }
27 |
28 | function doubleOddNumbers(arr){
29 | return arr.filter(function(val){
30 | return val % 2 !== 0;
31 | }).map(function(val){
32 | return val *2;
33 | })
34 | }
--------------------------------------------------------------------------------
/advanced-array-methods/filter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/advanced-array-methods/forEach/forEach-exercises.js:
--------------------------------------------------------------------------------
1 | // forEach
2 |
3 | function doubleValues(arr){
4 | var newArr = [];
5 | arr.forEach(function(val){
6 | newArr.push(val * 2)
7 | })
8 | return newArr;
9 | }
10 |
11 | function onlyEvenValues(arr){
12 | var newArr = [];
13 | arr.forEach(function(val){
14 | if(val % 2 === 0){
15 | newArr.push(val)
16 | }
17 | })
18 | return newArr;
19 | }
20 |
21 | function showFirstAndLast(arr){
22 | var newArr = [];
23 | arr.forEach(function(val){
24 | newArr.push(val[0] + val[val.length-1])
25 | });
26 | return newArr;
27 | }
28 |
29 | function addKeyAndValue(arr,key,value){
30 | arr.forEach(function(val){
31 | val[key] = value;
32 | });
33 | return arr;
34 | }
35 |
36 | function vowelCount(str){
37 | var splitArr = str.toLowerCase().split("");
38 | var obj = {};
39 | var vowels = "aeiou";
40 |
41 | splitArr.forEach(function(letter){
42 | if(vowels.indexOf(letter) !== -1){
43 | if(obj[letter]){
44 | obj[letter]++;
45 | } else{
46 | obj[letter] = 1;
47 | }
48 | }
49 | });
50 | return obj;
51 | }
52 |
--------------------------------------------------------------------------------
/advanced-array-methods/forEach/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/advanced-array-methods/map/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/advanced-array-methods/map/map-exercises.js:
--------------------------------------------------------------------------------
1 | function doubleValues(arr){
2 | return arr.map(function(val){
3 | return val * 2
4 | });
5 | }
6 |
7 | function valTimesIndex(arr){
8 | return arr.map(function(val,idx){
9 | return val*idx;
10 | })
11 | }
12 |
13 | function extractValue(arr,key){
14 | return arr.map(function(val){
15 | return val[key];
16 | });
17 | }
18 |
19 | function extractFullName(arr){
20 | return arr.map(function(val){
21 | return val.first + " " + val.last;
22 | });
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/advanced-array-methods/map/spec/map.spec.js:
--------------------------------------------------------------------------------
1 | // map Exercises
2 |
3 | describe("#doubleValues", function(){
4 | it("doubles values in an array", function(){
5 | expect(doubleValues([1,2,3])).toEqual([2,4,6])
6 | });
7 | it("works for negative numbers", function(){
8 | expect(doubleValues([1,-2,-3])).toEqual([2,-4,-6])
9 | });
10 | });
11 |
12 | describe("#valTimesIndex", function(){
13 | it("returns a new array with each value multiplied by the index", function(){
14 | expect(valTimesIndex([1,2,3])).toEqual([0,2,6])
15 | });
16 | it("works for negative numbers", function(){
17 | expect(valTimesIndex([1,-2,-3])).toEqual([0,-2,-6])
18 | });
19 | });
20 |
21 | describe("#extractValue", function(){
22 | it("returns a new array with the value of each key in an array objects", function(){
23 | var arr = [{name: 'Elie'}, {name: 'Tim'}, {name: 'Matt'}, {name: 'Colt'}]
24 | expect(extractValue(arr,'name')).toEqual(['Elie', 'Tim', 'Matt', 'Colt'])
25 | });
26 | });
27 |
28 | describe("#extractFulName", function(){
29 | var arr = [{first: 'Elie', last:"Schoppik"}, {first: 'Tim', last:"Garcia"}, {first: 'Matt', last:"Lane"}, {first: 'Colt', last:"Steele"}]
30 | it("returns a new array with the value of each key in an array objects", function(){
31 | expect(extractFullName(arr,'name')).toEqual(['Elie Schoppik', 'Tim Garcia', 'Matt Lane', 'Colt Steele'])
32 | });
33 | });
--------------------------------------------------------------------------------
/advanced-array-methods/reduce/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/advanced-array-methods/reduce/reduce-exercises.js:
--------------------------------------------------------------------------------
1 | function extractValue(arr, key){
2 | return arr.reduce(function(acc,next){
3 | acc.push(next[key]);
4 | return acc;
5 | },[]);
6 | }
7 |
8 | function vowelCount(str){
9 | var vowels = "aeiou";
10 | return str.toLowerCase().split('').reduce(function(acc,next){
11 | if(vowels.indexOf(next) !== -1){
12 | if(acc[next]){
13 | acc[next]++;
14 | } else {
15 | acc[next] = 1;
16 | }
17 | }
18 | return acc;
19 | }, {});
20 | }
21 |
22 | function addKeyAndValue(arr, key, value){
23 | return arr.reduce(function(acc,next,idx){
24 | acc[idx][key] = value;
25 | return acc;
26 | },arr);
27 | }
28 |
29 | function partition(arr, callback){
30 | return arr.reduce(function(acc,next){
31 | if(callback(next)){
32 | acc[0].push(next);
33 | } else {
34 | acc[1].push(next);
35 | }
36 | return acc;
37 | }, [[],[]]);
38 | }
--------------------------------------------------------------------------------
/advanced-array-methods/some-every/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/advanced-array-methods/some-every/some-every-exercises.js:
--------------------------------------------------------------------------------
1 | function hasOddNumber(arr){
2 | return arr.some(function(val){
3 | return val % 2 !== 0;
4 | })
5 | }
6 |
7 | function hasAZero(num){
8 | return num.toString().split('').some(function(val){
9 | return val === '0';
10 | })
11 | }
12 |
13 | function hasOnlyOddNumbers(arr){
14 | return arr.every(function(val){
15 | return val % 2 !== 0;
16 | })
17 | }
18 |
19 | function hasNoDuplicates(arr){
20 | return arr.every(function(val){
21 | return arr.indexOf(val) === arr.lastIndexOf(val)
22 | })
23 | }
24 |
25 | function hasCertainKey(arr, key){
26 | return arr.every(function(val){
27 | return key in val
28 | })
29 | }
30 |
31 | function hasCertainValue(arr, key, searchValue){
32 | return arr.every(function(val){
33 | return val[key] === searchValue;
34 | })
35 | }
36 |
--------------------------------------------------------------------------------
/closures-and-keyword-this/call-apply-bind/call-apply-bind-exercises.js:
--------------------------------------------------------------------------------
1 | // https://github.com/rithmschool/intermediate_javascript_exercises/blob/master/call_apply_bind_exercise/callApplyBindSpec.js
2 |
3 | function arrayFrom(arrayLikeObject) {}
4 |
5 | function sumEvenArguments() {}
6 |
7 | // Write a function called sumEvenArguments which takes all of the arguments passed to a function and returns the sum of the even ones.
8 |
9 | // sumEvenArguments(1,2,3,4) // 6
10 | // sumEvenArguments(1,2,6) // 8
11 | // sumEvenArguments(1,2) // 2
12 |
13 | // // Write a function called invokeMax which accepts a function and a maximum amount. invokeMax should return a function that when called increments a counter. If the counter is greater than the maximum amount, the inner function should return "Maxed Out"
14 |
15 | // var addOnlyThreeTimes = invokeMax(add,3);
16 | // addOnlyThreeTimes(1,2) // 3
17 | // addOnlyThreeTimes(2,2) // 4
18 | // addOnlyThreeTimes(1,2) // 3
19 | // addOnlyThreeTimes(1,2) // "Maxed Out!"
20 |
21 | function add(a, b) {
22 | return a + b;
23 | }
24 |
25 | function invokeMax(fn, num) {}
26 |
27 | function once(fn, thisArg) {}
28 |
29 | function bind(fn, thisArg) {}
30 |
31 | // BONUS!
32 | function flip(fn, thisArg) {}
33 |
--------------------------------------------------------------------------------
/closures-and-keyword-this/call-apply-bind/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/closures-and-keyword-this/closures/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/closures-and-keyword-this/closures/spec/closures.spec.js:
--------------------------------------------------------------------------------
1 | // closures
2 |
3 | describe("#specialMultiply", function(){
4 | it("returns a function if only one parameter is passed", function(){
5 | expect(specialMultiply(1)).toEqual(jasmine.any(Function))
6 | });
7 | it("returns a function if only one parameter is passed that can be invoked with a second parameter", function(){
8 | var m = specialMultiply(1)
9 | expect(specialMultiply(1)).toEqual(jasmine.any(Function))
10 | expect(m(3)).toEqual(3)
11 | });
12 | it("returns a the product of two numbers if two parameters are passed", function(){
13 | expect(specialMultiply(1)(3)).toEqual(3)
14 | });
15 | });
16 |
17 | describe("#guessingGame", function(){
18 | it("returns a function", function(){
19 | expect(guessingGame(1)).toEqual(jasmine.any(Function))
20 | });
21 | it("stops you from guessing once you have gotten the answer", function(){
22 | var g = guessingGame(10)
23 | g(0), g(1), g(2), g(3), g(4), g(5), g(6), g(7), g(8), g(9), g(10)
24 | expect(g(10)).toEqual("All done playing!")
25 | });
26 | });
--------------------------------------------------------------------------------
/css-project/01-starter-code/assets/css/styles.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/01-starter-code/assets/css/styles.css
--------------------------------------------------------------------------------
/css-project/01-starter-code/assets/img/main.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/01-starter-code/assets/img/main.jpg
--------------------------------------------------------------------------------
/css-project/01-starter-code/assets/img/mountain1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/01-starter-code/assets/img/mountain1.jpg
--------------------------------------------------------------------------------
/css-project/01-starter-code/assets/img/mountain2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/01-starter-code/assets/img/mountain2.jpg
--------------------------------------------------------------------------------
/css-project/01-starter-code/assets/img/mountain3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/01-starter-code/assets/img/mountain3.jpg
--------------------------------------------------------------------------------
/css-project/01-starter-code/assets/img/mountain4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/01-starter-code/assets/img/mountain4.jpg
--------------------------------------------------------------------------------
/css-project/01-starter-code/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Mountain Travel
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/css-project/02-nav-and-header/assets/img/main.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/02-nav-and-header/assets/img/main.jpg
--------------------------------------------------------------------------------
/css-project/02-nav-and-header/assets/img/mountain1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/02-nav-and-header/assets/img/mountain1.jpg
--------------------------------------------------------------------------------
/css-project/02-nav-and-header/assets/img/mountain2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/02-nav-and-header/assets/img/mountain2.jpg
--------------------------------------------------------------------------------
/css-project/02-nav-and-header/assets/img/mountain3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/02-nav-and-header/assets/img/mountain3.jpg
--------------------------------------------------------------------------------
/css-project/02-nav-and-header/assets/img/mountain4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/02-nav-and-header/assets/img/mountain4.jpg
--------------------------------------------------------------------------------
/css-project/02-nav-and-header/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Mountain Travel
7 |
8 |
9 |
10 |
11 |
12 |
13 |
21 |
22 |
23 |
24 |
25 |
Mountain Travel
26 |
Unmissable Adventure Tours Around The World
27 |
Contact Us Now
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/css-project/03-destinations-and-features/assets/img/main.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/03-destinations-and-features/assets/img/main.jpg
--------------------------------------------------------------------------------
/css-project/03-destinations-and-features/assets/img/mountain1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/03-destinations-and-features/assets/img/mountain1.jpg
--------------------------------------------------------------------------------
/css-project/03-destinations-and-features/assets/img/mountain2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/03-destinations-and-features/assets/img/mountain2.jpg
--------------------------------------------------------------------------------
/css-project/03-destinations-and-features/assets/img/mountain3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/03-destinations-and-features/assets/img/mountain3.jpg
--------------------------------------------------------------------------------
/css-project/03-destinations-and-features/assets/img/mountain4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/03-destinations-and-features/assets/img/mountain4.jpg
--------------------------------------------------------------------------------
/css-project/04-testimonials-contact-footer/assets/img/main.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/04-testimonials-contact-footer/assets/img/main.jpg
--------------------------------------------------------------------------------
/css-project/04-testimonials-contact-footer/assets/img/mountain1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/04-testimonials-contact-footer/assets/img/mountain1.jpg
--------------------------------------------------------------------------------
/css-project/04-testimonials-contact-footer/assets/img/mountain2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/04-testimonials-contact-footer/assets/img/mountain2.jpg
--------------------------------------------------------------------------------
/css-project/04-testimonials-contact-footer/assets/img/mountain3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/04-testimonials-contact-footer/assets/img/mountain3.jpg
--------------------------------------------------------------------------------
/css-project/04-testimonials-contact-footer/assets/img/mountain4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/04-testimonials-contact-footer/assets/img/mountain4.jpg
--------------------------------------------------------------------------------
/css-project/05-responsive-design/assets/img/main.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/05-responsive-design/assets/img/main.jpg
--------------------------------------------------------------------------------
/css-project/05-responsive-design/assets/img/mountain1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/05-responsive-design/assets/img/mountain1.jpg
--------------------------------------------------------------------------------
/css-project/05-responsive-design/assets/img/mountain2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/05-responsive-design/assets/img/mountain2.jpg
--------------------------------------------------------------------------------
/css-project/05-responsive-design/assets/img/mountain3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/05-responsive-design/assets/img/mountain3.jpg
--------------------------------------------------------------------------------
/css-project/05-responsive-design/assets/img/mountain4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/css-project/05-responsive-design/assets/img/mountain4.jpg
--------------------------------------------------------------------------------
/es2015-16-17-part-1/arrow-functions/arrow-functions-exercises.js:
--------------------------------------------------------------------------------
1 | // function tripleAndFilter(arr){
2 | // return arr.map(function(value){
3 | // return value * 3;
4 | // }).filter(function(value){
5 | // return value % 5;
6 | // })
7 | // }
8 |
9 | // 1
10 |
11 | // function doubleOddNumbers(arr){
12 | // return arr.filter(function(val){
13 | // return val % 2 !== 0;
14 | // }).map(function(val){
15 | // return val *2;
16 | // })
17 | // }
18 |
19 | // 2
20 |
21 | // function mapFilterAndReduce(arr){
22 | // return arr.map(function(val){
23 | // return val.firstName
24 | // }).filter(function(val){
25 | // return val.length < 5;
26 | // }).reduce(function(acc,next){
27 | // acc[next] = next.length
28 | // return acc;
29 | // }, {})
30 | // }
31 |
32 | // 3
33 |
34 | // 4
35 |
36 | // 5
37 | var instructor = {
38 | firstName: "Colt",
39 | sayHi: function() {
40 | setTimeout(function() {
41 | console.log("Hello " + this.firstName);
42 | }, 1000);
43 | }
44 | };
45 |
--------------------------------------------------------------------------------
/es2015-16-17-part-1/arrow-functions/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/es2015-16-17-part-1/arrow-functions/spec/es2015-part1-spec.js:
--------------------------------------------------------------------------------
1 | // arrow functions
2 | describe("#tripleAndFilter", function(){
3 | it("triples an array of numbers and returns an array of all those numbers divisible by 5", function(){
4 | expect(tripleAndFilter([1,2,3,4,5])).toEqual([15])
5 | });
6 | });
7 |
8 | describe("#doubleOddNumbers", function(){
9 | it("returns a new array of all odd numbers doubled", function(){
10 | expect(doubleOddNumbers([1,2,3,4,5])).toEqual([2,6,10])
11 | });
12 | });
13 |
14 | describe("#mapFilterAndReduce", function(){
15 | it("maps over an array and filters for a length less than 5 and reduces into an object with the key as the name and value as the length", function(){
16 | var arr = mapFilterAndReduce([{firstName: 'Elie'}, {firstName: 'Rusty'}, {firstName: 'Matthew'}, {firstName: 'Tim'}])
17 | expect(arr).toEqual({Elie: 4, Tim: 3})
18 | });
19 | });
20 |
21 | describe("#createStudent", function(){
22 | it("returns an object with the keys and values of firstName and lastName", function(){
23 | expect(createStudentObj('Elie', 'Schoppik')).toEqual({firstName: 'Elie', lastName: 'Schoppik'})
24 | });
25 | });
--------------------------------------------------------------------------------
/es2015-16-17-part-1/destructuring/destructuring-exercises.js:
--------------------------------------------------------------------------------
1 | function displayStudentInfo(obj) {}
2 |
3 | function printFullName({ first, last }) {}
4 |
5 | function createStudent({ likesJavaScript = true, likesES2015 = true } = {}) {}
6 |
7 | function reverseArray(arr) {}
8 |
--------------------------------------------------------------------------------
/es2015-16-17-part-1/destructuring/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/es2015-16-17-part-1/rest-spread/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/es2015-16-17-part-1/rest-spread/rest-spread-exercises.js:
--------------------------------------------------------------------------------
1 | // spread
2 | function smallestValue(...args) {}
3 |
4 | // placeInMiddle([1,2,6,7],[3,4,5])
5 | function placeInMiddle(arr, vals) {}
6 |
7 | // rest
8 | function joinArrays(...args) {}
9 |
10 | // rest
11 | function sumEvenArgs(...args) {}
12 |
13 | // rest
14 | function flip(fn, thisArg, ...outerArgs) {}
15 |
16 | // rest + spread
17 | function bind(fn, thisArg, ...outerArgs) {}
18 |
--------------------------------------------------------------------------------
/es2015-16-17-part-2/class-keyword/class-keyword-exercises.js:
--------------------------------------------------------------------------------
1 | // Write a method called multiplyFavoriteNumber that takes in a number and returns the product of the number and the Person's favorite number
2 |
3 | // function Person(firstName, lastName, favoriteColor, favoriteNumber){
4 | // this.firstName = firstName;
5 | // this.lastName = lastName;
6 | // this.favoriteColor = favoriteColor;
7 | // this.favoriteNumber = favoriteNumber;
8 | // this.multiplyFavoriteNumber = function(num){
9 | // return num * this.favoriteNumber;
10 | // }
11 | // }
12 |
13 | class Person {}
14 |
--------------------------------------------------------------------------------
/es2015-16-17-part-2/class-keyword/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/es2015-16-17-part-2/es2015-inheritance/es2015-inheritance-exercises.js:
--------------------------------------------------------------------------------
1 | class Vehicle {}
2 |
--------------------------------------------------------------------------------
/es2015-16-17-part-2/es2015-inheritance/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/es2015-16-17-part-2/es2015-methods/es2015-methods-exercises.js:
--------------------------------------------------------------------------------
1 | // Array.from
2 | // Object.assign
3 | // Number.isFinite
4 |
5 | function copyObject(obj) {}
6 |
7 | function checkIfFinite(num) {}
8 |
9 | function areAllNumbersFinite(arr) {}
10 |
11 | function convertArrayLikeObject(obj) {}
12 |
13 | function displayEvenArguments() {}
14 |
--------------------------------------------------------------------------------
/es2015-16-17-part-2/es2015-methods/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/es2015-16-17-part-2/maps-sets/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/es2015-16-17-part-2/maps-sets/maps-sets-exercises.js:
--------------------------------------------------------------------------------
1 | // maps
2 |
3 | class MessageBoard {}
4 |
5 | // sets
6 | function uniqueValues(arr) {}
7 |
8 | function hasDuplicates(arr) {}
9 |
10 | function countPairs(arr, num) {}
11 |
--------------------------------------------------------------------------------
/es2015-16-17-part-2/promises/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/es2015-16-17-part-2/promises/promises-exercises.js:
--------------------------------------------------------------------------------
1 | function getMostFollowers(...usernames) {}
2 | function starWarsString(id) {}
3 |
--------------------------------------------------------------------------------
/es2015-16-17-part-2/promises/spec/es2015-part-2.spec.js:
--------------------------------------------------------------------------------
1 | describe("#getMostFollowers", function(){
2 | it("returns a string with the most followers", function(done){
3 | getMostFollowers('elie','tim','defunkt').then(function(result){
4 | expect(result).toEqual('Chris Wanstrath has the most followers with 16213')
5 | done();
6 | })
7 | });
8 | });
9 |
10 | describe("#starWarsString", function(){
11 | it("returns a string with the most followers", function(done){
12 | starWarsString(1).then(function(result){
13 | expect(result).toEqual('Luke Skywalker is featured in The Empire Strikes Back, directed by Irvin Kershner and it takes place on Hoth')
14 | done();
15 | })
16 | starWarsString(5).then(function(result){
17 | expect(result).toEqual('Leia Organa is featured in The Empire Strikes Back, directed by Irvin Kershner and it takes place on Hoth')
18 | done();
19 | })
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/es2016-and-2017/async-functions/async-functions-exercises.js:
--------------------------------------------------------------------------------
1 | function getMostFollowers(...usernames) {}
2 |
3 | function starWarsString(id) {}
4 |
--------------------------------------------------------------------------------
/es2016-and-2017/async-functions/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/es2016-and-2017/async-functions/spec/es2015-part-2.spec.js:
--------------------------------------------------------------------------------
1 | // Async Spec
2 |
3 | describe("#getMostFollowers", function(){
4 | it("returns a string with the most followers", function(done){
5 | getMostFollowers('elie','tim','defunkt').then(function(result){
6 | expect(result).toEqual('Chris Wanstrath has the most followers')
7 | done();
8 | })
9 | });
10 | });
11 |
12 | describe("#starWarsString", function(){
13 | it("returns a string with the most followers", function(done){
14 | starWarsString(1).then(function(result){
15 | expect(result).toEqual('Luke Skywalker is featured in The Empire Strikes Back, directed by Irvin Kershner and it takes place on Hoth')
16 | done();
17 | })
18 | starWarsString(5).then(function(result){
19 | expect(result).toEqual('Leia Organa is featured in The Empire Strikes Back, directed by Irvin Kershner and it takes place on Hoth')
20 | done();
21 | })
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/object-oriented-programming/constructors/constructors-exercises.js:
--------------------------------------------------------------------------------
1 | // Create a constructor function for a Person, each person should have a firstName, lastName, favoriteColor and favoriteNumber.
2 |
3 | // Write a method called multiplyFavoriteNumber that takes in a number and returns the product of the number and the Person's favorite number
4 |
5 | // refactor
6 |
--------------------------------------------------------------------------------
/object-oriented-programming/constructors/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/object-oriented-programming/constructors/spec/oop.spec.js:
--------------------------------------------------------------------------------
1 | // constructors
2 |
3 | describe("Person", function(){
4 | var person = new Person("Elie", "Schoppik", "purple", 34)
5 | it("has a firstName", function(){
6 | expect(person.hasOwnProperty('firstName')).toEqual(true);
7 | });
8 | it("has a lastName", function(){
9 | expect(person.hasOwnProperty('lastName')).toEqual(true);
10 | });
11 | it("has a favoriteColor", function(){
12 | expect(person.hasOwnProperty('favoriteColor')).toEqual(true);
13 | });
14 | it("has a favoriteNumber", function(){
15 | expect(person.hasOwnProperty('favoriteNumber')).toEqual(true);
16 | });
17 | });
18 |
19 | describe("#multiplyFavoriteNumber", function(){
20 | var person = new Person("Elie", "Schoppik", "purple", 34)
21 | it("takes in a number and returns the product of the number and the Person's favorite number", function(){
22 | expect(person.multiplyFavoriteNumber(10)).toEqual(340)
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/object-oriented-programming/inheritance/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/object-oriented-programming/inheritance/inheritance-exercises.js:
--------------------------------------------------------------------------------
1 | // inherit 1 thing from another
2 |
3 | function Vehicle(make, model, year) {}
4 |
--------------------------------------------------------------------------------
/object-oriented-programming/prototypes/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | >
14 |
15 |
16 |
--------------------------------------------------------------------------------
/object-oriented-programming/prototypes/prototypes-exercises.js:
--------------------------------------------------------------------------------
1 | // Create a constructor function for a Person. Each person should have a firstName, lastName, favoriteColor, favoriteNumber)
2 |
3 | // Add a function on the Person.prototype called fullName that returns the firstName and lastName property of an object created by the Person constructor concatenated together.
4 |
5 | // Add a property on the Person object called family which is an empty array.
6 |
7 | // Add a function on the Person.prototype called addToFamily which adds an object constructed from the Person constructor to the family array. To make sure that the object you are adding is an object construced from the Person constructor - take a look at the instanceofoperator. Make sure that your family array does not include duplicates! This method should the length of the family array.
8 |
9 | function Person(firstName, lastName, favoriteColor, favoriteNumber) {}
10 |
11 | Person.prototype.fullName = function() {};
12 |
13 | Person.prototype.addToFamily = function(person) {};
14 |
15 | // Part II:
16 |
17 | // Make the tests pass for the following tasks:
18 |
19 | // Implement your own version of Array.prototype.map
20 |
21 | Array.prototype.map = function(callback) {};
22 |
23 | // Implement a function that reverses a string and place it on the String.prototype
24 |
25 | String.prototype.reverse = function() {};
26 |
--------------------------------------------------------------------------------
/react/flags/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/flags/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flags",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.0.0-rc.2",
7 | "react-dom": "^16.0.0-rc.2",
8 | "react-scripts": "1.0.13",
9 | "shuffle-array": "^1.0.1"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/react/flags/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/flags/public/favicon.ico
--------------------------------------------------------------------------------
/react/flags/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/flags/src/App.css:
--------------------------------------------------------------------------------
1 | .flag-app {
2 | text-align: center;
3 | }
4 |
5 | .title-header {
6 | display: flex;
7 | height: 20vh;
8 | background-size: cover;
9 | background-repeat: no-repeat;
10 | justify-content: center;
11 | align-items: flex-end;
12 | background-color: "#6b93d6";
13 | }
14 |
15 | .title-text {
16 | font-size: 3.5em;
17 | color: #e9eff9;
18 | text-shadow: 3px 3px 4px black;
19 | }
20 |
21 | @media (max-width: 450px) {
22 | .title-header {
23 | height: 14vh;
24 | }
25 |
26 | .title-text {
27 | font-size: 2.1em;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/react/flags/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import CountryGame from './CountryGame';
3 | import worldImg from './world.jpg';
4 | import './App.css';
5 |
6 |
7 | class App extends Component {
8 | render() {
9 | return (
10 |
11 |
16 |
17 |
18 | );
19 | }
20 | }
21 |
22 | export default App;
23 |
--------------------------------------------------------------------------------
/react/flags/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/flags/src/FlagAnswer.css:
--------------------------------------------------------------------------------
1 | .flag-answer {
2 | display: flex;
3 | justify-content: center;
4 | align-items: center;
5 | font-size: 1.3em;
6 | }
7 |
8 | .flag-answer button {
9 | margin-left: 25px;
10 | }
11 |
--------------------------------------------------------------------------------
/react/flags/src/FlagAnswer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import StyledButton from './StyledButton';
3 | import './FlagAnswer.css';
4 |
5 | const FlagAnswer = ({correct, answer, onNext}) => (
6 |
7 | {correct ?
8 | `Correct!: ${answer}` :
9 | `Incorrect! Correct Answer: ${answer}`}
10 |
11 |
12 | );
13 |
14 | export default FlagAnswer;
15 |
--------------------------------------------------------------------------------
/react/flags/src/FlagChoices.css:
--------------------------------------------------------------------------------
1 | .flag-form {
2 | display: flex;
3 | max-width: 1000px;
4 | margin: 0 auto;
5 | justify-content: space-around;
6 | font-size: 1.3em;
7 | }
8 |
--------------------------------------------------------------------------------
/react/flags/src/FlagChoices.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import StyledButton from './StyledButton';
3 | import './FlagChoices.css';
4 |
5 | const FlagChoices = props => {
6 | let options = props.options || []
7 | const {handleChange, handleSubmit} = props;
8 | let inputs = options.map(opt => (
9 |
17 | ));
18 |
19 | return (
20 |
24 | );
25 | }
26 |
27 | export default FlagChoices;
28 |
--------------------------------------------------------------------------------
/react/flags/src/FlagQuestion.css:
--------------------------------------------------------------------------------
1 | .flag-img {
2 | max-height: 65vh;
3 | max-width: 90%;
4 | border: 1px solid black;
5 | margin: 15px;
6 | }
7 |
--------------------------------------------------------------------------------
/react/flags/src/StyledButton.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const StyledButton = ({text, onClick, type}) => (
4 |
20 | );
21 |
22 | export default StyledButton;
23 |
--------------------------------------------------------------------------------
/react/flags/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | background-color: #e9eff9;
6 | }
7 |
--------------------------------------------------------------------------------
/react/flags/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/flags/src/world.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/flags/src/world.jpg
--------------------------------------------------------------------------------
/react/hacker-news/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/hacker-news/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "simple-todo",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.0.0-rc.3",
7 | "react-dom": "^16.0.0-rc.3",
8 | "react-scripts": "1.0.13"
9 | },
10 | "scripts": {
11 | "start": "react-scripts start",
12 | "build": "react-scripts build",
13 | "test": "react-scripts test --env=jsdom",
14 | "eject": "react-scripts eject"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/react/hacker-news/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/hacker-news/public/favicon.ico
--------------------------------------------------------------------------------
/react/hacker-news/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/hacker-news/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | display: flex;
3 | flex-direction: column;
4 | justify-content: center;
5 | align-items: center;
6 | }
7 |
8 | .App ol li {
9 | font-size: 1.2em;
10 | margin: 10px;
11 | }
12 |
13 | .todo-input {
14 | padding: 2px;
15 | min-width: 250px;
16 | min-height: 25px;
17 | font-size: 1.2em;
18 | margin: 10px;
19 | }
20 |
21 | .save-button {
22 | font-size: 1.2em;
23 | }
24 |
25 | .todo-content {
26 | width: 50%;
27 | }
28 |
29 | @media (max-width: 700px) {
30 | .todo-content {
31 | width: 95%;
32 | }
33 | }
--------------------------------------------------------------------------------
/react/hacker-news/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import './App.css';
3 |
4 | class App extends Component {
5 | constructor(props) {
6 | super(props);
7 | this.state = {
8 | stories: []
9 | };
10 | }
11 |
12 | componentDidMount() {
13 | const topStories = 'https://hacker-news.firebaseio.com/v0/topstories.json';
14 | const storyUrlBase = 'https://hacker-news.firebaseio.com/v0/item/';
15 |
16 | fetch(topStories)
17 | .then(data => data.json())
18 | .then(data => data.map(id => {
19 | const url = `${storyUrlBase}${id}.json`;
20 | return fetch(url).then(d => d.json());
21 | }))
22 | .then(promises => Promise.all(promises))
23 | .then(stories => this.setState({stories}));
24 | }
25 |
26 | render() {
27 | let views = Loading...
;
28 | const {stories} = this.state;
29 | if (stories && stories.length > 0) {
30 | views = stories.map(s=> (
31 |
32 | {s.title} from {s.by}
33 |
34 | ));
35 | }
36 |
37 | return (
38 |
39 |
Hacker News Top Stories
40 | {views}
41 |
42 | );
43 | }
44 | }
45 |
46 | export default App;
47 |
--------------------------------------------------------------------------------
/react/hacker-news/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/hacker-news/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/react/hacker-news/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/helloworld/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/helloworld/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "helloworld",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^15.6.1",
7 | "react-dom": "^15.6.1",
8 | "react-scripts": "1.0.13"
9 | },
10 | "scripts": {
11 | "start": "react-scripts start",
12 | "build": "react-scripts build",
13 | "test": "react-scripts test --env=jsdom",
14 | "eject": "react-scripts eject"
15 | }
16 | }
--------------------------------------------------------------------------------
/react/helloworld/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/helloworld/public/favicon.ico
--------------------------------------------------------------------------------
/react/helloworld/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/helloworld/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | animation: App-logo-spin infinite 20s linear;
7 | height: 80px;
8 | }
9 |
10 | .App-header {
11 | background-color: #222;
12 | height: 150px;
13 | padding: 20px;
14 | color: white;
15 | }
16 |
17 | .App-intro {
18 | font-size: large;
19 | }
20 |
21 | @keyframes App-logo-spin {
22 | from { transform: rotate(0deg); }
23 | to { transform: rotate(360deg); }
24 | }
25 |
--------------------------------------------------------------------------------
/react/helloworld/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import logo from './logo.svg';
3 | import './App.css';
4 |
5 | class App extends Component {
6 | render() {
7 | return (
8 |
9 |
10 |

11 |
HELLO WORLD!!
12 |
13 |
14 | To get started, edit src/App.js
and save to reload.
15 |
16 |
17 | );
18 | }
19 | }
20 |
21 | export { App };
22 |
--------------------------------------------------------------------------------
/react/helloworld/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/helloworld/src/HobbyList.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | class HobbyList extends Component {
4 | render() {
5 | const hobbies = ["Sleeping", "Eating", "Cuddling"];
6 | const style = {fontSize: '1.5em'};
7 | return (
8 |
9 | {hobbies.map((h, i) => {
10 | return - {h}
11 | })}
12 |
13 | );
14 | }
15 | }
16 |
17 | export default HobbyList;
--------------------------------------------------------------------------------
/react/helloworld/src/Pet.css:
--------------------------------------------------------------------------------
1 | .name {
2 | font-size: 3em;
3 | margin: .25em;
4 | }
5 | .card {
6 | font-family: Helvetica, Arial, sans-serif;
7 | background-color: #c1bcb6;
8 | margin: 10px;
9 | padding: 10px;
10 | border-radius: 10px;
11 | border: 4px solid #005365;
12 | color: #005365;
13 | display: flex;
14 | flex-direction: column;
15 | justify-content: center;
16 | align-items: center;
17 | }
18 | .card img {
19 | width: 300px;
20 | padding: 4px 20px 10px 20px;
21 | }
--------------------------------------------------------------------------------
/react/helloworld/src/Pet.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import HobbyList from './HobbyList';
3 | import './Pet.css';
4 |
5 | class Pet extends Component {
6 | render() {
7 | return (
8 |
Moxie
9 |

12 |
Hobbies:
13 |
14 |
);
15 | }
16 | }
17 |
18 | export default Pet;
--------------------------------------------------------------------------------
/react/helloworld/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
7 | #root {
8 | display: flex;
9 | flex-direction: row;
10 | justify-content: center;
11 | }
--------------------------------------------------------------------------------
/react/helloworld/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import Pet from './Pet';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/memory-game/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env
15 | npm-debug.log*
16 | yarn-debug.log*
17 | yarn-error.log*
18 |
19 |
--------------------------------------------------------------------------------
/react/memory-game/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "memory-game",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "prop-types": "^15.5.10",
7 | "react": "^16.0.0-rc.3",
8 | "react-dom": "^16.0.0-rc.3",
9 | "shuffle-array": "^1.0.1"
10 | },
11 | "devDependencies": {
12 | "react-scripts": "0.9.5"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test --env=jsdom",
18 | "eject": "react-scripts eject"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/react/memory-game/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/memory-game/public/favicon.ico
--------------------------------------------------------------------------------
/react/memory-game/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 | Memory Game
17 |
18 |
19 |
20 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/react/memory-game/src/Card.css:
--------------------------------------------------------------------------------
1 | .card-container {
2 | margin: 10px;
3 | height: 150px;
4 | min-width: 100px;
5 | width: 10%;
6 | background-color: grey;
7 | border: 6px solid grey;
8 | border-radius: 25px;
9 | display: inline-block;
10 | }
11 |
--------------------------------------------------------------------------------
/react/memory-game/src/Card.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import './Card.css'
4 |
5 | const Card = (props) => {
6 | let style = {};
7 | if (props.showing) {
8 | style.backgroundColor = props.backgroundColor;
9 | }
10 | return (
11 |
16 | );
17 | };
18 |
19 | Card.propTypes = {
20 | showing: PropTypes.bool.isRequired,
21 | backgroundColor: PropTypes.string.isRequired,
22 | onClick: PropTypes.func.isRequired
23 | };
24 |
25 | export default Card;
26 |
--------------------------------------------------------------------------------
/react/memory-game/src/Navbar.css:
--------------------------------------------------------------------------------
1 | header {
2 | background-color: #2c3e50;
3 | display: flex;
4 | justify-content: space-between;
5 | align-items: center;
6 | color: white;
7 | padding: 0 15px;
8 | }
9 |
10 | header h1 {
11 | text-align: center;
12 | }
13 |
14 | header li {
15 | list-style: none;
16 | }
17 |
18 | header a {
19 | text-decoration: none;
20 | color: inherit;
21 | cursor: pointer;
22 | opacity: 0.9;
23 | }
24 |
25 | header a:hover {
26 | opacity: 1;
27 | }
28 |
29 | header nav {
30 | display: flex;
31 | }
32 |
33 | header nav li {
34 | margin: 0 15px;
35 | }
36 |
37 | header nav li:first-child {
38 | margin-left: 0;
39 | }
40 |
41 | header nav li:last-child {
42 | margin-right: 0;
43 | }
44 |
45 | @media (max-width: 1000px) {
46 | header{
47 | padding: 20px 50px;
48 | }
49 | }
50 |
51 |
52 | @media (max-width: 700px) {
53 | header{
54 | flex-direction: column;
55 | }
56 |
57 | header h2{
58 | margin-bottom: 15px;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/react/memory-game/src/Navbar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import './Navbar.css';
4 |
5 | const Navbar = ({onNewGame}) => (
6 |
12 | );
13 |
14 | Navbar.propTypes = {
15 | onNewGame: PropTypes.func.isRequired
16 | };
17 |
18 | export default Navbar;
19 |
--------------------------------------------------------------------------------
/react/memory-game/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/react/memory-game/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import MemoryGame from './MemoryGame';
4 | import './index.css';
5 |
6 | ReactDOM.render(
7 | ,
8 | document.getElementById('root')
9 | );
10 |
--------------------------------------------------------------------------------
/react/pass-state-to-props-demo/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/pass-state-to-props-demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "update-complex-state",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "prop-types": "^15.5.10",
7 | "react": "^15.6.1",
8 | "react-dom": "^15.6.1",
9 | "react-scripts": "1.0.13"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/react/pass-state-to-props-demo/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/pass-state-to-props-demo/public/favicon.ico
--------------------------------------------------------------------------------
/react/pass-state-to-props-demo/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/pass-state-to-props-demo/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | padding: 20px;
3 | text-align: center;
4 | }
5 |
6 | .App ul {
7 | padding: 0;
8 | display: flex;
9 | justify-content: space-between;
10 | }
11 |
12 | .App li {
13 | list-style: none;
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/react/pass-state-to-props-demo/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/pass-state-to-props-demo/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | background: #ecf0f1;
6 | }
7 |
--------------------------------------------------------------------------------
/react/pass-state-to-props-demo/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/random-boxes-solution/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/random-boxes-solution/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "random-boxes-starter",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "prop-types": "^15.5.10",
7 | "react": "^16.0.0-rc.3",
8 | "react-dom": "^16.0.0-rc.3",
9 | "react-scripts": "1.0.13"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/react/random-boxes-solution/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/random-boxes-solution/public/favicon.ico
--------------------------------------------------------------------------------
/react/random-boxes-solution/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/random-boxes-solution/src/App.css:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/react/random-boxes-solution/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/random-boxes-solution/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/react/random-boxes-solution/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/random-boxes-starter/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/random-boxes-starter/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "random-boxes-starter",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "prop-types": "^15.5.10",
7 | "react": "^16.0.0-rc.3",
8 | "react-dom": "^16.0.0-rc.3",
9 | "react-scripts": "1.0.13"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/react/random-boxes-starter/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/random-boxes-starter/public/favicon.ico
--------------------------------------------------------------------------------
/react/random-boxes-starter/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/random-boxes-starter/src/App.css:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/react/random-boxes-starter/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/random-boxes-starter/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/react/random-boxes-starter/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/react-router-senators/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/react-router-senators/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-router-senators",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.0.0-rc.3",
7 | "react-dom": "^16.0.0-rc.3",
8 | "react-router-dom": "^4.2.2",
9 | "react-scripts": "1.0.13"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/react/react-router-senators/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/react-router-senators/public/favicon.ico
--------------------------------------------------------------------------------
/react/react-router-senators/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/react-router-senators/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
--------------------------------------------------------------------------------
/react/react-router-senators/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Main from './Main';
3 | import Navbar from './Navbar';
4 | import './App.css';
5 |
6 | const App = ({senators}) => (
7 |
8 |
9 |
12 |
13 | );
14 |
15 | export default App;
16 |
--------------------------------------------------------------------------------
/react/react-router-senators/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/react-router-senators/src/Main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Switch, Route} from 'react-router-dom';
3 | import SenatorList from './SenatorList';
4 | import SenatorDetails from './SenatorDetails';
5 |
6 | const Main = ({senators}) => (
7 |
8 | (
9 |
10 | )}/>
11 | (
12 |
13 | )}/>
14 |
15 | );
16 |
17 | export default Main;
18 |
--------------------------------------------------------------------------------
/react/react-router-senators/src/Navbar.css:
--------------------------------------------------------------------------------
1 | header {
2 | background-color: #2c3e50;
3 | display: flex;
4 | justify-content: space-between;
5 | align-items: center;
6 | color: white;
7 | padding: 0 15px;
8 | }
9 |
10 | header h2 {
11 | margin: 0 15px;
12 | }
13 |
14 | header li {
15 | list-style: none;
16 | }
17 |
18 | header a {
19 | text-decoration: none;
20 | color: inherit;
21 | cursor: pointer;
22 | opacity: 0.9;
23 | }
24 |
25 | header a:hover {
26 | opacity: 1;
27 | }
28 |
29 | @media (max-width: 1000px) {
30 | header{
31 | padding: 20px 50px;
32 | }
33 | }
34 |
35 |
36 | @media (max-width: 700px) {
37 | header{
38 | flex-direction: column;
39 | }
40 |
41 | header h2{
42 | margin-bottom: 15px;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/react/react-router-senators/src/Navbar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {NavLink} from 'react-router-dom';
3 | import './Navbar.css';
4 |
5 | const activeStyle={display: 'none'};
6 |
7 | const Navbar = () => (
8 |
11 | );
12 |
13 | export default Navbar;
14 |
--------------------------------------------------------------------------------
/react/react-router-senators/src/SenatorDetails.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const SenatorDetails = ({senators, match, ...rest}) => {
4 | const senator = senators.find(s => s.person.cspanid === +match.params.cspanid);
5 | if (!senator) {
6 | return (
7 | Sorry, no senator found
8 | );
9 | }
10 |
11 | return (
12 |
13 |
{senator.person.name}
14 |
{senator.description} - {senator.party}
15 |
{senator.website}
16 |
17 | );
18 | };
19 |
20 | export default SenatorDetails;
21 |
--------------------------------------------------------------------------------
/react/react-router-senators/src/SenatorList.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router-dom';
3 |
4 | const SenatorList = (props) => {
5 | const senators = props.senators.map(s => (
6 |
7 | {s.person.name}
8 |
9 | ));
10 | return (
11 |
17 | );
18 | }
19 |
20 | export default SenatorList;
21 |
--------------------------------------------------------------------------------
/react/react-router-senators/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/react/react-router-senators/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import {BrowserRouter as Router} from 'react-router-dom';
4 | import senators from './senators';
5 | import './index.css';
6 | import App from './App';
7 | import registerServiceWorker from './registerServiceWorker';
8 |
9 | ReactDOM.render(
10 |
11 |
12 | ,
13 | document.getElementById('root')
14 | );
15 | registerServiceWorker();
16 |
--------------------------------------------------------------------------------
/react/recipe-props-solution/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/recipe-props-solution/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "recipe-props-starter",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.0.0-rc.3",
7 | "react-dom": "^16.0.0-rc.3",
8 | "react-scripts": "1.0.13"
9 | },
10 | "scripts": {
11 | "start": "react-scripts start",
12 | "build": "react-scripts build",
13 | "test": "react-scripts test --env=jsdom",
14 | "eject": "react-scripts eject"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/react/recipe-props-solution/public/avocado_toast.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-props-solution/public/avocado_toast.jpg
--------------------------------------------------------------------------------
/react/recipe-props-solution/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-props-solution/public/favicon.ico
--------------------------------------------------------------------------------
/react/recipe-props-solution/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/recipe-props-solution/public/milkshake.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-props-solution/public/milkshake.jpg
--------------------------------------------------------------------------------
/react/recipe-props-solution/public/spaghetti.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-props-solution/public/spaghetti.jpg
--------------------------------------------------------------------------------
/react/recipe-props-solution/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/recipe-props-solution/src/Navbar.css:
--------------------------------------------------------------------------------
1 | header {
2 | background-color: #2c3e50;
3 | display: flex;
4 | justify-content: space-between;
5 | align-items: center;
6 | color: white;
7 | padding: 0 15px;
8 | }
9 |
10 | header h1 {
11 | text-align: center;
12 | }
13 |
14 | header li {
15 | list-style: none;
16 | }
17 |
18 | header a {
19 | text-decoration: none;
20 | color: inherit;
21 | cursor: pointer;
22 | opacity: 0.9;
23 | }
24 |
25 | header a:hover {
26 | opacity: 1;
27 | }
28 |
29 | header nav {
30 | display: flex;
31 | }
32 |
33 | header nav li {
34 | margin: 0 15px;
35 | }
36 |
37 | header nav li:first-child {
38 | margin-left: 0;
39 | }
40 |
41 | header nav li:last-child {
42 | margin-right: 0;
43 | }
44 |
45 | @media (max-width: 1000px) {
46 | header{
47 | padding: 20px 50px;
48 | }
49 | }
50 |
51 |
52 | @media (max-width: 700px) {
53 | header{
54 | flex-direction: column;
55 | }
56 |
57 | header h2{
58 | margin-bottom: 15px;
59 | }
60 | }
--------------------------------------------------------------------------------
/react/recipe-props-solution/src/Navbar.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import './Navbar.css';
3 |
4 | class Navbar extends Component {
5 | render() {
6 | return (
7 |
16 | );
17 | }
18 | }
19 |
20 | export default Navbar;
--------------------------------------------------------------------------------
/react/recipe-props-solution/src/Recipe.css:
--------------------------------------------------------------------------------
1 | .recipe-card {
2 | width: 31%;
3 | min-width: 240px;
4 | margin: 1%;
5 | border: 1px solid rgba(160,160,160,0.2);
6 | background: white;
7 | border-radius: 0 0 2px 2px;
8 | box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);
9 | }
10 |
11 |
12 | .recipe-card-content {
13 | padding: 16px;
14 | }
15 |
16 |
17 | .recipe-card-image {
18 | overflow: hidden;
19 | height: 50%;
20 | }
21 |
22 | .recipe-card img {
23 | width: 100%;
24 | max-height: 250px;
25 | }
26 |
27 | .recipe-title {
28 | margin: 0;
29 | }
--------------------------------------------------------------------------------
/react/recipe-props-solution/src/Recipe.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import PropTypes from 'prop-types';
3 | import './Recipe.css';
4 |
5 | class Recipe extends Component {
6 | static propTypes = {
7 | title: PropTypes.string.isRequired,
8 | ingredients: PropTypes.arrayOf(PropTypes.string).isRequired,
9 | instructions: PropTypes.string.isRequired,
10 | img: PropTypes.string.isRequired,
11 | }
12 |
13 | render() {
14 | const {title, img, instructions} = this.props;
15 | const ingredients = this.props.ingredients.map((ing, index) => (
16 | {ing}
17 | ));
18 | return (
19 |
20 |
21 |

22 |
23 |
24 |
{title}
25 |
Ingredients:
26 |
29 |
Instructions:
30 |
{instructions}
31 |
32 |
33 |
34 | );
35 | }
36 | }
37 |
38 | export default Recipe;
--------------------------------------------------------------------------------
/react/recipe-props-solution/src/RecipeApp.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-props-solution/src/RecipeApp.css
--------------------------------------------------------------------------------
/react/recipe-props-solution/src/RecipeApp.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Navbar from './Navbar';
3 | import RecipeList from './RecipeList';
4 | import './RecipeApp.css';
5 |
6 | class RecipeApp extends Component {
7 | render() {
8 | return (
9 |
10 |
11 |
12 |
13 | );
14 | }
15 | }
16 |
17 | export default RecipeApp;
18 |
--------------------------------------------------------------------------------
/react/recipe-props-solution/src/RecipeList.css:
--------------------------------------------------------------------------------
1 | .recipe-list {
2 | display: flex;
3 | flex-direction: row;
4 | flex-wrap: wrap;
5 | }
6 |
7 | @media (max-width: 580px) {
8 | .recipe-list {
9 | display: block;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/react/recipe-props-solution/src/RecipeList.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import Recipe from './Recipe';
3 | import PropTypes from 'prop-types';
4 | import './RecipeList.css';
5 |
6 | class RecipeList extends Component {
7 | static defaultProps = {
8 | recipes: [
9 | {
10 | title: "Spaghetti",
11 | instructions: "Open jar of Spaghetti sauce. Bring to simmer. Boil water. Cook pasta until done. Combine pasta and sauce",
12 | ingredients: ["pasta", "8 cups water", "1 box spaghetti"],
13 | img: "spaghetti.jpg"
14 | },
15 | {
16 | title: "Milkshake",
17 | instructions: "Combine ice cream and milk. Blend until creamy",
18 | ingredients: ["2 Scoops Ice cream", "8 ounces milk"],
19 | img: "milkshake.jpg"
20 | },
21 | {
22 | title: "Avocado Toast",
23 | instructions: "Toast bread. Slice avocado and spread on bread. Add salt, oil, and pepper to taste.",
24 | ingredients: ["2 slices of bread", "1 avocado", "1 tablespoon olive oil", "1 pinch of salt", "pepper"],
25 | img: "avocado_toast.jpg"
26 | }
27 | ]
28 | }
29 |
30 | static propTypes = {
31 | recipes: PropTypes.arrayOf(PropTypes.object).isRequired
32 | }
33 |
34 | render() {
35 | const recipes = this.props.recipes.map((r,index) => (
36 |
37 | ));
38 |
39 | return (
40 |
41 | {recipes}
42 |
43 | )
44 |
45 | }
46 | }
47 |
48 | export default RecipeList;
--------------------------------------------------------------------------------
/react/recipe-props-solution/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: roboto;
5 | background: #ecf0f1;
6 | }
7 |
--------------------------------------------------------------------------------
/react/recipe-props-solution/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import RecipeApp from './RecipeApp';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/recipe-props-starter/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/recipe-props-starter/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "recipe-props-starter",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.0.0-rc.3",
7 | "react-dom": "^16.0.0-rc.3",
8 | "react-scripts": "1.0.13"
9 | },
10 | "scripts": {
11 | "start": "react-scripts start",
12 | "build": "react-scripts build",
13 | "test": "react-scripts test --env=jsdom",
14 | "eject": "react-scripts eject"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/react/recipe-props-starter/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-props-starter/public/favicon.ico
--------------------------------------------------------------------------------
/react/recipe-props-starter/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/recipe-props-starter/public/spaghetti.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-props-starter/public/spaghetti.jpg
--------------------------------------------------------------------------------
/react/recipe-props-starter/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/recipe-props-starter/src/Recipe.css:
--------------------------------------------------------------------------------
1 | .recipe-card {
2 | width: 31%;
3 | min-width: 240px;
4 | margin: 1%;
5 | border: 1px solid rgba(160,160,160,0.2);
6 | background: white;
7 | border-radius: 0 0 2px 2px;
8 | box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);
9 | }
10 |
11 |
12 | .recipe-card-content {
13 | padding: 16px;
14 | }
15 |
16 |
17 | .recipe-card-image {
18 | overflow: hidden;
19 | height: 50%;
20 | }
21 |
22 | .recipe-card img {
23 | width: 100%;
24 | max-height: 250px;
25 | }
26 |
27 | .recipe-title {
28 | margin: 0;
29 | }
--------------------------------------------------------------------------------
/react/recipe-props-starter/src/Recipe.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import './Recipe.css';
3 |
4 | class Recipe extends Component {
5 | render() {
6 | const {title, img, instructions} = this.props;
7 | const ingredients = this.props.ingredients.map((ing, index) => (
8 | {ing}
9 | ));
10 | return (
11 |
12 |
13 |

14 |
15 |
16 |
{title}
17 |
Ingredients:
18 |
21 |
Instructions:
22 |
{instructions}
23 |
24 |
25 |
26 | );
27 | }
28 | }
29 |
30 | export default Recipe;
--------------------------------------------------------------------------------
/react/recipe-props-starter/src/RecipeApp.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-props-starter/src/RecipeApp.css
--------------------------------------------------------------------------------
/react/recipe-props-starter/src/RecipeApp.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Recipe from './Recipe';
3 | import './RecipeApp.css';
4 |
5 | class RecipeApp extends Component {
6 | render() {
7 | return (
8 |
9 |
15 |
16 | );
17 | }
18 | }
19 |
20 | export default RecipeApp;
21 |
--------------------------------------------------------------------------------
/react/recipe-props-starter/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: roboto;
5 | background: #ecf0f1;
6 | }
7 |
--------------------------------------------------------------------------------
/react/recipe-props-starter/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import RecipeApp from './RecipeApp';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "recipe-exercise",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "prop-types": "^15.5.10",
7 | "react": "^16.0.0-rc.3",
8 | "react-dom": "^16.0.0-rc.3",
9 | "react-redux": "^5.0.6",
10 | "react-scripts": "1.0.13",
11 | "redux": "^3.7.2"
12 | },
13 | "scripts": {
14 | "start": "react-scripts start",
15 | "build": "react-scripts build",
16 | "test": "react-scripts test --env=jsdom",
17 | "eject": "react-scripts eject"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/public/avocado_toast.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-redux-single-folder/public/avocado_toast.jpg
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-redux-single-folder/public/favicon.ico
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/public/milkshake.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-redux-single-folder/public/milkshake.jpg
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/public/spaghetti.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-redux-single-folder/public/spaghetti.jpg
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/src/Navbar.css:
--------------------------------------------------------------------------------
1 | header {
2 | background-color: #2c3e50;
3 | display: flex;
4 | justify-content: space-between;
5 | align-items: center;
6 | color: white;
7 | padding: 0 15px;
8 | }
9 |
10 | header h1 {
11 | text-align: center;
12 | }
13 |
14 | header li {
15 | list-style: none;
16 | }
17 |
18 | header a {
19 | text-decoration: none;
20 | color: inherit;
21 | cursor: pointer;
22 | opacity: 0.9;
23 | }
24 |
25 | header a:hover {
26 | opacity: 1;
27 | }
28 |
29 | header nav {
30 | display: flex;
31 | }
32 |
33 | header nav li {
34 | margin: 0 15px;
35 | }
36 |
37 | header nav li:first-child {
38 | margin-left: 0;
39 | }
40 |
41 | header nav li:last-child {
42 | margin-right: 0;
43 | }
44 |
45 | @media (max-width: 1000px) {
46 | header{
47 | padding: 20px 50px;
48 | }
49 | }
50 |
51 |
52 | @media (max-width: 700px) {
53 | header{
54 | flex-direction: column;
55 | }
56 |
57 | header h2{
58 | margin-bottom: 15px;
59 | }
60 | }
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/src/Navbar.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import PropTypes from 'prop-types';
3 | import './Navbar.css';
4 |
5 | class Navbar extends Component {
6 | static defaultProps = {
7 | onNewRecipe() {}
8 | }
9 |
10 | static propTypes = {
11 | onNewRecipe: PropTypes.func
12 | }
13 |
14 | render() {
15 | return (
16 |
25 | );
26 | }
27 | }
28 |
29 | export default Navbar;
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/src/Recipe.css:
--------------------------------------------------------------------------------
1 | .recipe-card {
2 | width: 31%;
3 | min-width: 240px;
4 | margin: 1%;
5 | border: 1px solid rgba(160,160,160,0.2);
6 | background: white;
7 | border-radius: 0 0 2px 2px;
8 | box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);
9 | }
10 |
11 |
12 | .recipe-card-content {
13 | padding: 16px;
14 | }
15 |
16 |
17 | .recipe-card-image {
18 | overflow: hidden;
19 | height: 50%;
20 | }
21 |
22 | .recipe-card img {
23 | width: 100%;
24 | max-height: 250px;
25 | }
26 |
27 | .recipe-title {
28 | margin: 0;
29 | }
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/src/Recipe.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import PropTypes from 'prop-types';
3 | import './Recipe.css';
4 |
5 | class Recipe extends Component {
6 | static propTypes = {
7 | title: PropTypes.string.isRequired,
8 | ingredients: PropTypes.arrayOf(PropTypes.string).isRequired,
9 | instructions: PropTypes.string.isRequired,
10 | img: PropTypes.string.isRequired,
11 | id: PropTypes.number.isRequired,
12 | onDelete: PropTypes.func.isRequired
13 | }
14 |
15 | render() {
16 | const {title, img, instructions, id, onDelete} = this.props;
17 | const ingredients = this.props.ingredients.map((ing, index) => (
18 | {ing}
19 | ));
20 | return (
21 |
22 |
23 |

24 |
25 |
26 |
{title}
27 |
Ingredients:
28 |
31 |
Instructions:
32 |
{instructions}
33 |
34 |
35 |
36 | );
37 | }
38 | }
39 |
40 | export default Recipe;
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/src/RecipeApp.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-redux-single-folder/src/RecipeApp.css
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/src/RecipeApp.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import {connect} from 'react-redux';
3 | import Navbar from './Navbar';
4 | import RecipeInput from './RecipeInput';
5 | import RecipeList from './RecipeList';
6 | import './RecipeApp.css';
7 |
8 | const RecipeApp = ({
9 | shouldShowForm,
10 | recipes,
11 | saveRecipe,
12 | deleteRecipe,
13 | showForm,
14 | hideForm
15 | }) => (
16 |
17 |
18 | { shouldShowForm ?
19 | :
23 | null }
24 |
25 |
26 | );
27 |
28 | const mapStateToProps = state => ({
29 | recipes: state.recipes,
30 | shouldShowForm: state.shouldShowForm
31 | });
32 |
33 | const mapDispatchToProps = dispatch => ({
34 | saveRecipe(recipe) {
35 | dispatch({
36 | type: "SAVE_RECIPE",
37 | recipe
38 | })
39 | },
40 | deleteRecipe(recipeId) {
41 | dispatch({
42 | type: "DELETE_RECIPE",
43 | recipeId
44 | })
45 | },
46 | showForm() {
47 | dispatch({
48 | type: "SHOW_FORM"
49 | })
50 | },
51 | hideForm() {
52 | dispatch({
53 | type: "HIDE_FORM"
54 | })
55 | }
56 | });
57 |
58 | export default connect(mapStateToProps, mapDispatchToProps)(RecipeApp);
59 |
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/src/RecipeInput.css:
--------------------------------------------------------------------------------
1 | .recipe-form {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: flex-start;
5 | justify-content: center;
6 | margin: 10px;
7 | padding: 15px;
8 | border-radius: 10px;
9 | border: 7px solid #2c3e50;
10 | }
11 |
12 | .recipe-form input[type=text] {
13 | padding: 5px 8px;
14 | box-sizing: border-box;
15 | }
16 |
17 | .recipe-form-line {
18 | display: flex;
19 | flex-direction: row;
20 | align-items: center;
21 | justify-content: flex-start;
22 | margin-top: 5px;
23 | }
24 |
25 | .recipe-form-line input {
26 | margin-left: 15px;
27 | }
28 |
29 | .buttons {
30 | color: white;
31 | background-color: #2c3e50;
32 | border-radius: 6px;
33 | padding: 0 10px 1px 10px;
34 | margin: 8px 0;
35 | align-self: flex-end;
36 | font-size: 1.1em;
37 | }
38 |
39 | .close-button {
40 | background-color: transparent;
41 | background-repeat: no-repeat;
42 | border: none;
43 | cursor: pointer;
44 | overflow: hidden;
45 | font-size: 0.9em;
46 | color: #777;
47 | text-shadow: 0 1px 0 #fff;
48 | align-self: flex-end;
49 | }
50 |
51 | .recipe-form-container {
52 | display: flex;
53 | align-items: center;
54 | justify-content: center;
55 | }
56 |
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/src/RecipeList.css:
--------------------------------------------------------------------------------
1 | .recipe-list {
2 | display: flex;
3 | flex-direction: row;
4 | flex-wrap: wrap;
5 | }
6 |
7 | @media (max-width: 580px) {
8 | .recipe-list {
9 | display: block;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/src/RecipeList.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import Recipe from './Recipe';
3 | import PropTypes from 'prop-types';
4 | import './RecipeList.css';
5 |
6 | class RecipeList extends Component {
7 | static propTypes = {
8 | recipes: PropTypes.arrayOf(PropTypes.object).isRequired,
9 | onDelete: PropTypes.func.isRequired
10 | }
11 |
12 | render() {
13 | const {onDelete} = this.props;
14 | const recipes = this.props.recipes.map((r,index) => (
15 |
16 | ));
17 |
18 | return (
19 |
20 | {recipes}
21 |
22 | )
23 |
24 | }
25 | }
26 |
27 | export default RecipeList;
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/src/images/spaghetti.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-redux-single-folder/src/images/spaghetti.jpg
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: roboto;
5 | background: #ecf0f1;
6 | }
7 |
--------------------------------------------------------------------------------
/react/recipe-redux-single-folder/src/reducers.js:
--------------------------------------------------------------------------------
1 | export default (state={}, action) => {
2 | switch(action.type) {
3 | case "SAVE_RECIPE":
4 | const newRecipe = {id: state.nextRecipeId, ...action.recipe};
5 | return {
6 | ...state,
7 | nextRecipeId: state.nextRecipeId + 1,
8 | shouldShowForm: false,
9 | recipes: [...state.recipes, newRecipe]
10 | };
11 | case "DELETE_RECIPE":
12 | const recipes = state.recipes.filter(r => r.id !== action.recipeId);
13 | return {...state, recipes};
14 | case "SHOW_FORM":
15 | return {...state, shouldShowForm: true};
16 | case "HIDE_FORM":
17 | return {...state, shouldShowForm: false};
18 | default:
19 | return state;
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/react/recipe-with-state/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/recipe-with-state/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "recipe-props-starter",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "prop-types": "^15.5.10",
7 | "react": "^16.0.0-rc.3",
8 | "react-dom": "^16.0.0-rc.3",
9 | "react-scripts": "1.0.13"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/react/recipe-with-state/public/avocado_toast.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-with-state/public/avocado_toast.jpg
--------------------------------------------------------------------------------
/react/recipe-with-state/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-with-state/public/favicon.ico
--------------------------------------------------------------------------------
/react/recipe-with-state/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/recipe-with-state/public/milkshake.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-with-state/public/milkshake.jpg
--------------------------------------------------------------------------------
/react/recipe-with-state/public/spaghetti.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-with-state/public/spaghetti.jpg
--------------------------------------------------------------------------------
/react/recipe-with-state/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/recipe-with-state/src/Navbar.css:
--------------------------------------------------------------------------------
1 | header {
2 | background-color: #2c3e50;
3 | display: flex;
4 | justify-content: space-between;
5 | align-items: center;
6 | color: white;
7 | padding: 0 15px;
8 | }
9 |
10 | header h1 {
11 | text-align: center;
12 | }
13 |
14 | header li {
15 | list-style: none;
16 | }
17 |
18 | header a {
19 | text-decoration: none;
20 | color: inherit;
21 | cursor: pointer;
22 | opacity: 0.9;
23 | }
24 |
25 | header a:hover {
26 | opacity: 1;
27 | }
28 |
29 | header nav {
30 | display: flex;
31 | }
32 |
33 | header nav li {
34 | margin: 0 15px;
35 | }
36 |
37 | header nav li:first-child {
38 | margin-left: 0;
39 | }
40 |
41 | header nav li:last-child {
42 | margin-right: 0;
43 | }
44 |
45 | @media (max-width: 1000px) {
46 | header{
47 | padding: 20px 50px;
48 | }
49 | }
50 |
51 |
52 | @media (max-width: 700px) {
53 | header{
54 | flex-direction: column;
55 | }
56 |
57 | header h2{
58 | margin-bottom: 15px;
59 | }
60 | }
--------------------------------------------------------------------------------
/react/recipe-with-state/src/Navbar.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import PropTypes from 'prop-types';
3 | import './Navbar.css';
4 |
5 | class Navbar extends Component {
6 | static defaultProps = {
7 | onNewRecipe() {}
8 | }
9 |
10 | static propTypes = {
11 | onNewRecipe: PropTypes.func
12 | }
13 |
14 | render() {
15 | return (
16 |
25 | );
26 | }
27 | }
28 |
29 | export default Navbar;
--------------------------------------------------------------------------------
/react/recipe-with-state/src/Recipe.css:
--------------------------------------------------------------------------------
1 | .recipe-card {
2 | width: 31%;
3 | min-width: 240px;
4 | margin: 1%;
5 | border: 1px solid rgba(160,160,160,0.2);
6 | background: white;
7 | border-radius: 0 0 2px 2px;
8 | box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 1px 5px 0 rgba(0,0,0,0.12), 0 3px 1px -2px rgba(0,0,0,0.2);
9 | }
10 |
11 |
12 | .recipe-card-content {
13 | padding: 16px;
14 | }
15 |
16 |
17 | .recipe-card-image {
18 | overflow: hidden;
19 | height: 50%;
20 | }
21 |
22 | .recipe-card img {
23 | width: 100%;
24 | max-height: 250px;
25 | }
26 |
27 | .recipe-title {
28 | margin: 0;
29 | }
--------------------------------------------------------------------------------
/react/recipe-with-state/src/Recipe.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import PropTypes from 'prop-types';
3 | import './Recipe.css';
4 |
5 | class Recipe extends Component {
6 | static propTypes = {
7 | title: PropTypes.string.isRequired,
8 | ingredients: PropTypes.arrayOf(PropTypes.string).isRequired,
9 | instructions: PropTypes.string.isRequired,
10 | img: PropTypes.string.isRequired,
11 | id: PropTypes.number.isRequired,
12 | onDelete: PropTypes.func.isRequired
13 | }
14 |
15 | render() {
16 | const {title, img, instructions, id, onDelete} = this.props;
17 | const ingredients = this.props.ingredients.map((ing, index) => (
18 | {ing}
19 | ));
20 | return (
21 |
22 |
23 |

24 |
25 |
26 |
{title}
27 |
Ingredients:
28 |
31 |
Instructions:
32 |
{instructions}
33 |
34 |
35 |
36 | );
37 | }
38 | }
39 |
40 | export default Recipe;
--------------------------------------------------------------------------------
/react/recipe-with-state/src/RecipeApp.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/recipe-with-state/src/RecipeApp.css
--------------------------------------------------------------------------------
/react/recipe-with-state/src/RecipeInput.css:
--------------------------------------------------------------------------------
1 | .recipe-form {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: flex-start;
5 | justify-content: center;
6 | margin: 10px;
7 | padding: 15px;
8 | border-radius: 10px;
9 | border: 7px solid #2c3e50;
10 | }
11 |
12 | .recipe-form input[type=text] {
13 | padding: 5px 8px;
14 | box-sizing: border-box;
15 | }
16 |
17 | .recipe-form-line {
18 | display: flex;
19 | flex-direction: row;
20 | align-items: center;
21 | justify-content: flex-start;
22 | margin-top: 5px;
23 | }
24 |
25 | .recipe-form-line input {
26 | margin-left: 15px;
27 | }
28 |
29 | .buttons {
30 | color: white;
31 | background-color: #2c3e50;
32 | border-radius: 6px;
33 | padding: 0 10px 1px 10px;
34 | margin: 8px 0;
35 | align-self: flex-end;
36 | font-size: 1.1em;
37 | }
38 |
39 | .close-button {
40 | background-color: transparent;
41 | background-repeat: no-repeat;
42 | border: none;
43 | cursor: pointer;
44 | overflow: hidden;
45 | font-size: 0.9em;
46 | color: #777;
47 | text-shadow: 0 1px 0 #fff;
48 | align-self: flex-end;
49 | }
50 |
51 | .recipe-form-container {
52 | display: flex;
53 | align-items: center;
54 | justify-content: center;
55 | }
56 |
--------------------------------------------------------------------------------
/react/recipe-with-state/src/RecipeList.css:
--------------------------------------------------------------------------------
1 | .recipe-list {
2 | display: flex;
3 | flex-direction: row;
4 | flex-wrap: wrap;
5 | }
6 |
7 | @media (max-width: 580px) {
8 | .recipe-list {
9 | display: block;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/react/recipe-with-state/src/RecipeList.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import Recipe from './Recipe';
3 | import PropTypes from 'prop-types';
4 | import './RecipeList.css';
5 |
6 | class RecipeList extends Component {
7 | static propTypes = {
8 | recipes: PropTypes.arrayOf(PropTypes.object).isRequired,
9 | onDelete: PropTypes.func.isRequired
10 | }
11 |
12 | render() {
13 | const {onDelete} = this.props;
14 | const recipes = this.props.recipes.map((r,index) => (
15 |
16 | ));
17 |
18 | return (
19 |
20 | {recipes}
21 |
22 | )
23 |
24 | }
25 | }
26 |
27 | export default RecipeList;
--------------------------------------------------------------------------------
/react/recipe-with-state/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: roboto;
5 | background: #ecf0f1;
6 | }
7 |
--------------------------------------------------------------------------------
/react/recipe-with-state/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import RecipeApp from './RecipeApp';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/redux-async/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 |
6 | # production
7 | build
8 |
9 | # misc
10 | .DS_Store
11 | npm-debug.log
12 |
--------------------------------------------------------------------------------
/react/redux-async/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "async",
3 | "version": "0.0.1",
4 | "private": true,
5 | "devDependencies": {
6 | "react-scripts": "^1.0.2",
7 | "redux-logger": "^3.0.6"
8 | },
9 | "dependencies": {
10 | "prop-types": "^15.5.10",
11 | "react": "^15.5.0",
12 | "react-dom": "^15.5.0",
13 | "react-redux": "^5.0.5",
14 | "redux": "^3.5.2",
15 | "redux-thunk": "^2.1.0"
16 | },
17 | "scripts": {
18 | "start": "react-scripts start",
19 | "build": "react-scripts build",
20 | "eject": "react-scripts eject",
21 | "test": "react-scripts test"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/react/redux-async/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Redux Async Example
7 |
8 |
9 |
10 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/react/redux-async/src/actions/index.js:
--------------------------------------------------------------------------------
1 | export const REQUEST_POSTS = 'REQUEST_POSTS'
2 | export const RECEIVE_POSTS = 'RECEIVE_POSTS'
3 | export const SELECT_REDDIT = 'SELECT_REDDIT'
4 | export const INVALIDATE_REDDIT = 'INVALIDATE_REDDIT'
5 |
6 | export const selectReddit = reddit => ({
7 | type: SELECT_REDDIT,
8 | reddit
9 | })
10 |
11 | export const invalidateReddit = reddit => ({
12 | type: INVALIDATE_REDDIT,
13 | reddit
14 | })
15 |
16 | export const requestPosts = reddit => ({
17 | type: REQUEST_POSTS,
18 | reddit
19 | })
20 |
21 | export const receivePosts = (reddit, json) => ({
22 | type: RECEIVE_POSTS,
23 | reddit,
24 | posts: json.data.children.map(child => child.data),
25 | receivedAt: Date.now()
26 | })
27 |
28 | const fetchPosts = reddit => dispatch => {
29 | dispatch(requestPosts(reddit))
30 | return fetch(`https://www.reddit.com/r/${reddit}.json`)
31 | .then(response => response.json())
32 | .then(json => dispatch(receivePosts(reddit, json)))
33 | }
34 |
35 | const shouldFetchPosts = (state, reddit) => {
36 | const posts = state.postsByReddit[reddit]
37 | if (!posts) {
38 | return true
39 | }
40 | if (posts.isFetching) {
41 | return false
42 | }
43 | return posts.didInvalidate
44 | }
45 |
46 | export const fetchPostsIfNeeded = reddit => (dispatch, getState) => {
47 | if (shouldFetchPosts(getState(), reddit)) {
48 | return dispatch(fetchPosts(reddit))
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/react/redux-async/src/components/Picker.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | const Picker = ({ value, onChange, options }) => (
5 |
6 | {value}
7 |
15 |
16 | )
17 |
18 | Picker.propTypes = {
19 | options: PropTypes.arrayOf(
20 | PropTypes.string.isRequired
21 | ).isRequired,
22 | value: PropTypes.string.isRequired,
23 | onChange: PropTypes.func.isRequired
24 | }
25 |
26 | export default Picker
27 |
--------------------------------------------------------------------------------
/react/redux-async/src/components/Posts.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | const Posts = ({posts}) => (
5 |
6 | {posts.map((post, i) =>
7 | - {post.title}
8 | )}
9 |
10 | )
11 |
12 | Posts.propTypes = {
13 | posts: PropTypes.array.isRequired
14 | }
15 |
16 | export default Posts
17 |
--------------------------------------------------------------------------------
/react/redux-async/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render } from 'react-dom'
3 | import { createStore, applyMiddleware } from 'redux'
4 | import { Provider } from 'react-redux'
5 | import thunk from 'redux-thunk'
6 | import { createLogger } from 'redux-logger'
7 | import reducer from './reducers'
8 | import App from './containers/App'
9 |
10 | const middleware = [ thunk ]
11 | if (process.env.NODE_ENV !== 'production') {
12 | middleware.push(createLogger())
13 | }
14 |
15 | const store = createStore(
16 | reducer,
17 | applyMiddleware(...middleware)
18 | )
19 |
20 | render(
21 |
22 |
23 | ,
24 | document.getElementById('root')
25 | )
26 |
--------------------------------------------------------------------------------
/react/redux-todos/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 |
6 | # production
7 | build
8 |
9 | # misc
10 | .DS_Store
11 | npm-debug.log
12 |
--------------------------------------------------------------------------------
/react/redux-todos/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "todos",
3 | "version": "0.0.1",
4 | "private": true,
5 | "devDependencies": {
6 | "enzyme": "^2.8.2",
7 | "react-addons-test-utils": "^15.5.1",
8 | "react-scripts": "^1.0.2"
9 | },
10 | "dependencies": {
11 | "prop-types": "^15.5.10",
12 | "react": "^15.5.0",
13 | "react-dom": "^15.5.0",
14 | "react-redux": "^5.0.5",
15 | "redux": "^3.5.2"
16 | },
17 | "scripts": {
18 | "start": "react-scripts start",
19 | "build": "react-scripts build",
20 | "eject": "react-scripts eject",
21 | "test": "react-scripts test"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/react/redux-todos/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Redux Todos Example
7 |
8 |
9 |
10 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/react/redux-todos/src/actions/index.js:
--------------------------------------------------------------------------------
1 | let nextTodoId = 0
2 | export const addTodo = (text) => ({
3 | type: 'ADD_TODO',
4 | id: nextTodoId++,
5 | text
6 | })
7 |
8 | export const setVisibilityFilter = (filter) => ({
9 | type: 'SET_VISIBILITY_FILTER',
10 | filter
11 | })
12 |
13 | export const toggleTodo = (id) => ({
14 | type: 'TOGGLE_TODO',
15 | id
16 | })
17 |
--------------------------------------------------------------------------------
/react/redux-todos/src/actions/index.spec.js:
--------------------------------------------------------------------------------
1 | import * as actions from './index'
2 |
3 | describe('todo actions', () => {
4 | it('addTodo should create ADD_TODO action', () => {
5 | expect(actions.addTodo('Use Redux')).toEqual({
6 | type: 'ADD_TODO',
7 | id: 0,
8 | text: 'Use Redux'
9 | })
10 | })
11 |
12 | it('setVisibilityFilter should create SET_VISIBILITY_FILTER action', () => {
13 | expect(actions.setVisibilityFilter('active')).toEqual({
14 | type: 'SET_VISIBILITY_FILTER',
15 | filter: 'active'
16 | })
17 | })
18 |
19 | it('toggleTodo should create TOGGLE_TODO action', () => {
20 | expect(actions.toggleTodo(1)).toEqual({
21 | type: 'TOGGLE_TODO',
22 | id: 1
23 | })
24 | })
25 | })
26 |
--------------------------------------------------------------------------------
/react/redux-todos/src/components/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Footer from './Footer'
3 | import AddTodo from '../containers/AddTodo'
4 | import VisibleTodoList from '../containers/VisibleTodoList'
5 |
6 | const App = () => (
7 |
12 | )
13 |
14 | export default App
15 |
--------------------------------------------------------------------------------
/react/redux-todos/src/components/Footer.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import FilterLink from '../containers/FilterLink'
3 |
4 | const Footer = () => (
5 |
6 | Show:
7 | {" "}
8 |
9 | All
10 |
11 | {", "}
12 |
13 | Active
14 |
15 | {", "}
16 |
17 | Completed
18 |
19 |
20 | )
21 |
22 | export default Footer
23 |
--------------------------------------------------------------------------------
/react/redux-todos/src/components/Link.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | const Link = ({ active, children, onClick }) => {
5 | if (active) {
6 | return {children}
7 | }
8 |
9 | return (
10 | // eslint-disable-next-line
11 | {
13 | e.preventDefault()
14 | onClick()
15 | }}
16 | >
17 | {children}
18 |
19 | )
20 | }
21 |
22 | Link.propTypes = {
23 | active: PropTypes.bool.isRequired,
24 | children: PropTypes.node.isRequired,
25 | onClick: PropTypes.func.isRequired
26 | }
27 |
28 | export default Link
29 |
--------------------------------------------------------------------------------
/react/redux-todos/src/components/Todo.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | const Todo = ({ onClick, completed, text }) => (
5 |
11 | {text}
12 |
13 | )
14 |
15 | Todo.propTypes = {
16 | onClick: PropTypes.func.isRequired,
17 | completed: PropTypes.bool.isRequired,
18 | text: PropTypes.string.isRequired
19 | }
20 |
21 | export default Todo
22 |
--------------------------------------------------------------------------------
/react/redux-todos/src/components/TodoList.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import Todo from './Todo'
4 |
5 | const TodoList = ({ todos, onTodoClick }) => (
6 |
7 | {todos.map(todo =>
8 | onTodoClick(todo.id)}
12 | />
13 | )}
14 |
15 | )
16 |
17 | TodoList.propTypes = {
18 | todos: PropTypes.arrayOf(PropTypes.shape({
19 | id: PropTypes.number.isRequired,
20 | completed: PropTypes.bool.isRequired,
21 | text: PropTypes.string.isRequired
22 | }).isRequired).isRequired,
23 | onTodoClick: PropTypes.func.isRequired
24 | }
25 |
26 | export default TodoList
27 |
--------------------------------------------------------------------------------
/react/redux-todos/src/containers/AddTodo.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { connect } from 'react-redux'
3 | import { addTodo } from '../actions'
4 |
5 | let AddTodo = ({ dispatch }) => {
6 | let input
7 |
8 | return (
9 |
10 |
25 |
26 | )
27 | }
28 | AddTodo = connect()(AddTodo)
29 |
30 | export default AddTodo
31 |
--------------------------------------------------------------------------------
/react/redux-todos/src/containers/FilterLink.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { setVisibilityFilter } from '../actions'
3 | import Link from '../components/Link'
4 |
5 | const mapStateToProps = (state, ownProps) => ({
6 | active: ownProps.filter === state.visibilityFilter
7 | })
8 |
9 | const mapDispatchToProps = (dispatch, ownProps) => ({
10 | onClick: () => {
11 | dispatch(setVisibilityFilter(ownProps.filter))
12 | }
13 | })
14 |
15 | const FilterLink = connect(
16 | mapStateToProps,
17 | mapDispatchToProps
18 | )(Link)
19 |
20 | export default FilterLink
21 |
--------------------------------------------------------------------------------
/react/redux-todos/src/containers/VisibleTodoList.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { toggleTodo } from '../actions'
3 | import TodoList from '../components/TodoList'
4 |
5 | const getVisibleTodos = (todos, filter) => {
6 | switch (filter) {
7 | case 'SHOW_ALL':
8 | return todos
9 | case 'SHOW_COMPLETED':
10 | return todos.filter(t => t.completed)
11 | case 'SHOW_ACTIVE':
12 | return todos.filter(t => !t.completed)
13 | default:
14 | throw new Error('Unknown filter: ' + filter)
15 | }
16 | }
17 |
18 | const mapStateToProps = (state) => ({
19 | todos: getVisibleTodos(state.todos, state.visibilityFilter)
20 | })
21 |
22 | const mapDispatchToProps = {
23 | onTodoClick: toggleTodo
24 | }
25 |
26 | const VisibleTodoList = connect(
27 | mapStateToProps,
28 | mapDispatchToProps
29 | )(TodoList)
30 |
31 | export default VisibleTodoList
32 |
--------------------------------------------------------------------------------
/react/redux-todos/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render } from 'react-dom'
3 | import { createStore } from 'redux'
4 | import { Provider } from 'react-redux'
5 | import App from './components/App'
6 | import reducer from './reducers'
7 |
8 | const store = createStore(reducer)
9 |
10 | render(
11 |
12 |
13 | ,
14 | document.getElementById('root')
15 | )
16 |
--------------------------------------------------------------------------------
/react/redux-todos/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux'
2 | import todos from './todos'
3 | import visibilityFilter from './visibilityFilter'
4 |
5 | const todoApp = combineReducers({
6 | todos,
7 | visibilityFilter
8 | })
9 |
10 | export default todoApp
11 |
--------------------------------------------------------------------------------
/react/redux-todos/src/reducers/todos.js:
--------------------------------------------------------------------------------
1 | const todos = (state = [], action) => {
2 | switch (action.type) {
3 | case 'ADD_TODO':
4 | return [
5 | ...state,
6 | {
7 | id: action.id,
8 | text: action.text,
9 | completed: false
10 | }
11 | ]
12 | case 'TOGGLE_TODO':
13 | return state.map(todo =>
14 | (todo.id === action.id)
15 | ? {...todo, completed: !todo.completed}
16 | : todo
17 | )
18 | default:
19 | return state
20 | }
21 | }
22 |
23 | export default todos
24 |
--------------------------------------------------------------------------------
/react/redux-todos/src/reducers/visibilityFilter.js:
--------------------------------------------------------------------------------
1 | const visibilityFilter = (state = 'SHOW_ALL', action) => {
2 | switch (action.type) {
3 | case 'SET_VISIBILITY_FILTER':
4 | return action.filter
5 | default:
6 | return state
7 | }
8 | }
9 |
10 | export default visibilityFilter
11 |
--------------------------------------------------------------------------------
/react/routing-demo/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/routing-demo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "routing-demo",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.0.0-rc.3",
7 | "react-dom": "^16.0.0-rc.3",
8 | "react-router-dom": "^4.2.2",
9 | "react-scripts": "1.0.13"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/react/routing-demo/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/routing-demo/public/favicon.ico
--------------------------------------------------------------------------------
/react/routing-demo/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/routing-demo/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | animation: App-logo-spin infinite 20s linear;
7 | height: 80px;
8 | }
9 |
10 | .App-header {
11 | background-color: #222;
12 | height: 150px;
13 | padding: 20px;
14 | color: white;
15 | }
16 |
17 | .App-intro {
18 | font-size: large;
19 | }
20 |
21 | @keyframes App-logo-spin {
22 | from { transform: rotate(0deg); }
23 | to { transform: rotate(360deg); }
24 | }
25 |
--------------------------------------------------------------------------------
/react/routing-demo/src/App.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {NavLink} from 'react-router-dom';
3 | import './App.css';
4 | import SwitchDemo from './SwitchDemo';
5 |
6 | class App extends Component {
7 | render() {
8 | const active = {textDecoration: 'none', cursor: 'default', color: 'grey'};
9 | const defaultStyle = {
10 | margin: '5px'
11 | }
12 | return (
13 |
14 |
15 | HOME
16 |
17 |
18 | ABOUT
19 |
20 |
21 |
22 |
23 |
24 | );
25 | }
26 | }
27 |
28 | export default App;
29 |
--------------------------------------------------------------------------------
/react/routing-demo/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/routing-demo/src/SwitchDemo.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Switch, Route} from 'react-router-dom';
3 |
4 | const Homepage = () => (
5 | HOMEPAGE
6 | );
7 | const About = () => (
8 | ABOUT
9 | );
10 |
11 | const SwitchDemo = () => (
12 |
13 |
14 |
15 |
16 | );
17 |
18 | export default SwitchDemo;
19 |
--------------------------------------------------------------------------------
/react/routing-demo/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/react/routing-demo/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import {BrowserRouter as Router} from 'react-router-dom';
4 | import './index.css';
5 | import App from './App';
6 | import registerServiceWorker from './registerServiceWorker';
7 |
8 | ReactDOM.render(
9 |
10 |
11 | ,
12 | document.getElementById('root')
13 | );
14 | registerServiceWorker();
15 |
--------------------------------------------------------------------------------
/react/simple-todo/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/simple-todo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "simple-todo",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^15.6.1",
7 | "react-dom": "^15.6.1",
8 | "react-scripts": "1.0.13"
9 | },
10 | "scripts": {
11 | "start": "react-scripts start",
12 | "build": "react-scripts build",
13 | "test": "react-scripts test --env=jsdom",
14 | "eject": "react-scripts eject"
15 | }
16 | }
--------------------------------------------------------------------------------
/react/simple-todo/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/simple-todo/public/favicon.ico
--------------------------------------------------------------------------------
/react/simple-todo/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/simple-todo/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | display: flex;
3 | flex-direction: column;
4 | justify-content: center;
5 | align-items: center;
6 | }
7 |
8 | .App ol li {
9 | font-size: 1.2em;
10 | margin: 10px;
11 | }
12 |
13 | .todo-input {
14 | padding: 2px;
15 | min-width: 250px;
16 | min-height: 25px;
17 | font-size: 1.2em;
18 | margin: 10px;
19 | }
20 |
21 | .save-button {
22 | font-size: 1.2em;
23 | }
24 |
25 | .todo-content {
26 | width: 50%;
27 | }
28 |
29 | @media (max-width: 700px) {
30 | .todo-content {
31 | width: 95%;
32 | }
33 | }
--------------------------------------------------------------------------------
/react/simple-todo/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import './App.css';
3 |
4 | const TodoItem = ({text}) => (
5 | {text}
6 | );
7 |
8 | class App extends Component {
9 | constructor(props) {
10 | super(props);
11 | this.state = {
12 | todos: [],
13 | newTodo: ''
14 | };
15 | this.handleSubmit = this.handleSubmit.bind(this);
16 | }
17 | handleSubmit(e) {
18 | e.preventDefault();
19 | const todos = [...this.state.todos, this.state.newTodo];
20 | this.setState({todos, newTodo: ''});
21 | }
22 | render() {
23 | const {newTodo} = this.state;
24 | const todos = this.state.todos.map((t, i) => (
25 |
26 | ));
27 | return (
28 |
29 |
Simple Todo App
30 |
47 |
48 |
49 | {todos}
50 |
51 |
52 |
53 | );
54 | }
55 | }
56 |
57 | export default App;
58 |
--------------------------------------------------------------------------------
/react/simple-todo/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/simple-todo/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/react/simple-todo/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/update-complex-state-solution/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/update-complex-state-solution/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "update-complex-state",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^15.6.1",
7 | "react-dom": "^15.6.1",
8 | "react-scripts": "1.0.13"
9 | },
10 | "scripts": {
11 | "start": "react-scripts start",
12 | "build": "react-scripts build",
13 | "test": "react-scripts test --env=jsdom",
14 | "eject": "react-scripts eject"
15 | }
16 | }
--------------------------------------------------------------------------------
/react/update-complex-state-solution/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/update-complex-state-solution/public/favicon.ico
--------------------------------------------------------------------------------
/react/update-complex-state-solution/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/update-complex-state-solution/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | padding: 20px;
3 | text-align: center;
4 | }
5 |
6 | .App ul {
7 | display: flex;
8 | justify-content: space-between;
9 | }
10 |
11 | .App li {
12 | list-style: none;
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/react/update-complex-state-solution/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/update-complex-state-solution/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | background: #ecf0f1;
6 | }
7 |
--------------------------------------------------------------------------------
/react/update-complex-state-solution/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/update-complex-state/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/update-complex-state/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "update-complex-state",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^15.6.1",
7 | "react-dom": "^15.6.1",
8 | "react-scripts": "1.0.13"
9 | },
10 | "scripts": {
11 | "start": "react-scripts start",
12 | "build": "react-scripts build",
13 | "test": "react-scripts test --env=jsdom",
14 | "eject": "react-scripts eject"
15 | }
16 | }
--------------------------------------------------------------------------------
/react/update-complex-state/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/update-complex-state/public/favicon.ico
--------------------------------------------------------------------------------
/react/update-complex-state/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/update-complex-state/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | padding: 20px;
3 | text-align: center;
4 | }
5 |
6 | .App ul {
7 | display: flex;
8 | justify-content: space-between;
9 | }
10 |
11 | .App li {
12 | list-style: none;
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/react/update-complex-state/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import './App.css';
3 |
4 | class App extends Component {
5 | constructor(props) {
6 | super(props);
7 | this.state = {
8 | instructors: [
9 | {
10 | name: 'Tim',
11 | hobbies: ['sailing', 'react']
12 | }, {
13 | name: 'Matt',
14 | hobbies: ['math', 'd3']
15 | }, {
16 | name: 'Colt',
17 | hobbies: ['css', 'hiking']
18 | }, {
19 | name: 'Elie',
20 | hobbies: ['music', 'es2015']
21 | }
22 | ]
23 | };
24 | }
25 | render() {
26 | const instructors = this.state.instructors.map((instructor, index) => (
27 |
28 | {instructor.name}
29 | Hobbies: {instructor.hobbies.join(", ")}
30 |
31 | ));
32 | return (
33 |
38 | );
39 | }
40 | }
41 |
42 | export default App;
43 |
--------------------------------------------------------------------------------
/react/update-complex-state/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/update-complex-state/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | background: #ecf0f1;
6 | }
7 |
--------------------------------------------------------------------------------
/react/update-complex-state/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/warbler-solution/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "warbler-client",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "moment": "^2.18.1",
7 | "react": "^16.0.0-rc.3",
8 | "react-dom": "^16.0.0-rc.3",
9 | "react-moment": "^0.6.5",
10 | "react-redux": "^5.0.6",
11 | "react-router-dom": "^4.2.2",
12 | "react-scripts": "1.0.13",
13 | "redux": "^3.7.2",
14 | "redux-logger": "^3.0.6",
15 | "redux-thunk": "^2.2.0"
16 | },
17 | "proxy": "http://localhost:8081",
18 | "scripts": {
19 | "start": "react-scripts start",
20 | "build": "react-scripts build",
21 | "test": "react-scripts test --env=jsdom",
22 | "eject": "react-scripts eject"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/warbler-solution/warbler-client/public/favicon.ico
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/components/AuthForm.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/warbler-solution/warbler-client/src/components/AuthForm.css
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/components/Homepage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import MessageTimeline from '../components/MessageTimeline';
3 |
4 | const Homepage = ({currentUser, messages}) => {
5 | if (!currentUser) {
6 | return Please login
;
7 | }
8 | return (
9 |
14 | );
15 | }
16 |
17 | export default Homepage;
18 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/components/MessageForm.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | class MessageForm extends Component {
4 | static defaultProps = {
5 | onSubmit() {}
6 | }
7 |
8 | constructor(props) {
9 | super(props);
10 | this.state = {
11 | message: ''
12 | }
13 | }
14 |
15 | render() {
16 | const {message} = this.state;
17 | const {onSubmit, errorMessage} = this.props;
18 | return (
19 |
42 | );
43 | }
44 | }
45 |
46 | export default MessageForm;
47 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/components/MessageItem.css:
--------------------------------------------------------------------------------
1 | .timeline-image {
2 | border-radius: 5px;
3 | height: 48px;
4 | width: 48px;
5 | margin-top: 2px;
6 | flex: 1
7 | }
8 |
9 | .message-area,
10 | .timeline-image {
11 | display: inline-block;
12 | }
13 |
14 | .message-area {
15 | margin-left: 5px;
16 | flex: 1;
17 | }
18 |
19 | .message-area a {
20 | margin-right: 3px;
21 | }
22 |
23 | .message-container {
24 | text-align: left;
25 | display: flex;
26 | flex-direction: row;
27 | }
28 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/components/MessageItem.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router-dom';
3 | import Moment from 'react-moment';
4 | import './MessageItem.css';
5 | import DefaultProfileImg from '../images/default-profile-image.jpg';
6 |
7 | const MessageItem = (props) => {
8 | const {profileImageUrl, username, text, date} = props;
9 | return (
10 |
11 |
12 |
17 |
18 |
19 |
@{username}
20 |
{date}
21 |
{text}
22 |
23 |
24 | );
25 | }
26 |
27 | export default MessageItem;
28 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/components/MessageList.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import MessageItem from './MessageItem';
3 |
4 | const MessageList = ({messages}) => {
5 | let messageList = messages.map(m => (
6 |
13 | ));
14 | return (
15 |
20 | );
21 | }
22 |
23 | MessageList.defaultProps = {
24 | messages: []
25 | }
26 |
27 | export default MessageList;
28 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/components/MessageTimeline.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import MessageList from './MessageList';
3 | import UserAside from './UserAside';
4 |
5 | const MessageTimeline = ({profileImageUrl, username, messages}) => (
6 |
7 |
11 |
12 |
13 | );
14 |
15 | export default MessageTimeline;
16 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/components/Navbar.css:
--------------------------------------------------------------------------------
1 | .navbar-brand > img {
2 | display: inline-block;
3 | margin-bottom: 2px;
4 | width: 20px;
5 | border-radius: 2px;
6 | }
7 |
8 | .nav > li > a > img {
9 | margin: -20px 0 -15px;
10 | width: 40px;
11 | border-radius: 3px;
12 | }
13 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/components/Navbar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router-dom';
3 | import Logo from '../images/warbler-logo.png';
4 | import './Navbar.css';
5 |
6 | const Navbar = props => {
7 | const {currentUser, onLogout, profileImageUrl} = props;
8 | return (
9 |
30 | );
31 | }
32 |
33 | export default Navbar;
34 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/components/PrivateRoute.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Redirect, Route} from 'react-router-dom';
3 |
4 | const PrivateRoute = ({component: Component, componentProps, currentUser, ...rest}) => (
5 | (
6 | currentUser ?
7 | :
8 |
12 | )}/>
13 | );
14 |
15 | export default PrivateRoute;
16 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/components/UserAside.css:
--------------------------------------------------------------------------------
1 | #profile-image,
2 | #profile-avatar {
3 | border-radius: 5px;
4 | display: block;
5 | margin-left: -15px;
6 | }
7 |
8 | #profile-image {
9 | margin: 0 auto 15px;
10 | width: 100%;
11 | }
12 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/components/UserAside.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './UserAside.css';
3 |
4 | const UserAside = ({
5 | profileImageUrl,
6 | username,
7 | messageCount
8 | }) => (
9 |
18 | );
19 |
20 | export default UserAside;
21 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/containers/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 | import {withRouter} from 'react-router-dom';
4 | import * as actions from '../actions';
5 | import Main from './Main';
6 | import Navbar from '../components/Navbar';
7 |
8 | const App = ({
9 | currentUser,
10 | authErrorMessage,
11 | onLogout
12 | }) => (
13 |
14 |
22 |
23 |
24 | );
25 |
26 |
27 | const mapStateToProps = state => ({
28 | currentUser: state.currentUser
29 | });
30 |
31 | const mapDispatchToProps = dispatch => ({
32 | onLogout() { dispatch(actions.userLogout()) },
33 | });
34 |
35 | export default withRouter(connect(mapStateToProps, mapDispatchToProps)(App));
36 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/containers/Warbler.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Provider} from 'react-redux';
3 | import {createStore, applyMiddleware} from 'redux';
4 | import thunk from 'redux-thunk';
5 | import {createLogger} from 'redux-logger';
6 | import {BrowserRouter as Router} from 'react-router-dom';
7 | import rootReducer, {getCurrentUser} from '../reducers';
8 | import {authenticateUser} from '../actions';
9 | import App from './App';
10 |
11 | const middleware = [thunk];
12 | if (process.env.NODE_ENV !== 'production') {
13 | middleware.push(createLogger())
14 | }
15 |
16 | const store = createStore(
17 | rootReducer,
18 | applyMiddleware(...middleware)
19 | );
20 |
21 | let user = getCurrentUser();
22 |
23 | if (user) {
24 | store.dispatch(authenticateUser(user));
25 | }
26 |
27 |
28 | const Warbler = () => (
29 |
30 |
31 |
32 |
33 |
34 | );
35 |
36 | export default Warbler;
37 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/images/default-profile-image.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/warbler-solution/warbler-client/src/images/default-profile-image.jpg
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/images/warbler-hero.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/warbler-solution/warbler-client/src/images/warbler-hero.jpg
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/images/warbler-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/warbler-solution/warbler-client/src/images/warbler-logo.png
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import Warbler from './containers/Warbler';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(
8 | ,
9 | document.getElementById('root')
10 | );
11 | registerServiceWorker();
12 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/reducers/currentUser.js:
--------------------------------------------------------------------------------
1 | const LOCAL_STORAGE_USER_KEY = 'warbler-user-auth-info';
2 |
3 | const setCurrentUser = (currentUser) => {
4 | localStorage.setItem(LOCAL_STORAGE_USER_KEY, JSON.stringify(currentUser));
5 | };
6 |
7 | const clearCurrentUser = () => {
8 | localStorage.removeItem(LOCAL_STORAGE_USER_KEY);
9 | };
10 |
11 | export const getCurrentUser = () => {
12 | try {
13 | return JSON.parse(localStorage.getItem(LOCAL_STORAGE_USER_KEY));
14 | } catch(e) {
15 | return undefined;
16 | }
17 | };
18 |
19 |
20 | const currentUser = (state=null, action) => {
21 | switch(action.type) {
22 | case "USER_LOGOUT":
23 | clearCurrentUser();
24 | return null;
25 | case "AUTHENTICATE_USER":
26 | setCurrentUser(action.currentUser);
27 | return {...action.currentUser};
28 | default:
29 | return state;
30 | }
31 | };
32 |
33 | export default currentUser;
34 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import {combineReducers} from 'redux';
2 | import currentUser, {getCurrentUser} from './currentUser';
3 | import messages from './messages';
4 |
5 | export {getCurrentUser};
6 |
7 | const rootReducer = combineReducers({
8 | currentUser,
9 | messages,
10 | });
11 |
12 | export default rootReducer;
13 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-client/src/reducers/messages.js:
--------------------------------------------------------------------------------
1 | const messages = (state=[], action) => {
2 | switch(action.type) {
3 | case "LOAD_MESSAGES":
4 | return [...action.messages];
5 | case "ADD_MESSAGE":
6 | return [action.message, ...state];
7 | default:
8 | return state;
9 | }
10 | };
11 |
12 | export default messages;
13 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-server/.env:
--------------------------------------------------------------------------------
1 | SECRET_KEY=b9a4566aaa7a098e97a0a3d94036cfbd81538b4418199796
2 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-server/README.md:
--------------------------------------------------------------------------------
1 | # Warbler Server Starter
2 |
3 | The sever does token based authentication for signup and sign in
4 |
5 | ## Setup
6 |
7 | The server is a NodeJS application that uses express and mongoDB. To get setup:
8 |
9 | * run: `npm install`
10 | * Create a `.env` file. In the file, add
11 |
12 | ```js
13 | SECRET_KEY=longRandomStringOfCharacters
14 | ```
15 | __DO NOT CHECK IN THIS FILE__
16 |
17 | * npm start
18 |
19 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-server/helpers/auth.js:
--------------------------------------------------------------------------------
1 | var db = require('../models');
2 | var jwt = require('jsonwebtoken');
3 |
4 | exports.signin = function(req,res){
5 | db.User.findOne({email: req.body.email}).then(function(user){
6 | user.comparePassword(req.body.password, function(err, isMatch){
7 | if(isMatch){
8 | var token = jwt.sign({userId: user.id}, process.env.SECRET_KEY);
9 | res.status(200).json({userId: user.id,
10 | username: user.username,
11 | profileImageUrl: user.profileImageUrl,
12 | token
13 | });
14 | } else {
15 | res.status(400).json({message: 'Invalid Email/Password.'})
16 | }
17 | })
18 | }).catch(function(err){
19 | res.status(400).json({message: 'Invalid Email/Password'})
20 | })
21 | };
22 |
23 | exports.signup = function(req, res, next){
24 | db.User.create(req.body).then(function(user){
25 | var token = jwt.sign({ userId: user.id}, process.env.SECRET_KEY);
26 | res.status(200).json({userId: user.id,
27 | username: user.username,
28 | profileImageUrl: user.profileImageUrl,
29 | token
30 | });
31 | }).catch(function(err) {
32 | res.status(400).json(err);
33 | });
34 | };
35 |
36 | module.exports = exports;
37 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-server/helpers/messages.js:
--------------------------------------------------------------------------------
1 | var db = require('../models');
2 |
3 | exports.createMessage = function(req,res,next){
4 | const newMessage = {
5 | text: req.body.text,
6 | userId: req.params.id
7 | };
8 |
9 | db.Message.create(newMessage).then(function(message){
10 | db.User.findById(req.params.id).then(function(user){
11 | user.messages.push(message.id)
12 | user.save().then(function(user) {
13 | return db.Message.findById(message._id)
14 | .populate("userId", {username: true, profileImageUrl: true})
15 | }).then(function(m) {
16 | return res.status(200).json(m);
17 | }).catch(next);
18 | }).catch(next);
19 | }).catch(next);
20 | };
21 |
22 | module.exports = exports;
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-server/index.js:
--------------------------------------------------------------------------------
1 | require("dotenv").config()
2 | var express = require("express");
3 | var app = express();
4 | var cors = require('cors');
5 | var bodyParser = require("body-parser");
6 | var authRoutes = require("./routes/auth");
7 | var messagesRoutes = require("./routes/messages");
8 | var auth = require('./middleware/auth');
9 | var db = require("./models");
10 |
11 | app.use(cors());
12 | app.use(bodyParser.json());
13 | app.use(bodyParser.urlencoded({extended:true}));
14 |
15 | app.get("/", function(req,res){
16 | res.json({message: "Make a POST requst to /api/auth/signup to signup"});
17 | });
18 |
19 | app.use('/api/users/:id/messages',
20 | auth.loginRequired, auth.ensureCorrectUser,
21 | messagesRoutes);
22 | app.use('/api/auth', authRoutes);
23 | app.get('/api/messages', function(req, res, next) {
24 | db.Message.find().sort({createAt: 'desc'})
25 | .populate("userId", {username: true, profileImageUrl: true})
26 | .then(function(messages) {
27 | res.json(messages);
28 | }).catch(function(err) {
29 | res.status(500).json(err);
30 | })
31 | });
32 |
33 | const PORT = 8081
34 |
35 | app.listen(PORT, function(){
36 | console.log(`Server is listening on port ${PORT}`);
37 | });
38 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-server/models/index.js:
--------------------------------------------------------------------------------
1 | var mongoose = require("mongoose");
2 | mongoose.set('debug', true);
3 | mongoose.Promise = global.Promise;
4 | mongoose.connect('mongodb://localhost/warbler', {
5 | keepAlive: true,
6 | reconnectTries: Number.MAX_VALUE,
7 | useMongoClient: true
8 | });
9 |
10 | module.exports.User = require("./user");
11 | module.exports.Message = require("./message");
12 |
13 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-server/models/message.js:
--------------------------------------------------------------------------------
1 | var mongoose = require("mongoose");
2 | var User = require("./user");
3 |
4 |
5 | var messageSchema = new mongoose.Schema({
6 | text: {
7 | type: String,
8 | required: true,
9 | maxLength: 160
10 | },
11 | userId: {
12 | type: mongoose.Schema.Types.ObjectId,
13 | ref: "User",
14 | required: true
15 | }
16 | }, {
17 | timestamps: true
18 | });
19 |
20 | messageSchema.pre('remove', function(next){
21 | User.findById(this.userId).then(user => {
22 | user.messages.remove(this.id);
23 | user.save().then(function(e){
24 | next();
25 | });
26 | }).catch(function(err) {
27 | next(err);
28 | });
29 | });
30 |
31 | var Message = mongoose.model('Message', messageSchema);
32 | module.exports = Message;
33 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-server/models/user.js:
--------------------------------------------------------------------------------
1 | var mongoose = require("mongoose");
2 | var bcrypt = require("bcryptjs");
3 |
4 | var userSchema = new mongoose.Schema({
5 | email: {
6 | type: String,
7 | required: true,
8 | unique: true
9 | },
10 | username: {
11 | type: String,
12 | required: true,
13 | unique: true
14 | },
15 | password: {
16 | type: String,
17 | required: true
18 | },
19 | profileImageUrl: {
20 | type:String,
21 | },
22 | messages: [{
23 | type: mongoose.Schema.Types.ObjectId,
24 | ref: 'Message'
25 | }]
26 | });
27 |
28 | userSchema.pre('save', function(next){
29 | var user = this;
30 | if (!user.isModified('password')) return next();
31 | bcrypt.hash(user.password, 10).then(function(hashedPassword) {
32 | user.password = hashedPassword
33 | next();
34 | }, function(err){
35 | return next(err)
36 | });
37 | });
38 |
39 | userSchema.methods.comparePassword = function(candidatePassword, next) {
40 | bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
41 | if(err) return next(err);
42 | next(null, isMatch);
43 | });
44 | };
45 |
46 | var User = mongoose.model('User', userSchema);
47 | module.exports = User;
48 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "warbler-server",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node ./node_modules/nodemon/bin/nodemon.js index.js",
9 | "debug": "node --inspect-brk app.js"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "dependencies": {
15 | "bcryptjs": "^2.4.3",
16 | "body-parser": "^1.16.1",
17 | "cors": "^2.8.3",
18 | "dotenv": "^4.0.0",
19 | "express": "^4.14.1",
20 | "faker": "^4.1.0",
21 | "jsonwebtoken": "^7.3.0",
22 | "mongoose": "^4.8.4"
23 | },
24 | "devDependencies": {
25 | "locus": "^2.0.1",
26 | "nodemon": "^1.11.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-server/routes/auth.js:
--------------------------------------------------------------------------------
1 | var express = require("express");
2 | var router = express.Router();
3 | var db = require("../models");
4 | var jwt = require('jsonwebtoken');
5 | var helpers = require('../helpers/auth');
6 |
7 | router.post('/signin', helpers.signin);
8 | router.post('/signup', helpers.signup);
9 |
10 | module.exports = router;
11 |
--------------------------------------------------------------------------------
/react/warbler-solution/warbler-server/routes/messages.js:
--------------------------------------------------------------------------------
1 | var express = require("express");
2 | var router = express.Router({mergeParams: true});
3 | var db = require("../models");
4 | var helpers = require('../helpers/messages');
5 |
6 | router.post('/', helpers.createMessage);
7 |
8 |
9 | module.exports = router;
10 |
--------------------------------------------------------------------------------
/react/warbler-starter-server/.env:
--------------------------------------------------------------------------------
1 | SECRET_KEY=b9a4566aaa7a098e97a0a3d94036cfbd81538b4418199796
2 |
--------------------------------------------------------------------------------
/react/warbler-starter-server/README.md:
--------------------------------------------------------------------------------
1 | # Warbler Server Starter
2 |
3 | The sever does token based authentication for signup and sign in
4 |
5 | ## Setup
6 |
7 | The server is a NodeJS application that uses express and mongoDB. To get setup:
8 |
9 | * run: `npm install`
10 | * Create a `.env` file. In the file, add
11 |
12 | ```js
13 | SECRET_KEY=longRandomStringOfCharacters
14 | ```
15 | __DO NOT CHECK IN THIS FILE__
16 |
17 | * npm start
18 |
19 |
--------------------------------------------------------------------------------
/react/warbler-starter-server/helpers/auth.js:
--------------------------------------------------------------------------------
1 | var db = require('../models');
2 | var jwt = require('jsonwebtoken');
3 |
4 | exports.signin = function(req,res){
5 | db.User.findOne({email: req.body.email}).then(function(user){
6 | user.comparePassword(req.body.password, function(err, isMatch){
7 | if(isMatch){
8 | var token = jwt.sign({userId: user.id}, process.env.SECRET_KEY);
9 | res.status(200).json({userId: user.id,
10 | username: user.username,
11 | profileImageUrl: user.profileImageUrl,
12 | token
13 | });
14 | } else {
15 | res.status(400).json({message: 'Invalid Email/Password.'})
16 | }
17 | })
18 | }).catch(function(err){
19 | res.status(400).json({message: 'Invalid Email/Password'})
20 | })
21 | };
22 |
23 | exports.signup = function(req, res, next){
24 | db.User.create(req.body).then(function(user){
25 | var token = jwt.sign({ userId: user.id}, process.env.SECRET_KEY);
26 | res.status(200).json({userId: user.id,
27 | username: user.username,
28 | profileImageUrl: user.profileImageUrl,
29 | token
30 | });
31 | }).catch(function(err) {
32 | res.status(400).json(err);
33 | });
34 | };
35 |
36 | module.exports = exports;
37 |
--------------------------------------------------------------------------------
/react/warbler-starter-server/helpers/messages.js:
--------------------------------------------------------------------------------
1 | var db = require('../models');
2 |
3 | exports.createMessage = function(req,res,next){
4 | const newMessage = {
5 | text: req.body.text,
6 | userId: req.params.id
7 | };
8 |
9 | db.Message.create(newMessage).then(function(message){
10 | db.User.findById(req.params.id).then(function(user){
11 | user.messages.push(message.id)
12 | user.save().then(function(user) {
13 | return db.Message.findById(message._id)
14 | .populate("userId", {username: true, profileImageUrl: true})
15 | }).then(function(m) {
16 | return res.status(200).json(m);
17 | }).catch(next);
18 | }).catch(next);
19 | }).catch(next);
20 | };
21 |
22 | module.exports = exports;
--------------------------------------------------------------------------------
/react/warbler-starter-server/index.js:
--------------------------------------------------------------------------------
1 | require("dotenv").config()
2 | var express = require("express");
3 | var app = express();
4 | var cors = require('cors');
5 | var bodyParser = require("body-parser");
6 | var authRoutes = require("./routes/auth");
7 | var messagesRoutes = require("./routes/messages");
8 | var auth = require('./middleware/auth');
9 | var db = require("./models");
10 |
11 | app.use(cors());
12 | app.use(bodyParser.json());
13 | app.use(bodyParser.urlencoded({extended:true}));
14 |
15 | app.get("/", function(req,res){
16 | res.json({message: "Make a POST requst to /api/auth/signup to signup"});
17 | });
18 |
19 | app.use('/api/users/:id/messages',
20 | auth.loginRequired, auth.ensureCorrectUser,
21 | messagesRoutes);
22 | app.use('/api/auth', authRoutes);
23 | app.get('/api/messages', function(req, res, next) {
24 | db.Message.find().sort({createAt: 'desc'})
25 | .populate("userId", {username: true, profileImageUrl: true})
26 | .then(function(messages) {
27 | res.json(messages);
28 | }).catch(function(err) {
29 | res.status(500).json(err);
30 | })
31 | });
32 |
33 | const PORT = 8081
34 |
35 | app.listen(PORT, function(){
36 | console.log(`Server is listening on port ${PORT}`);
37 | });
38 |
--------------------------------------------------------------------------------
/react/warbler-starter-server/models/index.js:
--------------------------------------------------------------------------------
1 | var mongoose = require("mongoose");
2 | mongoose.set('debug', true);
3 | mongoose.Promise = global.Promise;
4 | mongoose.connect('mongodb://localhost/warbler', {
5 | keepAlive: true,
6 | reconnectTries: Number.MAX_VALUE,
7 | useMongoClient: true
8 | });
9 |
10 | module.exports.User = require("./user");
11 | module.exports.Message = require("./message");
12 |
13 |
--------------------------------------------------------------------------------
/react/warbler-starter-server/models/message.js:
--------------------------------------------------------------------------------
1 | var mongoose = require("mongoose");
2 | var User = require("./user");
3 |
4 |
5 | var messageSchema = new mongoose.Schema({
6 | text: {
7 | type: String,
8 | required: true,
9 | maxLength: 160
10 | },
11 | userId: {
12 | type: mongoose.Schema.Types.ObjectId,
13 | ref: "User",
14 | required: true
15 | }
16 | }, {
17 | timestamps: true
18 | });
19 |
20 | messageSchema.pre('remove', function(next){
21 | User.findById(this.userId).then(user => {
22 | user.messages.remove(this.id);
23 | user.save().then(function(e){
24 | next();
25 | });
26 | }).catch(function(err) {
27 | next(err);
28 | });
29 | });
30 |
31 | var Message = mongoose.model('Message', messageSchema);
32 | module.exports = Message;
33 |
--------------------------------------------------------------------------------
/react/warbler-starter-server/models/user.js:
--------------------------------------------------------------------------------
1 | var mongoose = require("mongoose");
2 | var bcrypt = require("bcryptjs");
3 |
4 | var userSchema = new mongoose.Schema({
5 | email: {
6 | type: String,
7 | required: true,
8 | unique: true
9 | },
10 | username: {
11 | type: String,
12 | required: true,
13 | unique: true
14 | },
15 | password: {
16 | type: String,
17 | required: true
18 | },
19 | profileImageUrl: {
20 | type:String,
21 | },
22 | messages: [{
23 | type: mongoose.Schema.Types.ObjectId,
24 | ref: 'Message'
25 | }]
26 | });
27 |
28 | userSchema.pre('save', function(next){
29 | var user = this;
30 | if (!user.isModified('password')) return next();
31 | bcrypt.hash(user.password, 10).then(function(hashedPassword) {
32 | user.password = hashedPassword
33 | next();
34 | }, function(err){
35 | return next(err)
36 | });
37 | });
38 |
39 | userSchema.methods.comparePassword = function(candidatePassword, next) {
40 | bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
41 | if(err) return next(err);
42 | next(null, isMatch);
43 | });
44 | };
45 |
46 | var User = mongoose.model('User', userSchema);
47 | module.exports = User;
48 |
--------------------------------------------------------------------------------
/react/warbler-starter-server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "warbler-server",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node ./node_modules/nodemon/bin/nodemon.js index.js",
9 | "debug": "node --inspect-brk app.js"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "dependencies": {
15 | "bcryptjs": "^2.4.3",
16 | "body-parser": "^1.16.1",
17 | "cors": "^2.8.3",
18 | "dotenv": "^4.0.0",
19 | "express": "^4.14.1",
20 | "faker": "^4.1.0",
21 | "jsonwebtoken": "^7.3.0",
22 | "mongoose": "^4.8.4"
23 | },
24 | "devDependencies": {
25 | "locus": "^2.0.1",
26 | "nodemon": "^1.11.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/react/warbler-starter-server/routes/auth.js:
--------------------------------------------------------------------------------
1 | var express = require("express");
2 | var router = express.Router();
3 | var db = require("../models");
4 | var jwt = require('jsonwebtoken');
5 | var helpers = require('../helpers/auth');
6 |
7 | router.post('/signin', helpers.signin);
8 | router.post('/signup', helpers.signup);
9 |
10 | module.exports = router;
11 |
--------------------------------------------------------------------------------
/react/warbler-starter-server/routes/messages.js:
--------------------------------------------------------------------------------
1 | var express = require("express");
2 | var router = express.Router({mergeParams: true});
3 | var db = require("../models");
4 | var helpers = require('../helpers/messages');
5 |
6 | router.post('/', helpers.createMessage);
7 |
8 |
9 | module.exports = router;
10 |
--------------------------------------------------------------------------------
/react/warbler/warbler-client/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/react/warbler/warbler-client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "warbler-client",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.0.0-rc.3",
7 | "react-dom": "^16.0.0-rc.3",
8 | "react-scripts": "1.0.13"
9 | },
10 | "proxy": "http://localhost:8081",
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
--------------------------------------------------------------------------------
/react/warbler/warbler-client/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rithmschool/udemy_course_exercises/ab8246fa47b5c1158f9467eee37eec78475df559/react/warbler/warbler-client/public/favicon.ico
--------------------------------------------------------------------------------
/react/warbler/warbler-client/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/react/warbler/warbler-client/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | animation: App-logo-spin infinite 20s linear;
7 | height: 80px;
8 | }
9 |
10 | .App-header {
11 | background-color: #222;
12 | height: 150px;
13 | padding: 20px;
14 | color: white;
15 | }
16 |
17 | .App-intro {
18 | font-size: large;
19 | }
20 |
21 | @keyframes App-logo-spin {
22 | from { transform: rotate(0deg); }
23 | to { transform: rotate(360deg); }
24 | }
25 |
--------------------------------------------------------------------------------
/react/warbler/warbler-client/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import logo from './logo.svg';
3 | import './App.css';
4 |
5 | class App extends Component {
6 | render() {
7 | return (
8 |
9 |
10 |

11 |
Welcome to React
12 |
13 |
14 | To get started, edit src/App.js
and save to reload.
15 |
16 |
17 | );
18 | }
19 | }
20 |
21 | export default App;
22 |
--------------------------------------------------------------------------------
/react/warbler/warbler-client/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/react/warbler/warbler-client/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/react/warbler/warbler-client/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/react/warbler/warbler-server/.env:
--------------------------------------------------------------------------------
1 | SECRET_KEY=b9a4566aaa7a098e97a0a3d94036cfbd81538b4418199796
2 |
--------------------------------------------------------------------------------
/react/warbler/warbler-server/README.md:
--------------------------------------------------------------------------------
1 | # Warbler Server Starter
2 |
3 | The sever does token based authentication for signup and sign in
4 |
5 | ## Setup
6 |
7 | The server is a NodeJS application that uses express and mongoDB. To get setup:
8 |
9 | * run: `npm install`
10 | * Create a `.env` file. In the file, add
11 |
12 | ```js
13 | SECRET_KEY=longRandomStringOfCharacters
14 | ```
15 | __DO NOT CHECK IN THIS FILE__
16 |
17 | * npm start
18 |
19 |
--------------------------------------------------------------------------------
/react/warbler/warbler-server/helpers/auth.js:
--------------------------------------------------------------------------------
1 | var db = require('../models');
2 | var jwt = require('jsonwebtoken');
3 |
4 | exports.signin = function(req,res){
5 | db.User.findOne({email: req.body.email}).then(function(user){
6 | user.comparePassword(req.body.password, function(err, isMatch){
7 | if(isMatch){
8 | var token = jwt.sign({userId: user.id}, process.env.SECRET_KEY);
9 | res.status(200).json({userId: user.id,
10 | username: user.username,
11 | profileImageUrl: user.profileImageUrl,
12 | token
13 | });
14 | } else {
15 | res.status(400).json({message: 'Invalid Email/Password.'})
16 | }
17 | })
18 | }).catch(function(err){
19 | res.status(400).json({message: 'Invalid Email/Password'})
20 | })
21 | };
22 |
23 | exports.signup = function(req, res, next){
24 | db.User.create(req.body).then(function(user){
25 | var token = jwt.sign({ userId: user.id}, process.env.SECRET_KEY);
26 | res.status(200).json({userId: user.id,
27 | username: user.username,
28 | profileImageUrl: user.profileImageUrl,
29 | token
30 | });
31 | }).catch(function(err) {
32 | res.status(400).json(err);
33 | });
34 | };
35 |
36 | module.exports = exports;
37 |
--------------------------------------------------------------------------------
/react/warbler/warbler-server/helpers/messages.js:
--------------------------------------------------------------------------------
1 | var db = require('../models');
2 |
3 | exports.createMessage = function(req,res,next){
4 | const newMessage = {
5 | text: req.body.text,
6 | userId: req.params.id
7 | };
8 |
9 | db.Message.create(newMessage).then(function(message){
10 | db.User.findById(req.params.id).then(function(user){
11 | user.messages.push(message.id)
12 | user.save().then(function(user) {
13 | return db.Message.findById(message._id)
14 | .populate("userId", {username: true, profileImageUrl: true})
15 | }).then(function(m) {
16 | return res.status(200).json(m);
17 | }).catch(next);
18 | }).catch(next);
19 | }).catch(next);
20 | };
21 |
22 | module.exports = exports;
--------------------------------------------------------------------------------
/react/warbler/warbler-server/index.js:
--------------------------------------------------------------------------------
1 | require("dotenv").config()
2 | var express = require("express");
3 | var app = express();
4 | var cors = require('cors');
5 | var bodyParser = require("body-parser");
6 | var authRoutes = require("./routes/auth");
7 | var messagesRoutes = require("./routes/messages");
8 | var auth = require('./middleware/auth');
9 | var db = require("./models");
10 |
11 | app.use(cors());
12 | app.use(bodyParser.json());
13 | app.use(bodyParser.urlencoded({extended:true}));
14 |
15 | app.get("/", function(req,res){
16 | res.json({message: "Make a POST requst to /api/auth/signup to signup"});
17 | });
18 |
19 | app.use('/api/users/:id/messages',
20 | auth.loginRequired, auth.ensureCorrectUser,
21 | messagesRoutes);
22 | app.use('/api/auth', authRoutes);
23 | app.get('/api/messages', function(req, res, next) {
24 | db.Message.find().sort({createAt: 'desc'})
25 | .populate("userId", {username: true, profileImageUrl: true})
26 | .then(function(messages) {
27 | res.json(messages);
28 | }).catch(function(err) {
29 | res.status(500).json(err);
30 | })
31 | });
32 |
33 | const PORT = 8081
34 |
35 | app.listen(PORT, function(){
36 | console.log(`Server is listening on port ${PORT}`);
37 | });
38 |
--------------------------------------------------------------------------------
/react/warbler/warbler-server/models/index.js:
--------------------------------------------------------------------------------
1 | var mongoose = require("mongoose");
2 | mongoose.set('debug', true);
3 | mongoose.Promise = global.Promise;
4 | mongoose.connect('mongodb://localhost/warbler', {
5 | keepAlive: true,
6 | reconnectTries: Number.MAX_VALUE,
7 | useMongoClient: true
8 | });
9 |
10 | module.exports.User = require("./user");
11 | module.exports.Message = require("./message");
12 |
13 |
--------------------------------------------------------------------------------
/react/warbler/warbler-server/models/message.js:
--------------------------------------------------------------------------------
1 | var mongoose = require("mongoose");
2 | var User = require("./user");
3 |
4 |
5 | var messageSchema = new mongoose.Schema({
6 | text: {
7 | type: String,
8 | required: true,
9 | maxLength: 160
10 | },
11 | userId: {
12 | type: mongoose.Schema.Types.ObjectId,
13 | ref: "User",
14 | required: true
15 | }
16 | }, {
17 | timestamps: true
18 | });
19 |
20 | messageSchema.pre('remove', function(next){
21 | User.findById(this.userId).then(user => {
22 | user.messages.remove(this.id);
23 | user.save().then(function(e){
24 | next();
25 | });
26 | }).catch(function(err) {
27 | next(err);
28 | });
29 | });
30 |
31 | var Message = mongoose.model('Message', messageSchema);
32 | module.exports = Message;
33 |
--------------------------------------------------------------------------------
/react/warbler/warbler-server/models/user.js:
--------------------------------------------------------------------------------
1 | var mongoose = require("mongoose");
2 | var bcrypt = require("bcryptjs");
3 |
4 | var userSchema = new mongoose.Schema({
5 | email: {
6 | type: String,
7 | required: true,
8 | unique: true
9 | },
10 | username: {
11 | type: String,
12 | required: true,
13 | unique: true
14 | },
15 | password: {
16 | type: String,
17 | required: true
18 | },
19 | profileImageUrl: {
20 | type:String,
21 | },
22 | messages: [{
23 | type: mongoose.Schema.Types.ObjectId,
24 | ref: 'Message'
25 | }]
26 | });
27 |
28 | userSchema.pre('save', function(next){
29 | var user = this;
30 | if (!user.isModified('password')) return next();
31 | bcrypt.hash(user.password, 10).then(function(hashedPassword) {
32 | user.password = hashedPassword
33 | next();
34 | }, function(err){
35 | return next(err)
36 | });
37 | });
38 |
39 | userSchema.methods.comparePassword = function(candidatePassword, next) {
40 | bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
41 | if(err) return next(err);
42 | next(null, isMatch);
43 | });
44 | };
45 |
46 | var User = mongoose.model('User', userSchema);
47 | module.exports = User;
48 |
--------------------------------------------------------------------------------
/react/warbler/warbler-server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "warbler-server",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node ./node_modules/nodemon/bin/nodemon.js index.js",
9 | "debug": "node --inspect-brk app.js"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "dependencies": {
15 | "bcryptjs": "^2.4.3",
16 | "body-parser": "^1.16.1",
17 | "cors": "^2.8.3",
18 | "dotenv": "^4.0.0",
19 | "express": "^4.14.1",
20 | "faker": "^4.1.0",
21 | "jsonwebtoken": "^7.3.0",
22 | "mongoose": "^4.8.4"
23 | },
24 | "devDependencies": {
25 | "locus": "^2.0.1",
26 | "nodemon": "^1.11.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/react/warbler/warbler-server/routes/auth.js:
--------------------------------------------------------------------------------
1 | var express = require("express");
2 | var router = express.Router();
3 | var db = require("../models");
4 | var jwt = require('jsonwebtoken');
5 | var helpers = require('../helpers/auth');
6 |
7 | router.post('/signin', helpers.signin);
8 | router.post('/signup', helpers.signup);
9 |
10 | module.exports = router;
11 |
--------------------------------------------------------------------------------
/react/warbler/warbler-server/routes/messages.js:
--------------------------------------------------------------------------------
1 | var express = require("express");
2 | var router = express.Router({mergeParams: true});
3 | var db = require("../models");
4 | var helpers = require('../helpers/messages');
5 |
6 | router.post('/', helpers.createMessage);
7 |
8 |
9 | module.exports = router;
10 |
--------------------------------------------------------------------------------
/todos_api/helpers/todos.js:
--------------------------------------------------------------------------------
1 | var db = require('../models');
2 |
3 | exports.getTodos = function(req, res){
4 | db.Todo.find()
5 | .then(function(todos){
6 | res.json(todos);
7 | })
8 | .catch(function(err){
9 | res.send(err);
10 | })
11 | }
12 |
13 | exports.createTodo = function(req, res){
14 | db.Todo.create(req.body)
15 | .then(function(newTodo){
16 | res.status(201).json(newTodo);
17 | })
18 | .catch(function(err){
19 | res.send(err);
20 | })
21 | }
22 |
23 | exports.getTodo = function(req, res){
24 | db.Todo.findById(req.params.todoId)
25 | .then(function(foundTodo){
26 | res.json(foundTodo);
27 | })
28 | .catch(function(err){
29 | res.send(err);
30 | })
31 | }
32 |
33 | exports.updateTodo = function(req, res){
34 | db.Todo.findOneAndUpdate({_id: req.params.todoId}, req.body, {new: true})
35 | .then(function(todo){
36 | res.json(todo);
37 | })
38 | .catch(function(err){
39 | res.send(err);
40 | })
41 | }
42 |
43 | exports.deleteTodo = function(req, res){
44 | db.Todo.remove({_id: req.params.todoId})
45 | .then(function(){
46 | res.json({message: 'We deleted it!'});
47 | })
48 | .catch(function(err){
49 | res.send(err);
50 | })
51 | }
52 |
53 | module.exports = exports;
--------------------------------------------------------------------------------
/todos_api/index.js:
--------------------------------------------------------------------------------
1 | var express = require('express'),
2 | app = express(),
3 | port = process.env.PORT || 3000,
4 | bodyParser = require('body-parser');
5 |
6 | var todoRoutes = require("./routes/todos");
7 |
8 | app.use(bodyParser.json());
9 | app.use(bodyParser.urlencoded({extended: true}));
10 | app.use(express.static(__dirname +'/public'));
11 | app.use(express.static(__dirname + '/views'));
12 |
13 | app.get('/', function(req, res){
14 | res.sendFile("index.html");
15 | });
16 |
17 | app.use('/api/todos', todoRoutes);
18 |
19 | app.listen(port, function(){
20 | console.log("APP IS RUNNING ON PORT " + process.env.PORT);
21 | })
22 |
23 |
--------------------------------------------------------------------------------
/todos_api/models/index.js:
--------------------------------------------------------------------------------
1 | var mongoose = require('mongoose');
2 | mongoose.set('debug', true);
3 | mongoose.connect('mongodb://localhost/todo-api');
4 |
5 | mongoose.Promise = Promise;
6 |
7 | module.exports.Todo = require("./todo");
--------------------------------------------------------------------------------
/todos_api/models/todo.js:
--------------------------------------------------------------------------------
1 | var mongoose = require('mongoose');
2 |
3 | var todoSchema = new mongoose.Schema({
4 | name: {
5 | type: String,
6 | required: 'Name cannot be blank!'
7 | },
8 | completed: {
9 | type: Boolean,
10 | default: false
11 | },
12 | created_date: {
13 | type: Date,
14 | default: Date.now
15 | }
16 | });
17 |
18 | var Todo = mongoose.model('Todo', todoSchema);
19 |
20 | module.exports = Todo;
--------------------------------------------------------------------------------
/todos_api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "todos_api",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "body-parser": "^1.17.2",
13 | "express": "^4.15.4",
14 | "mongoose": "^4.11.9"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/todos_api/routes/todos.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var db = require("../models");
4 | var helpers = require("../helpers/todos");
5 |
6 | router.route('/')
7 | .get(helpers.getTodos)
8 | .post(helpers.createTodo)
9 |
10 | router.route('/:todoId')
11 | .get(helpers.getTodo)
12 | .put(helpers.updateTodo)
13 | .delete(helpers.deleteTodo)
14 |
15 | module.exports = router;
--------------------------------------------------------------------------------
/todos_api/views/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 | todolist
12 | A simple todo list app built with node
13 |
14 |
15 |
18 |
19 |
21 |
22 |
23 |
--------------------------------------------------------------------------------