├── README.md ├── appendix ├── components │ └── MyComponent.vue ├── es6 │ ├── arrow_funcs.js │ ├── arrow_funcs_jukebox_1.js │ ├── arrow_funcs_jukebox_2.js │ ├── const_let.js │ ├── default_args.js │ ├── destructuring_assignments.js │ ├── enhanced_object_literals.js │ ├── object_assign.js │ ├── spread_operator_arrays.js │ ├── template_literals_1.js │ └── template_literals_2.js └── store │ └── simpleStore │ ├── NumberDisplay.vue │ ├── NumberSubmit.vue │ └── store.js ├── calendar_app ├── .gitignore ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public │ ├── bulma │ │ ├── bulma.css │ │ └── bulma.css.map │ ├── favicon.ico │ ├── font-awesome │ │ ├── HELP-US-OUT.txt │ │ ├── css │ │ │ ├── font-awesome.css │ │ │ └── font-awesome.min.css │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ ├── less │ │ │ ├── animated.less │ │ │ ├── bordered-pulled.less │ │ │ ├── core.less │ │ │ ├── fixed-width.less │ │ │ ├── font-awesome.less │ │ │ ├── icons.less │ │ │ ├── larger.less │ │ │ ├── list.less │ │ │ ├── mixins.less │ │ │ ├── path.less │ │ │ ├── rotated-flipped.less │ │ │ ├── screen-reader.less │ │ │ ├── stacked.less │ │ │ └── variables.less │ │ └── scss │ │ │ ├── _animated.scss │ │ │ ├── _bordered-pulled.scss │ │ │ ├── _core.scss │ │ │ ├── _fixed-width.scss │ │ │ ├── _icons.scss │ │ │ ├── _larger.scss │ │ │ ├── _list.scss │ │ │ ├── _mixins.scss │ │ │ ├── _path.scss │ │ │ ├── _rotated-flipped.scss │ │ │ ├── _screen-reader.scss │ │ │ ├── _stacked.scss │ │ │ ├── _variables.scss │ │ │ └── font-awesome.scss │ └── index.html └── src │ ├── app-1 │ ├── App.vue │ ├── components │ │ ├── CalendarEntry.vue │ │ └── CalendarWeek.vue │ └── seed.js │ ├── app-2 │ ├── App.vue │ ├── components │ │ ├── CalendarDay.vue │ │ ├── CalendarEntry.vue │ │ └── CalendarWeek.vue │ ├── seed.js │ └── store.js │ ├── app-3 │ ├── App.vue │ ├── components │ │ ├── CalendarDay.vue │ │ ├── CalendarEntry.vue │ │ ├── CalendarEvent.vue │ │ └── CalendarWeek.vue │ ├── seed.js │ └── store.js │ ├── app-4 │ ├── App.vue │ ├── components │ │ ├── CalendarDay.vue │ │ ├── CalendarEntry.vue │ │ ├── CalendarEvent.vue │ │ └── CalendarWeek.vue │ ├── seed.js │ └── store.js │ ├── app-5 │ ├── App.vue │ ├── components │ │ ├── CalendarDay.vue │ │ ├── CalendarEntry.vue │ │ ├── CalendarEvent.vue │ │ └── CalendarWeek.vue │ ├── seed.js │ └── store.js │ ├── app-6 │ ├── App.vue │ ├── components │ │ ├── CalendarDay.vue │ │ ├── CalendarEntry.vue │ │ ├── CalendarEvent.vue │ │ └── CalendarWeek.vue │ ├── seed.js │ └── store.js │ ├── app-7 │ ├── App.vue │ ├── components │ │ ├── CalendarDay.vue │ │ ├── CalendarEntry.vue │ │ ├── CalendarEvent.vue │ │ └── CalendarWeek.vue │ ├── seed.js │ └── store.js │ ├── app-complete │ ├── App.vue │ ├── components │ │ ├── CalendarDay.vue │ │ ├── CalendarEntry.vue │ │ ├── CalendarEvent.vue │ │ └── CalendarWeek.vue │ ├── seed.js │ └── store.js │ ├── app │ ├── App.vue │ └── seed.js │ └── main.js ├── custom_events ├── app-1 │ ├── index.html │ └── main.js ├── app-2 │ ├── index.html │ └── main.js ├── app-complete │ ├── index.html │ └── main.js ├── app │ ├── index.html │ └── main.js └── public │ └── styles.css ├── form_handling ├── 01-basic-button │ ├── index.html │ └── main.js ├── 02-basic-button │ ├── index.html │ └── main.js ├── 03-basic-input │ ├── index.html │ └── main.js ├── 04-data-input │ ├── index.html │ └── main.js ├── 05-data-input-list │ ├── index.html │ └── main.js ├── 06-data-input-multi │ ├── index.html │ └── main.js ├── 07-basic-form-validation │ ├── index.html │ └── main.js ├── 08-basic-field-validation │ ├── index.html │ └── main.js ├── 09-remote-persist │ ├── index.html │ └── main.js ├── 10-vuex-app │ ├── index.html │ ├── main.js │ └── store.js ├── app │ ├── index.html │ └── main.js └── public │ └── semantic.min.css ├── index.json ├── my └── upvote │ └── index.html ├── package.json ├── routing ├── basics │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ └── styles.css │ ├── src │ │ ├── app │ │ │ ├── app-1.js │ │ │ ├── app-2.js │ │ │ ├── app-3.js │ │ │ ├── app-complete.js │ │ │ └── app.js │ │ └── main.js │ └── vue.config.js └── shopping_cart │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── bulma │ │ ├── bulma.css │ │ └── bulma.css.map │ ├── favicon.ico │ ├── font-awesome │ │ ├── HELP-US-OUT.txt │ │ ├── css │ │ │ ├── font-awesome.css │ │ │ └── font-awesome.min.css │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ ├── less │ │ │ ├── animated.less │ │ │ ├── bordered-pulled.less │ │ │ ├── core.less │ │ │ ├── fixed-width.less │ │ │ ├── font-awesome.less │ │ │ ├── icons.less │ │ │ ├── larger.less │ │ │ ├── list.less │ │ │ ├── mixins.less │ │ │ ├── path.less │ │ │ ├── rotated-flipped.less │ │ │ ├── screen-reader.less │ │ │ ├── stacked.less │ │ │ └── variables.less │ │ └── scss │ │ │ ├── _animated.scss │ │ │ ├── _bordered-pulled.scss │ │ │ ├── _core.scss │ │ │ ├── _fixed-width.scss │ │ │ ├── _icons.scss │ │ │ ├── _larger.scss │ │ │ ├── _list.scss │ │ │ ├── _mixins.scss │ │ │ ├── _path.scss │ │ │ ├── _rotated-flipped.scss │ │ │ ├── _screen-reader.scss │ │ │ ├── _stacked.scss │ │ │ ├── _variables.scss │ │ │ └── font-awesome.scss │ └── index.html │ ├── server-cart-data.json │ ├── server-product-data.json │ ├── server.js │ ├── src │ ├── app-1 │ │ ├── App.vue │ │ ├── assets │ │ │ ├── cap.png │ │ │ ├── hoodie.png │ │ │ ├── jacket.png │ │ │ └── tee.png │ │ ├── components │ │ │ ├── NotFound.vue │ │ │ ├── cart │ │ │ │ ├── CartList.vue │ │ │ │ └── CartListItem.vue │ │ │ └── product │ │ │ │ ├── ProductList.vue │ │ │ │ └── ProductListItem.vue │ │ ├── router │ │ │ └── index.js │ │ └── store │ │ │ ├── index.js │ │ │ └── modules │ │ │ ├── cart │ │ │ └── index.js │ │ │ └── product │ │ │ └── index.js │ ├── app-2 │ │ ├── App.vue │ │ ├── assets │ │ │ ├── cap.png │ │ │ ├── hoodie.png │ │ │ ├── jacket.png │ │ │ └── tee.png │ │ ├── components │ │ │ ├── NotFound.vue │ │ │ ├── cart │ │ │ │ ├── CartList.vue │ │ │ │ └── CartListItem.vue │ │ │ └── product │ │ │ │ ├── ProductItem.vue │ │ │ │ ├── ProductList.vue │ │ │ │ └── ProductListItem.vue │ │ ├── router │ │ │ └── index.js │ │ └── store │ │ │ ├── index.js │ │ │ └── modules │ │ │ ├── cart │ │ │ └── index.js │ │ │ └── product │ │ │ └── index.js │ ├── app-3 │ │ ├── App.vue │ │ ├── assets │ │ │ ├── cap.png │ │ │ ├── hoodie.png │ │ │ ├── jacket.png │ │ │ └── tee.png │ │ ├── components │ │ │ ├── NotFound.vue │ │ │ ├── cart │ │ │ │ ├── CartList.vue │ │ │ │ └── CartListItem.vue │ │ │ ├── login │ │ │ │ └── LoginBox.vue │ │ │ └── product │ │ │ │ ├── ProductItem.vue │ │ │ │ ├── ProductList.vue │ │ │ │ └── ProductListItem.vue │ │ ├── router │ │ │ └── index.js │ │ └── store │ │ │ ├── index.js │ │ │ └── modules │ │ │ ├── cart │ │ │ └── index.js │ │ │ ├── login │ │ │ └── index.js │ │ │ └── product │ │ │ └── index.js │ ├── app-complete │ │ ├── App.vue │ │ ├── assets │ │ │ ├── cap.png │ │ │ ├── hoodie.png │ │ │ ├── jacket.png │ │ │ └── tee.png │ │ ├── components │ │ │ ├── NotFound.vue │ │ │ ├── cart │ │ │ │ ├── CartList.vue │ │ │ │ └── CartListItem.vue │ │ │ ├── login │ │ │ │ └── LoginBox.vue │ │ │ └── product │ │ │ │ ├── ProductItem.vue │ │ │ │ ├── ProductList.vue │ │ │ │ └── ProductListItem.vue │ │ ├── router │ │ │ └── index.js │ │ └── store │ │ │ ├── index.js │ │ │ └── modules │ │ │ ├── cart │ │ │ └── index.js │ │ │ ├── login │ │ │ └── index.js │ │ │ └── product │ │ │ └── index.js │ ├── app │ │ ├── App.vue │ │ ├── assets │ │ │ ├── cap.png │ │ │ ├── hoodie.png │ │ │ ├── jacket.png │ │ │ └── tee.png │ │ ├── components │ │ │ ├── cart │ │ │ │ ├── CartList.vue │ │ │ │ └── CartListItem.vue │ │ │ └── product │ │ │ │ ├── ProductList.vue │ │ │ │ └── ProductListItem.vue │ │ └── store │ │ │ ├── index.js │ │ │ └── modules │ │ │ ├── cart │ │ │ └── index.js │ │ │ └── product │ │ │ └── index.js │ └── main.js │ └── vue.config.js ├── testing ├── basics │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ └── semantic.min.css │ ├── src │ │ ├── App.vue │ │ └── main.js │ └── tests │ │ └── unit │ │ ├── .eslintrc.js │ │ ├── App.1.spec.js │ │ ├── App.2.spec.js │ │ ├── App.3.spec.js │ │ ├── App.4.spec.js │ │ ├── App.5.spec.js │ │ ├── App.complete.spec.js │ │ └── App.spec.js └── weather │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── bulma.css │ ├── favicon.ico │ └── index.html │ ├── server.js │ ├── src │ ├── App.vue │ ├── assets │ │ ├── c.png │ │ ├── h.png │ │ ├── hc.png │ │ ├── hr.png │ │ ├── lc.png │ │ ├── lr.png │ │ ├── s.png │ │ ├── sl.png │ │ ├── sn.png │ │ └── t.png │ ├── components │ │ ├── HomeContainer.vue │ │ ├── NotFoundContainer.vue │ │ └── WeatherContainer.vue │ ├── main.js │ ├── router.js │ └── store.js │ ├── tests │ └── unit │ │ ├── .eslintrc.js │ │ ├── weather-1 │ │ ├── App.spec.js │ │ └── components │ │ │ ├── HomeContainer.spec.js │ │ │ ├── NotFoundContainer.spec.js │ │ │ └── WeatherContainer.spec.js │ │ ├── weather-2 │ │ ├── App.spec.js │ │ └── components │ │ │ ├── HomeContainer.spec.js │ │ │ ├── NotFoundContainer.spec.js │ │ │ └── WeatherContainer.spec.js │ │ ├── weather-3 │ │ ├── App.spec.js │ │ └── components │ │ │ ├── HomeContainer.spec.js │ │ │ ├── NotFoundContainer.spec.js │ │ │ └── WeatherContainer.spec.js │ │ ├── weather-complete │ │ ├── App.spec.js │ │ └── components │ │ │ ├── HomeContainer.spec.js │ │ │ ├── NotFoundContainer.spec.js │ │ │ └── WeatherContainer.spec.js │ │ └── weather │ │ ├── App.spec.js │ │ └── components │ │ ├── HomeContainer.spec.js │ │ ├── NotFoundContainer.spec.js │ │ └── WeatherContainer.spec.js │ └── vue.config.js ├── upvote ├── app │ ├── index.html │ ├── main.js │ └── seed.js ├── app_1 │ ├── index.html │ ├── main.js │ └── seed.js ├── app_2 │ ├── index.html │ ├── main.js │ └── seed.js ├── app_3 │ ├── index.html │ ├── main.js │ └── seed.js ├── app_4 │ ├── index.html │ ├── main.js │ └── seed.js ├── app_5 │ ├── index.html │ ├── main.js │ └── seed.js ├── app_complete │ ├── index.html │ ├── main.js │ └── seed.js └── public │ ├── images │ ├── avatars │ │ ├── daniel.jpg │ │ ├── kristy.png │ │ ├── molly.png │ │ └── veronika.jpg │ └── submissions │ │ ├── image-aqua.png │ │ ├── image-rose.png │ │ ├── image-steel.png │ │ └── image-yellow.png │ └── styles.css └── vuex ├── note_taking ├── app-complete │ ├── index.html │ └── main.js ├── app │ ├── index.html │ └── main.js └── public │ └── styles.css └── shopping_cart ├── .gitignore ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public ├── bulma │ ├── bulma.css │ └── bulma.css.map ├── favicon.ico ├── font-awesome │ ├── HELP-US-OUT.txt │ ├── css │ │ ├── font-awesome.css │ │ └── font-awesome.min.css │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 │ ├── less │ │ ├── animated.less │ │ ├── bordered-pulled.less │ │ ├── core.less │ │ ├── fixed-width.less │ │ ├── font-awesome.less │ │ ├── icons.less │ │ ├── larger.less │ │ ├── list.less │ │ ├── mixins.less │ │ ├── path.less │ │ ├── rotated-flipped.less │ │ ├── screen-reader.less │ │ ├── stacked.less │ │ └── variables.less │ └── scss │ │ ├── _animated.scss │ │ ├── _bordered-pulled.scss │ │ ├── _core.scss │ │ ├── _fixed-width.scss │ │ ├── _icons.scss │ │ ├── _larger.scss │ │ ├── _list.scss │ │ ├── _mixins.scss │ │ ├── _path.scss │ │ ├── _rotated-flipped.scss │ │ ├── _screen-reader.scss │ │ ├── _stacked.scss │ │ ├── _variables.scss │ │ └── font-awesome.scss └── index.html ├── server-cart-data.json ├── server-product-data.json ├── server.js ├── src ├── app-1 │ ├── App.vue │ ├── components │ │ ├── cart │ │ │ └── CartList.vue │ │ └── product │ │ │ └── ProductList.vue │ └── store │ │ ├── index.js │ │ └── modules │ │ ├── cart │ │ └── index.js │ │ └── product │ │ └── index.js ├── app-2 │ ├── App.vue │ ├── components │ │ ├── cart │ │ │ └── CartList.vue │ │ └── product │ │ │ ├── ProductList.vue │ │ │ └── ProductListItem.vue │ └── store │ │ ├── index.js │ │ └── modules │ │ ├── cart │ │ └── index.js │ │ └── product │ │ └── index.js ├── app-3 │ ├── App.vue │ ├── components │ │ ├── cart │ │ │ ├── CartList.vue │ │ │ └── CartListItem.vue │ │ └── product │ │ │ ├── ProductList.vue │ │ │ └── ProductListItem.vue │ └── store │ │ ├── index.js │ │ └── modules │ │ ├── cart │ │ └── index.js │ │ └── product │ │ └── index.js ├── app-complete │ ├── App.vue │ ├── components │ │ ├── cart │ │ │ ├── CartList.vue │ │ │ └── CartListItem.vue │ │ └── product │ │ │ ├── ProductList.vue │ │ │ └── ProductListItem.vue │ └── store │ │ ├── index.js │ │ └── modules │ │ ├── cart │ │ └── index.js │ │ └── product │ │ └── index.js ├── app │ ├── App.vue │ └── components │ │ ├── cart │ │ └── CartList.vue │ │ └── product │ │ └── ProductList.vue └── main.js └── vue.config.js /README.md: -------------------------------------------------------------------------------- 1 | # Code examples for Fullstack Vue 2 | 3 | ## Setup 4 | 5 | Please refer to the second chapter in the book for instructions on setting up your environment with Node & npm. 6 | 7 | ## Installing packages for all projects 8 | 9 | You can install all the packages for all the projects up front, saving you time in the future. To do so, from this directory: 10 | 11 | ``` 12 | npm i 13 | npm run install-all 14 | ``` 15 | 16 | Unless you have a quantum computer connected directly to an Amazon data center, this task will take a long time to complete. 17 | 18 | ## Running the code 19 | 20 | See the respective `README.md` for each project. 21 | -------------------------------------------------------------------------------- /appendix/components/MyComponent.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 21 | 22 | 28 | -------------------------------------------------------------------------------- /appendix/es6/arrow_funcs.js: -------------------------------------------------------------------------------- 1 | const cities = [ 2 | { name: 'Cairo', pop: 7764700 }, 3 | { name: 'Lagos', pop: 8029200 }, 4 | ]; 5 | 6 | const formattedPopulations = cities.map((city) => { 7 | const popMM = (city.pop / 1000000).toFixed(2); 8 | return popMM + ' million'; 9 | }); 10 | console.log(formattedPopulations); 11 | // -> [ "7.76 million", "8.03 million" ] 12 | 13 | const formattedPopulations2 = cities.map((city) => ( 14 | (city.pop / 1000000).toFixed(2) + ' million' 15 | )); 16 | 17 | const pops = cities.map(city => city.pop); 18 | console.log(pops); 19 | // [ 7764700, 8029200 ] 20 | 21 | const popsNoArrow = cities.map(function(city) { return city.pop }); 22 | -------------------------------------------------------------------------------- /appendix/es6/arrow_funcs_jukebox_1.js: -------------------------------------------------------------------------------- 1 | function printSong() { 2 | console.log("Oops - The Global Object"); 3 | } 4 | 5 | const jukebox = { 6 | songs: [ 7 | { 8 | title: "Wanna Be Startin' Somethin'", 9 | artist: "Michael Jackson", 10 | }, 11 | { 12 | title: "Superstar", 13 | artist: "Madonna", 14 | }, 15 | ], 16 | printSong: function (song) { 17 | console.log(song.title + " - " + song.artist); 18 | }, 19 | printSongs: function () { 20 | // `this` bound to the object (OK) 21 | this.songs.forEach(function(song) { 22 | // `this` bound to global object (bad) 23 | this.printSong(song); 24 | }); 25 | }, 26 | } 27 | 28 | jukebox.printSongs(); 29 | // > "Oops - The Global Object" 30 | // > "Oops - The Global Object" 31 | -------------------------------------------------------------------------------- /appendix/es6/arrow_funcs_jukebox_2.js: -------------------------------------------------------------------------------- 1 | function printSong() { 2 | console.log("Oops - The Global Object"); 3 | } 4 | 5 | const jukebox = { 6 | songs: [ 7 | { 8 | title: "Wanna Be Startin' Somethin'", 9 | artist: "Michael Jackson", 10 | }, 11 | { 12 | title: "Superstar", 13 | artist: "Madonna", 14 | }, 15 | ], 16 | printSong: function (song) { 17 | console.log(song.title + " - " + song.artist); 18 | }, 19 | printSongs: function () { 20 | this.songs.forEach((song) => { 21 | // `this` bound to same `this` as `printSongs()` (`jukebox`) 22 | this.printSong(song); 23 | }); 24 | }, 25 | } 26 | 27 | jukebox.printSongs(); 28 | // > "Wanna Be Startin' Somethin' - Michael Jackson" 29 | // > "Superstar - Madonna" 30 | -------------------------------------------------------------------------------- /appendix/es6/const_let.js: -------------------------------------------------------------------------------- 1 | var myVariable = 5; 2 | -------------------------------------------------------------------------------- /appendix/es6/default_args.js: -------------------------------------------------------------------------------- 1 | function divide(a, b) { 2 | // Default divisor to `1` 3 | const divisor = typeof b === 'undefined' ? 1 : b; 4 | 5 | return a / divisor; 6 | } 7 | 8 | function divide(a, b = 1) { 9 | return a / b; 10 | } 11 | 12 | divide(14, 2); 13 | // => 7 14 | divide(14, undefined); 15 | // => 14 16 | divide(14); 17 | // => 14 18 | 19 | divide(14, null); // `null` is used as divisor 20 | // => Infinity // 14 / null 21 | -------------------------------------------------------------------------------- /appendix/es6/destructuring_assignments.js: -------------------------------------------------------------------------------- 1 | var fruits = [ 'apples', 'bananas', 'oranges' ]; 2 | var fruit1 = fruits[0]; 3 | var fruit2 = fruits[1]; 4 | 5 | const [ veg1, veg2 ] = [ 'asparagus', 'broccoli', 'onion' ]; 6 | console.log(veg1); // -> 'asparagus' 7 | console.log(veg2); // -> 'broccoli' 8 | 9 | const smoothie = { 10 | fats: [ 'avocado', 'peanut butter', 'greek yogurt' ], 11 | liquids: [ 'almond milk' ], 12 | greens: [ 'spinach' ], 13 | fruits: [ 'blueberry', 'banana' ], 14 | }; 15 | 16 | const { liquids, fruits } = smoothie; 17 | 18 | console.log(liquids); // -> [ 'almond milk' ] 19 | console.log(fruits); // -> [ 'blueberry', 'banana' ] 20 | 21 | const containsSpinach = ({ greens }) => { 22 | if (greens.find(g => g === 'spinach')) { 23 | return true; 24 | } else { 25 | return false; 26 | } 27 | }; 28 | 29 | containsSpinach(smoothie); // -> true 30 | -------------------------------------------------------------------------------- /appendix/es6/enhanced_object_literals.js: -------------------------------------------------------------------------------- 1 | const explicit = { 2 | getState: getState, 3 | dispatch: dispatch, 4 | }; 5 | 6 | const implicit = { 7 | getState, 8 | dispatch, 9 | }; 10 | -------------------------------------------------------------------------------- /appendix/es6/object_assign.js: -------------------------------------------------------------------------------- 1 | const coffee = { }; 2 | const noCream = { cream: false }; 3 | const noMilk = { milk: false }; 4 | Object.assign(coffee, noCream); 5 | // coffee is now: `{ cream: false }` 6 | Object.assign(coffee, noMilk); 7 | // coffee is now: `{ cream: false, milk: false }` 8 | 9 | const coffeeWithMilk = Object.assign({}, coffee, { milk: true }); 10 | // coffeeWithMilk is: `{ cream: false, milk: true }` 11 | // coffee was not modified: `{ cream: false, milk: false }` 12 | -------------------------------------------------------------------------------- /appendix/es6/spread_operator_arrays.js: -------------------------------------------------------------------------------- 1 | const a = [ 1, 2, 3 ]; 2 | const b = [ 4, 5, 6 ]; 3 | const c = [ ...a, ...b, 7, 8, 9 ]; 4 | 5 | console.log(c); // -> [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] 6 | 7 | const d = [ a, b, 7, 8, 9 ]; 8 | console.log(d); // -> [ [ 1, 2, 3 ], [ 4, 5, 6 ], 7, 8, 9 ] 9 | -------------------------------------------------------------------------------- /appendix/es6/template_literals_1.js: -------------------------------------------------------------------------------- 1 | 2 | var greeting = 'Hello, ' + user + '! It is ' + degF + ' degrees outside.'; 3 | -------------------------------------------------------------------------------- /appendix/es6/template_literals_2.js: -------------------------------------------------------------------------------- 1 | 2 | const greeting = `Hello, ${user}! It is ${degF} degrees outside.`; 3 | -------------------------------------------------------------------------------- /appendix/store/simpleStore/NumberDisplay.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 19 | -------------------------------------------------------------------------------- /appendix/store/simpleStore/NumberSubmit.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 25 | -------------------------------------------------------------------------------- /appendix/store/simpleStore/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | export const store = { 4 | state: { 5 | numbers: [1, 2, 3] 6 | }, 7 | pushNewNumber(newNumberString) { 8 | this.state.numbers.push(Number(newNumberString)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /calendar_app/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw* 22 | -------------------------------------------------------------------------------- /calendar_app/README.md: -------------------------------------------------------------------------------- 1 | # Fullstack Vue 2 | 3 | ## Single-file components - Calendar App 4 | 5 | 1. Ensure you have `npm` installed. 6 | 7 | 2. Install the dependencies 8 | 9 | ```` 10 | npm install 11 | ```` 12 | 13 | 3. Boot the app 14 | 15 | ```` 16 | npm run serve 17 | ```` 18 | 19 | The server is now running - watch the console output for instructions, but by default, your server is now running (with hot reload) at [http://localhost:8080/](http://localhost:8080/) -------------------------------------------------------------------------------- /calendar_app/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /calendar_app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "calendar_app", 3 | "description": "Project Two: Calendar App", 4 | "version": "1.0.0", 5 | "author": "Fullstack.io", 6 | "private": true, 7 | "scripts": { 8 | "serve": "vue-cli-service serve", 9 | "build": "vue-cli-service build", 10 | "lint": "vue-cli-service lint" 11 | }, 12 | "dependencies": { 13 | "vue": "^2.5.17" 14 | }, 15 | "devDependencies": { 16 | "@vue/cli-service": "^3.0.0", 17 | "@vue/cli-plugin-babel": "^3.0.0", 18 | "@vue/cli-plugin-eslint": "^3.0.0", 19 | "node-sass": "^4.9.0", 20 | "sass-loader": "^7.0.1", 21 | "vue-template-compiler": "^2.5.17" 22 | }, 23 | "eslintConfig": { 24 | "root": true, 25 | "env": { 26 | "node": true 27 | }, 28 | "extends": [ 29 | "plugin:vue/essential", 30 | "eslint:recommended" 31 | ], 32 | "rules": {}, 33 | "parserOptions": { 34 | "parser": "babel-eslint" 35 | } 36 | }, 37 | "postcss": { 38 | "plugins": { 39 | "autoprefixer": {} 40 | } 41 | }, 42 | "browserslist": [ 43 | "> 1%", 44 | "last 2 versions", 45 | "not ie <= 8" 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /calendar_app/public/bulma/bulma.css.map: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/calendar_app/public/bulma/bulma.css.map -------------------------------------------------------------------------------- /calendar_app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/calendar_app/public/favicon.ico -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/HELP-US-OUT.txt: -------------------------------------------------------------------------------- 1 | I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project, 2 | Fort Awesome (https://fortawesome.com). It makes it easy to put the perfect icons on your website. Choose from our awesome, 3 | comprehensive icon sets or copy and paste your own. 4 | 5 | Please. Check it out. 6 | 7 | -Dave Gandy 8 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/calendar_app/public/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/calendar_app/public/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/calendar_app/public/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/calendar_app/public/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/calendar_app/public/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/less/animated.less: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .@{fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .@{fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/less/bordered-pulled.less: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em @fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .@{fa-css-prefix}-pull-left { float: left; } 11 | .@{fa-css-prefix}-pull-right { float: right; } 12 | 13 | .@{fa-css-prefix} { 14 | &.@{fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.@{fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .@{fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/less/core.less: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .@{fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/less/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | @import "path.less"; 9 | @import "core.less"; 10 | @import "larger.less"; 11 | @import "fixed-width.less"; 12 | @import "list.less"; 13 | @import "bordered-pulled.less"; 14 | @import "animated.less"; 15 | @import "rotated-flipped.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | @import "screen-reader.less"; 19 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/less/larger.less: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .@{fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .@{fa-css-prefix}-2x { font-size: 2em; } 11 | .@{fa-css-prefix}-3x { font-size: 3em; } 12 | .@{fa-css-prefix}-4x { font-size: 4em; } 13 | .@{fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/less/list.less: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: @fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), 9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/less/screen-reader.less: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { .sr-only(); } 5 | .sr-only-focusable { .sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .#{$fa-css-prefix}-pull-left { float: left; } 11 | .#{$fa-css-prefix}-pull-right { float: right; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .#{$fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), 9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/scss/_screen-reader.scss: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { @include sr-only(); } 5 | .sr-only-focusable { @include sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /calendar_app/public/font-awesome/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "animated"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | @import "screen-reader"; 19 | -------------------------------------------------------------------------------- /calendar_app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Project Two: Calendar App 9 | 10 | 12 | 14 | 15 | 16 | 19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /calendar_app/src/app-1/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 26 | 27 | 39 | -------------------------------------------------------------------------------- /calendar_app/src/app-1/components/CalendarEntry.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 18 | 19 | 61 | -------------------------------------------------------------------------------- /calendar_app/src/app-2/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 26 | 27 | 39 | -------------------------------------------------------------------------------- /calendar_app/src/app-2/components/CalendarWeek.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | 28 | 36 | -------------------------------------------------------------------------------- /calendar_app/src/app-2/store.js: -------------------------------------------------------------------------------- 1 | import { seedData } from './seed.js'; 2 | 3 | export const store = { 4 | state: { 5 | seedData 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /calendar_app/src/app-3/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 26 | 27 | 39 | -------------------------------------------------------------------------------- /calendar_app/src/app-3/components/CalendarDay.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 25 | 26 | 58 | -------------------------------------------------------------------------------- /calendar_app/src/app-3/components/CalendarEvent.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 26 | 27 | 55 | -------------------------------------------------------------------------------- /calendar_app/src/app-3/components/CalendarWeek.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | 28 | 36 | -------------------------------------------------------------------------------- /calendar_app/src/app-3/store.js: -------------------------------------------------------------------------------- 1 | import { seedData } from './seed.js'; 2 | 3 | export const store = { 4 | state: { 5 | seedData 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /calendar_app/src/app-4/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 26 | 27 | 39 | -------------------------------------------------------------------------------- /calendar_app/src/app-4/components/CalendarEvent.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 26 | 27 | 55 | -------------------------------------------------------------------------------- /calendar_app/src/app-4/components/CalendarWeek.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | 28 | 36 | -------------------------------------------------------------------------------- /calendar_app/src/app-4/store.js: -------------------------------------------------------------------------------- 1 | import { seedData } from './seed.js'; 2 | 3 | export const store = { 4 | state: { 5 | seedData 6 | }, 7 | getActiveDay () { 8 | return this.state.seedData.find((day) => day.active); 9 | }, 10 | setActiveDay (dayId) { 11 | this.state.seedData.map((dayObj) => { 12 | dayObj.id === dayId ? dayObj.active = true : dayObj.active = false; 13 | }); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /calendar_app/src/app-5/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 26 | 27 | 39 | -------------------------------------------------------------------------------- /calendar_app/src/app-5/components/CalendarEvent.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 26 | 27 | 55 | -------------------------------------------------------------------------------- /calendar_app/src/app-5/components/CalendarWeek.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | 28 | 36 | -------------------------------------------------------------------------------- /calendar_app/src/app-5/store.js: -------------------------------------------------------------------------------- 1 | import { seedData } from './seed.js'; 2 | 3 | export const store = { 4 | state: { 5 | seedData 6 | }, 7 | getActiveDay () { 8 | return this.state.seedData.find((day) => day.active); 9 | }, 10 | setActiveDay (dayId) { 11 | this.state.seedData.map((dayObj) => { 12 | dayObj.id === dayId ? dayObj.active = true : dayObj.active = false; 13 | }); 14 | }, 15 | submitEvent (eventDetails) { 16 | const activeDay = this.getActiveDay(); 17 | activeDay.events.push({ "details": eventDetails, "edit": false }); 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /calendar_app/src/app-6/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 26 | 27 | 39 | -------------------------------------------------------------------------------- /calendar_app/src/app-6/components/CalendarWeek.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | 28 | 36 | -------------------------------------------------------------------------------- /calendar_app/src/app-6/store.js: -------------------------------------------------------------------------------- 1 | import { seedData } from './seed.js'; 2 | 3 | export const store = { 4 | state: { 5 | seedData 6 | }, 7 | getActiveDay () { 8 | return this.state.seedData.find((day) => day.active); 9 | }, 10 | setActiveDay (dayId) { 11 | this.state.seedData.map((dayObj) => { 12 | dayObj.id === dayId ? dayObj.active = true : dayObj.active = false; 13 | }); 14 | }, 15 | submitEvent (eventDetails) { 16 | const activeDay = this.getActiveDay(); 17 | activeDay.events.push({ "details": eventDetails, "edit": false }); 18 | }, 19 | editEvent (dayId, eventDetails) { 20 | this.resetEditOfAllEvents(); 21 | const dayObj = this.state.seedData.find( 22 | day => day.id === dayId 23 | ); 24 | const eventObj = dayObj.events.find( 25 | event => event.details === eventDetails 26 | ); 27 | eventObj.edit = true; 28 | }, 29 | resetEditOfAllEvents () { 30 | this.state.seedData.map((dayObj) => { 31 | dayObj.events.map((event) => { 32 | event.edit = false; 33 | }); 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /calendar_app/src/app-7/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 26 | 27 | 39 | -------------------------------------------------------------------------------- /calendar_app/src/app-7/components/CalendarWeek.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | 28 | 36 | -------------------------------------------------------------------------------- /calendar_app/src/app-complete/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | 26 | 27 | 39 | -------------------------------------------------------------------------------- /calendar_app/src/app-complete/components/CalendarWeek.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | 28 | 36 | -------------------------------------------------------------------------------- /calendar_app/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './app-complete/App.vue'; 3 | 4 | new Vue({ 5 | render: h => h(App) 6 | }).$mount('#app'); 7 | -------------------------------------------------------------------------------- /custom_events/app-1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Custom Events 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 | Notes 16 |
17 |
18 | Timestamp 19 |
20 |
21 | 22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /custom_events/app-1/main.js: -------------------------------------------------------------------------------- 1 | const inputComponent = { 2 | template: ``, 7 | props: ['placeholder'], 8 | data() { 9 | return { 10 | input: '' 11 | } 12 | } 13 | } 14 | 15 | new Vue({ 16 | el: '#app', 17 | data: { 18 | notes: [], 19 | timestamps: [], 20 | placeholder: 'Enter a note' 21 | }, 22 | components: { 23 | 'input-component': inputComponent 24 | } 25 | }) 26 | -------------------------------------------------------------------------------- /custom_events/app-2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Custom Events 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 | Notes 16 |
17 | {{ note }} 18 |
19 |
20 |
21 | Timestamp 22 |
23 | {{ timestamp }} 24 |
25 |
26 |
27 | 29 |
30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /custom_events/app-2/main.js: -------------------------------------------------------------------------------- 1 | const inputComponent = { 2 | template: ``, 7 | props: ['placeholder'], 8 | data() { 9 | return { 10 | input: '' 11 | }; 12 | }, 13 | methods: { 14 | monitorEnterKey() { 15 | this.$emit('add-note', { 16 | note: this.input, 17 | timestamp: new Date().toLocaleString() 18 | }); 19 | this.input = ''; 20 | } 21 | } 22 | }; 23 | 24 | new Vue({ 25 | el: '#app', 26 | data: { 27 | notes: [], 28 | timestamps: [], 29 | placeholder: 'Enter a note' 30 | }, 31 | methods: { 32 | addNote(event) { 33 | this.notes.push(event.note); 34 | this.timestamps.push(event.timestamp); 35 | } 36 | }, 37 | components: { 38 | 'input-component': inputComponent 39 | } 40 | }); 41 | -------------------------------------------------------------------------------- /custom_events/app-complete/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Custom Events 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 | Notes 16 |
17 | {{ note }} 18 |
19 |
20 |
21 | Timestamp 22 |
23 | {{ timestamp }} 24 |
25 |
26 |
27 | 28 |
29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /custom_events/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | Custom Events 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 | Notes 18 |
19 |
20 | Timestamp 21 |
22 |
23 | 24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /custom_events/app/main.js: -------------------------------------------------------------------------------- 1 | const inputComponent = { 2 | template: `` 3 | } 4 | 5 | new Vue({ 6 | el: '#app', 7 | components: { 8 | 'input-component': inputComponent 9 | } 10 | }) 11 | -------------------------------------------------------------------------------- /custom_events/public/styles.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | } 4 | 5 | #app { 6 | height: inherit; 7 | margin: 0 auto; 8 | display: flex; 9 | flex-direction: column; 10 | align-items: center; 11 | -webkit-align-items: center; 12 | justify-content: center; 13 | -webkit-justify-content: center; 14 | } 15 | 16 | .notes-section { 17 | width: 500px; 18 | } 19 | 20 | .columns { 21 | width: 100%; 22 | } 23 | 24 | .notes, .timestamps { 25 | padding: 5px 0px; 26 | } 27 | 28 | .note-count { 29 | margin-top: 48px; 30 | } -------------------------------------------------------------------------------- /form_handling/01-basic-button/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 01_Basic_Button 7 | 12 | 13 | 14 | 15 |
16 |

