Skip to content

Commit 5e765e0

Browse files
Cadastro de ciclo de pagamento
1 parent 601916d commit 5e765e0

File tree

8 files changed

+157
-49
lines changed

8 files changed

+157
-49
lines changed

my-money-app/frontend/src/billingCycle/billingCycle.jsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,15 @@ import TabsHeader from '../common/tab/tabsHeader'
99
import TabsContent from '../common/tab/tabsContent'
1010
import TabHeader from '../common/tab/tabHeader'
1111
import TabContent from '../common/tab/tabContent'
12-
import { selectTab, showTabs } from '../common/tab/tabActions'
13-
import { create, update, remove } from './billingCycleActions'
12+
import { init, create, update, remove } from './billingCycleActions'
1413

1514
import List from './billingCycleList'
1615
import Form from './billingCycleForm'
1716

1817
class BillingCycle extends Component {
1918

2019
componentWillMount() {
21-
this.props.selectTab('tabList')
22-
this.props.showTabs('tabList', 'tabCreate')
20+
this.props.init()
2321
}
2422

2523
render() {
@@ -39,26 +37,26 @@ class BillingCycle extends Component {
3937
<List />
4038
</TabContent>
4139
<TabContent id='tabCreate'>
42-
<Form onSubmit={this.props.create}
40+
<Form onSubmit={this.props.create}
4341
submitLabel='Incluir' submitClass='primary' />
4442
</TabContent>
4543
<TabContent id='tabUpdate'>
46-
<Form onSubmit={this.props.update}
44+
<Form onSubmit={this.props.update}
4745
submitLabel='Alterar' submitClass='info' />
4846
</TabContent>
4947
<TabContent id='tabDelete'>
50-
<Form onSubmit={this.props.remove} readOnly={true}
48+
<Form onSubmit={this.props.remove} readOnly={true}
5149
submitLabel='Excluir' submitClass='danger' />
5250
</TabContent>
5351
</TabsContent>
5452
</Tabs>
5553
</Content>
56-
</div>
54+
</div>
5755
)
5856
}
5957
}
6058

6159
const mapDispatchToProps = dispatch => bindActionCreators({
62-
selectTab, showTabs, create, update, remove
60+
init, create, update, remove
6361
}, dispatch)
6462
export default connect(null, mapDispatchToProps)(BillingCycle)

my-money-app/frontend/src/billingCycle/billingCycleActions.js

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { reset as resetForm, initialize } from 'redux-form'
44
import { showTabs, selectTab } from '../common/tab/tabActions'
55

66
const BASE_URL = 'http://localhost:3003/api'
7+
const INITIAL_VALUES = {credits: [{}], debts: [{}]}
78

