diff --git a/dist/index.html b/dist/index.html
index 559b18ecd..48a2b50da 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -3,11 +3,53 @@
Backbone Baseline
+
-
+
+
+
+
+
+
+
+
+
Store Library
+
+
+
+
+
+
+
diff --git a/package-lock.json b/package-lock.json
index 2d3371d51..a9569be1a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5036,6 +5036,21 @@
"esprima": "2.7.3"
}
},
+ "jscroll": {
+ "version": "2.3.9",
+ "resolved": "https://registry.npmjs.org/jscroll/-/jscroll-2.3.9.tgz",
+ "integrity": "sha512-eb9rc/QNMmd+AP6aeoNXKe1Lv0ISV6F9edt2Onku15UpEb2PJqxkwudAe3J/IN7R0bFLvWNpw+wDssXEgrie9w==",
+ "requires": {
+ "jquery": "1.12.4"
+ },
+ "dependencies": {
+ "jquery": {
+ "version": "1.12.4",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-1.12.4.tgz",
+ "integrity": "sha1-AeHfuikP5z3rp3zurLD5ui/sngw="
+ }
+ }
+ },
"jsesc": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
@@ -6828,6 +6843,12 @@
"unpipe": "1.0.0"
}
},
+ "raw-loader": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz",
+ "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=",
+ "dev": true
+ },
"read-pkg": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
@@ -7211,6 +7232,15 @@
"ajv": "5.5.1"
}
},
+ "script-loader": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/script-loader/-/script-loader-0.7.2.tgz",
+ "integrity": "sha512-UMNLEvgOAQuzK8ji8qIscM3GIrRCWN6MmMXGD4SD5l6cSycgGsCo0tX5xRnfQcoghqct0tjHjcykgI1PyBE2aA==",
+ "dev": true,
+ "requires": {
+ "raw-loader": "0.5.1"
+ }
+ },
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
diff --git a/package.json b/package.json
index 97144b128..7ae695e6b 100644
--- a/package.json
+++ b/package.json
@@ -51,6 +51,7 @@
"jasmine-core": "^2.8.0",
"jasmine-expect": "^3.8.1",
"module-resolver": "^1.0.0",
+ "script-loader": "^0.7.2",
"style-loader": "^0.19.0",
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.4"
@@ -59,6 +60,7 @@
"backbone": "^1.3.3",
"foundation-sites": "^6.4.4-rc1",
"jquery": "^3.2.1",
- "underscore": "^1.8.3"
+ "underscore": "^1.8.3",
+ "jscroll": "*"
}
}
diff --git a/src/app.js b/src/app.js
index 30c00d594..9d5b1bc8d 100644
--- a/src/app.js
+++ b/src/app.js
@@ -3,12 +3,56 @@ import 'foundation-sites/dist/css/foundation.css';
import './css/styles.css';
// Import jQuery & Underscore
-import $ from 'jquery';
import _ from 'underscore';
+import $ from 'jquery';
+
+import StoreLibrary from 'collections/store_library';
+import StoreMovie from 'models/store_movie';
+import APIMovies from 'collections/api_movies';
+import APIMovie from 'models/api_movie';
+
+import StoreLibraryView from 'views/store_library_view';
+import StoreMovieView from 'views/store_movie_view';
+import APIMoviesView from 'views/api_movies_view';
+import APIMovieView from 'views/api_movie_view';
-// ready to go
$(document).ready(function() {
- $('#main-content').append('Hello World!
');
+ $('.api-movies-container').hide();
+
+ const storeLibrary = new StoreLibrary();
+ storeLibrary.fetch();
+
+ const storeLibraryView = new StoreLibraryView({
+ model: storeLibrary,
+ template: _.template($('#store-movie-template').html()),
+ el: 'main'
+ });
+ storeLibraryView.render();
+
+ const apiMovies = new APIMovies();
+
+ const apiMoviesView = new APIMoviesView({
+ model: apiMovies,
+ template: _.template($('#api-movie-template').html()),
+ el: 'main'
+ });
+ apiMoviesView.storeLibrary = storeLibrary;
+ $('.submit-btn').on('click', function(e) {
+ e.preventDefault();
+ $('.errors').empty();
+ const query = $('input[name=query]').val();
+ apiMovies.fetch({data: {query:`${query}`}}).then(function(){
+ if (apiMoviesView.model.length === 0) {
+ $('.errors').append('There are no movies with that keyword search.');
+ $('.api-movies-container').hide();
+ } else {
+ $('.api-movies-container').show();
+ apiMoviesView.render();
+ console.log(apiMovies.length);
+ }
+ });
+ });
+ $('.store-library-container').jscroll();
});
diff --git a/src/collections/api_movies.js b/src/collections/api_movies.js
new file mode 100644
index 000000000..d0282bee2
--- /dev/null
+++ b/src/collections/api_movies.js
@@ -0,0 +1,19 @@
+import Backbone from 'backbone';
+import APIMovie from 'models/api_movie';
+import StoreMovie from 'models/store_movie';
+import StoreLibrary from 'collections/store_library';
+
+const APIMovies = Backbone.Collection.extend({
+ model: APIMovie,
+ sync: function(method, model, options) {
+ switch(method) {
+ case 'read':
+ options.url = 'http://localhost:3000/movies';
+
+ // options.url = 'http://localhost:3000/movies/' + 'search';
+ return Backbone.sync(method, model, options);
+ }
+ }
+});
+
+export default APIMovies;
diff --git a/src/collections/store_library.js b/src/collections/store_library.js
new file mode 100644
index 000000000..5fb1b3913
--- /dev/null
+++ b/src/collections/store_library.js
@@ -0,0 +1,15 @@
+import Backbone from 'backbone';
+import StoreMovie from 'models/store_movie';
+
+const StoreLibrary = Backbone.Collection.extend({
+ model: StoreMovie,
+ sync: function(method, model, options) {
+ switch(method) {
+ case 'read':
+ options.url = 'http://localhost:3000/movies';
+ return Backbone.sync(method, model, options);
+ }
+ }
+});
+
+export default StoreLibrary;
diff --git a/src/css/styles.css b/src/css/styles.css
index 68a79a569..b885a4b70 100644
--- a/src/css/styles.css
+++ b/src/css/styles.css
@@ -1,44 +1,90 @@
@include foundation-everything;
main {
- background: lightblue;
+ background-image: url('https://i.pinimg.com/originals/2c/6b/a3/2c6ba31d76936549fb3376552cb4070c.jpg');
+ background-size: 1000px 1000px;
+ font-family: 'Londrina Solid', cursive;
}
-header {
- background-color: lightgreen;
- padding: 0.5rem;
+button:hover {
+ background-color: #e22ef7;
}
-#completed-checkbox {
+div {
display: inline;
}
-label {
- display: inline;
+#search-form, .errors {
+ margin-right: 20%;
+ margin-left: 20%;
+ width: 60%;
+ text-align: center;
}
-button.success {
- margin-right: 1.2rem;
- display: inline;
+.logo {
+ font-size: 5rem;
+ text-align: center;
+ /*text-shadow: 10px 10px #f7add3;*/
}
-aside.create-tasklist {
- background-color: navy;
- color: #FFFFFF;
+#store-library, #api-movies {
+ margin-right: 10%;
+ margin-left: 10%;
+ display: inline-flex;
+ flex-flow: row;
+ flex-wrap: wrap;
+ justify-content: center;
}
-aside label {
- color: #FFFFFF;
+
+.logo, .api-movies-container h2, .store-library-container h2 {
+ color: #f4c842;
+ text-shadow: 6px 4px 0 #000;
+ background: url('https://i.pinimg.com/736x/41/79/3a/41793a2a1b0406da3f4e0d29b2e3de3a--pattern-print-print-patterns.jpg');
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ font-family: 'Londrina Solid', cursive;
}
-.completed {
- text-decoration: line-through;
+.api-movies-container h2, .store-library-container h2 {
+ text-align: center;
+ text-transform: uppercase;
+ font-size: 4rem;
+ text-shadow: 6px 4px 0 #e22ef7;
}
-div {
- display: inline;
+.errors {
+ color: white;
+ font-size: 2rem;
+ list-style: none;
+}
+.title {
+ display: block;
+}
+
+.single-api-movie, .single-store-movie {
+ margin: 1em;
+ box-shadow: 13px 13px #08c4d0;
+ position: relative;
}
-/*
-* {
+
+.single-api-movie img, .single-store-movie img{
border-style: solid;
+ border-width: medium;
+ border-color: #2eebf7;
+ width: 185px;
+}
+
+#submit-button:hover, #add-movie-btn:hover {
+ background-color: #2eebf7;
+}
+
+.add-movie-btn {
+ position: absolute;
+ background-color: #e22ef7;
+ bottom: 10px;
+ right: 10px;
+}
+
+.submit-btn {
+ background-color: #e22ef7;
}
-*/
diff --git a/src/css/stylesheet.css b/src/css/stylesheet.css
new file mode 100644
index 000000000..f854a404c
--- /dev/null
+++ b/src/css/stylesheet.css
@@ -0,0 +1,48 @@
+/*! Generated by Font Squirrel (https://www.fontsquirrel.com) on December 20, 2017 */
+
+
+
+@font-face {
+ font-family: 'kirvyregular';
+ src: url('kirvy-regular-webfont.woff2') format('woff2'),
+ url('kirvy-regular-webfont.woff') format('woff');
+ font-weight: normal;
+ font-style: normal;
+
+}
+
+
+
+
+@font-face {
+ font-family: 'gravitylight';
+ src: url('gravity-light-webfont.woff2') format('woff2'),
+ url('gravity-light-webfont.woff') format('woff');
+ font-weight: normal;
+ font-style: normal;
+
+}
+
+
+
+
+@font-face {
+ font-family: 'gravityregular';
+ src: url('gravity-regular-webfont.woff2') format('woff2'),
+ url('gravity-regular-webfont.woff') format('woff');
+ font-weight: normal;
+ font-style: normal;
+
+}
+
+
+
+
+@font-face {
+ font-family: 'geosanslightregular';
+ src: url('geosanslight-webfont.woff2') format('woff2'),
+ url('geosanslight-webfont.woff') format('woff');
+ font-weight: normal;
+ font-style: normal;
+
+}
diff --git a/src/models/api_movie.js b/src/models/api_movie.js
new file mode 100644
index 000000000..1b1f98d9e
--- /dev/null
+++ b/src/models/api_movie.js
@@ -0,0 +1,20 @@
+import Backbone from 'backbone';
+
+import APIMovies from 'collections/api_movies';
+
+const APIMovie = Backbone.Model.extend({
+
+ sync: function(method, model, options) {
+ switch(method) {
+ case 'read':
+ options.url = 'http://localhost:3000/movies';
+ return Backbone.sync(method, model, options);
+ }
+ }
+ // idAttribute: 'title',
+ // urlRoot: 'http://localhost:3000/movies',
+
+
+});
+
+export default APIMovie;
diff --git a/src/models/store_movie.js b/src/models/store_movie.js
new file mode 100644
index 000000000..371609688
--- /dev/null
+++ b/src/models/store_movie.js
@@ -0,0 +1,27 @@
+import Backbone from 'backbone';
+
+const StoreMovie = Backbone.Model.extend({
+ validate(attributes) {
+ const errors = {};
+ if (!attributes.title) {
+ errors['title'] = ['You need a movie with a title.'];
+ }
+ if ( Object.keys(errors).length > 0 ) {
+ return errors;
+ } else {
+ return false;
+ }
+ },
+ sync: function(method, model, options) {
+ switch(method) {
+ case 'read':
+ options.url = 'http://localhost:3000/movies' + model.get('title');
+ return Backbone.sync(method, model, options);
+ case 'create':
+ options.url = 'http://localhost:3000/movies';
+ return Backbone.sync(method, model, options);
+ }
+ }
+});
+
+export default StoreMovie;
diff --git a/src/views/api_movie_view.js b/src/views/api_movie_view.js
new file mode 100644
index 000000000..265fabaa9
--- /dev/null
+++ b/src/views/api_movie_view.js
@@ -0,0 +1,74 @@
+import Backbone from 'backbone';
+import $ from 'jquery';
+import _ from 'underscore';
+
+// import StoreMovie from 'models/store_movie';
+// import StoreMoviesView from 'models/store_movies';
+import APIMovie from 'models/api_movie'
+import StoreMovie from 'models/store_movie'
+
+import APIMoviesView from '../views/api_movies_view'
+import StoreMovieView from '../views/store_movie_view';
+
+import APIMovies from 'collections/api_movies'
+import StoreLibrary from '/collections/store_library';
+
+const APIMovieView = Backbone.View.extend({
+ initialize(params) {
+ this.template = params.template;
+ this.listenTo(this.model, "change", this.render);
+ },
+ render() {
+ const compiledTemplate = this.template(this.model.toJSON());
+ this.$el.html(compiledTemplate);
+ return this;
+ },
+ events: {
+ 'click .add-movie-btn': 'addMovieToLibrary',
+ },
+
+ addMovieToLibrary: function() {
+
+ const newStoreMovie = new StoreMovie({
+ title: this.model.attributes.title,
+ release_date: this.model.attributes.release_date,
+ overview: this.model.attributes.overview,
+ image_url: this.model.attributes.image_url,
+ });
+
+ let duplicate = false;
+ this.storeLibrary.forEach(function(storeMovie) {
+ if (storeMovie.attributes.title === newStoreMovie.attributes.title) {
+ duplicate = true;
+ }
+ });
+ if (duplicate === true) {
+ this.failureMessages({duplicate: ['This film is already in your library.']});
+ } else {
+ if (newStoreMovie.isValid()) {
+ newStoreMovie.save();
+ this.storeLibrary.add(newStoreMovie);
+ this.$el.empty();
+ this.successMessages(`${newStoreMovie.attributes.title} has been successfully added to your rental library.`);
+ } else
+ this.failureMessages(newStoreMovie.validationError);
+ }
+ },
+
+ failureMessages: function(messageHash) {
+ const statusMessagesEl = $('.errors');
+ statusMessagesEl.empty();
+ _.each(messageHash, (messageType) => {
+ messageType.forEach((message) => {
+ statusMessagesEl.append(`${message}`);
+ })
+ });
+ },
+ successMessages: function(message) {
+ const statusMessagesEl = $('.errors');
+ statusMessagesEl.empty();
+ statusMessagesEl.append(`${message}`);
+ },
+});
+
+export default APIMovieView;
diff --git a/src/views/api_movies_view.js b/src/views/api_movies_view.js
new file mode 100644
index 000000000..bba501442
--- /dev/null
+++ b/src/views/api_movies_view.js
@@ -0,0 +1,35 @@
+import Backbone from 'backbone';
+
+import _ from 'underscore';
+import $ from 'jquery';
+
+// import StoreMovieView from '../views/store_movie_view';
+// import StoreMovie from 'models/store_movie';
+// import StoreMovies from '/collections/store_movies';
+// import StoreMoviesView from 'models/store_movies';
+import APIMovieView from '../views/api_movie_view';
+import APIMovie from 'models/api_movie';
+import APIMovies from 'collections/api_movies';
+
+
+const APIMoviesView = Backbone.View.extend({
+ initialize(params) {
+ this.template = params.template;
+ this.listenTo(this.model, 'update', this.render);
+ },
+ render() {
+ this.$('#api-movies').empty();
+ this.model.each((apiMovie) => {
+ const apiMovieView = new APIMovieView({
+ model: apiMovie,
+ template: this.template,
+ className: 'apiMovie',
+ });
+ apiMovieView.storeLibrary = this.storeLibrary;
+ this.$('#api-movies').append(apiMovieView.render().$el);
+ });
+ return this;
+ },
+});
+
+export default APIMoviesView;
diff --git a/src/views/store_library_view.js b/src/views/store_library_view.js
new file mode 100644
index 000000000..782a36138
--- /dev/null
+++ b/src/views/store_library_view.js
@@ -0,0 +1,26 @@
+import Backbone from 'backbone';
+import StoreMovieView from '../views/store_movie_view';
+import StoreMovie from 'models/store_movie';
+
+
+const StoreLibraryView = Backbone.View.extend({
+ initialize(params) {
+ this.template = params.template;
+ this.listenTo(this.model, 'update', this.render);
+ this.listenTo(this.model, 'change', this.render);
+ },
+ render() {
+ this.model.each((storeMovie) => {
+ const storeMovieView = new StoreMovieView({
+ model: storeMovie,
+ template: this.template,
+ className: 'storeMovie',
+ });
+ this.$('#store-library').append(storeMovieView.render().$el);
+ });
+ return this;
+ },
+
+});
+
+export default StoreLibraryView;
diff --git a/src/views/store_movie_view.js b/src/views/store_movie_view.js
new file mode 100644
index 000000000..c739979d2
--- /dev/null
+++ b/src/views/store_movie_view.js
@@ -0,0 +1,17 @@
+import Backbone from 'backbone';
+import $ from 'jquery';
+import _ from 'underscore';
+
+const StoreMovieView = Backbone.View.extend({
+ initialize(params) {
+ this.template = params.template;
+ this.listenTo(this.model, "change", this.render);
+ },
+ render() {
+ const compiledTemplate = this.template(this.model.toJSON());
+ this.$el.html(compiledTemplate);
+ return this;
+ },
+});
+
+export default StoreMovieView;