What's your favorite Fullstack clothing item?

17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /form_handling/01-basic-button/main.js: -------------------------------------------------------------------------------- 1 | const ButtonRow = { 2 | template: ` 3 |
4 | 5 | 6 | 7 | 8 |
`, 9 | methods: { 10 | onHoodieClick(evt) { 11 | console.log('The user clicked button-hoodie', evt); 12 | }, 13 | onTeeClick(evt) { 14 | console.log('The user clicked button-tee', evt); 15 | }, 16 | onFittedCapClick(evt) { 17 | console.log('The user clicked button-fitted-cap', evt); 18 | }, 19 | onJacketClick(evt) { 20 | console.log('The user clicked button-jacket', evt); 21 | } 22 | } 23 | } 24 | 25 | new Vue({ 26 | el: '#app', 27 | components: { 28 | 'button-row': ButtonRow 29 | } 30 | }) 31 | -------------------------------------------------------------------------------- /form_handling/02-basic-button/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 02_Basic_Button 7 | 12 | 13 | 14 | 15 |
16 |

What's your favorite Fullstack clothing item?

17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /form_handling/02-basic-button/main.js: -------------------------------------------------------------------------------- 1 | const ButtonRow = { 2 | template: ` 3 |
4 | 8 | 12 | 16 | 20 |
`, 21 | methods: { 22 | onButtonClick(evt) { 23 | const button = evt.target; 24 | console.log(`The user clicked ${button.name}: ${button.value}`); 25 | } 26 | } 27 | } 28 | 29 | new Vue({ 30 | el: '#app', 31 | components: { 32 | 'button-row': ButtonRow 33 | } 34 | }) 35 | -------------------------------------------------------------------------------- /form_handling/03-basic-input/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 03_Basic_Input 7 | 15 | 16 | 17 | 18 |
19 |

