Skip to content
This repository was archived by the owner on Mar 3, 2019. It is now read-only.

Commit aa7fe41

Browse files
committed
add stakeholder update form
1 parent 5e465e3 commit aa7fe41

File tree

17 files changed

+323
-97
lines changed

17 files changed

+323
-97
lines changed

src/common/API/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@ const API = {
1717
}
1818
};
1919
return fetch(url, config).then(res => res.json());
20+
},
21+
updateStakeholder: (stakeholderId, updates) => {
22+
const url = `${API_END_POINT}/parties/${stakeholderId}`;
23+
const config = {
24+
method: 'PATCH',
25+
body: JSON.stringify(updates),
26+
headers: {
27+
'content-type': 'application/json'
28+
}
29+
};
30+
return fetch(url, config).then(res => res.json());
2031
}
2132
};
2233

src/dashboard/Stakeholders/actions.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export const FETCH_STAKEHOLDERS_FAILURE = 'FETCH_STAKEHOLDERS_FAILURE';
77
export const SEARCH_STAKEHOLDERS = 'SEARCH_STAKEHOLDERS';
88
export const SELECT_STAKEHOLDER = 'SELECT_STAKEHOLDER';
99
export const ADD_NEW_STAKEHOLDER_SUCCESS = 'ADD_NEW_STAKEHOLDER_SUCCESS';
10+
export const UPDATE_STAKEHOLDER_SUCCESS = 'UPDATE_STAKEHOLDER_SUCCESS';
1011

1112

