diff --git a/.jshintrc b/.jshintrc index 584ed78..30f558c 100644 --- a/.jshintrc +++ b/.jshintrc @@ -47,7 +47,8 @@ "$": true, "_": true, "Backbone": true, - "Bloodhound": true + "Bloodhound": true, + "cf": true }, "regexdash": false, "scripturl": false, diff --git a/controllers/coinbase_api.js b/controllers/coinbase_api.js index f2678ed..5133dc2 100644 --- a/controllers/coinbase_api.js +++ b/controllers/coinbase_api.js @@ -17,7 +17,7 @@ exports.getExchangeRates = function(params, cb) { }); }; -// @Todo: Figure this out. +// TODO: Figure this out. exports.sendMoney = function(params, cb) { var accessToken = getCoinbaseAccessToken(params.user); if (!accessToken) { @@ -25,7 +25,7 @@ exports.sendMoney = function(params, cb) { } }; -// @Todo: Figure this out. +// TODO: Figure this out. exports.getBalance = function(params, cb) { var accessToken = getCoinbaseAccessToken(params.user); if (!accessToken) { diff --git a/controllers/new_transaction.js b/controllers/new_transaction.js index 453908c..0e35d1e 100644 --- a/controllers/new_transaction.js +++ b/controllers/new_transaction.js @@ -11,6 +11,7 @@ var coinbase_api = require('./coinbase_api.js'); exports.getNewTransaction = function(req, res, next) { var token = _.findWhere(req.user.tokens, { kind: 'facebook' }); graph.setAccessToken(token.accessToken); + // TODO: Filter out friends that do not match a user in DB async.parallel( { getMyFriends: function(done) { @@ -51,6 +52,7 @@ exports.getNewTransaction = function(req, res, next) { } res.render('new_transaction', { + controllerJs: 'new_transaction', title: 'New Transaction', balance_amount: balance_amount, balance_currency: balance_currency, diff --git a/public/css/styles.less b/public/css/styles.less index 6032964..6081921 100644 --- a/public/css/styles.less +++ b/public/css/styles.less @@ -85,7 +85,15 @@ body { bottom: 25px; } +// New Transaction +// ------------------------- + +.form-control.amount { + margin-top: 15px; +} + // Buttons + .btn.btn-pay { background-color: @brand-primary; color: white; @@ -97,20 +105,18 @@ body { } // Typeahead +// ------------------------- -typeahead, +.tt-dropdown-menu, +.tt-hint, +.tt-input, .tt-query, +.twitter-typeahead { + width: 100%; +} + .tt-hint { - width: 396px; - height: 30px; - padding: 8px 12px; - font-size: 14px; - line-height: 30px; - border: 2px solid #ccc; - -webkit-border-radius: 8px; - -moz-border-radius: 8px; - border-radius: 8px; - outline: none; + color: #999 } .typeahead { @@ -121,29 +127,12 @@ typeahead, border: 2px solid #0097cf; } -.tt-query { - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); -} - -.tt-hint { - color: #999 -} - .tt-dropdown-menu { - width: 396px; margin-top: 12px; padding: 8px 0; background-color: #fff; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, 0.2); - -webkit-border-radius: 8px; - -moz-border-radius: 8px; - border-radius: 8px; - -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); - -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); - box-shadow: 0 5px 10px rgba(0,0,0,.2); } .tt-suggestion { diff --git a/public/js/application.js b/public/js/application.js index 7c0d502..2ad3c64 100644 --- a/public/js/application.js +++ b/public/js/application.js @@ -13,3 +13,4 @@ //= require lib/bootstrap.min //= require lib/typeahead.bundle.min //= require main +//= require new_transaction diff --git a/public/js/main.js b/public/js/main.js index 7b3308e..ed465c3 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -1,19 +1,7 @@ -$(document).ready(function() { - var $transactionRecipient = $('#transactionRecipient'); - if ($transactionRecipient.length) { - var names = new Bloodhound({ - datumTokenizer: function(d) { - return Bloodhound.tokenizers.whitespace(d.name); - }, - queryTokenizer: Bloodhound.tokenizers.whitespace, - local: window.cf.dump.friends - }); +if (typeof window.cf === 'undefined') { + window.cf = { apps: {} }; +} - names.initialize(); - - $transactionRecipient.typeahead(null, { - displayKey: 'name', - source: names.ttAdapter() - }); - } -}); +if (typeof window.cf.apps === 'undefined') { + window.cf.apps = {}; +} diff --git a/public/js/new_transaction.js b/public/js/new_transaction.js new file mode 100644 index 0000000..93b98a6 --- /dev/null +++ b/public/js/new_transaction.js @@ -0,0 +1,47 @@ +function usdToBtc(usd) { + return (Number(usd) * Number(window.cf.dump.rates.usd_to_btc)); +} + +function btcToUsd(btc) { + return (Number(btc) / Number(window.cf.dump.rates.usd_to_btc)); +} + +cf.apps.new_transaction = function() { + this.initializeForm(); +}; + +cf.apps.new_transaction.prototype.initializeForm = function() { + var $transactionRecipient = $('.transactionRecipient'); + if ($transactionRecipient.length) { + var names = new Bloodhound({ + datumTokenizer: function(d) { + return Bloodhound.tokenizers.whitespace(d.name); + }, + queryTokenizer: Bloodhound.tokenizers.whitespace, + local: window.cf.dump.friends + }); + + names.initialize(); + + $transactionRecipient.typeahead(null, { + displayKey: 'name', + source: names.ttAdapter() + }); + } + + $(".currency-btns label").on('click', function(event) { + var $target = $(event.target); + var $amount = $('.amount'); + var $currencyLabel = $('.currencyLabel'); + + // TODO: Check if valid currency format + // TODO: If you click fast enough, the conversion will be incorrect + if ($target.is(".optionBTC:not(.active)")) { + $currencyLabel.html(''); + $amount.val(usdToBtc($amount.val())); + } else if ($target.is(".optionUSD:not(.active)")) { + $currencyLabel.html(''); + $amount.val(btcToUsd($amount.val())); + } + }); +}; diff --git a/views/layout.jade b/views/layout.jade index f8fa779..5cccc59 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -17,3 +17,8 @@ html include partials/footer include partials/dump != js('application') + if controllerJs + script. + $(document).ready(function() { + cf.currentApp = new window.cf.apps.#{controllerJs}(); + }); diff --git a/views/new_transaction.jade b/views/new_transaction.jade index 71617bb..8155fbd 100644 --- a/views/new_transaction.jade +++ b/views/new_transaction.jade @@ -11,24 +11,34 @@ block content form.form-horizontal(role='form', method='POST') input(type='hidden', name='_csrf', value=token) .form-group - label(class='col-sm-2 control-label', for='name') To - .col-sm-8 + label(class='col-xs-2 control-label', for='name') + i.fa.fa-user + .col-xs-8 .example-numbers - input#transactionRecipient.form-control(class='tt-query typeahead', type='text', autofocus=true, autocomplete='off', spellcheck='false', dir='auto', style='position: relative; vertical-align: top; background-color: transparent;') + input.form-control.transactionRecipient(class='typeahead', type='text', autofocus=true, autocomplete='off', spellcheck='false', dir='auto') .form-group - label(class='col-sm-2 control-label', for='amount') Amount - .col-sm-8 - input.form-control(class='tt-query', type='text', name='amount', id='amount') + label.currencyLabel(class='col-xs-2 control-label', for='amount') + i.fa.fa-btc + .col-xs-8 + .btn-group.btn-group-justified.currency-btns(data-toggle='buttons') + label.btn.btn-primary.optionBTC.active + input(type='radio') + i.fa.fa-btc + label.btn.btn-primary.optionUSD + input(type='radio') + i.fa.fa-usd + input.form-control.amount(type='text', name='amount') .form-group - label(class='col-sm-2 control-label', for='message') What's it for? - .col-sm-8 - textarea.form-control(class='tt-query', type='text', name='message', id='message', rows='7') + label(class='col-xs-2 control-label', for='message') + i.fa.fa-comment + .col-xs-8 + textarea.form-control(type='text', name='message', id='message', rows='7') .form-group - .col-sm-offset-2.col-sm-2 + .col-xs-offset-2.col-xs-2 button.btn.btn-pay(type='submit') i.fa.fa-btc | Pay - .col-sm-2 + .col-xs-2 button.btn.btn-charge(type='submit') i.fa.fa-btc | Charge