Fullstack Clothing Inquiry Sheet

20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /form_handling/03-basic-input/main.js: -------------------------------------------------------------------------------- 1 | const InputForm = { 2 | template: ` 3 |
4 |
5 |
6 | 7 |
8 | 9 |
10 |
`, 11 | methods: { 12 | submitForm(evt) { 13 | evt.preventDefault(); 14 | console.log(this.$refs.newItem.value) 15 | } 16 | } 17 | } 18 | 19 | new Vue({ 20 | el: '#app', 21 | components: { 22 | 'input-form': InputForm 23 | } 24 | }) 25 | -------------------------------------------------------------------------------- /form_handling/04-data-input/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 04_Data_Input 7 | 15 | 16 | 17 | 18 |
19 |

Fullstack Clothing Inquiry Sheet

20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /form_handling/04-data-input/main.js: -------------------------------------------------------------------------------- 1 | const InputForm = { 2 | template: ` 3 |
4 |
\ 5 |
6 | 7 |
8 | 9 |
10 |
`, 11 | data() { 12 | return { 13 | newItem: '' 14 | } 15 | }, 16 | methods: { 17 | submitForm(evt) { 18 | evt.preventDefault(); 19 | console.log(this.newItem) 20 | } 21 | } 22 | } 23 | 24 | new Vue({ 25 | el: '#app', 26 | components: { 27 | 'input-form': InputForm 28 | } 29 | }) 30 | -------------------------------------------------------------------------------- /form_handling/05-data-input-list/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 05_Data_Input_List 7 | 15 | 16 | 17 | 18 |
19 |

