Skip to content

Commit 4d6ec6b

Browse files
authored
OBPIH-7494 Split main state from general component in CC (#5551)
1 parent f049e60 commit 4d6ec6b

46 files changed

Lines changed: 2449 additions & 1551 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package-lock.json

Lines changed: 8 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
"redux-persist": "6.0.0",
118118
"redux-promise": "0.6.0",
119119
"redux-thunk": "2.4.2",
120+
"reselect": "5.1.1",
120121
"zod": "3.22.4"
121122
},
122123
"devDependencies": {

src/js/actions/index.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import _ from 'lodash';
33
import { addTranslationForLanguage } from 'react-localize-redux';
44

55
import {
6+
ADD_EMPTY_ROW,
67
ADD_INFO_BAR,
78
ADD_STOCK_MOVEMENT_DRAFT,
89
CHANGE_CURRENT_LOCALE,
@@ -15,6 +16,7 @@ import {
1516
FETCH_BUYERS,
1617
FETCH_CONFIG,
1718
FETCH_CONFIG_AND_SET_ACTIVE,
19+
FETCH_CYCLE_COUNTS,
1820
FETCH_GRAPHS,
1921
FETCH_INVOICE_STATUSES,
2022
FETCH_INVOICE_TYPE_CODES,
@@ -40,15 +42,18 @@ import {
4042
HIDE_INFO_BAR,
4143
HIDE_INFO_BAR_MODAL,
4244
HIDE_SPINNER,
45+
MARK_ALL_AS_UPDATED,
4346
REBUILD_FILTER_FORM_PARAMS,
4447
REMOVE_FROM_INDICATORS,
48+
REMOVE_ROW,
4549
REMOVE_STOCK_MOVEMENT_DRAFT,
4650
REORDER_INDICATORS,
4751
RESET_INDICATORS,
4852
SET_ACTIVE_CONFIG,
4953
SET_OFFLINE,
5054
SET_ONLINE,
5155
SET_SCROLL_TO_BOTTOM,
56+
SET_UPDATED,
5257
SHOW_INFO_BAR,
5358
SHOW_INFO_BAR_MODAL,
5459
SHOW_SPINNER,
@@ -57,6 +62,9 @@ import {
5762
START_RESOLUTION,
5863
TOGGLE_USER_ACTION_MENU,
5964
TRANSLATIONS_FETCHED,
65+
UPDATE_COUNTED_BY,
66+
UPDATE_DATE_COUNTED,
67+
UPDATE_FIELD_VALUE,
6068
} from 'actions/types';
6169
import cycleCountApi from 'api/services/CycleCountApi';
6270
import genericApi from 'api/services/GenericApi';
@@ -818,3 +826,120 @@ export const fetchLotNumbersByProductIds = (productIds) => async (dispatch) => {
818826
payload: lotNumbersWithExpiration,
819827
});
820828
};
829+
830+
export const fetchCycleCounts = (
831+
cycleCountIds,
832+
currentLocationId,
833+
sortByProductName,
834+
) => async (dispatch) => {
835+
dispatch(showSpinner());
836+
try {
837+
const cycleCounts = await cycleCountApi.getCycleCounts(
838+
currentLocationId,
839+
cycleCountIds,
840+
sortByProductName && 'productName',
841+
);
842+
dispatch({
843+
type: FETCH_CYCLE_COUNTS,
844+
payload: cycleCounts?.data?.data,
845+
});
846+
} finally {
847+
dispatch(hideSpinner());
848+
}
849+
};
850+
851+
export const setUpdated = (cycleCountId, updated) => (dispatch) => {
852+
dispatch({
853+
type: SET_UPDATED,
854+
payload: {
855+
id: cycleCountId,
856+
updated,
857+
},
858+
});
859+
};
860+
861+
export const updateDateCounted = (cycleCountId, dateCounted) => (dispatch) => {
862+
dispatch({
863+
type: UPDATE_DATE_COUNTED,
864+
payload: {
865+
id: cycleCountId,
866+
dateCounted,
867+
},
868+
});
869+
dispatch(setUpdated(cycleCountId, true));
870+
};
871+
872+
export const updateCountedBy = (cycleCountId, countedBy) => (dispatch) => {
873+
dispatch({
874+
type: UPDATE_COUNTED_BY,
875+
payload: {
876+
id: cycleCountId,
877+
countedBy,
878+
},
879+
});
880+
dispatch(setUpdated(cycleCountId, true));
881+
};
882+
883+
export const addEmptyRow = (cycleCountId) => (dispatch) => {
884+
dispatch({
885+
type: ADD_EMPTY_ROW,
886+
payload: {
887+
id: cycleCountId,
888+
},
889+
});
890+
};
891+
892+
export const removeRow = (cycleCountId, rowId, currentLocationId) => async (dispatch) => {
893+
try {
894+
dispatch(showSpinner());
895+
// We need to send request only if the row is already persisted.
896+
if (!rowId.includes('newRow')) {
897+
await cycleCountApi.deleteCycleCountItem(currentLocationId, rowId);
898+
}
899+
900+
dispatch({
901+
type: REMOVE_ROW,
902+
payload: {
903+
id: cycleCountId,
904+
rowId,
905+
},
906+
});
907+
} finally {
908+
dispatch(hideSpinner());
909+
}
910+
};
911+
912+
export const markAllItemsAsUpdated = (cycleCountIds) => (dispatch) => {
913+
dispatch({
914+
type: MARK_ALL_AS_UPDATED,
915+
payload: {
916+
cycleCountIds,
917+
updated: true,
918+
},
919+
});
920+
};
921+
922+
export const markAllItemsAsNotUpdated = (cycleCountIds) => (dispatch) => {
923+
dispatch({
924+
type: MARK_ALL_AS_UPDATED,
925+
payload: {
926+
cycleCountIds,
927+
updated: false,
928+
},
929+
});
930+
};
931+
932+
export const updateFieldValue = ({
933+
cycleCountId, rowId, field, value,
934+
}) => (dispatch) => {
935+
dispatch({
936+
type: UPDATE_FIELD_VALUE,
937+
payload: {
938+
id: cycleCountId,
939+
rowId,
940+
field,
941+
value,
942+
},
943+
});
944+
dispatch(setUpdated(cycleCountId, true));
945+
};

src/js/actions/types.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ export const FETCH_CYCLE_COUNT_REASON_CODES = 'FETCH_CYCLE_COUNT_REASON_CODES';
7676
export const FETCH_BIN_LOCATIONS = 'FETCH_BIN_LOCATIONS';
7777
export const ERASE_DRAFT = 'ERASE_DRAFT';
7878
export const UPDATE_CYCLE_COUNT_IDS = 'UPDATE_CYCLE_COUNT_IDS';
79+
export const FETCH_CYCLE_COUNTS = 'FETCH_CYCLE_COUNTS';
80+
export const UPDATE_DATE_COUNTED = 'UPDATE_DATE_COUNTED';
81+
export const UPDATE_COUNTED_BY = 'UPDATE_COUNTED_BY';
82+
export const ADD_EMPTY_ROW = 'ADD_EMPTY_ROW';
83+
export const REMOVE_ROW = 'REMOVE_ROW';
84+
export const SET_UPDATED = 'SET_UPDATED';
85+
export const MARK_ALL_AS_UPDATED = 'MARK_ALL_AS_UPDATED';
86+
export const IMPORT_CYCLE_COUNTS = 'IMPORT_CYCLE_COUNTS';
87+
export const UPDATE_FIELD_VALUE = 'UPDATE_FIELD_VALUE';
7988

8089
// Lot numbers
8190
export const FETCH_LOT_NUMBERS_BY_PRODUCT_IDS = 'FETCH_LOT_NUMBERS_BY_PRODUCT_IDS';

src/js/components/DataTable/v2/DataTable.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ const DataTable = ({
8888
defaultEmptyTableMessage={defaultEmptyTableMessage}
8989
loading={loading}
9090
rowModel={table.getRowModel()}
91-
dataLength={data?.length}
91+
dataLength={totalCount}
9292
tableWithPinnedColumns={tableWithPinnedColumns}
9393
isScreenWiderThanTable={isScreenWiderThanTable}
9494
/>

src/js/components/Router.jsx

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
1-
import React from 'react';
1+
import React, { useMemo } from 'react';
22

3-
import PropTypes from 'prop-types';
43
import queryString from 'query-string';
54
import Loadable from 'react-loadable';
6-
import { connect } from 'react-redux';
5+
import { useSelector } from 'react-redux';
76
import {
87
BrowserRouter, Redirect, Route, Switch,
98
} from 'react-router-dom';
109
import Alert from 'react-s-alert';
1110
import { ClimbingBoxLoader } from 'react-spinners';
11+
import {
12+
getCurrentLocationSupportedActivities,
13+
getNotificationAutohideDelay,
14+
getSpinner,
15+
} from 'selectors';
1216

1317
import CustomAlert from 'components/dashboard/CustomAlert';
1418
import MainLayoutRoute from 'components/Layout/MainLayoutRoute';
1519
import Loading from 'components/Loading';
20+
import ActivityCode from 'consts/activityCode';
1621
import { DASHBOARD_URL } from 'consts/applicationUrls';
1722
import useConnectionListener from 'hooks/useConnectionListener';
1823
import FlashScopeListenerWrapper from 'wrappers/FlashScopeListenerWrapper';
@@ -227,12 +232,19 @@ const AsyncStockTransferList = Loadable({
227232
loading: Loading,
228233
});
229234

230-
const Router = (props) => {
235+
const Router = () => {
231236
useConnectionListener();
232237

233-
const Dashboard = !props.supportedActivities.includes('MANAGE_INVENTORY') && props.supportedActivities.includes('SUBMIT_REQUEST')
234-
? AsyncStockRequestDashboard
235-
: AsyncDashboard;
238+
const spinner = useSelector(getSpinner);
239+
const supportedActivities = useSelector(getCurrentLocationSupportedActivities);
240+
const notificationAutohideDelay = useSelector(getNotificationAutohideDelay);
241+
242+
const Dashboard = useMemo(
243+
() => (!supportedActivities?.includes(ActivityCode.MANAGE_INVENTORY)
244+
&& supportedActivities?.includes(ActivityCode.SUBMIT_REQUEST)
245+
? AsyncStockRequestDashboard
246+
: AsyncDashboard), [supportedActivities],
247+
);
236248

237249
return (
238250
<div>
@@ -286,12 +298,12 @@ const Router = (props) => {
286298
<div className="spinner-container">
287299
<ClimbingBoxLoader
288300
color="#0c769e"
289-
loading={props.spinner}
290-
style={{ top: '40%', lefft: '50%' }}
301+
loading={spinner}
302+
style={{ top: '40%', left: '50%' }}
291303
/>
292304
</div>
293305
<Alert
294-
timeout={props.notificationAutohideDelay}
306+
timeout={notificationAutohideDelay}
295307
stack={{ limit: 3 }}
296308
contentTemplate={CustomAlert}
297309
position="top-right"
@@ -302,16 +314,4 @@ const Router = (props) => {
302314
);
303315
};
304316

305-
const mapStateToProps = (state) => ({
306-
spinner: state.spinner.show,
307-
supportedActivities: state.session.supportedActivities,
308-
notificationAutohideDelay: state.session.notificationAutohideDelay,
309-
});
310-
311-
export default connect(mapStateToProps, {})(Router);
312-
313-
Router.propTypes = {
314-
spinner: PropTypes.bool.isRequired,
315-
supportedActivities: PropTypes.arrayOf(PropTypes.string).isRequired,
316-
notificationAutohideDelay: PropTypes.number.isRequired,
317-
};
317+
export default Router;

src/js/components/cycleCount/ConfirmStepHeader.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { memo } from 'react';
22

33
import PropTypes from 'prop-types';
44

@@ -54,7 +54,7 @@ const ConfirmStepHeader = ({
5454
);
5555
};
5656

57-
export default ConfirmStepHeader;
57+
export default memo(ConfirmStepHeader);
5858

5959
ConfirmStepHeader.propTypes = {
6060
back: PropTypes.func.isRequired,
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import React, { useMemo } from 'react';
2+
3+
import PropTypes from 'prop-types';
4+
import { RiDeleteBinLine } from 'react-icons/ri';
5+
import { useSelector } from 'react-redux';
6+
import { Tooltip } from 'react-tippy';
7+
import { makeGetCycleCountItem } from 'selectors';
8+
9+
import { TableCell } from 'components/DataTable';
10+
import { NEW_ROW } from 'consts/cycleCount';
11+
import useTranslate from 'hooks/useTranslate';
12+
13+
const ActionsCell = ({
14+
id,
15+
cycleCountId,
16+
isStepEditable,
17+
isFormDisabled,
18+
removeRow,
19+
}) => {
20+
const translate = useTranslate();
21+
22+
const getCycleCountItem = useMemo(() => makeGetCycleCountItem(), []);
23+
const item = useSelector(
24+
(state) => getCycleCountItem(state, cycleCountId, id),
25+
);
26+
const { custom } = item;
27+
28+
return (
29+
<TableCell className="rt-td d-flex justify-content-center count-step-actions">
30+
<Tooltip
31+
arrow="true"
32+
delay="150"
33+
duration="250"
34+
hideDelay="50"
35+
className="text-overflow-ellipsis"
36+
html={(
37+
<span className="p-2">
38+
{translate('react.default.button.delete.label', 'Delete')}
39+
</span>
40+
)}
41+
disabled={id}
42+
>
43+
{(id?.includes(NEW_ROW) || custom) && isStepEditable && (
44+
<RiDeleteBinLine
45+
className={isFormDisabled ? 'disabled-icon' : 'cursor-pointer'}
46+
onClick={() => removeRow(id)}
47+
size={22}
48+
/>
49+
)}
50+
</Tooltip>
51+
</TableCell>
52+
);
53+
};
54+
55+
export default ActionsCell;
56+
57+
ActionsCell.propTypes = {
58+
id: PropTypes.string.isRequired,
59+
cycleCountId: PropTypes.string.isRequired,
60+
isStepEditable: PropTypes.bool.isRequired,
61+
isFormDisabled: PropTypes.bool.isRequired,
62+
removeRow: PropTypes.func.isRequired,
63+
};

0 commit comments

Comments
 (0)