diff --git a/dist/index.html b/dist/index.html index 559b18ecd..34a8dbdb7 100644 --- a/dist/index.html +++ b/dist/index.html @@ -1,15 +1,89 @@ - - - Backbone Baseline - - -
- -
- - - - - + + + Video Store + + + + +
+
+

Video Store

+
+
+
+ + +
+

Movies

+ +
+ +
+ + + + + + + + diff --git a/package-lock.json b/package-lock.json index 2d3371d51..860cd2be4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5014,6 +5014,11 @@ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz", "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c=" }, + "jquery-serializejson": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/jquery-serializejson/-/jquery-serializejson-2.8.1.tgz", + "integrity": "sha1-/EDdEeXZpv0qNhT9y6ieSveU8Kg=" + }, "js-base64": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.0.tgz", diff --git a/package.json b/package.json index 97144b128..1da6b2231 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "backbone": "^1.3.3", "foundation-sites": "^6.4.4-rc1", "jquery": "^3.2.1", + "jquery-serializejson": "^2.8.1", "underscore": "^1.8.3" } } diff --git a/src/app.js b/src/app.js index 30c00d594..d001d635f 100644 --- a/src/app.js +++ b/src/app.js @@ -6,9 +6,107 @@ import './css/styles.css'; import $ from 'jquery'; import _ from 'underscore'; +// Our stuff +import Movie from 'models/movie'; +import MovieList from 'collections/movie_list'; +import MovieView from 'views/movie_view'; +import MovieListView from 'views/movie_list_view'; + +let movieTemplate; +let movieListView; +let movieDetailTemplate; + +const movieList = new MovieList(); + +const movieSearch = function movieSearch(e) { + e.preventDefault(); + + const query = $('#search input[name="query"]').val(); + + const searchList = new MovieList( + { + query: query, + } + ); + + searchList.fetch({ + success: () => { + const newView = new MovieListView({ + model: searchList, + template: movieTemplate, + detail_template: movieDetailTemplate, + el: $('#movie-list'), + }); + newView.render(); + } + }); +}; + +const addMovie = function addMovie(e) { + e.preventDefault(); + + const error_box = $('#error-box'); + error_box.html(''); + let formInfo = $('#new-movie').serializeArray(); + formInfo = arrayToJSON(formInfo); + const movie = new Movie(formInfo); + if (movie.isValid()) { + movie.save({}, { + success: () => { + console.log("this is working"); + movieList.add(movie); + }, + error: (e, r) => { + displayMovieFormErrors(r.responseJSON['errors']); + } + }); + } else { + displayMovieFormErrors(movie.validationError); + } +}; + +const displayMovieFormErrors = function displayMovieFormErrors(errors) { + const error_box = $('#error-box'); + for (let field in errors) { + for (let error of errors[field]) { + error_box.append(`

${field}: ${error}