Fullstack Clothing Inquiry Sheet

20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /form_handling/05-data-input-list/main.js: -------------------------------------------------------------------------------- 1 | const InputForm = { 2 | template: ` 3 |
4 |
5 |
6 | 7 |
8 | 9 |
10 |
11 |

Items

12 | 15 |
16 |
`, 17 | data() { 18 | return { 19 | newItem: '', 20 | items: [] 21 | } 22 | }, 23 | methods: { 24 | submitForm(evt) { 25 | this.items.push(this.newItem); 26 | this.newItem = ''; 27 | evt.preventDefault(); 28 | } 29 | } 30 | } 31 | 32 | new Vue({ 33 | el: '#app', 34 | components: { 35 | 'input-form': InputForm 36 | } 37 | }) 38 | -------------------------------------------------------------------------------- /form_handling/06-data-input-multi/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 06_Data_Input_Multi 7 | 15 | 16 | 17 | 18 |
19 |

Fullstack Clothing Inquiry Sheet

20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /form_handling/07-basic-form-validation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 07_Basic_Form_Validation 7 | 15 | 16 | 17 | 18 |
19 |

Fullstack Clothing Inquiry Sheet

20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /form_handling/08-basic-field-validation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 08_Basic_Field_Validation 7 | 15 | 16 | 17 | 18 |
19 |

Fullstack Clothing Inquiry Sheet

20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /form_handling/09-remote-persist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 09_Remote_Persist 7 | 15 | 16 | 17 | 18 |
19 |

Fullstack Clothing Inquiry Sheet

20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /form_handling/10-vuex-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10_Vuex_App 7 | 15 | 16 | 17 | 18 |
19 |

Fullstack Clothing Inquiry Sheet

20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /form_handling/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Form App 7 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /form_handling/app/main.js: -------------------------------------------------------------------------------- 1 | new Vue({ 2 | el: '#app', 3 | }) 4 | -------------------------------------------------------------------------------- /my/upvote/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |

UpVote!

