diff --git a/dist/Like.png b/dist/Like.png new file mode 100644 index 000000000..af5b5602b Binary files /dev/null and b/dist/Like.png differ diff --git a/dist/index.html b/dist/index.html index 559b18ecd..7542415a2 100644 --- a/dist/index.html +++ b/dist/index.html @@ -2,13 +2,45 @@ - Backbone Baseline + + VideoVideo +
+

VideoStore

+ +
+
+ + + + +
+
+
+
- + + + +
+ + + + diff --git a/spec/models/movie_spec.js b/spec/models/movie_spec.js new file mode 100644 index 000000000..8d87135e2 --- /dev/null +++ b/spec/models/movie_spec.js @@ -0,0 +1,22 @@ +import Movie from 'models/movie'; + +describe('Movie spec', () => { + let movie; + beforeEach(() => { + movie = new Movie({ + title: 'HELLO', + }); + }); + + describe('movie validations', () => { + + it('movie is valid with a title', () => { + expect(movie.isValid()).toEqual(true); + }); + + it('movie invalid without title', () => { + movie.set('title', ''); + expect(movie.isValid()).toEqual(false); + }); + }); +}); diff --git a/src/app.js b/src/app.js index 30c00d594..2f4b0fbcf 100644 --- a/src/app.js +++ b/src/app.js @@ -1,14 +1,50 @@ import 'css/_settings.css'; import 'foundation-sites/dist/css/foundation.css'; -import './css/styles.css'; - // Import jQuery & Underscore import $ from 'jquery'; import _ from 'underscore'; +import Backbone from 'backbone'; + +import MovieList from 'collections/movie_list'; +import CustomerList from 'collections/customer_list'; + +import MovieListView from 'views/movie_list_view'; +import CustomerListView from 'views/customer_list_view'; + +import './css/styles.css'; // ready to go $(document).ready(function() { - $('#main-content').append('

Hello World!

