diff --git a/app/assets/javascripts/components/transaction_form.jsx.coffee b/app/assets/javascripts/components/transaction_form.jsx.coffee index 1a54e1c..2aa6c24 100644 --- a/app/assets/javascripts/components/transaction_form.jsx.coffee +++ b/app/assets/javascripts/components/transaction_form.jsx.coffee @@ -1,4 +1,4 @@ -{ button, div, h3, input, option, select } = React.DOM +{ button, div, form, h3, input, option, select } = React.DOM Action = React.createFactory React.createClass buttonClass: (b) -> @@ -22,23 +22,21 @@ Amount = React.createFactory React.createClass @props.setAmount ref.target.value format: (ref) -> t = ref.target - t.value = parseFloat(t.value).toFixed(2) + t.value = parseFloat(t.value).toFixed(2) if t.value render: -> div className: 'row', div className: 'col-xs-4', div className: 'input-group', div className: 'input-group-addon', '€' input { - type: 'number', className: 'form-control input-lg', - placeholder: '0.00', + name: 'transaction[euros]' + onBlur: @format, onChange: @onChange, - onBlur: @format + placeholder: '0.00', + type: 'number', } -Suggestions = React.createFactory React.createClass - render: -> - Peer = React.createFactory React.createClass onChange: (ref) -> @props.setPeer ref.target.value @@ -62,7 +60,13 @@ Peer = React.createFactory React.createClass div className: 'row', div className: 'col-xs-4', div className: 'suggestions-wrapper', - input type: 'text', className: @inputClass(options.length), onChange: @onChange, placeholder: 'Zeus member', value: (@props.peer || '') + input { + className: @inputClass(options.length), + onChange: @onChange, + placeholder: 'Zeus member', + type: 'text', + value: (@props.peer || '') + } if options.length != 0 div className: 'suggestions', @options().map (s, i) => @@ -75,53 +79,135 @@ Message = React.createFactory React.createClass render: -> div className: 'row', div className: 'col-xs-8', - input type: 'text', className: 'form-control input-lg', onChange: @onChange, placeholder: 'Message' + input { + className: 'form-control input-lg', + name: 'transaction[message]', + onChange: @onChange, + placeholder: 'Message' + type: 'text', + } Submit = React.createFactory React.createClass render: -> + { onClick } = @props div className: 'row', div className: 'col-xs-4 col-xs-offset-4', - button type: 'submit', onClick: @props.onClick, className: 'btn btn-default btn-lg form-control', 'Confirm' + button { + className: 'btn btn-default btn-lg btn-block', + onClick: onClick, + type: 'submit', + }, 'Confirm' Step = React.createFactory React.createClass render: -> + { error } = @props div className: 'form-step', div className: 'form-step-counter', @props.step div className: 'form-step-content', - div className: 'form-step-title', @props.title + div className: 'form-step-title', + @props.title, + div className: 'form-step-error', + error div className: 'clear-both' @props.children div className: 'clear-both' @TransactionForm = React.createClass getInitialState: -> - giving: null, amount: null, peer: null, message: null + step: 1, giving: null, amount: null, peer: null, message: null setAction: (b) -> @setState giving: b + @setState step: 2 unless @state.step > 1 setAmount: (a) -> @setState amount: a + @setState step: 3 unless @state.step > 2 setPeer: (p) -> @setState peer: p + @setState step: 4 unless @state.step > 3 setMessage: (m) -> @setState message: m + @setState step: 5 unless @state.step > 4 submit: (e) -> - console.log 'submit' - render: -> + e.preventDefault() + + { giving, peer } = @state + { user } = @props + + errors = @errors() + if Object.keys(errors).length != 0 + return + + if giving + debtor = user.name + creditor = peer + else + debtor = peer + creditor = user.name + + $('') + .attr('name', 'transaction[debtor]') + .attr('value', debtor) + .attr('type', 'hidden') + .appendTo(@refs.form) + $('') + .attr('name', 'transaction[creditor]') + .attr('value', creditor) + .attr('type', 'hidden') + .appendTo(@refs.form) + + @refs.form.submit() + errors: -> { amount, giving, message, peer } = @state - { peers } = @props + { peers, user } = @props + + errors = {} + + errors['giving'] = 'Please select an action.' unless giving != null + + unless amount + errors['amount'] = 'Please fill in an amount.' + else if parseFloat(amount) <= 0 + errors['amount'] = 'Please fill in a positive number.' + + unless message && message != "" + errors['message'] = 'Please fill in a message.' + + unless peer && peers.includes(peer) && peer != user + errors['peer'] = 'Please select a valid Zeus member.' + + errors + render: -> + { step, amount, giving, message, peer } = @state + { peers } = @props + + errors = @errors() + div id: 'transaction-form', h3 null, 'Transfer some money' - Step step: 1, title: 'What do you want to do?', - Action giving: giving, setAction: @setAction - if giving != null - Step step: 2, title: 'How much do you want to give?', - Amount setAmount: @setAmount - if amount != null - Step step: 3, title: 'Who do you want to give it to?', - Peer peer: peer, peers: peers, setPeer: @setPeer - if peer != null - Step step: 4, title: 'Why do you want to give this?', - Message setMessage: @setMessage - if message != null - Submit null + form ref: 'form', action: '/transactions', acceptCharset: 'UTF-8', method: 'post', + Step step: 1, title: 'What do you want to do?', + Action giving: giving, setAction: @setAction + if step >= 2 + Step { + step: 2, + title: "How much do you want to #{if giving then 'give' else 'receive'}?", + error: errors['amount'] if step > 2 + }, + Amount setAmount: @setAmount + if step >= 3 + Step { + step: 3, + title: "Who do you want to #{if giving then 'give it to' else 'receive it from'}?", + error: errors['peer'] if step > 3 + }, + Peer peer: peer, peers: peers, setPeer: @setPeer + if step >= 4 + Step { + step: 4, + title: "Why do you want to #{if giving then 'give' else 'receive'} this?", + error: errors['message'] if step > 4 + }, + Message setMessage: @setMessage + if step >= 5 + Submit onClick: @submit div className: 'clear-both' diff --git a/app/assets/stylesheets/transaction_form.scss b/app/assets/stylesheets/transaction_form.scss index 3617b15..e92de6e 100644 --- a/app/assets/stylesheets/transaction_form.scss +++ b/app/assets/stylesheets/transaction_form.scss @@ -31,7 +31,13 @@ $step-width: 26px; .form-step-title { display: inline-block; font-weight: bold; - margin-bottom: 10px; + margin-bottom: 5px; + } + + .form-step-error { + color: red; + font-size: 11px; + height: 15px; } .form-options { diff --git a/app/controllers/concerns/transactions_query.rb b/app/controllers/concerns/transactions_query.rb index bd87edc..2311809 100644 --- a/app/controllers/concerns/transactions_query.rb +++ b/app/controllers/concerns/transactions_query.rb @@ -6,7 +6,7 @@ class TransactionsQuery @transactions = Arel::Table.new(:transactions) @perspectived = Arel::Table.new(:perspectived_transactions) @peers = Arel::Table.new(:users).alias('peers') - @arel_table = Arel::Table.new(@user.name.concat('_transactions')) + @arel_table = Arel::Table.new("#{@user.name}_transactions") end def query diff --git a/app/controllers/transactions_controller.rb b/app/controllers/transactions_controller.rb index d4d1a45..4227c7e 100644 --- a/app/controllers/transactions_controller.rb +++ b/app/controllers/transactions_controller.rb @@ -10,21 +10,21 @@ class TransactionsController < ApplicationController @transaction = Transaction.new(transaction_params) @transaction.reverse if @transaction.amount < 0 - if can? :create, @transaction - if @transaction.save - render json: @transaction, status: :created - else - render json: @transaction.errors.full_messages, - status: :unprocessable_entity + unless can? :create, @transaction + @transaction = Request.new @transaction.info + authorize!(:create, @transaction) + end + + if @transaction.save + respond_to do |format| + format.html { redirect_to root_path } + format.json { render json: @transaction, status: :created } end else - request = Request.new @transaction.info - authorize!(:create, request) - if request.save - render json: request, status: :created - else - render json: request.errors.full_messages, - status: :unprocessable_entity + respond_to do |format| + format.html { redirect_to root_path } + format.json { render json: @transaction.errors.full_messages, + status: :unprocessable_entity } end end end diff --git a/app/models/concerns/base_transaction.rb b/app/models/concerns/base_transaction.rb index ece8add..80fb884 100644 --- a/app/models/concerns/base_transaction.rb +++ b/app/models/concerns/base_transaction.rb @@ -8,7 +8,9 @@ module BaseTransaction belongs_to :creditor, class_name: 'User' belongs_to :issuer, polymorphic: true - validates :amount, numericality: { greater_than: 0 } + validates :debtor, presence: true + validates :creditor, presence: true + validates :amount, numericality: { greater_than: 0 } validate :different_debtor_creditor end