`); + } + } +}; + +const arrayToJSON = function arrayToJSON(arr) { + const output = {}; + arr.forEach((item) => { + if (item.value) { + output[item.name] = item.value; + } + }); + return output; +}; + // ready to go $(document).ready(function() { + movieTemplate = _.template($('#movie-template').html()); + movieDetailTemplate = _.template($('#movie-detail-template').html()); + + movieList.fetch({ + success: () => { + movieListView = new MovieListView({ + model: movieList, + detail_template: movieDetailTemplate, + template: movieTemplate, + el: $('#movie-list'), + }); + movieListView.render(); + }, + }); + + $('#search').on('submit', movieSearch); - $('#main-content').append('

Hello World!

'); + $('.add-btn').on('click', () => { + $('.add-btn').hide(200); + $('#new-movie').show(500); + }); + $('#new-movie').on('submit', addMovie); }); diff --git a/src/collections/movie_list.js b/src/collections/movie_list.js new file mode 100644 index 000000000..aa3b0df9e --- /dev/null +++ b/src/collections/movie_list.js @@ -0,0 +1,20 @@ +import Backbone from 'backbone'; +import Movie from '../models/movie'; + +const MovieList = Backbone.Collection.extend({ + model: Movie, + url: function() { + console.log("building URL..."); + return 'http://localhost:3000/movies' + this.query; + }, + + initialize(params) { + if (params){ + this.query = params.query ? `/search?query=${params.query}` : ''; + } else { + this.query = ''; + } + }, +}); + +export default MovieList; diff --git a/src/css/styles.css b/src/css/styles.css index 68a79a569..0c7ece4da 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -1,44 +1,176 @@ @include foundation-everything; -main { - background: lightblue; +/***** MAIN *****/ + +:root { + --charcoal: #2A2B2A; + --red: #D7263D; + --orange: #F46036; + --gold: #FFB238; + --jade: #1B998B; +} + +* { + /* border: 1px solid green; */ +} + +body { + background-color: var(--charcoal); } header { - background-color: lightgreen; - padding: 0.5rem; + background-color: var(--orange); + border: 15px solid var(--red); + border-radius: 5rem; + margin: 1rem auto; + min-width: 47rem; + text-align: center; + width: 80%; } -#completed-checkbox { - display: inline; +h1 { + color: var(--jade); + font-family: 'Monoton', sans-serif; + font-size: 4rem; + font-weight: normal; + line-height: 0.5; + margin: 2rem; } -label { - display: inline; +h2 { + color: var(--jade); + font-family: 'Monoton', sans-serif; + font-size: 3rem; + font-weight: normal; + line-height: 0.5; + margin: 1.5rem auto; } -button.success { - margin-right: 1.2rem; - display: inline; +h3 { + color: var(--gold); + font-family: 'Monoton'; + font-size: 1.5rem; + font-weight: normal; + /*line-height: 0;*/ } -aside.create-tasklist { - background-color: navy; - color: #FFFFFF; +h4 { + color: var(--jade); + font-family: 'Fredoka One', sans-serif; + font-size: 2rem; + font-weight: normal; + line-height: 0; } -aside label { - color: #FFFFFF; + +ul { + list-style: none; + margin: 1rem; } -.completed { - text-decoration: line-through; +.container { + background-color: var(--gold); + border-radius: 3rem; + color: #D7263D; + display: inline-block; + margin: 1rem; + vertical-align: top; + width: 95%; } -div { - display: inline; +main { + background-color: #F46036; + border: 15px solid #D7263D; + border-radius: 5rem; + margin: 1rem auto; + min-width: 47rem; + text-align: center; + width: 80%; } -/* -* { - border-style: solid; + +.button { + align-items: flex-start; + color: white; + background-color: #D7263D; + border-color: buttonface; + border-image: initial; + border-style: outset; + border-radius: 5rem; + border-width: 2px; + box-sizing: border-box; + display: inline-block; + height: 2.5rem; + margin: 1rem auto; + padding: 10px 6px 3px; + text-align: center; + width: 100%; +} + +.button:active { + border-style: inset; +} + +/***** NAV BAR *****/ + +#nav-bar { + width: 30%; +} + +input[type="text"] { + border-radius: 2rem; +} + +form.search input { + border-radius: 2rem; + display: inline-block; +} + +form.search input[type="text"] { + width: 70%; +} + +input[type="submit"] { + background-color: var(--red); + border-radius: 2rem; + color: white; + height: 2.5rem; + width: 25%; +} + +/***** MOVIE LIST *****/ + +#movie-container { + width: 60%; +} + +.movie { + color: #D7263D; + background-color: #FFB238; + border: 5px solid #D7263D; + border-radius: 1rem; + padding: 5%; + margin: 1rem auto; + min-width: 19.5rem; + text-align: left; + width: 90%; +} + +.movie:hover { + background-color: #D7263D; + color: #FFB238; +} + +.movie .name { + font-family: 'Fredoka One', sans-serif; + font-size: 2rem; + font-weight: bold; +} + +.movie-options ul { + margin: 0; +} + +.movie-options li { + display: inline; + font-family: 'Comfortaa', sans-serif; + font-size: 1.25rem; } -*/ diff --git a/src/models/movie.js b/src/models/movie.js new file mode 100644 index 000000000..eecf0f480 --- /dev/null +++ b/src/models/movie.js @@ -0,0 +1,30 @@ +import Backbone from 'backbone'; + +const Movie = Backbone.Model.extend({ + urlRoot: 'http://localhost:3000/movies', + defaults: { + 'inventory': 0, + 'release_date': new Date(), + 'overview': "No description", + }, + validate(attr) { + const errors = {}; + if (!attr.title) { + if (errors['title']) { + errors['title'].push("can't be blank"); + } else { + errors['title'] = ["can't be blank"]; + } + } + if (Object.keys(errors).length > 0) { + return errors; + } else { + return false; + } + }, + getByTitle() { + this.url = this.urlRoot + "/" + this.get('title'); + }, +}); + +export default Movie; diff --git a/src/views/movie_list_view.js b/src/views/movie_list_view.js new file mode 100644 index 000000000..49d5965f4 --- /dev/null +++ b/src/views/movie_list_view.js @@ -0,0 +1,30 @@ +import Backbone from 'backbone'; +import MovieView from '../views/movie_view'; +import Movie from '../models/movie'; + + +const MovieListView = Backbone.View.extend({ + initialize(params) { + this.template = params.template; + this.detail_template = params.detail_template; + }, + + render() { + this.$el.empty(); + + this.model.each((movie) => { + const movieView = new MovieView({ + template: this.template, + detail_template: this.detail_template, + model: movie, + tagName: 'li', + className: 'movie', + }); + this.$el.append(movieView.render().$el) + }); + + return this; + }, +}); + +export default MovieListView; diff --git a/src/views/movie_view.js b/src/views/movie_view.js new file mode 100644 index 000000000..9ba52ee7e --- /dev/null +++ b/src/views/movie_view.js @@ -0,0 +1,39 @@ +import $ from 'jquery'; +import Backbone from 'backbone'; +import Movie from '../models/movie'; + +const MovieView = Backbone.View.extend({ + initialize(params) { + this.template = params.template; + this.detail_template = params.detail_template; + }, + + render() { + const compiledTemplate = this.template(this.model.toJSON()); + this.$el.html(compiledTemplate); + + return this; + }, + + events: { + 'click': 'showDetails', + }, + + showDetails(e) { + $('.movie-detail').remove(); + let responseJSON; + this.model.getByTitle(); + this.model.fetch({ + success: (r) => { + responseJSON = r.toJSON(); + const generatedHTML = this.detail_template(responseJSON); + this.$el.append(generatedHTML).find('.movie-detail').show(500); + }, + }); + }, +}); + + + + +export default MovieView;