1213
export const fetchStakeholders = () => ({ type: FETCH_STAKEHOLDERS });
@@ -27,5 +28,10 @@ export const selectStakeholder = stakeholder => ({ type: SELECT_STAKEHOLDER, sta
2728
// action fired when search for stakeholder using search box
2829
export const searchStakeholders = searchText => ({ type: SEARCH_STAKEHOLDERS, searchText });
2930

30-
// action fired on add new stakeholder
31-
export const addNewStakeholderSuccess = stakeholder => ({ type: ADD_NEW_STAKEHOLDER_SUCCESS, stakeholder });
31+
// action fired on add new stakeholder success
32+
export const addNewStakeholderSuccess =
33+
stakeholder => ({ type: ADD_NEW_STAKEHOLDER_SUCCESS, stakeholder });
34+
35+
// action fired on update stakeholder successfully
36+
export const updateStakeholderSuccess =
37+
stakeholder => ({ type: UPDATE_STAKEHOLDER_SUCCESS, stakeholder });

src/dashboard/Stakeholders/components/StakeholderForm/index.js

Lines changed: 103 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,85 @@
11
import React, { Component } from 'react';
2-
import { Form, Input, Select, Button, Radio } from 'antd';
2+
import { Form, Input, Select, Button, Radio, Checkbox } from 'antd';
33
import { connect } from 'react-redux'
4+
import { from } from 'rxjs';
45
import API from 'API';
5-
import classnames from 'classnames';
6-
import { addNewStakeholderSuccess } from '../../actions';
6+
import classNames from 'classnames/bind';
7+
import { addNewStakeholderSuccess, updateStakeholderSuccess } from '../../actions';
78
import styles from './styles.css';
89

910

10-
const cx = classnames.bind(styles);
11+
const cx = classNames.bind(styles);
1112
const FormItem = Form.Item;
1213
const Option = Select.Option;
1314
const RadioGroup = Radio.Group;
15+
const CheckboxGroup = Checkbox.Group;
1416

1517
class BasicDetailsForm extends Component {
1618
state = { errorMsg: '', submitting: false };
19+
20+
componentDidMount() {
21+
const { stakeholder } = this.props;
22+
if (stakeholder) {
23+
const formFields = Object.keys(this.props.form.getFieldsValue());
24+
// set field values only available in a form to prevent
25+
// antd warning i.e you cannot set field before registering it.
26+
let fieldsValues = {};
27+
formFields.forEach(field => fieldsValues[field] = stakeholder[field]);
28+
this.props.form.setFieldsValue(fieldsValues);
29+
}
30+
}
31+
1732
handleSubmit = (e) => {
1833
e.preventDefault();
1934
this.props.form.validateFieldsAndScroll((err, data) => {
2035
if (!err) {
21-
this.setState({ submitting: true });
22-
API.createStakeholder(data)
23-
.then(result => {
24-
console.log(result);
25-
if (!result.status) {
26-
this.props.addNewStakeholderSuccess(result);
27-
this.setState({ submitting: false });
28-
this.props.handleCancelClick();
29-
} else {
30-
this.setState({ submitting: false });
31-
this.setState({ errorMsg: result.message });
32-
}
33-
});
36+
const { stakeholder } = this.props;
37+
if (stakeholder) {
38+
this.updateStakeholder(stakeholder._id, data);
39+
} else {
40+
this.createStakeholder(data);
41+
}
3442
}
3543
});
3644
}
3745

46+
/**
47+
* Create stakeholder helper function
48+
*/
49+
createStakeholder = (data) => {
50+
this.setState({ submitting: true });
51+
from(API.createStakeholder(data))
52+
.subscribe(result => {
53+
if (result.error) {
54+
// There is an error upon submitting
55+
this.setState({ submitting: false });
56+
this.setState({ errorMsg: result.message });
57+
} else {
58+
// submitted successfully
59+
this.props.addNewStakeholderSuccess(result);
60+
this.setState({ submitting: false });
61+
this.props.handleCancelClick();
62+
}
63+
});
64+
}
65+
66+
updateStakeholder = (stakeholderId, updates) => {
67+
this.setState({ submitting: true });
68+
from(API.updateStakeholder(stakeholderId, updates))
69+
.subscribe(result => {
70+
if (result.error) {
71+
// There is an error upon submitting
72+
this.setState({ submitting: false });
73+
this.setState({ errorMsg: result.message });
74+
} else {
75+
// patch submitted successfully
76+
this.props.updateStakeholderSuccess(result);
77+
this.setState({ submitting: false });
78+
this.props.handleCancelClick();
79+
}
80+
});
81+
}
82+
3883

3984
render() {
4085
const { handleCancelClick, form } = this.props;
@@ -83,6 +128,13 @@ class BasicDetailsForm extends Component {
83128
<Input placeholder='Stakeholder Name' />
84129
)}
85130
</FormItem>
131+
<FormItem label='Phone' {...formItemLayout} >
132+
{getFieldDecorator('phone', {
133+
rules: [{ required: true, message: 'Please input phone number!' }],
134+
})(
135+
<Input addonBefore={prefixSelector} placeholder='Phone Number' />
136+
)}
137+
</FormItem>
86138
<FormItem label='Email' {...formItemLayout} >
87139
{getFieldDecorator('email', {
88140
rules: [{
@@ -95,20 +147,13 @@ class BasicDetailsForm extends Component {
95147
)}
96148

97149
</FormItem>
98-
<FormItem label='Phone' {...formItemLayout} >
99-
{getFieldDecorator('phone', {
100-
rules: [{ required: true, message: 'Please input phone number!' }],
101-
})(
102-
<Input addonBefore={prefixSelector} placeholder='Phone Number' />
103-
)}
104-
</FormItem>
105-
<FormItem label='Category' {...formItemLayout} >
150+
<FormItem label='Type' {...formItemLayout} >
106151
{getFieldDecorator('type', {
107152
rules: [
108153
{ required: true, message: 'Please select stakeholder category' },
109154
],
110155
})(
111-
<Select placeholder='Select Category'>
156+
<Select placeholder='Select Type'>
112157
<Option value='Agency'>Agency</Option>
113158
<Option value='Committee'>Committee</Option>
114159
<Option value='Team'>Team</Option>
@@ -124,20 +169,47 @@ class BasicDetailsForm extends Component {
124169
</RadioGroup>
125170
)}
126171
</FormItem>
172+
<FormItem label='Area' {...formItemLayout} >
173+
{getFieldDecorator('area')(
174+
<Input placeholder='Area' />
175+
)}
176+
</FormItem>
177+
<FormItem label='Physical Address' {...formItemLayout} >
178+
{getFieldDecorator('physicalAddress')(
179+
<Input placeholder='Physical Address' />
180+
)}
181+
</FormItem>
182+
<FormItem label='Postal Address' {...formItemLayout} >
183+
{getFieldDecorator('postalAddress')(
184+
<Input placeholder='Postal Address' />
185+
)}
186+
</FormItem>
127187
<FormItem label='Fax' {...formItemLayout} >
128-
<Input />
188+
{getFieldDecorator('fax')(
189+
<Input placeholder='Fax' />
190+
)}
129191
</FormItem>
130192
<FormItem label='Website' {...formItemLayout} >
131-
<Input />
193+
{getFieldDecorator('website')(
194+
<Input placeholder='Website' />
195+
)}
196+
</FormItem>
197+
<FormItem label='Phase' {...formItemLayout} >
198+
{getFieldDecorator('phases', { initialValue: ['Mitigation'] })(
199+
<CheckboxGroup options={['Mitigation', 'Preparedness', 'Response', 'Recovery']} />
200+
)}
132201
</FormItem>
133202
<FormItem {...tailFormItemLayout}>
134-
<Button type="primary" htmlType="submit" loading={submitting}>Add Stakeholder</Button>
135-
<Button onClick={handleCancelClick} style={{ marginLeft: 8 }}>Cancel</Button>
203+
<Button onClick={handleCancelClick} >Cancel</Button>
204+
<Button type="primary" htmlType="submit" style={{ marginLeft: 8 }} loading={submitting}>Save</Button>
136205
</FormItem>
137206
</Form>
138207
</div>
139208
)
140209
}
141210
}
142211

143-
export default connect(null, { addNewStakeholderSuccess })(Form.create()(BasicDetailsForm));
212+
export default connect(null, {
213+
addNewStakeholderSuccess,
214+
updateStakeholderSuccess
215+
})(Form.create()(BasicDetailsForm));

src/dashboard/Stakeholders/components/StakeholderList/components/StakeholderItem/index.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import React, { Component } from 'react';
22
import PropTypes from 'prop-types';
3+
import classNames from 'classnames/bind';
34
import { connect } from 'react-redux';
45
import { Button, Checkbox, Col, List, Popover, Row } from 'antd';
56
import { selectStakeholder } from '../../../../actions';
7+
import styles from './styles.module.css';
8+
9+
10+
const cx = classNames.bind(styles);
611

712

813
const actions = (
@@ -42,36 +47,37 @@ class StakeholderItem extends Component {
4247
};
4348

4449
render() {
45-
const { stakeholder } = this.props;
46-
const { name, phone, email } = stakeholder;
50+
const { stakeholder, selectedStakeholder } = this.props;
51+
const { name, phone, email, _id } = stakeholder;
52+
const isSelected = selectedStakeholder ? selectedStakeholder._id === _id : false;
4753
return (
48-
<List.Item className="p-l-20">
54+
<List.Item className={cx("p-l-20", { 'isSelected': isSelected })}>
4955
<List.Item.Meta
50-
onClick={this.onClick}
56+
5157
avatar={<Checkbox />}
5258
title={(
5359
<Row>
54-
<Col xs={21}>
55-
<span className="f-600 f-15">
60+
<Col xs={21} >
61+
<span className={cx('f-600 f-15', 'name')} onClick={this.onClick} title='Click to view more'>
5662
{name}
5763
</span>
5864
</Col>
5965
<Col xs={3}>
6066
<Popover placement="bottom" trigger="click" content={actions}>
61-
<Button icon="ellipsis" className="f-20 b-0" />
67+
<Button icon="ellipsis" className={cx("f-20 b-0", { 'isSelected': isSelected })} />
6268
</Popover>
6369
</Col>
6470
</Row>
6571
)}
6672
description={(
6773
<Row>
6874
<Col span={8}>
69-
<Button icon="mobile" className="b-0">
75+
<Button icon="mobile" className={cx("b-0", { 'isSelected': isSelected })}>
7076
{phone}
7177
</Button>
7278
</Col>
7379
<Col span={8}>
74-
<Button icon="mail" className="b-0">
80+
<Button icon="mail" className={cx("b-0", { 'isSelected': isSelected })}>
7581
{email}
7682
</Button>
7783
</Col>
@@ -89,7 +95,11 @@ StakeholderItem.propTypes = {
8995
stakeholder: PropTypes.object,
9096
};
9197

98+
const mapStateToProps = state => ({
99+
selectedStakeholder: state.stakeholders.selected,
100+
});
101+
92102

93-
export default connect(null, { selectStakeholder })(StakeholderItem);
103+
export default connect(mapStateToProps, { selectStakeholder })(StakeholderItem);
94104

95105

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.isSelected {
2+
background: #f9f9f9;
3+
}
4+
5+
.name {
6+
cursor: pointer;
7+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React, { Component, Fragment } from 'react';
2+
import { Button, Row, Col, Divider, AutoComplete, Input, Icon } from 'antd';
3+
import './styles.css';
4+
5+
6+
class AddPersonnelForm extends Component {
7+
state = { showAddPersonnelForm: false, dataSource: [], selected: null };
8+
9+
onSelect = (value) => {
10+
console.log(value);
11+
this.setState({ selected: value });
12+
}
13+
14+
handleSearch = (value) => {
15+
this.setState({ selected: null });
16+
this.setState({
17+
dataSource: !value ? [] : [
18+
value,
19+
value + value,
20+
value + value + value,
21+
],
22+
});
23+
}
24+
25+
render() {
26+
const { showAddPersonnelForm, dataSource, selected } = this.state;
27+
return (<Fragment>
28+
{
29+
showAddPersonnelForm ? '' : (
30+
<Row type="flex" align="middle" justify="center">
31+
<Col span={10}>
32+
<div>
33+
<div style={{ width: '100%' }}>
34+
<AutoComplete
35+
className="search-stakeholder"
36+
style={{ width: '100%' }}
37+
dataSource={dataSource}
38+
onSelect={this.onSelect}
39+
onSearch={this.handleSearch}
40+
placeholder="Search stakeholder...."
41+
>
42+
<Input
43+
suffix={selected ? (
44+
<Button className="search-btn" type="primary">
45+
<Icon type="plus" /> Add
46+
</Button>
47+
) : (
48+
<Button className="search-btn" type="primary" disabled>
49+
<Icon type="plus" /> Add
50+
</Button>
51+
)}
52+
/>
53+
</AutoComplete>
54+
</div>
55+
<Divider><div>OR</div></Divider>
56+
<Button type="primary" block className='block' >Create New Personnel</Button>
57+
</div>
58+
</Col>
59+
</Row>
60+
)
61+
}
62+
63+
</Fragment>)
64+
}
65+
}
66+
67+
export default AddPersonnelForm;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.search-stakeholder.ant-select-auto-complete .ant-input-affix-wrapper .ant-input-suffix button {
2+
border-top-left-radius: 0;
3+
border-bottom-left-radius: 0;
4+
}
5+
6+
.search-stakeholder.ant-select-auto-complete .ant-input-affix-wrapper .ant-input-suffix {
7+
right: 0;
8+
}

0 commit comments

Comments
 (0)