12 |
13 | 14 | 15 | 17 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-1/components/product/ProductList.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 34 | 35 | 53 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-1/components/product/ProductListItem.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 30 | 31 | 36 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-1/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import VueRouter from 'vue-router'; 3 | import CartList from '../components/cart/CartList.vue'; 4 | import ProductList from '../components/product/ProductList.vue'; 5 | import NotFound from '../components/NotFound.vue'; 6 | 7 | Vue.use(VueRouter); 8 | 9 | const router = new VueRouter({ 10 | mode: 'history', 11 | routes: [ 12 | { 13 | path: '/products', 14 | component: ProductList 15 | }, 16 | { 17 | path: '/cart', 18 | component: CartList 19 | }, 20 | { 21 | path: '/', 22 | redirect: '/products' 23 | }, 24 | { 25 | path: '*', 26 | component: NotFound 27 | } 28 | ] 29 | }); 30 | 31 | export default router; 32 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-1/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import product from './modules/product'; 4 | import cart from './modules/cart'; 5 | 6 | Vue.use(Vuex); 7 | 8 | export default new Vuex.Store({ 9 | modules: { 10 | product, 11 | cart 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-1/store/modules/product/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const state = { 4 | productItems: [] 5 | } 6 | 7 | const mutations = { 8 | UPDATE_PRODUCT_ITEMS (state, payload) { 9 | state.productItems = payload; 10 | } 11 | } 12 | 13 | const actions = { 14 | getProductItems ({ commit }) { 15 | axios.get('/api/products?token=D6W69PRgCoDKgHZGJmRUNA').then((response) => { 16 | commit('UPDATE_PRODUCT_ITEMS', response.data) 17 | }); 18 | } 19 | } 20 | 21 | const getters = { 22 | productItems: state => state.productItems 23 | } 24 | 25 | const productModule = { 26 | state, 27 | mutations, 28 | actions, 29 | getters 30 | } 31 | 32 | export default productModule; 33 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-2/assets/cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app-2/assets/cap.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-2/assets/hoodie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app-2/assets/hoodie.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-2/assets/jacket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app-2/assets/jacket.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-2/assets/tee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app-2/assets/tee.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-2/components/NotFound.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 17 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-2/components/product/ProductList.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 34 | 35 | 53 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-2/components/product/ProductListItem.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 32 | 33 | 38 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-2/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import VueRouter from 'vue-router'; 3 | import CartList from '../components/cart/CartList.vue'; 4 | import ProductList from '../components/product/ProductList.vue'; 5 | import ProductItem from '../components/product/ProductItem.vue'; 6 | import NotFound from '../components/NotFound.vue'; 7 | 8 | Vue.use(VueRouter); 9 | 10 | const router = new VueRouter({ 11 | mode: 'history', 12 | routes: [ 13 | { 14 | path: '/products', 15 | component: ProductList 16 | }, 17 | { 18 | path: '/products/:id', 19 | component: ProductItem, 20 | props: true 21 | }, 22 | { 23 | path: '/cart', 24 | component: CartList 25 | }, 26 | { 27 | path: '/', 28 | redirect: '/products' 29 | }, 30 | { 31 | path: '*', 32 | component: NotFound 33 | } 34 | ] 35 | }); 36 | 37 | export default router; 38 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-2/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import product from './modules/product'; 4 | import cart from './modules/cart'; 5 | 6 | Vue.use(Vuex); 7 | 8 | export default new Vuex.Store({ 9 | modules: { 10 | product, 11 | cart 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-2/store/modules/product/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const state = { 4 | productItems: [] 5 | } 6 | 7 | const mutations = { 8 | UPDATE_PRODUCT_ITEMS (state, payload) { 9 | state.productItems = payload; 10 | } 11 | } 12 | 13 | const actions = { 14 | getProductItems ({ commit }) { 15 | axios.get('/api/products?token=D6W69PRgCoDKgHZGJmRUNA').then((response) => { 16 | commit('UPDATE_PRODUCT_ITEMS', response.data) 17 | }); 18 | } 19 | } 20 | 21 | const getters = { 22 | productItems: state => state.productItems, 23 | productItemFromId: (state) => (id) => { 24 | return state.productItems.find(productItem => productItem.id === id) 25 | } 26 | } 27 | 28 | const productModule = { 29 | state, 30 | mutations, 31 | actions, 32 | getters 33 | } 34 | 35 | export default productModule; 36 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-3/assets/cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app-3/assets/cap.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-3/assets/hoodie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app-3/assets/hoodie.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-3/assets/jacket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app-3/assets/jacket.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-3/assets/tee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app-3/assets/tee.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-3/components/NotFound.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 17 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-3/components/login/LoginBox.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 30 | 31 | 36 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-3/components/product/ProductList.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 34 | 35 | 53 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-3/components/product/ProductListItem.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 32 | 33 | 38 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-3/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import VueRouter from 'vue-router'; 3 | import CartList from '../components/cart/CartList.vue'; 4 | import ProductList from '../components/product/ProductList.vue'; 5 | import ProductItem from '../components/product/ProductItem.vue'; 6 | import LoginBox from '../components/login/LoginBox.vue'; 7 | import NotFound from '../components/NotFound.vue'; 8 | 9 | Vue.use(VueRouter); 10 | 11 | const router = new VueRouter({ 12 | mode: 'history', 13 | routes: [ 14 | { 15 | path: '/products', 16 | component: ProductList 17 | }, 18 | { 19 | path: '/products/:id', 20 | component: ProductItem, 21 | props: true 22 | }, 23 | { 24 | path: '/cart', 25 | component: CartList 26 | }, 27 | { 28 | path: '/login', 29 | component: LoginBox 30 | }, 31 | { 32 | path: '/', 33 | redirect: '/products' 34 | }, 35 | { 36 | path: '*', 37 | component: NotFound 38 | } 39 | ] 40 | }); 41 | 42 | export default router; 43 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-3/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import product from './modules/product'; 4 | import cart from './modules/cart'; 5 | import login from './modules/login'; 6 | 7 | Vue.use(Vuex); 8 | 9 | export default new Vuex.Store({ 10 | modules: { 11 | product, 12 | cart, 13 | login 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-3/store/modules/login/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const state = { 4 | token: null, 5 | loading: false 6 | } 7 | 8 | const mutations = { 9 | SET_TOKEN (state, token) { 10 | state.token = token; 11 | }, 12 | LOGIN_PENDING (state) { 13 | state.loading = true; 14 | }, 15 | LOGIN_SUCCESS (state) { 16 | state.loading = false; 17 | } 18 | } 19 | 20 | const actions = { 21 | login ({ commit }) { 22 | commit('LOGIN_PENDING'); // login pending 23 | return axios.post('/api/login').then((response) => { 24 | localStorage.setItem("token", response.data.token); 25 | commit('SET_TOKEN', response.data.token); 26 | commit('LOGIN_SUCCESS'); // login success 27 | }); 28 | }, 29 | logout ({ commit }) { 30 | return new Promise((resolve) => { 31 | localStorage.removeItem("token"); 32 | commit('SET_TOKEN', null); 33 | resolve(); 34 | }); 35 | } 36 | } 37 | 38 | const getters = { 39 | token: state => state.token, 40 | loading: state => state.loading 41 | } 42 | 43 | const loginModule = { 44 | state, 45 | mutations, 46 | actions, 47 | getters 48 | } 49 | 50 | export default loginModule; 51 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-3/store/modules/product/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const state = { 4 | productItems: [] 5 | } 6 | 7 | const mutations = { 8 | UPDATE_PRODUCT_ITEMS (state, payload) { 9 | state.productItems = payload; 10 | } 11 | } 12 | 13 | const actions = { 14 | getProductItems ({ commit }, token) { 15 | axios.get(`/api/products?token=${token}`).then((response) => { 16 | commit('UPDATE_PRODUCT_ITEMS', response.data) 17 | }); 18 | } 19 | } 20 | 21 | const getters = { 22 | productItems: state => state.productItems, 23 | productItemFromId: (state) => (id) => { 24 | return state.productItems.find(productItem => productItem.id === id) 25 | } 26 | } 27 | 28 | const productModule = { 29 | state, 30 | mutations, 31 | actions, 32 | getters 33 | } 34 | 35 | export default productModule; 36 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-complete/assets/cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app-complete/assets/cap.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-complete/assets/hoodie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app-complete/assets/hoodie.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-complete/assets/jacket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app-complete/assets/jacket.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-complete/assets/tee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app-complete/assets/tee.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-complete/components/NotFound.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 17 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-complete/components/login/LoginBox.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 30 | 31 | 36 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-complete/components/product/ProductList.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 34 | 35 | 53 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-complete/components/product/ProductListItem.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 32 | 33 | 38 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-complete/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import product from './modules/product'; 4 | import cart from './modules/cart'; 5 | import login from './modules/login'; 6 | 7 | Vue.use(Vuex); 8 | 9 | export default new Vuex.Store({ 10 | modules: { 11 | product, 12 | cart, 13 | login 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-complete/store/modules/login/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const state = { 4 | token: null, 5 | loading: false 6 | } 7 | 8 | const mutations = { 9 | SET_TOKEN (state, token) { 10 | state.token = token; 11 | }, 12 | LOGIN_PENDING (state) { 13 | state.loading = true; 14 | }, 15 | LOGIN_SUCCESS (state) { 16 | state.loading = false; 17 | } 18 | } 19 | 20 | const actions = { 21 | login ({ commit }) { 22 | commit('LOGIN_PENDING'); 23 | return axios.post('/api/login').then((response) => { 24 | localStorage.setItem("token", response.data.token); 25 | commit('SET_TOKEN', response.data.token); 26 | commit('LOGIN_SUCCESS'); 27 | }); 28 | }, 29 | logout ({ commit }) { 30 | return new Promise((resolve) => { 31 | localStorage.removeItem("token"); 32 | commit('SET_TOKEN', null); 33 | resolve(); 34 | }); 35 | } 36 | } 37 | 38 | const getters = { 39 | token: state => state.token, 40 | loading: state => state.loading 41 | } 42 | 43 | const loginModule = { 44 | state, 45 | mutations, 46 | actions, 47 | getters 48 | } 49 | 50 | export default loginModule; 51 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app-complete/store/modules/product/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const state = { 4 | productItems: [] 5 | } 6 | 7 | const mutations = { 8 | UPDATE_PRODUCT_ITEMS (state, payload) { 9 | state.productItems = payload; 10 | } 11 | } 12 | 13 | const actions = { 14 | getProductItems ({ commit }, token) { 15 | axios.get(`/api/products?token=${token}`).then((response) => { 16 | commit('UPDATE_PRODUCT_ITEMS', response.data) 17 | }); 18 | } 19 | } 20 | 21 | const getters = { 22 | productItems: state => state.productItems, 23 | productItemFromId: (state) => (id) => { 24 | return state.productItems.find(productItem => productItem.id === id) 25 | } 26 | } 27 | 28 | const productModule = { 29 | state, 30 | mutations, 31 | actions, 32 | getters 33 | } 34 | 35 | export default productModule; 36 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app/App.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 28 | 29 | 65 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app/assets/cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app/assets/cap.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app/assets/hoodie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app/assets/hoodie.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app/assets/jacket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app/assets/jacket.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app/assets/tee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/routing/shopping_cart/src/app/assets/tee.png -------------------------------------------------------------------------------- /routing/shopping_cart/src/app/components/product/ProductList.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 37 | 38 | 56 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app/components/product/ProductListItem.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 30 | 31 | 36 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import product from './modules/product'; 4 | import cart from './modules/cart'; 5 | 6 | Vue.use(Vuex); 7 | 8 | export default new Vuex.Store({ 9 | modules: { 10 | product, 11 | cart 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/app/store/modules/product/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const state = { 4 | productItems: [] 5 | } 6 | 7 | const mutations = { 8 | UPDATE_PRODUCT_ITEMS (state, payload) { 9 | state.productItems = payload; 10 | } 11 | } 12 | 13 | const actions = { 14 | getProductItems ({ commit }) { 15 | axios.get('/api/products?token=D6W69PRgCoDKgHZGJmRUNA').then((response) => { 16 | commit('UPDATE_PRODUCT_ITEMS', response.data) 17 | }); 18 | } 19 | } 20 | 21 | const getters = { 22 | productItems: state => state.productItems 23 | } 24 | 25 | const productModule = { 26 | state, 27 | mutations, 28 | actions, 29 | getters 30 | } 31 | 32 | export default productModule; 33 | -------------------------------------------------------------------------------- /routing/shopping_cart/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './app-complete/App.vue'; 3 | import router from './app-complete/router'; 4 | import store from './app-complete/store'; 5 | 6 | new Vue({ 7 | router, 8 | store, 9 | render: h => h(App) 10 | }).$mount('#app'); 11 | -------------------------------------------------------------------------------- /routing/shopping_cart/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | devServer: { 3 | proxy: { 4 | '/api': { 5 | target: 'http://localhost:3000/', 6 | changeOrigin: true, 7 | pathRewrite: { 8 | '^/api': '' 9 | } 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /testing/basics/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw* 22 | -------------------------------------------------------------------------------- /testing/basics/README.md: -------------------------------------------------------------------------------- 1 | # Fullstack Vue 2 | 3 | ## Testing - Basics 4 | 5 | 1. Ensure you have `npm` installed. 6 | 7 | 2. Install the dependencies 8 | 9 | ```` 10 | npm install 11 | ```` 12 | 13 | 3. Boot the app 14 | 15 | ```` 16 | npm run serve 17 | ```` 18 | 19 | The server is now running - watch the console output for instructions, but by default, your server is now running (with hot reload) at [http://localhost:8080/](http://localhost:8080/) 20 | 21 | 4. Run unit tests of working file 22 | 23 | ```` 24 | npm run test 25 | ```` 26 | 27 | 5. Run unit tests of working file, in watch mode 28 | 29 | ```` 30 | npm run test:watch 31 | ```` 32 | 33 | 6. Run all unit tests 34 | 35 | ```` 36 | npm run test:unit 37 | ```` -------------------------------------------------------------------------------- /testing/basics/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /testing/basics/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/testing/basics/public/favicon.ico -------------------------------------------------------------------------------- /testing/basics/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Testing - Basics 9 | 10 | 11 | 12 | 13 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /testing/basics/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | 4 | new Vue({ 5 | render: h => h(App) 6 | }).$mount('#app'); 7 | -------------------------------------------------------------------------------- /testing/basics/tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | mocha: true 4 | } 5 | } -------------------------------------------------------------------------------- /testing/basics/tests/unit/App.1.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from '@/App'; 3 | import { expect } from 'chai'; 4 | 5 | describe('App.vue', () => { 6 | it('should render correct contents', () => { 7 | const Constructor = Vue.extend(App); 8 | const vm = new Constructor().$mount(); 9 | 10 | expect( 11 | vm.$el.querySelector('.ui.selectable thead tr th').textContent 12 | ).to.contain('Items'); 13 | expect( 14 | vm.$el.querySelector('.ui.button').textContent 15 | ).to.contain('Add'); 16 | expect( 17 | vm.$el.querySelector('.ui.label').textContent 18 | ).to.contain('Remove all'); 19 | }); 20 | 21 | it('should set correct default data', () => { 22 | const initialData = App.data(); 23 | 24 | expect(initialData.item).to.equal(''); 25 | expect(initialData.items).to.deep.equal([]); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /testing/basics/tests/unit/App.2.spec.js: -------------------------------------------------------------------------------- 1 | import App from '@/App'; 2 | import {shallowMount} from '@vue/test-utils'; 3 | import { expect } from 'chai'; 4 | 5 | describe('App.vue', () => { 6 | let wrapper; 7 | 8 | beforeEach(() => { 9 | wrapper = shallowMount(App); 10 | }); 11 | 12 | it('should render correct contents', () => { 13 | expect(wrapper.html()).to.contain('Items'); 14 | expect(wrapper.html()).to.contain( 15 | '' 16 | ); 17 | expect(wrapper.html()).to.contain( 18 | '' 19 | ); 20 | expect(wrapper.html()).to.contain( 21 | 'Remove all' 22 | ); 23 | }); 24 | 25 | it('should set correct default data', () => { 26 | expect(wrapper.vm.item).to.equal(''); 27 | expect(wrapper.vm.items).to.deep.equal([]); 28 | }); 29 | 30 | it('should have the "Add" button disabled', () => { 31 | const addItemButton = wrapper.find('.ui.button'); 32 | 33 | expect(addItemButton.element.disabled).to.be.true; 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /testing/basics/tests/unit/App.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | 3 | describe('App.vue', () => { 4 | it('should run this dummy test', () => { 5 | expect('Dummy' + ' Test!').to.equal('Dummy Test!'); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /testing/weather/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw* 22 | -------------------------------------------------------------------------------- /testing/weather/README.md: -------------------------------------------------------------------------------- 1 | # Fullstack Vue 2 | 3 | ## Testing - Weather 4 | 5 | 1. Ensure you have `npm` installed. 6 | 7 | 2. Install the dependencies 8 | 9 | ```` 10 | npm install 11 | ```` 12 | 13 | 3. Boot the app 14 | 15 | ```` 16 | npm run start 17 | ```` 18 | 19 | The Node and Webpack servers are now running - watch the console output for instructions. Your entire application is now available at [http://localhost:8080/](http://localhost:8080/) 20 | 21 | 4. Run unit tests of working file 22 | 23 | ```` 24 | npm run test 25 | ```` 26 | 27 | 5. Run unit tests of working file, in watch mode 28 | 29 | ```` 30 | npm run test:watch 31 | ```` 32 | 33 | 6. Run all unit tests 34 | 35 | ```` 36 | npm run test:unit 37 | ```` -------------------------------------------------------------------------------- /testing/weather/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /testing/weather/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/testing/weather/public/favicon.ico -------------------------------------------------------------------------------- /testing/weather/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Testing - Weather 9 | 10 | 11 | 12 | 13 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /testing/weather/server.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-param-reassign */ 2 | const express = require("express"); 3 | const bodyParser = require("body-parser"); 4 | const axios = require("axios"); 5 | 6 | const app = express(); 7 | 8 | app.set("port", process.env.PORT || 3000); 9 | 10 | app.use(bodyParser.json()); 11 | app.use(bodyParser.urlencoded({ extended: true })); 12 | 13 | app.use((req, res, next) => { 14 | res.setHeader( 15 | "Cache-Control", 16 | "no-cache, no-store, must-revalidate" 17 | ); 18 | res.setHeader("Pragma", "no-cache"); 19 | res.setHeader("Expires", "0"); 20 | next(); 21 | }); 22 | 23 | app.get("/weather", (req, res) => { 24 | const id = Number(req.query.id); 25 | axios.get(`https://www.metaweather.com/api/location/${id}/`) 26 | .then(response => { 27 | res.setHeader("Cache-Control", "no-cache"); 28 | res.json(response.data); 29 | }) 30 | .catch(error => { 31 | console.log(error); // eslint-disable-line no-console 32 | }); 33 | }); 34 | 35 | app.listen(app.get("port"), () => { 36 | console.log( // eslint-disable-line no-console 37 | `Find the server at: http://localhost:${app.get( 38 | "port" 39 | )}/` 40 | ); 41 | }); 42 | -------------------------------------------------------------------------------- /testing/weather/src/assets/c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/testing/weather/src/assets/c.png -------------------------------------------------------------------------------- /testing/weather/src/assets/h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/testing/weather/src/assets/h.png -------------------------------------------------------------------------------- /testing/weather/src/assets/hc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/testing/weather/src/assets/hc.png -------------------------------------------------------------------------------- /testing/weather/src/assets/hr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/testing/weather/src/assets/hr.png -------------------------------------------------------------------------------- /testing/weather/src/assets/lc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/testing/weather/src/assets/lc.png -------------------------------------------------------------------------------- /testing/weather/src/assets/lr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/testing/weather/src/assets/lr.png -------------------------------------------------------------------------------- /testing/weather/src/assets/s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/testing/weather/src/assets/s.png -------------------------------------------------------------------------------- /testing/weather/src/assets/sl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/testing/weather/src/assets/sl.png -------------------------------------------------------------------------------- /testing/weather/src/assets/sn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/testing/weather/src/assets/sn.png -------------------------------------------------------------------------------- /testing/weather/src/assets/t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/testing/weather/src/assets/t.png -------------------------------------------------------------------------------- /testing/weather/src/components/HomeContainer.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /testing/weather/src/components/NotFoundContainer.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /testing/weather/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App'; 3 | import router from './router'; 4 | import store from './store'; 5 | 6 | new Vue({ 7 | router, 8 | store, 9 | render: h => h(App) 10 | }).$mount('#app'); 11 | -------------------------------------------------------------------------------- /testing/weather/src/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import VueRouter from 'vue-router'; 3 | import HomeContainer from './components/HomeContainer.vue'; 4 | import WeatherContainer from './components/WeatherContainer.vue'; 5 | import NotFoundContainer from './components/NotFoundContainer.vue'; 6 | 7 | Vue.use(VueRouter); 8 | 9 | const router = new VueRouter({ 10 | mode: 'history', 11 | routes: [ 12 | { 13 | path: '/', 14 | component: HomeContainer 15 | }, 16 | { 17 | path: '/weather/:id', 18 | component: WeatherContainer, 19 | props: true, 20 | beforeEnter: (to, from, next) => { 21 | const id = to.params.id; 22 | if ( 23 | ![ 24 | 2459115, 25 | 468739, 26 | 2122265, 27 | 1118370, 28 | 1105779, 29 | 1398823 30 | ].includes(Number(id)) 31 | ) { 32 | next("/not-found"); 33 | } else { 34 | next(); 35 | } 36 | } 37 | }, 38 | { 39 | path: '*', 40 | component: NotFoundContainer 41 | } 42 | ] 43 | }); 44 | 45 | export default router; 46 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | mocha: true 4 | } 5 | } -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather-1/App.spec.js: -------------------------------------------------------------------------------- 1 | import Vuex from 'vuex'; 2 | import App from '@/App'; 3 | import { shallowMount, createLocalVue } from '@vue/test-utils'; 4 | import { expect } from 'chai'; 5 | 6 | describe('App.vue', () => { 7 | let wrapper; 8 | let store; 9 | let getters; 10 | 11 | beforeEach(() => { 12 | const localVue = createLocalVue(); 13 | localVue.use(Vuex); 14 | 15 | getters = { 16 | loading: () => { return false } 17 | } 18 | 19 | store = new Vuex.Store({ 20 | getters 21 | }); 22 | 23 | wrapper = shallowMount(App, { 24 | localVue, 25 | store, 26 | stubs: ['router-link', 'router-view'] 27 | }); 28 | }); 29 | 30 | it("should display the current day's date", () => { 31 | const formattedDate = new Date().toDateString(); 32 | expect(wrapper.html()).to.contain(formattedDate); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather-1/components/HomeContainer.spec.js: -------------------------------------------------------------------------------- 1 | import HomeContainer from '@/components/HomeContainer'; 2 | import {shallowMount} from '@vue/test-utils'; 3 | import { expect } from 'chai'; 4 | 5 | describe('HomeContainer.vue', () => { 6 | it('should display the appropriate index message', () => { 7 | const wrapper = shallowMount(HomeContainer); 8 | expect( 9 | wrapper.html() 10 | ).to.contain( 11 | '

Pick a city below to see the weather!

' 12 | ); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather-1/components/NotFoundContainer.spec.js: -------------------------------------------------------------------------------- 1 | import NotFoundContainer from '@/components/NotFoundContainer'; 2 | import {shallowMount} from '@vue/test-utils'; 3 | import { expect } from 'chai'; 4 | 5 | describe('NotFoundContainer.vue', () => { 6 | it('should display the appropriate not found message', () => { 7 | const wrapper = shallowMount(NotFoundContainer); 8 | expect( 9 | wrapper.html() 10 | ).to.contain( 11 | '

Sorry, this route does not exist :(

' 12 | ); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather-1/components/WeatherContainer.spec.js: -------------------------------------------------------------------------------- 1 | describe('WeatherContainer.vue', () => { 2 | 3 | }); 4 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather-2/components/HomeContainer.spec.js: -------------------------------------------------------------------------------- 1 | import HomeContainer from '@/components/HomeContainer'; 2 | import {shallowMount} from '@vue/test-utils'; 3 | import { expect } from 'chai'; 4 | 5 | describe('HomeContainer.vue', () => { 6 | it('should display the appropriate index message', () => { 7 | const wrapper = shallowMount(HomeContainer); 8 | expect( 9 | wrapper.html() 10 | ).to.contain( 11 | '

Pick a city below to see the weather!

' 12 | ); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather-2/components/NotFoundContainer.spec.js: -------------------------------------------------------------------------------- 1 | import NotFoundContainer from '@/components/NotFoundContainer'; 2 | import {shallowMount} from '@vue/test-utils'; 3 | import { expect } from 'chai'; 4 | 5 | describe('NotFoundContainer.vue', () => { 6 | it('should display the appropriate not found message', () => { 7 | const wrapper = shallowMount(NotFoundContainer); 8 | expect( 9 | wrapper.html() 10 | ).to.contain( 11 | '

Sorry, this route does not exist :(

' 12 | ); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather-2/components/WeatherContainer.spec.js: -------------------------------------------------------------------------------- 1 | describe('WeatherContainer.vue', () => { 2 | 3 | }); 4 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather-3/components/HomeContainer.spec.js: -------------------------------------------------------------------------------- 1 | import HomeContainer from '@/components/HomeContainer'; 2 | import {shallowMount} from '@vue/test-utils'; 3 | import { expect } from 'chai'; 4 | 5 | describe('HomeContainer.vue', () => { 6 | it('should display the appropriate index message', () => { 7 | const wrapper = shallowMount(HomeContainer); 8 | expect( 9 | wrapper.html() 10 | ).to.contain( 11 | '

Pick a city below to see the weather!

' 12 | ); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather-3/components/NotFoundContainer.spec.js: -------------------------------------------------------------------------------- 1 | import NotFoundContainer from '@/components/NotFoundContainer'; 2 | import {shallowMount} from '@vue/test-utils'; 3 | import { expect } from 'chai'; 4 | 5 | describe('NotFoundContainer.vue', () => { 6 | it('should display the appropriate not found message', () => { 7 | const wrapper = shallowMount(NotFoundContainer); 8 | expect( 9 | wrapper.html() 10 | ).to.contain( 11 | '

Sorry, this route does not exist :(

' 12 | ); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather-complete/components/HomeContainer.spec.js: -------------------------------------------------------------------------------- 1 | import HomeContainer from '@/components/HomeContainer'; 2 | import {shallowMount} from '@vue/test-utils'; 3 | import { expect } from 'chai'; 4 | 5 | describe('HomeContainer.vue', () => { 6 | it('should display the appropriate index message', () => { 7 | const wrapper = shallowMount(HomeContainer); 8 | expect( 9 | wrapper.html() 10 | ).to.contain( 11 | '

Pick a city below to see the weather!

' 12 | ); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather-complete/components/NotFoundContainer.spec.js: -------------------------------------------------------------------------------- 1 | import NotFoundContainer from '@/components/NotFoundContainer'; 2 | import {shallowMount} from '@vue/test-utils'; 3 | import { expect } from 'chai'; 4 | 5 | describe('NotFoundContainer.vue', () => { 6 | it('should display the appropriate not found message', () => { 7 | const wrapper = shallowMount(NotFoundContainer); 8 | expect( 9 | wrapper.html() 10 | ).to.contain( 11 | '

Sorry, this route does not exist :(

' 12 | ); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather/App.spec.js: -------------------------------------------------------------------------------- 1 | describe('App.vue', () => { 2 | 3 | }); 4 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather/components/HomeContainer.spec.js: -------------------------------------------------------------------------------- 1 | import HomeContainer from '@/components/HomeContainer'; 2 | import {shallowMount} from '@vue/test-utils'; 3 | import { expect } from 'chai'; 4 | 5 | describe('HomeContainer.vue', () => { 6 | it('should display the appropriate index message', () => { 7 | const wrapper = shallowMount(HomeContainer); 8 | expect( 9 | wrapper.html() 10 | ).to.contain( 11 | '

Pick a city below to see the weather!

' 12 | ); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather/components/NotFoundContainer.spec.js: -------------------------------------------------------------------------------- 1 | import NotFoundContainer from '@/components/NotFoundContainer'; 2 | import {shallowMount} from '@vue/test-utils'; 3 | import { expect } from 'chai'; 4 | 5 | describe('NotFoundContainer.vue', () => { 6 | it('should display the appropriate not found message', () => { 7 | const wrapper = shallowMount(NotFoundContainer); 8 | expect( 9 | wrapper.html() 10 | ).to.contain( 11 | '

Sorry, this route does not exist :(

' 12 | ); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /testing/weather/tests/unit/weather/components/WeatherContainer.spec.js: -------------------------------------------------------------------------------- 1 | describe('WeatherContainer.vue', () => { 2 | 3 | }); 4 | -------------------------------------------------------------------------------- /testing/weather/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | devServer: { 3 | proxy: { 4 | '/api': { 5 | target: 'http://localhost:3000/', 6 | changeOrigin: true, 7 | pathRewrite: { 8 | '^/api': '' 9 | } 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /upvote/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 9 | 11 | 12 | 13 | 14 |
15 |

UpVote!

16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /upvote/app/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/upvote/app/main.js -------------------------------------------------------------------------------- /upvote/app_1/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/upvote/app_1/main.js -------------------------------------------------------------------------------- /upvote/app_2/main.js: -------------------------------------------------------------------------------- 1 | new Vue({ 2 | el: '#app', 3 | data: { 4 | submissions: Seed.submissions 5 | } 6 | }); 7 | -------------------------------------------------------------------------------- /upvote/app_3/main.js: -------------------------------------------------------------------------------- 1 | new Vue({ 2 | el: '#app', 3 | data: { 4 | submissions: Seed.submissions 5 | } 6 | }) 7 | -------------------------------------------------------------------------------- /upvote/app_4/main.js: -------------------------------------------------------------------------------- 1 | new Vue({ 2 | el: "#app", 3 | data: { 4 | submissions: Seed.submissions 5 | }, 6 | computed: { 7 | sortedSubmissions() { 8 | return this.submissions.sort((a, b) => { 9 | return b.votes - a.votes; 10 | }); 11 | } 12 | }, 13 | methods: { 14 | upvote(submissionId) { 15 | const submission = this.submissions.find( 16 | submission => submission.id === submissionId 17 | ); 18 | submission.votes++; 19 | } 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /upvote/app_5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 9 | 11 | 12 | 13 | 14 |
15 |

UpVote!

16 | 17 |
18 |
22 | 25 | 26 |
27 |
28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /upvote/app_complete/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 9 | 11 | 12 | 13 | 14 |
15 |

UpVote!

16 | 17 |
18 |
22 | 25 | 26 |
27 |
28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /upvote/public/images/avatars/daniel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/upvote/public/images/avatars/daniel.jpg -------------------------------------------------------------------------------- /upvote/public/images/avatars/kristy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/upvote/public/images/avatars/kristy.png -------------------------------------------------------------------------------- /upvote/public/images/avatars/molly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/upvote/public/images/avatars/molly.png -------------------------------------------------------------------------------- /upvote/public/images/avatars/veronika.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/upvote/public/images/avatars/veronika.jpg -------------------------------------------------------------------------------- /upvote/public/images/submissions/image-aqua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/upvote/public/images/submissions/image-aqua.png -------------------------------------------------------------------------------- /upvote/public/images/submissions/image-rose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/upvote/public/images/submissions/image-rose.png -------------------------------------------------------------------------------- /upvote/public/images/submissions/image-steel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/upvote/public/images/submissions/image-steel.png -------------------------------------------------------------------------------- /upvote/public/images/submissions/image-yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/upvote/public/images/submissions/image-yellow.png -------------------------------------------------------------------------------- /upvote/public/styles.css: -------------------------------------------------------------------------------- 1 | /* Miscellaneous Styles */ 2 | 3 | .dividing-header { 4 | margin-top: 1em; 5 | margin-bottom: 2em; 6 | } 7 | 8 | .section { 9 | padding: 2rem 1.5rem; 10 | } 11 | 12 | .media { 13 | max-width: 600px; 14 | margin: 0 auto; 15 | border: 1px solid #e6e7e9; 16 | padding: 1em 1.5em 0.5em 1.5em; 17 | border-radius: 0.3em; 18 | } 19 | 20 | .media + .media { 21 | margin-top: 1.5rem; 22 | } 23 | 24 | .blue-border { 25 | border: 1px solid #3373dc !important; 26 | } 27 | 28 | .tag { 29 | font-size: 0.6rem !important; 30 | } 31 | 32 | .icon { 33 | cursor: pointer; 34 | } 35 | 36 | .image.is-24x24 { 37 | display: inline; 38 | position: relative; 39 | top: 5px; 40 | border-radius: 20px; 41 | } -------------------------------------------------------------------------------- /vuex/note_taking/app-complete/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vuex: Note-taking 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 | Notes 16 |
17 | {{ note }} 18 |
19 |
20 |
21 | Timestamp 22 |
23 | {{ timestamp }} 24 |
25 |
26 |
27 | 28 |
29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /vuex/note_taking/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vuex: Note-taking 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 | Notes 16 |
17 |
18 | Timestamp 19 |
20 |
21 | 22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /vuex/note_taking/app/main.js: -------------------------------------------------------------------------------- 1 | const inputComponent = { 2 | template: ``, 3 | } 4 | 5 | new Vue({ 6 | el: '#app', 7 | components: { 8 | 'input-component': inputComponent 9 | } 10 | }) 11 | -------------------------------------------------------------------------------- /vuex/note_taking/public/styles.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | } 4 | 5 | #app { 6 | height: inherit; 7 | margin: 0 auto; 8 | display: flex; 9 | flex-direction: column; 10 | align-items: center; 11 | -webkit-align-items: center; 12 | justify-content: center; 13 | -webkit-justify-content: center; 14 | } 15 | 16 | .notes-section { 17 | width: 500px; 18 | } 19 | 20 | .columns { 21 | width: 100%; 22 | } 23 | 24 | .notes, .timestamps { 25 | padding: 5px 0px; 26 | } 27 | 28 | .note-count { 29 | margin-top: 48px; 30 | } -------------------------------------------------------------------------------- /vuex/shopping_cart/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw* 22 | -------------------------------------------------------------------------------- /vuex/shopping_cart/README.md: -------------------------------------------------------------------------------- 1 | # Fullstack Vue 2 | 3 | ## Vuex - Shopping Cart 4 | 5 | 1. Ensure you have `npm` installed. 6 | 7 | 2. Install the dependencies 8 | 9 | ```` 10 | npm install 11 | ```` 12 | 13 | 3. Boot the app 14 | 15 | ```` 16 | npm run start 17 | ```` 18 | 19 | The Node and Webpack servers are now running - watch the console output for instructions. Your entire application is now available at [http://localhost:8080/](http://localhost:8080/) -------------------------------------------------------------------------------- /vuex/shopping_cart/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /vuex/shopping_cart/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shopping_cart", 3 | "description": "Project Four: Shopping Cart", 4 | "version": "1.0.0", 5 | "author": "Fullstack.io", 6 | "private": true, 7 | "scripts": { 8 | "start": "concurrently \"npm run server\" \"npm run serve\"", 9 | "server": "node server", 10 | "serve": "vue-cli-service serve", 11 | "build": "vue-cli-service build", 12 | "lint": "vue-cli-service lint" 13 | }, 14 | "dependencies": { 15 | "vue": "^2.5.17", 16 | "vuex": "^3.0.1", 17 | "axios": "^0.18.0" 18 | }, 19 | "devDependencies": { 20 | "@vue/cli-service": "^3.0.0", 21 | "@vue/cli-plugin-babel": "^3.0.0", 22 | "@vue/cli-plugin-eslint": "^3.0.0", 23 | "vue-template-compiler": "^2.5.17", 24 | "concurrently": "^3.6.1" 25 | }, 26 | "eslintConfig": { 27 | "root": true, 28 | "env": { 29 | "node": true 30 | }, 31 | "extends": [ 32 | "plugin:vue/essential", 33 | "eslint:recommended" 34 | ], 35 | "rules": {}, 36 | "parserOptions": { 37 | "parser": "babel-eslint" 38 | } 39 | }, 40 | "postcss": { 41 | "plugins": { 42 | "autoprefixer": {} 43 | } 44 | }, 45 | "browserslist": [ 46 | "> 1%", 47 | "last 2 versions", 48 | "not ie <= 8" 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/bulma/bulma.css.map: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/vuex/shopping_cart/public/bulma/bulma.css.map -------------------------------------------------------------------------------- /vuex/shopping_cart/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/vuex/shopping_cart/public/favicon.ico -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/HELP-US-OUT.txt: -------------------------------------------------------------------------------- 1 | I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project, 2 | Fort Awesome (https://fortawesome.com). It makes it easy to put the perfect icons on your website. Choose from our awesome, 3 | comprehensive icon sets or copy and paste your own. 4 | 5 | Please. Check it out. 6 | 7 | -Dave Gandy 8 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/vuex/shopping_cart/public/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/vuex/shopping_cart/public/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/vuex/shopping_cart/public/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/vuex/shopping_cart/public/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnWall2016/fullstack-vue-code/84b6928f0222763e0882e161edaabfe67810dfef/vuex/shopping_cart/public/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/less/animated.less: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .@{fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .@{fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/less/bordered-pulled.less: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em @fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .@{fa-css-prefix}-pull-left { float: left; } 11 | .@{fa-css-prefix}-pull-right { float: right; } 12 | 13 | .@{fa-css-prefix} { 14 | &.@{fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.@{fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .@{fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/less/core.less: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .@{fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/less/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | @import "path.less"; 9 | @import "core.less"; 10 | @import "larger.less"; 11 | @import "fixed-width.less"; 12 | @import "list.less"; 13 | @import "bordered-pulled.less"; 14 | @import "animated.less"; 15 | @import "rotated-flipped.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | @import "screen-reader.less"; 19 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/less/larger.less: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .@{fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .@{fa-css-prefix}-2x { font-size: 2em; } 11 | .@{fa-css-prefix}-3x { font-size: 3em; } 12 | .@{fa-css-prefix}-4x { font-size: 4em; } 13 | .@{fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/less/list.less: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: @fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), 9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/less/screen-reader.less: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { .sr-only(); } 5 | .sr-only-focusable { .sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .#{$fa-css-prefix}-pull-left { float: left; } 11 | .#{$fa-css-prefix}-pull-right { float: right; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .#{$fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), 9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/scss/_screen-reader.scss: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { @include sr-only(); } 5 | .sr-only-focusable { @include sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/font-awesome/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "animated"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | @import "screen-reader"; 19 | -------------------------------------------------------------------------------- /vuex/shopping_cart/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Project Four: Shopping Cart 9 | 10 | 11 | 12 | 13 | 14 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /vuex/shopping_cart/server-cart-data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "title": "The Fullstack Hoodie", 5 | "description": "Lightweight, breathable hoodie with the Fullstack Crest. Guaranteed to keep you looking fresh while warm.", 6 | "price": 19.99, 7 | "quantity": 2 8 | } 9 | ] -------------------------------------------------------------------------------- /vuex/shopping_cart/server-product-data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "title": "The Fullstack Hoodie", 5 | "description": "Lightweight, breathable hoodie with the Fullstack Crest. Guaranteed to keep you looking fresh while warm.", 6 | "price": 19.99 7 | }, 8 | { 9 | "id": 2, 10 | "title": "The Fullstack Tee", 11 | "description": "The original Fullstack clothing item. Always prepared to keep your style in check.", 12 | "price": 15.99 13 | }, 14 | { 15 | "id": 3, 16 | "title": "The Fullstack Fitted Cap", 17 | "description": "Stay comfortable and cool with the first Fullstack Fitted Cap, featuring a normal bill and medium crown.", 18 | "price": 15.99 19 | }, 20 | { 21 | "id": 4, 22 | "title": "The Fullstack Jacket", 23 | "description": "Keep warm and protected with the rugged, durable Fullstack lightweight jacket.", 24 | "price": 49.99 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-1/App.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 28 | 29 | 47 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-1/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import product from './modules/product'; 4 | import cart from './modules/cart'; 5 | 6 | Vue.use(Vuex); 7 | 8 | export default new Vuex.Store({ 9 | modules: { 10 | product, 11 | cart 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-1/store/modules/cart/index.js: -------------------------------------------------------------------------------- 1 | 2 | const state = {}; 3 | 4 | const mutations = {}; 5 | 6 | const actions = {}; 7 | 8 | const getters = {}; 9 | 10 | const cartModule = { 11 | state, 12 | mutations, 13 | actions, 14 | getters 15 | } 16 | 17 | export default cartModule; 18 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-1/store/modules/product/index.js: -------------------------------------------------------------------------------- 1 | 2 | const state = {}; 3 | 4 | const mutations = {}; 5 | 6 | const actions = {}; 7 | 8 | const getters = {}; 9 | 10 | const productModule = { 11 | state, 12 | mutations, 13 | actions, 14 | getters 15 | } 16 | 17 | export default productModule; 18 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-2/App.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 28 | 29 | 47 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-2/components/product/ProductList.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 37 | 38 | 56 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-2/components/product/ProductListItem.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 24 | 25 | 30 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-2/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import product from './modules/product'; 4 | import cart from './modules/cart'; 5 | 6 | Vue.use(Vuex); 7 | 8 | export default new Vuex.Store({ 9 | modules: { 10 | product, 11 | cart 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-2/store/modules/cart/index.js: -------------------------------------------------------------------------------- 1 | const state = {}; 2 | 3 | const mutations = {}; 4 | 5 | const actions = {}; 6 | 7 | const getters = {}; 8 | 9 | const cartModule = { 10 | state, 11 | mutations, 12 | actions, 13 | getters 14 | } 15 | 16 | export default cartModule; 17 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-2/store/modules/product/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const state = { 4 | productItems: [] 5 | } 6 | 7 | const mutations = { 8 | UPDATE_PRODUCT_ITEMS (state, payload) { 9 | state.productItems = payload; 10 | } 11 | } 12 | 13 | const actions = { 14 | getProductItems ({ commit }) { 15 | axios.get('/api/products').then((response) => { 16 | commit('UPDATE_PRODUCT_ITEMS', response.data) 17 | }); 18 | } 19 | } 20 | 21 | const getters = { 22 | productItems: state => state.productItems 23 | } 24 | 25 | const productModule = { 26 | state, 27 | mutations, 28 | actions, 29 | getters 30 | } 31 | 32 | export default productModule; 33 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-3/App.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 28 | 29 | 47 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-3/components/cart/CartListItem.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 25 | 26 | 32 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-3/components/product/ProductList.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 36 | 37 | 55 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-3/components/product/ProductListItem.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 24 | 25 | 30 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-3/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import product from './modules/product'; 4 | import cart from './modules/cart'; 5 | 6 | Vue.use(Vuex); 7 | 8 | export default new Vuex.Store({ 9 | modules: { 10 | product, 11 | cart 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-3/store/modules/product/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const state = { 4 | productItems: [] 5 | } 6 | 7 | const mutations = { 8 | UPDATE_PRODUCT_ITEMS (state, payload) { 9 | state.productItems = payload; 10 | } 11 | } 12 | 13 | const actions = { 14 | getProductItems ({ commit }) { 15 | axios.get('/api/products').then((response) => { 16 | commit('UPDATE_PRODUCT_ITEMS', response.data) 17 | }); 18 | } 19 | } 20 | 21 | const getters = { 22 | productItems: state => state.productItems 23 | } 24 | 25 | const productModule = { 26 | state, 27 | mutations, 28 | actions, 29 | getters 30 | } 31 | 32 | export default productModule; 33 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-complete/App.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 28 | 29 | 47 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-complete/components/cart/CartListItem.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 35 | 36 | 42 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-complete/components/product/ProductList.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 36 | 37 | 55 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-complete/components/product/ProductListItem.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 30 | 31 | 36 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-complete/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import product from './modules/product'; 4 | import cart from './modules/cart'; 5 | 6 | Vue.use(Vuex); 7 | 8 | export default new Vuex.Store({ 9 | modules: { 10 | product, 11 | cart 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app-complete/store/modules/product/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const state = { 4 | productItems: [] 5 | } 6 | 7 | const mutations = { 8 | UPDATE_PRODUCT_ITEMS (state, payload) { 9 | state.productItems = payload; 10 | } 11 | } 12 | 13 | const actions = { 14 | getProductItems ({ commit }) { 15 | axios.get('/api/products').then((response) => { 16 | commit('UPDATE_PRODUCT_ITEMS', response.data) 17 | }); 18 | } 19 | } 20 | 21 | const getters = { 22 | productItems: state => state.productItems 23 | } 24 | 25 | const productModule = { 26 | state, 27 | mutations, 28 | actions, 29 | getters 30 | } 31 | 32 | export default productModule; 33 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/app/App.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 28 | 29 | 49 | -------------------------------------------------------------------------------- /vuex/shopping_cart/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './app-complete/App.vue'; 3 | import store from './app-complete/store'; 4 | 5 | new Vue({ 6 | store, 7 | render: h => h(App) 8 | }).$mount('#app'); 9 | -------------------------------------------------------------------------------- /vuex/shopping_cart/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | devServer: { 3 | proxy: { 4 | '/api': { 5 | target: 'http://localhost:3000/', 6 | changeOrigin: true, 7 | pathRewrite: { 8 | '^/api': '' 9 | } 10 | } 11 | } 12 | } 13 | } 14 | --------------------------------------------------------------------------------