Transaction form
This commit is contained in:
parent
546d918700
commit
af33a89790
9 changed files with 239 additions and 3 deletions
1
Gemfile
1
Gemfile
|
@ -95,3 +95,4 @@ gem 'high_voltage', '~> 2.4.0'
|
||||||
gem 'airbrake'
|
gem 'airbrake'
|
||||||
|
|
||||||
gem 'bootstrap-sass', '~> 3.3.5'
|
gem 'bootstrap-sass', '~> 3.3.5'
|
||||||
|
gem 'react-rails'
|
||||||
|
|
15
Gemfile.lock
15
Gemfile.lock
|
@ -46,6 +46,10 @@ GEM
|
||||||
autoprefixer-rails (6.0.2)
|
autoprefixer-rails (6.0.2)
|
||||||
execjs
|
execjs
|
||||||
json
|
json
|
||||||
|
babel-source (5.8.35)
|
||||||
|
babel-transpiler (0.7.0)
|
||||||
|
babel-source (>= 4.0, < 6)
|
||||||
|
execjs (~> 2.0)
|
||||||
bcrypt (3.1.10)
|
bcrypt (3.1.10)
|
||||||
binding_of_caller (0.7.2)
|
binding_of_caller (0.7.2)
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
|
@ -79,6 +83,7 @@ GEM
|
||||||
execjs
|
execjs
|
||||||
coffee-script-source (1.9.1.1)
|
coffee-script-source (1.9.1.1)
|
||||||
colorize (0.7.7)
|
colorize (0.7.7)
|
||||||
|
connection_pool (2.2.1)
|
||||||
coveralls (0.8.2)
|
coveralls (0.8.2)
|
||||||
json (~> 1.8)
|
json (~> 1.8)
|
||||||
rest-client (>= 1.6.8, < 2)
|
rest-client (>= 1.6.8, < 2)
|
||||||
|
@ -205,6 +210,13 @@ GEM
|
||||||
thor (>= 0.18.1, < 2.0)
|
thor (>= 0.18.1, < 2.0)
|
||||||
rake (10.4.2)
|
rake (10.4.2)
|
||||||
rdoc (4.2.0)
|
rdoc (4.2.0)
|
||||||
|
react-rails (1.10.0)
|
||||||
|
babel-transpiler (>= 0.7.0)
|
||||||
|
coffee-script-source (~> 1.8)
|
||||||
|
connection_pool
|
||||||
|
execjs
|
||||||
|
railties (>= 3.2)
|
||||||
|
tilt
|
||||||
responders (2.1.0)
|
responders (2.1.0)
|
||||||
railties (>= 4.2.0, < 5)
|
railties (>= 4.2.0, < 5)
|
||||||
rest-client (1.8.0)
|
rest-client (1.8.0)
|
||||||
|
@ -313,6 +325,7 @@ DEPENDENCIES
|
||||||
omniauth-oauth2
|
omniauth-oauth2
|
||||||
purecss-rails
|
purecss-rails
|
||||||
rails (= 4.2.4)
|
rails (= 4.2.4)
|
||||||
|
react-rails
|
||||||
rspec-rails
|
rspec-rails
|
||||||
sass-rails (~> 5.0)
|
sass-rails (~> 5.0)
|
||||||
sdoc (~> 0.4.0)
|
sdoc (~> 0.4.0)
|
||||||
|
@ -324,4 +337,4 @@ DEPENDENCIES
|
||||||
web-console (~> 2.0)
|
web-console (~> 2.0)
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.10.6
|
1.13.7
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
//= require select2
|
//= require select2
|
||||||
//= require jquery-dateFormat
|
//= require jquery-dateFormat
|
||||||
//= require turbolinks
|
//= require turbolinks
|
||||||
|
//= require react
|
||||||
|
//= require react_ujs
|
||||||
|
//= require components
|
||||||
//= require_tree .
|
//= require_tree .
|
||||||
|
|
||||||
ready = function() {
|
ready = function() {
|
||||||
|
|
1
app/assets/javascripts/components.js
Normal file
1
app/assets/javascripts/components.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
//= require_tree ./components
|
0
app/assets/javascripts/components/.gitkeep
Normal file
0
app/assets/javascripts/components/.gitkeep
Normal file
127
app/assets/javascripts/components/transaction_form.jsx.coffee
Normal file
127
app/assets/javascripts/components/transaction_form.jsx.coffee
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
{ button, div, h3, input, option, select } = React.DOM
|
||||||
|
|
||||||
|
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
|
||||||
|
t.value = parseFloat(t.value).toFixed(2)
|
||||||
|
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',
|
||||||
|
onChange: @onChange,
|
||||||
|
onBlur: @format
|
||||||
|
}
|
||||||
|
|
||||||
|
Suggestions = React.createFactory React.createClass
|
||||||
|
render: ->
|
||||||
|
|
||||||
|
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',
|
||||||
|
input type: 'text', className: @inputClass(options.length), onChange: @onChange, placeholder: 'Zeus member', value: (@props.peer || '')
|
||||||
|
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',
|
||||||
|
input type: 'text', className: 'form-control input-lg', onChange: @onChange, placeholder: 'Message'
|
||||||
|
|
||||||
|
Submit = React.createFactory React.createClass
|
||||||
|
render: ->
|
||||||
|
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'
|
||||||
|
|
||||||
|
Step = React.createFactory React.createClass
|
||||||
|
render: ->
|
||||||
|
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: 'clear-both'
|
||||||
|
@props.children
|
||||||
|
div className: 'clear-both'
|
||||||
|
|
||||||
|
@TransactionForm = React.createClass
|
||||||
|
getInitialState: ->
|
||||||
|
giving: null, amount: null, peer: null, message: null
|
||||||
|
setAction: (b) ->
|
||||||
|
@setState giving: b
|
||||||
|
setAmount: (a) ->
|
||||||
|
@setState amount: a
|
||||||
|
setPeer: (p) ->
|
||||||
|
@setState peer: p
|
||||||
|
setMessage: (m) ->
|
||||||
|
@setState message: m
|
||||||
|
submit: (e) ->
|
||||||
|
console.log 'submit'
|
||||||
|
render: ->
|
||||||
|
{ amount, giving, message, peer } = @state
|
||||||
|
{ peers } = @props
|
||||||
|
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
|
||||||
|
div className: 'clear-both'
|
|
@ -5,5 +5,9 @@
|
||||||
.card {
|
.card {
|
||||||
box-shadow: 0 1px 3px rgba(0,0,0, 0.12), 0 1px 2px rgba(0,0,0, 0.24);
|
box-shadow: 0 1px 3px rgba(0,0,0, 0.12), 0 1px 2px rgba(0,0,0, 0.24);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
|
||||||
|
&.padded {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
87
app/assets/stylesheets/transaction_form.scss
Normal file
87
app/assets/stylesheets/transaction_form.scss
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
$step-color: #b5b5b5;;
|
||||||
|
$step-padding-top: 3px;
|
||||||
|
$step-width: 26px;
|
||||||
|
|
||||||
|
#transaction-form {
|
||||||
|
.form-step {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.form-step-counter {
|
||||||
|
float: left;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
vertical-align: middle;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-align: center;
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 10px;
|
||||||
|
padding: $step-padding-top 7px;
|
||||||
|
height: $step-width;
|
||||||
|
width: $step-width;
|
||||||
|
background: $step-color;
|
||||||
|
color: #fff;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-step-content {
|
||||||
|
margin-left: $step-width + 10px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.form-step-title {
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-options {
|
||||||
|
& > div {
|
||||||
|
border: 1px solid #000;
|
||||||
|
display: inline-block;
|
||||||
|
width: 40%;
|
||||||
|
margin-right: 10px;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestions-wrapper {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
input.active {
|
||||||
|
border-radius: 6px 6px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestions {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-top: 0;
|
||||||
|
border-radius: 0 0 6px 6px;
|
||||||
|
background: #fff;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
.suggestion {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 8px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-radius: 0 0 6px 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
&:focus, &:active {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,8 +3,8 @@
|
||||||
= render 'transactions'
|
= render 'transactions'
|
||||||
.pure-u-5-12
|
.pure-u-5-12
|
||||||
.card-wrapper
|
.card-wrapper
|
||||||
.card
|
.card.padded
|
||||||
nieuwe transactie
|
= react_component 'TransactionForm', user: current_user, peers: User.all.order(:name).pluck(:name)
|
||||||
.card-wrapper
|
.card-wrapper
|
||||||
.card
|
.card
|
||||||
requests
|
requests
|
||||||
|
|
Loading…
Reference in a new issue