89
export function getList() {
910
const request = axios.get(`${BASE_URL}/billingCycles`)
@@ -31,12 +32,7 @@ function submit(values, method) {
3132
axios[method](`${BASE_URL}/billingCycles/${id}`, values)
3233
.then(resp => {
3334
toastr.success('Sucesso', 'Operação Realizada com sucesso.')
34-
dispatch([
35-
resetForm('billingCycleForm'),
36-
getList(),
37-
selectTab('tabList'),
38-
showTabs('tabList', 'tabCreate')
39-
])
35+
dispatch(init())
4036
})
4137
.catch(e => {
4238
e.response.data.errors.forEach(error => toastr.error('Erro', error))
@@ -48,30 +44,23 @@ export function showUpdate(billingCycle) {
4844
return [
4945
showTabs('tabUpdate'),
5046
selectTab('tabUpdate'),
51-
select(billingCycle)
47+
initialize('billingCycleForm', billingCycle)
5248
]
5349
}
5450

5551
export function showDelete(billingCycle) {
5652
return [
5753
showTabs('tabDelete'),
5854
selectTab('tabDelete'),
59-
select(billingCycle)
55+
initialize('billingCycleForm', billingCycle)
6056
]
6157
}
6258

63-
export function select(billingCycle) {
64-
return {
65-
type: 'BILLING_CYCLE_SELECTED',
66-
payload: billingCycle
67-
}
68-
}
69-
70-
export function cancel() {
71-
return [
59+
export function init() {
60+
return [
7261
showTabs('tabList', 'tabCreate'),
7362
selectTab('tabList'),
74-
resetForm('billingCycleForm'),
75-
{ type: 'BILLING_CYCLE_CANCELED' }
63+
getList(),
64+
initialize('billingCycleForm', INITIAL_VALUES)
7665
]
7766
}
Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,58 @@
11
import React, { Component } from 'react'
22
import { connect } from 'react-redux'
33
import { bindActionCreators } from 'redux'
4-
import { reduxForm, Field, initialize } from 'redux-form'
5-
import labelAndInput from '../common/form/labelAndInput'
6-
import { cancel } from './billingCycleActions'
4+
import { reduxForm, Field, formValueSelector } from 'redux-form'
5+
6+
import { init } from './billingCycleActions'
7+
import LabelAndInput from '../common/form/labelAndInput'
8+
import ItemList from './itemList'
9+
import Summary from './summary'
710

811
class BillingCycleForm extends Component {
912

10-
componentWillMount() {
11-
initialize('billingCycleForm', this.props.initialValues)
13+
calculateSummary() {
14+
const sum = (t, v) => t + v
15+
return {
16+
sumOfCredits: this.props.credits.map(c => +c.value || 0).reduce(sum),
17+
sumOfDebts: this.props.debts.map(d => +d.value || 0).reduce(sum)
18+
}
1219
}
1320

1421
render() {
15-
const { handleSubmit, readOnly } = this.props
22+
const { handleSubmit, readOnly, credits, debts } = this.props
23+
const { sumOfCredits, sumOfDebts } = this.calculateSummary()
1624
return (
1725
<form role='form' onSubmit={handleSubmit}>
1826
<div className='box-body'>
19-
<Field name='name' component={labelAndInput} readOnly={readOnly}
27+
<Field name='name' component={LabelAndInput} readOnly={readOnly}
2028
label='Nome' cols='12 4' placeholder='Informe o nome' />
21-
<Field name='month' component={labelAndInput} type='number' readOnly={readOnly}
29+
<Field name='month' component={LabelAndInput} type='number' readOnly={readOnly}
2230
label='Mês' cols='12 4' placeholder='Informe o mês' />
23-
<Field name='year' component={labelAndInput} type='number' readOnly={readOnly}
31+
<Field name='year' component={LabelAndInput} type='number' readOnly={readOnly}
2432
label='Ano' cols='12 4' placeholder='Informe o ano' />
33+
<Summary credit={sumOfCredits} debt={sumOfDebts} />
34+
<ItemList cols='12 6' list={credits} readOnly={readOnly}
35+
field='credits' legend='Créditos' />
36+
<ItemList cols='12 6' list={debts} readOnly={readOnly}
37+
field='debts' legend='Débitos' showStatus={true} />
2538
</div>
2639
<div className='box-footer'>
2740
<button type='submit' className={`btn btn-${this.props.submitClass}`}>
2841
{this.props.submitLabel}
2942
</button>
3043
<button type='button' className='btn btn-default'
31-
onClick={this.props.cancel}>Cancelar</button>
44+
onClick={this.props.init}>Cancelar</button>
3245
</div>
3346
</form>
3447
)
3548
}
3649
}
3750

38-
BillingCycleForm = reduxForm({form: 'billingCycleForm'})(BillingCycleForm)
39-
const mapStateToProps = state => ({initialValues: state.billingCycle.initialValues})
40-
const mapDispatchToProps = dispatch => bindActionCreators({cancel}, dispatch)
51+
BillingCycleForm = reduxForm({form: 'billingCycleForm', destroyOnUnmount: false})(BillingCycleForm)
52+
const selector = formValueSelector('billingCycleForm')
53+
const mapStateToProps = state => ({
54+
credits: selector(state, 'credits'),
55+
debts: selector(state, 'debts')
56+
})
57+
const mapDispatchToProps = dispatch => bindActionCreators({init}, dispatch)
4158
export default connect(mapStateToProps, mapDispatchToProps)(BillingCycleForm)

my-money-app/frontend/src/billingCycle/billingCycleList.jsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,5 @@ class BillingCycleList extends Component {
5050
}
5151

5252
const mapStateToProps = state => ({list: state.billingCycle.list})
53-
const mapDispatchToProps = dispatch => bindActionCreators({
54-
getList, showUpdate, showDelete
55-
}, dispatch)
53+
const mapDispatchToProps = dispatch => bindActionCreators({getList, showUpdate, showDelete}, dispatch)
5654
export default connect(mapStateToProps, mapDispatchToProps)(BillingCycleList)

my-money-app/frontend/src/billingCycle/billingCycleReducer.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
const INITIAL_STATE = {list: [], initialValues: {}}
1+
const INITIAL_STATE = {list: []}
22

33
export default (state = INITIAL_STATE, action) => {
44
switch (action.type) {
55
case 'BILLING_CYCLES_FETCHED':
66
return { ...state, list: action.payload.data }
7-
case 'BILLING_CYCLE_SELECTED':
8-
return { ...state, initialValues: action.payload }
9-
case 'BILLING_CYCLE_CANCELED':
10-
return { ...state, initialValues: INITIAL_STATE.initialValues }
117
default:
128
return state
139
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import React, { Component } from 'react'
2+
import { connect } from 'react-redux'
3+
import { bindActionCreators } from 'redux'
4+
import { Field, arrayInsert, arrayRemove } from 'redux-form'
5+
import Grid from '../common/layout/grid'
6+
import Input from '../common/form/input'
7+
import If from '../common/operator/if'
8+
9+
class ItemList extends Component {
10+
11+
add(index, item = {}) {
12+
if(!this.props.readOnly) {
13+
this.props.arrayInsert('billingCycleForm', this.props.field, index, item)
14+
}
15+
}
16+
17+
remove(index) {
18+
if(!this.props.readOnly && this.props.list.length > 1) {
19+
this.props.arrayRemove('billingCycleForm', this.props.field, index)
20+
}
21+
}
22+
23+
renderRows() {
24+
const list = this.props.list || []
25+
return list.map((item, index) => (
26+
<tr key={index}>
27+
<td><Field name={`${this.props.field}[${index}].name`} component={Input}
28+
placeholder='Informe o nome' readOnly={this.props.readOnly} /></td>
29+
<td><Field name={`${this.props.field}[${index}].value`} component={Input}
30+
placeholder='Informe o valor' readOnly={this.props.readOnly} /></td>
31+
<If test={this.props.showStatus}>
32+
<td><Field name={`${this.props.field}[${index}].status`} component={Input}
33+
placeholder='Informe o status' readOnly={this.props.readOnly} /></td>
34+
</If>
35+
<td>
36+
<button type='button' className='btn btn-success'
37+
onClick={() => this.add(index + 1)}>
38+
<i className="fa fa-plus"></i>
39+
</button>
40+
<button type='button' className='btn btn-warning'
41+
onClick={() => this.add(index + 1, item)}>
42+
<i className="fa fa-clone"></i>
43+
</button>
44+
<button type='button' className='btn btn-danger'
45+
onClick={() => this.remove(index)}>
46+
<i className="fa fa-trash-o"></i>
47+
</button>
48+
</td>
49+
</tr>
50+
))
51+
}
52+
53+
render() {
54+
return (
55+
<Grid cols={this.props.cols}>
56+
<fieldset>
57+
<legend>{this.props.legend}</legend>
58+
<table className='table'>
59+
<thead>
60+
<tr>
61+
<th>Nome</th>
62+
<th>Valor</th>
63+
<If test={this.props.showStatus}>
64+
<th>Status</th>
65+
</If>
66+
<th className='table-actions'>Ações</th>
67+
</tr>
68+
</thead>
69+
<tbody>
70+
{this.renderRows()}
71+
</tbody>
72+
</table>
73+
</fieldset>
74+
</Grid>
75+
)
76+
}
77+
}
78+
79+
const mapDispatchToProps = dispatch => bindActionCreators({ arrayInsert, arrayRemove }, dispatch)
80+
export default connect(null, mapDispatchToProps)(ItemList)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React, { Component } from 'react'
2+
3+
import Grid from '../common/layout/grid'
4+
import Row from '../common/layout/row'
5+
import ValueBox from '../common/widget/valueBox'
6+
7+
export default ({credit, debt}) => (
8+
<Grid cols='12'>
9+
<fieldset>
10+
<legend>Resumo</legend>
11+
<Row>
12+
<ValueBox cols='12 4' color='green' icon='bank'
13+
value={`R$ ${credit}`} text='Total de Créditos' />
14+
<ValueBox cols='12 4' color='red' icon='credit-card'
15+
value={`R$ ${debt}`} text='Total de Débitos' />
16+
<ValueBox cols='12 4' color='blue' icon='money'
17+
value={`R$ ${credit - debt}`} text='Valor Consolidado' />
18+
</Row>
19+
</fieldset>
20+
</Grid>
21+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React from 'react'
2+
3+
export default props => (
4+
<input {...props.input}
5+
className='form-control'
6+
placeholder={props.placeholder}
7+
readOnly={props.readOnly}
8+
type={props.type} />
9+
)

0 commit comments

Comments
 (0)