diff --git a/src/app.js b/src/app.js index 03ec910..1129790 100644 --- a/src/app.js +++ b/src/app.js @@ -2,9 +2,13 @@ import 'foundation-sites/dist/foundation.css'; import 'css/app.css'; import $ from 'jquery'; +import _ from 'underscore'; import Simulator from 'models/simulator'; import QuoteList from 'collections/quote_list'; +import QuoteListView from 'views/quote_list_view'; +import OrderList from 'collections/order_list'; +import OrderListView from 'views/order_list_view'; const quoteData = [ { @@ -26,10 +30,46 @@ const quoteData = [ ]; $(document).ready(function() { + let bus = {}; + bus = _.extend(bus, Backbone.Events); + const quotes = new QuoteList(quoteData); + const orders = new OrderList(); const simulator = new Simulator({ quotes: quotes, }); + const quoteTemp = _.template($('#quote-template').html()); + const tradeTemp = _.template($('#trade-template').html()); + const orderTemp = _.template($('#order-template').html()); + + const dropdown = function dropdown() { + quotes.each((quote) => { + const symbol = quote.get('symbol'); + $('select[name="symbol"]').append(``); + }); + }; + + //create new quote view obj + const quoteListView = new QuoteListView({ + model: quotes, + quoteTemplate: quoteTemp, + tradeTemplate: tradeTemp, + el: 'main', + bus: bus, + }); + + const orderListView = new OrderListView({ + model: orders, + quotes: quotes, + template: orderTemp, + bus: bus, + el: '#order-workspace' + }); + + dropdown(); + orderListView.render(); + quoteListView.render(); simulator.start(); + }); diff --git a/src/collections/order_list.js b/src/collections/order_list.js new file mode 100644 index 0000000..6b77957 --- /dev/null +++ b/src/collections/order_list.js @@ -0,0 +1,8 @@ +import Backbone from 'backbone'; +import Order from '../models/order'; + +const OrderList = Backbone.Collection.extend({ + model: Order, +}); + +export default OrderList; diff --git a/src/models/order.js b/src/models/order.js new file mode 100644 index 0000000..90d5269 --- /dev/null +++ b/src/models/order.js @@ -0,0 +1,31 @@ +import Backbone from 'backbone'; + + +const Order = Backbone.Model.extend ({ + initialize(attributes) { + + }, + validate(attributes) { + const errors = {}; + if (!attributes.symbol) { + errors['symbol'] = ["You must specify a symbol"]; + } + if (!attributes.targetPrice) { + errors['price'] = ["You must specify price."]; + } + if (this.get('buy') && attributes.targetPrice >= this.get('quote').get('price')) { + errors['price'] = ["The buy price needs to be less than the current price."] + } + if (!this.get('buy') && attributes.targetPrice <= this.get('quote').get('price')) { + errors['price'] = ["The price is lower than the market price."] + } + if ( Object.keys(errors).length > 0 ) { + return errors; + } else { + return false; + } + }, +}); + + +export default Order; diff --git a/src/models/quote.js b/src/models/quote.js index 4fbf466..b06f361 100644 --- a/src/models/quote.js +++ b/src/models/quote.js @@ -8,10 +8,24 @@ const Quote = Backbone.Model.extend({ buy() { // Implement this function to increase the price by $1.00 + const data = { + buy: true, + symbol: this.get('symbol'), + price: this.get('price') + } + this.trigger('addQuote', data); + this.set('price', this.get('price') + 1.00 ) }, sell() { // Implement this function to decrease the price by $1.00 + const data = { + buy: false, + symbol: this.get('symbol'), + price: this.get('price') + } + this.trigger('addQuote', data); + this.set('price', this.get('price') - 1.00 ) }, }); diff --git a/src/views/order_list_view.js b/src/views/order_list_view.js new file mode 100644 index 0000000..6703fe0 --- /dev/null +++ b/src/views/order_list_view.js @@ -0,0 +1,74 @@ +import Backbone from 'backbone'; +import Order from '../models/order'; +import OrderView from './order_view'; +import $ from 'jquery'; + +const OrderListView = Backbone.View.extend({ + initialize(params) { + this.bus = params.bus; + this.template = params.template; + this.quotes = params.quotes; + this.listenTo(this.model, 'update', this.render); + }, + render() { + this.$('#orders').empty(); + + this.model.each((order) => { + const orderView = new OrderView({ + model: order, + template: this.template, + bus: this.bus, + tagName: 'li', + quotes: 'this.quotes', + className: 'order', + }); + this.$('#orders').append(orderView.render().$el); + }); + return this; + }, + events: { + 'click .btn-buy': 'buyOrder', + 'click .btn-sell': 'sellOrder', + }, + makeOrder(value) { + this.$('.form-errors').empty(); + + const orderData = { + bus: this.bus, + symbol: this.$('select[name=symbol]').val(), + quote: this.quotes.find({symbol: this.$('select[name=symbol]').val()}), + buy: value.buy, + targetPrice: parseFloat(this.$('input[name=price-target]').val()) + }; + return new Order(orderData); + }, + buyOrder: function(e) { + e.preventDefault(); + const order = this.makeOrder({buy: true}); + this.validate(order); + }, + sellOrder: function(e) { + e.preventDefault(); + const order = this.makeOrder({buy: false}); + this.validate(order); + }, + validate(order) { + if (order.isValid()) { + this.model.add(order); + this.$el.find('form').trigger('reset'); + } else { + const errors = order.validationError; + const errorSection = this.$('.form-errors'); + + Object.keys(errors).forEach((field) => { + errors[field].forEach((error) => { + const html = `