tab/app/assets/javascripts/components/transaction_form.jsx.coffee

215 lines
6.2 KiB
CoffeeScript
Raw Normal View History

2017-01-14 22:45:51 +01:00
{ button, div, form, h3, input, option, select } = React.DOM
2017-01-16 23:50:03 +01:00
window = @window
2017-01-12 16:29:49 +01:00
Action = React.createFactory React.createClass
buttonClass: (b) ->
{ giving } = @props
c = ['btn', 'btn-default']
c.push 'active' if b == giving
c.join ' '
onClick: (b) ->
=>
@props.setAction b
render: ->
{ giving } = @props
div className: 'btn-group btn-group-lg',
button type: 'button', className: @buttonClass(true), onClick: @onClick(true),
'Give Money'
button type: 'button', className: @buttonClass(false), onClick: @onClick(false),
'Request Money'
Amount = React.createFactory React.createClass
onChange: (ref) ->
@props.setAmount ref.target.value
format: (ref) ->
t = ref.target
2017-01-14 22:45:51 +01:00
t.value = parseFloat(t.value).toFixed(2) if t.value
2017-01-12 16:29:49 +01:00
render: ->
div className: 'row',
div className: 'col-xs-4',
div className: 'input-group',
div className: 'input-group-addon', ''
input {
className: 'form-control input-lg',
2017-01-14 22:45:51 +01:00
name: 'transaction[euros]'
onBlur: @format,
2017-01-12 16:29:49 +01:00
onChange: @onChange,
2017-01-14 22:45:51 +01:00
placeholder: '0.00',
type: 'number',
2017-01-12 16:29:49 +01:00
}
Peer = React.createFactory React.createClass
onChange: (ref) ->
@props.setPeer ref.target.value
options: ->
{ peer, peers } = @props
if peer == '' or peers.includes(peer)
[]
else
re = new RegExp peer
peers.filter (s) ->
s.match(re) != null
inputClass: (n) ->
c = ['form-control', 'input-lg']
c.push 'active' if n > 0
c.join ' '
setPeer: (p) ->
=>
@props.setPeer p
render: ->
options = @options()
div className: 'row',
div className: 'col-xs-4',
div className: 'suggestions-wrapper',
2017-01-14 22:45:51 +01:00
input {
className: @inputClass(options.length),
onChange: @onChange,
placeholder: 'Zeus member',
type: 'text',
value: (@props.peer || '')
}
2017-01-12 16:29:49 +01:00
if options.length != 0
div className: 'suggestions',
@options().map (s, i) =>
div className: 'suggestion', key: i, onClick: @setPeer(s),
s
Message = React.createFactory React.createClass
onChange: (ref) ->
@props.setMessage ref.target.value
render: ->
div className: 'row',
div className: 'col-xs-8',
2017-01-14 22:45:51 +01:00
input {
className: 'form-control input-lg',
name: 'transaction[message]',
onChange: @onChange,
placeholder: 'Message'
type: 'text',
}
2017-01-12 16:29:49 +01:00
Submit = React.createFactory React.createClass
render: ->
2017-01-14 22:45:51 +01:00
{ onClick } = @props
2017-01-12 16:29:49 +01:00
div className: 'row',
div className: 'col-xs-4 col-xs-offset-4',
2017-01-14 22:45:51 +01:00
button {
className: 'btn btn-default btn-lg btn-block',
onClick: onClick,
type: 'submit',
}, 'Confirm'
2017-01-12 16:29:49 +01:00
Step = React.createFactory React.createClass
render: ->
2017-01-14 22:45:51 +01:00
{ error } = @props
2017-01-12 16:29:49 +01:00
div className: 'form-step',
div className: 'form-step-counter', @props.step
div className: 'form-step-content',
2017-01-14 22:45:51 +01:00
div className: 'form-step-title',
@props.title,
div className: 'form-step-error',
error
2017-01-12 16:29:49 +01:00
div className: 'clear-both'
@props.children
div className: 'clear-both'
@TransactionForm = React.createClass
getInitialState: ->
2017-01-14 22:45:51 +01:00
step: 1, giving: null, amount: null, peer: null, message: null
2017-01-12 16:29:49 +01:00
setAction: (b) ->
@setState giving: b
2017-01-14 22:45:51 +01:00
@setState step: 2 unless @state.step > 1
2017-01-12 16:29:49 +01:00
setAmount: (a) ->
@setState amount: a
2017-01-14 22:45:51 +01:00
@setState step: 3 unless @state.step > 2
2017-01-12 16:29:49 +01:00
setPeer: (p) ->
@setState peer: p
2017-01-14 22:45:51 +01:00
@setState step: 4 unless @state.step > 3
2017-01-12 16:29:49 +01:00
setMessage: (m) ->
@setState message: m
2017-01-14 22:45:51 +01:00
@setState step: 5 unless @state.step > 4
2017-01-12 16:29:49 +01:00
submit: (e) ->
2017-01-14 22:45:51 +01:00
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
$('<input />')
.attr('name', 'transaction[debtor]')
.attr('value', debtor)
.attr('type', 'hidden')
.appendTo(@refs.form)
$('<input />')
.attr('name', 'transaction[creditor]')
.attr('value', creditor)
.attr('type', 'hidden')
.appendTo(@refs.form)
@refs.form.submit()
errors: ->
2017-01-12 16:29:49 +01:00
{ amount, giving, message, peer } = @state
2017-01-14 22:45:51 +01:00
{ 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()
2017-01-12 16:29:49 +01:00
div id: 'transaction-form',
h3 null, 'Transfer some money'
2017-01-16 23:50:03 +01:00
form ref: 'form', action: "#{window.base_url}/transactions", acceptCharset: 'UTF-8', method: 'post',
2017-01-14 22:45:51 +01:00
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
2017-01-12 16:29:49 +01:00
div className: 'clear-both'