Skip to content
Open
40 changes: 40 additions & 0 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
{
Expand All @@ -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(`<option value="${symbol}">${symbol}</option>`);
});
};

//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();

});
8 changes: 8 additions & 0 deletions src/collections/order_list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Backbone from 'backbone';
import Order from '../models/order';

const OrderList = Backbone.Collection.extend({
model: Order,
});

export default OrderList;
31 changes: 31 additions & 0 deletions src/models/order.js
Original file line number Diff line number Diff line change
@@ -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;
14 changes: 14 additions & 0 deletions src/models/quote.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 )
},
});

Expand Down
74 changes: 74 additions & 0 deletions src/views/order_list_view.js
Original file line number Diff line number Diff line change
@@ -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 = `<h3>${error}</h3>`;
errorSection.append(html);
});
});
}
},
});


export default OrderListView;
38 changes: 38 additions & 0 deletions src/views/order_view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Backbone from 'backbone';


const OrderView = Backbone.View.extend({
initialize(params) {
this.template = params.template;
this.bus = params.bus;
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model.get('quote'), 'change', this.swapOrder);
},
render() {
const compiledTemplate = this.template(this.model.toJSON());
this.$el.html(compiledTemplate);
return this;
},
events: {
'click .btn-cancel': 'cancelOrder',
},
cancelOrder() {
this.model.destroy();
this.remove();
},
swapOrder() {
if (this.model.get('buy')) {
if (this.model.get('quote').get('price') <= this.model.get('targetPrice')) {
this.bus.trigger('buyOrder', this);
this.cancelOrder();
}
} else {
if (this.model.get('quote').get('price') >= this.model.get('targetPrice')) {
this.bus.trigger('sellOrder', this);
this.cancelOrder();
}
}
},
});

export default OrderView;
41 changes: 41 additions & 0 deletions src/views/quote_list_view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import Backbone from 'backbone';
import _ from 'underscore';
import Quote from '../models/quote';
import QuoteView from '../views/quote_view';

const QuoteListView = Backbone.View.extend ({
initialize(params) {
this.quoteTemplate = params.quoteTemplate;
this.tradeTemplate = params.tradeTemplate;
this.listenTo(this.model, 'update', this.render);
this.bus = params.bus;
},
render() {
this.$('#quotes').empty();
//use the template
this.model.each((quote) => {
const quoteView = new QuoteView({
model: quote,
template: this.quoteTemplate,
bus: this.bus,
tagName: 'li',
className: 'quote',
});
this.listenTo(quote, 'addQuote', this.events.seeTrade);
this.$('#quotes').append(quoteView.render().$el);
});


//append template to html
return this;
},

events: {
seeTrade: function(data) {
const seeTradeTemp = this.tradeTemplate(data);
this.$('#trades').prepend(seeTradeTemp);
}
}
});

export default QuoteListView;
29 changes: 29 additions & 0 deletions src/views/quote_view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Backbone from 'backbone';
import Quote from '../models/quote';

const QuoteView = Backbone.View.extend({
initialize(params) {
this.template = params.template;
this.bus = params.bus;
this.listenTo(this.model, "change", this.render);
},
render() {
const compiledTemplate = this.template(this.model.toJSON());
this.$el.html(compiledTemplate);

return this;
},
events: {
'click button.btn-buy': 'buyTrade',
'click button.btn-sell': 'sellTrade',
},

buyTrade: function(event) {
this.model.buy();
},
sellTrade: function(event) {
this.model.sell();
},
});

export default QuoteView;
18 changes: 18 additions & 0 deletions src/views/trade_view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// import Backbone from 'backbone';
// import Quote from '../models/quote';
//
// const TradeView = Backbone.View.extend ({
// initialize(params) {
// this.template = params.template;
// },
//
// render() {
// const compiledTemplate = this.template(this.model.toJSON());
// this.$el.html(compiledTemplate);
//
// return this;
// },
// });
//
//
// export default TradeView;