'); + let bus = {}; + bus = _.extend(bus, Backbone.Events); + + // movies + const movies = new MovieList(); + movies.fetch(); + + const movieListView = new MovieListView({ + model: movies, + template: _.template($('#movie-template').html()), + bus: bus, + el: 'body' + }); + + // customers + const customers = new CustomerList(); + customers.fetch(); + + const customerListView = new CustomerListView({ + model: customers, + template: _.template($('#customer-template').html()), + el: 'main' + }); + + $('body').on('mouseenter', 'li', function() { + $(this).find('.moviehover').fadeIn(200); + }); + $('body').on('mouseleave', 'li', function() { + $(this).find('.moviehover').fadeOut(200); + }); }); diff --git a/src/collections/customer_list.js b/src/collections/customer_list.js new file mode 100644 index 000000000..4330e193e --- /dev/null +++ b/src/collections/customer_list.js @@ -0,0 +1,12 @@ +import Backbone from 'backbone'; +import Customer from '../models/customer'; + +const CustomerList = Backbone.Collection.extend({ + model: Customer, + url: 'http://localhost:3000/customers', + parse(response) { + return response; + }, +}); + +export default CustomerList; diff --git a/src/collections/movie_list.js b/src/collections/movie_list.js new file mode 100644 index 000000000..87754fe63 --- /dev/null +++ b/src/collections/movie_list.js @@ -0,0 +1,13 @@ +import Backbone from 'backbone'; +import Movie from '../models/movie'; + +const MovieList = Backbone.Collection.extend({ + model: Movie, + url: 'http://localhost:3000/movies', + parse(response) { + return response; + }, + +}); + +export default MovieList; diff --git a/src/collections/rental_list.js b/src/collections/rental_list.js new file mode 100644 index 000000000..bd8a2bb6c --- /dev/null +++ b/src/collections/rental_list.js @@ -0,0 +1,8 @@ +import Backbone from 'backbone'; +import Rental from '../models/rental'; + +const RentalList = Backbone.Collection.extend({ + model: Rental, +}); + +export default RentalList; diff --git a/src/css/styles.css b/src/css/styles.css index 68a79a569..6ce3d071a 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -1,44 +1,124 @@ @include foundation-everything; -main { - background: lightblue; +/* General styling */ + +body { + text-align: center; + background: #141414; +} + +h1, h2, h3, h4, h5, p,[type='radio'] + label[for] { + font-family: 'Raleway', sans-serif; + color: #e5e5e5; } +h4 { + height: 80px; + font-size: 1.2em; + overflow: hidden; +} + +/* Header */ + header { - background-color: lightgreen; - padding: 0.5rem; + max-width: 600px; + margin: 20px auto; +} + +/* List styling */ + +li { + margin: 30px; + display: inline-block; + list-style: none; + position: relative; + max-width: 185px; + transition: all .1s ease-in-out; +} + +li:hover { +transform: scale(1.1); } -#completed-checkbox { - display: inline; +img { + height: 276px; + border-radius: 2px; } -label { - display: inline; +.summary { + font-size: 0.9em; + line-height: 1.3em; + padding: 80px 10px 0; + border-radius: 2px; + height: 276px; + position:absolute; + overflow: hidden; + top: 0; + left: -1px; + right: -1px; + background: rgba(0,0,0,0.8); } -button.success { - margin-right: 1.2rem; - display: inline; + +/* Movie */ + +.add-inventory { + font-weight: bolder; + padding: 7px 11px 9px; + background: rgba(255,0,0,0.6); + text-shadow: 2px 2px 5px rgba(0,0,0,0.3); + position: absolute; + top: 5px; + right: 5px; + border-radius: 50%; +} + +.add-inventory:hover { + background: rgba(255,0,0,0.85); } -aside.create-tasklist { - background-color: navy; - color: #FFFFFF; +.details { + font-size: 0.85em; + padding-left: 10px; + text-align: left; + position: absolute; + width: 100%; + bottom: 95px; + font-weight: bold; } -aside label { - color: #FFFFFF; + +.rating { + font-weight: normal; + color: rgba(255,255,255,0.5); + margin-left: 3px; + padding: 2px 3px; + border: 1px solid rgba(255,255,255,0.5); } -.completed { - text-decoration: line-through; +.thumbs { + position: absolute; + right: 8px; + bottom: 95px; } -div { - display: inline; +.like, .dislike { + border: 1px solid rgba(255,255,255,0.4); + background: rgba(0,0,0,0.4); + border-radius: 50%; + padding: 5px; + width: 24px; + height: 24px; } -/* -* { - border-style: solid; + +.dislike { + transform: rotate(180deg); } -*/ + +.like { + margin-top: -60px; +} + +/* Customer */ + + +/* Footer */ diff --git a/src/models/customer.js b/src/models/customer.js new file mode 100644 index 000000000..3043cd68e --- /dev/null +++ b/src/models/customer.js @@ -0,0 +1,11 @@ +import Backbone from 'backbone'; + + +const Customer = Backbone.Model.extend({ + initialize(attributes) { + }, + validate(attributes) { + } +}); + +export default Customer; diff --git a/src/models/movie.js b/src/models/movie.js new file mode 100644 index 000000000..2c6580b29 --- /dev/null +++ b/src/models/movie.js @@ -0,0 +1,24 @@ +import Backbone from 'backbone'; + + +const Movie = Backbone.Model.extend({ + initialize(attributes) { + this.title = this.attributes.title; + this.bus = this.bus + this.attributes.upperCaseTitle = this.title.toUpperCase(); + }, + validate(attributes) { + const errors = {}; + + if (!attributes.title) { + errors['title'] = ['Title is required']; + } + if ( Object.keys(errors).length > 0 ) { + return errors; + } else { + return false; + } + } +}); + +export default Movie; diff --git a/src/models/rental.js b/src/models/rental.js new file mode 100644 index 000000000..8266faeda --- /dev/null +++ b/src/models/rental.js @@ -0,0 +1,17 @@ +import Backbone from 'backbone'; + + +const Rental = Backbone.Model.extend({ + initialize(attributes) { + }, + validate(attributes) { + const errors = {}; + + if (!attributes.due_date) { + errors['due_date'] = ['Due Date is required']; + } + } + +}); + +export default Rental; diff --git a/src/views/customer_list_view.js b/src/views/customer_list_view.js new file mode 100644 index 000000000..eef5ef2fc --- /dev/null +++ b/src/views/customer_list_view.js @@ -0,0 +1,30 @@ +import Backbone from 'backbone'; +import CustomerView from './customer_view'; + +const CustomerListView = Backbone.View.extend({ + initialize(params) { + this.template = params.template; + + }, + render() { + // console.log('IN RENDER'); + // console.log(this.model); + this.$('#list').empty(); + + this.model.each((customer) => { + const customerView = new CustomerView({ + model: customer, + template: this.template, + tagName: 'li', + className: 'customer', + }); + this.$('#list').append(customerView.render().$el); + }) + return this; +}, + events: { + 'click #customer-button': 'render', + } +}); + +export default CustomerListView; diff --git a/src/views/customer_view.js b/src/views/customer_view.js new file mode 100644 index 000000000..429774c00 --- /dev/null +++ b/src/views/customer_view.js @@ -0,0 +1,15 @@ +import Backbone from 'backbone'; +import Customer from '../models/customer'; + +const CustomerView = Backbone.View.extend({ + initialize(params) { + this.template = params.template; + }, + render() { + const compileTemplate = this.template(this.model.toJSON()); + this.$el.html(compileTemplate); + return this; + }, +}); + +export default CustomerView; diff --git a/src/views/movie_list_view.js b/src/views/movie_list_view.js new file mode 100644 index 000000000..383c7bf29 --- /dev/null +++ b/src/views/movie_list_view.js @@ -0,0 +1,88 @@ +import Backbone from 'backbone'; +import MovieView from './movie_view'; +import $ from 'jquery'; +// import Movie from '../models/movie'; + +const MovieListView = Backbone.View.extend({ + initialize(params) { + this.template = params.template; + this.listenTo(this.model, 'change', this.render); + this.bus = params.bus; + this.listenTo(this.bus, 'addMe', this.addInventory); + }, + render() { + this.$('#list').empty(); + + this.model.fetch({}).done(() => { + + this.model.each((movie) => { + const movieView = new MovieView({ + model: movie, + template: this.template, + tagName: 'li', + className: 'movie', + bus: this.bus, + }); + this.$('#list').append(movieView.render().$el); + $('.add-inventory').hide(); + }) + return this; + }); + }, + submit(event) { + event.preventDefault(); + + const searchType = this.$('input[name=search-type]:checked').val(); + const searchTerm = this.$('input[name=search]').val().toUpperCase(); + const regSearchTerm = this.$('input[name=search]').val(); + + if (searchType === 'search inventory') { + this.model.fetch({}).done(() => { + const movieList = this.model.models; + const filteredMovies = movieList.filter(movie => movie.get('upperCaseTitle').includes(searchTerm)); + + this.$('#list').empty(); + + filteredMovies.forEach((movie) => { + const movieView = new MovieView({ + model: movie, + template: this.template, + tagName: 'li', + className: 'movie', + }); + this.$('#list').append(movieView.render().$el); + $('.add-inventory').hide(); + }); + return this; + }); + } else { + this.$('#list').empty(); + const imdbList = this.model.fetch({data: {query: regSearchTerm}}); + + imdbList.then((data, status, response) => { + + this.model.models.forEach((movie) => { + const movieView = new MovieView({ + model: movie, + template: this.template, + tagName: 'li', + className: 'imdb-movie', + bus: this.bus, + }); + this.$('#list').append(movieView.render().$el); + $('.rating').hide(); + }); + }); + } + }, + addInventory(attributes) { + this.model.create(attributes.title); + this.render(); + }, + events: { + 'click #movie-button': 'render', + 'click #searchButton': 'submit', + } +}); + +export default MovieListView; diff --git a/src/views/movie_view.js b/src/views/movie_view.js new file mode 100644 index 000000000..452a08157 --- /dev/null +++ b/src/views/movie_view.js @@ -0,0 +1,31 @@ +import Backbone from 'backbone'; +import Movie from '../models/movie'; + +const MovieView = Backbone.View.extend({ + initialize(params) { + this.template = params.template; + this.model = params.model; + this.bus = params.bus; + }, + render() { + const compileTemplate = this.template(this.model.toJSON()); + this.$el.html(compileTemplate); + return this; + }, + addInventory(event) { + this.model.save({}, { + success: (model, response) => { + console.log('success'); + }, + error: (model, response) => { + console.log('error'); + } + }) + }, + events: { + 'click .add-inventory': 'addInventory' + }, + +}); + +export default MovieView; diff --git a/src/views/rental_list_view.js b/src/views/rental_list_view.js new file mode 100644 index 000000000..e69de29bb diff --git a/src/views/rental_view.js b/src/views/rental_view.js new file mode 100644 index 000000000..e69de29bb