Skip to content

Commit 01da5dc

Browse files
committed
feat(item categories): display a list of item categories
closes #121
1 parent dc1e03c commit 01da5dc

File tree

1 file changed

+288
-0
lines changed
  • src/Resources/components/ItemCategories/List

1 file changed

+288
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
import { httpActions } from '@codetanzania/emis-api-client';
2+
import {
3+
deleteItemCategory,
4+
paginateItemCategories,
5+
refreshItemCategories,
6+
} from '@codetanzania/emis-api-states';
7+
import { List } from 'antd';
8+
import concat from 'lodash/concat';
9+
import intersectionBy from 'lodash/intersectionBy';
10+
import map from 'lodash/map';
11+
import remove from 'lodash/remove';
12+
import uniq from 'lodash/uniq';
13+
import uniqBy from 'lodash/uniqBy';
14+
import PropTypes from 'prop-types';
15+
import React, { Component, Fragment } from 'react';
16+
import ListHeader from '../../../../components/ListHeader';
17+
import Toolbar from '../../../../components/Toolbar';
18+
import { notifyError, notifySuccess } from '../../../../util';
19+
import ListItem from '../ListItem';
20+
21+
/* constants */
22+
const headerLayout = [
23+
{ span: 6, header: 'Name' },
24+
{ span: 14, header: 'Description' },
25+
];
26+
const { getItemCategoriesExportUrl } = httpActions;
27+
28+
/**
29+
* @class
30+
* @name ItemCategoriesList
31+
* @description Render ItemCategoriesList component which have actionBar, ItemCategories
32+
* header and ItemCategories list components
33+
*
34+
* @version 0.1.0
35+
* @since 0.1.0
36+
*/
37+
class ItemCategoriesList extends Component {
38+
static propTypes = {
39+
loading: PropTypes.bool.isRequired,
40+
itemCategories: PropTypes.arrayOf(
41+
PropTypes.shape({
42+
_id: PropTypes.string.isRequired,
43+
value: PropTypes.string.isRequired,
44+
abbreviation: PropTypes.string.isRequired,
45+
color: PropTypes.string.isRequired,
46+
description: PropTypes.string.isRequired,
47+
})
48+
).isRequired,
49+
page: PropTypes.number.isRequired,
50+
total: PropTypes.number.isRequired,
51+
onEdit: PropTypes.func.isRequired,
52+
onFilter: PropTypes.func.isRequired,
53+
onNotify: PropTypes.func.isRequired,
54+
onShare: PropTypes.func.isRequired,
55+
onBulkShare: PropTypes.func.isRequired,
56+
};
57+
58+
state = {
59+
selectedItemCategories: [],
60+
selectedPages: [],
61+
};
62+
63+
/**
64+
* @function
65+
* @name handleOnSelectItem
66+
* @description Handle select a single itemCategory action
67+
*
68+
* @param {Object} itemCategory selected itemCategory object
69+
*
70+
* @version 0.1.0
71+
* @since 0.1.0
72+
*/
73+
handleOnSelectItem = itemCategory => {
74+
const { selectedItemCategories } = this.state;
75+
this.setState({
76+
selectedItemCategories: concat([], selectedItemCategories, itemCategory),
77+
});
78+
};
79+
80+
/**
81+
* @function
82+
* @name handleSelectAll
83+
* @description Handle select all itemCategories actions from current page
84+
*
85+
* @version 0.1.0
86+
* @since 0.1.0
87+
*/
88+
handleSelectAll = () => {
89+
const { selectedItemCategories, selectedPages } = this.state;
90+
const { itemCategories, page } = this.props;
91+
const selectedList = uniqBy(
92+
[...selectedItemCategories, ...itemCategories],
93+
'_id'
94+
);
95+
const pages = uniq([...selectedPages, page]);
96+
this.setState({
97+
selectedItemCategories: selectedList,
98+
selectedPages: pages,
99+
});
100+
};
101+
102+
/**
103+
* @function
104+
* @name handleDeselectAll
105+
* @description Handle deselect all itemCategories in a current page
106+
*
107+
* @returns {undefined} undefined
108+
*
109+
* @version 0.1.0
110+
* @since 0.1.0
111+
*/
112+
handleDeselectAll = () => {
113+
const { itemCategories, page } = this.props;
114+
const { selectedItemCategories, selectedPages } = this.state;
115+
const selectedList = uniqBy([...selectedItemCategories], '_id');
116+
const pages = uniq([...selectedPages]);
117+
118+
remove(pages, itemCategory => itemCategory === page);
119+
120+
itemCategories.forEach(itemCategory => {
121+
remove(
122+
selectedList,
123+
item => item._id === itemCategory._id // eslint-disable-line
124+
);
125+
});
126+
127+
this.setState({
128+
selectedItemCategories: selectedList,
129+
selectedPages: pages,
130+
});
131+
};
132+
133+
/**
134+
* @function
135+
* @name handleFilterByStatus
136+
* @description Handle filter itemCategories by status action
137+
*
138+
* @version 0.1.0
139+
* @since 0.1.0
140+
*/
141+
handleFilterByStatus = () => {
142+
// if (status === 'All') {
143+
// filter({});
144+
// } else if (status === 'Active') {
145+
// filter({});
146+
// } else if (status === 'Archived') {
147+
// filter({});
148+
// }
149+
};
150+
151+
/**
152+
* @function
153+
* @name handleOnDeselectItem
154+
* @description Handle deselect a single itemCategory action
155+
*
156+
* @param {Object} itemCategory itemCategory to be removed from selected itemCategories
157+
* @returns {undefined} undefined
158+
*
159+
* @version 0.1.0
160+
* @since 0.1.0
161+
*/
162+
handleOnDeselectItem = itemCategory => {
163+
const { selectedItemCategories } = this.state;
164+
const selectedList = [...selectedItemCategories];
165+
166+
remove(
167+
selectedList,
168+
item => item._id === itemCategory._id // eslint-disable-line
169+
);
170+
171+
this.setState({ selectedItemCategories: selectedList });
172+
};
173+
174+
render() {
175+
const {
176+
itemCategories,
177+
loading,
178+
page,
179+
total,
180+
onEdit,
181+
onFilter,
182+
onNotify,
183+
onShare,
184+
onBulkShare,
185+
} = this.props;
186+
const { selectedItemCategories, selectedPages } = this.state;
187+
const selectedItemsCount = intersectionBy(
188+
this.state.selectedItemCategories,
189+
itemCategories,
190+
'_id'
191+
).length;
192+
193+
return (
194+
<Fragment>
195+
{/* toolbar */}
196+
<Toolbar
197+
itemName="itemCategory"
198+
page={page}
199+
total={total}
200+
selectedItemsCount={selectedItemsCount}
201+
exportUrl={getItemCategoriesExportUrl({
202+
filter: { _id: map(selectedItemCategories, '_id') },
203+
})}
204+
onFilter={onFilter}
205+
onNotify={() => onNotify(selectedItemCategories)}
206+
onPaginate={nextPage => {
207+
paginateItemCategories(nextPage);
208+
}}
209+
onRefresh={() =>
210+
refreshItemCategories(
211+
() => {
212+
notifySuccess('ItemCategories refreshed successfully');
213+
},
214+
() => {
215+
notifyError(
216+
'An Error occurred while refreshing ItemCategories please contact system administrator'
217+
);
218+
}
219+
)
220+
}
221+
onShare={() => onBulkShare(selectedItemCategories)}
222+
/>
223+
{/* end toolbar */}
224+
225+
{/* itemCategory list header */}
226+
<ListHeader
227+
headerLayout={headerLayout}
228+
onSelectAll={this.handleSelectAll}
229+
onDeselectAll={this.handleDeselectAll}
230+
isBulkSelected={selectedPages.includes(page)}
231+
/>
232+
{/* end itemCategory list header */}
233+
234+
{/* itemCategories list */}
235+
<List
236+
loading={loading}
237+
dataSource={itemCategories}
238+
renderItem={itemCategory => (
239+
<ListItem
240+
key={itemCategory._id} // eslint-disable-line
241+
abbreviation={itemCategory.abbreviation}
242+
name={itemCategory.value}
243+
color={itemCategory.color}
244+
description={
245+
itemCategory.description ? itemCategory.description : 'N/A'
246+
}
247+
isSelected={
248+
// eslint-disable-next-line
249+
map(
250+
selectedItemCategories,
251+
item => item._id // eslint-disable-line
252+
).includes(
253+
itemCategory._id // eslint-disable-line
254+
)
255+
}
256+
onSelectItem={() => {
257+
this.handleOnSelectItem(itemCategory);
258+
}}
259+
onDeselectItem={() => {
260+
this.handleOnDeselectItem(itemCategory);
261+
}}
262+
onEdit={() => onEdit(itemCategory)}
263+
onArchive={() =>
264+
deleteItemCategory(
265+
itemCategory._id, // eslint-disable-line
266+
() => {
267+
notifySuccess('Item was archived successfully');
268+
},
269+
() => {
270+
notifyError(
271+
'An Error occurred while archiving Item please contact system administrator'
272+
);
273+
}
274+
)
275+
}
276+
onShare={() => {
277+
onShare(itemCategory);
278+
}}
279+
/>
280+
)}
281+
/>
282+
{/* end itemCategories list */}
283+
</Fragment>
284+
);
285+
}
286+
}
287+
288+
export default ItemCategoriesList;

0 commit comments

Comments
 (0)