@openmrs/esm-stock-management-app 1.0.1-pre.785 → 1.0.1-pre.790

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/493.js +1 -1
  2. package/dist/493.js.map +1 -1
  3. package/dist/880.js +1 -0
  4. package/dist/880.js.map +1 -0
  5. package/dist/942.js +1 -0
  6. package/dist/942.js.map +1 -0
  7. package/dist/main.js +1 -1
  8. package/dist/main.js.map +1 -1
  9. package/dist/openmrs-esm-stock-management-app.js +1 -1
  10. package/dist/openmrs-esm-stock-management-app.js.buildmanifest.json +41 -41
  11. package/dist/routes.json +1 -1
  12. package/package.json +1 -1
  13. package/src/config-schema.ts +6 -0
  14. package/src/index.ts +15 -21
  15. package/src/routes.json +5 -4
  16. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-items-table.scss +34 -0
  17. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-items-table.tsx +111 -0
  18. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operation-expanded-row.component.tsx +116 -0
  19. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operation-expanded-row.scss +31 -0
  20. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operations-status.tsx +45 -0
  21. package/src/stock-operations/edit-stock-operation/edit-stock-operation-action-menu.component.tsx +2 -2
  22. package/src/stock-operations/stock-operation-actions.component.tsx +81 -0
  23. package/src/stock-operations/stock-operation-links.component.tsx +82 -0
  24. package/src/stock-operations/stock-operation-reference.component.tsx +2 -2
  25. package/src/stock-operations/stock-operation-types-selector/stock-operation-types-selector.component.tsx +2 -2
  26. package/src/stock-operations/stock-operation.utils.tsx +8 -13
  27. package/src/stock-operations/stock-operations-dialog/stock-operations-issue-stock-button.component.tsx +2 -2
  28. package/src/stock-operations/stock-operations-forms/input-components/stock-item-search.component.tsx +30 -7
  29. package/src/stock-operations/stock-operations-forms/step1.test.tsx +158 -17
  30. package/src/stock-operations/stock-operations-forms/step2.test.tsx +59 -10
  31. package/src/stock-operations/stock-operations-forms/step3.test.tsx +63 -10
  32. package/src/stock-operations/stock-operations-forms/steps/base-operation-details-form-step.tsx +11 -9
  33. package/src/stock-operations/stock-operations-forms/steps/received-items.component.tsx +111 -0
  34. package/src/stock-operations/stock-operations-forms/steps/stock-operation-item-cell.component.tsx +20 -9
  35. package/src/stock-operations/stock-operations-forms/steps/stock-operation-items-form-step.component.tsx +21 -46
  36. package/src/stock-operations/stock-operations-forms/steps/stock-operation-items-form-step.scc.scss +4 -18
  37. package/src/stock-operations/stock-operations-forms/steps/stock-operation-submission-form-step.component.tsx +22 -10
  38. package/src/stock-operations/stock-operations-forms/stock-issue-form-initializer-with-related-requisition-operation.component.tsx +20 -3
  39. package/src/stock-operations/stock-operations-forms/stock-item-form/stock-item-form.workspace.tsx +19 -7
  40. package/src/stock-operations/stock-operations-forms/stock-operation-form.component.tsx +114 -67
  41. package/src/stock-operations/stock-operations-forms/stock-operation-form.scss +5 -24
  42. package/src/stock-operations/stock-operations-forms/stock-operation-related-link.component.tsx +2 -2
  43. package/src/stock-operations/stock-operations-forms/stock-operation-stepper/stepper.scss +14 -11
  44. package/src/stock-operations/stock-operations-forms/stock-operation-stepper/stock-operation-stepper.component.tsx +2 -6
  45. package/src/stock-operations/stock-operations-table.component.tsx +39 -38
  46. package/src/stock-operations/stock-operations-table.scss +20 -0
  47. package/dist/155.js +0 -1
  48. package/dist/155.js.map +0 -1
  49. package/dist/914.js +0 -1
  50. package/dist/914.js.map +0 -1
  51. package/src/stock-operations/received-items.component.tsx +0 -93
  52. package/src/stock-operations/stock-operations-forms/stock-operation-form-header.component.tsx +0 -166
@@ -0,0 +1,111 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { StockOperationDTO } from '../../../core/api/types/stockOperation/StockOperationDTO';
4
+ import {
5
+ DataTable,
6
+ Table,
7
+ TableBody,
8
+ TableContainer,
9
+ TableHead,
10
+ TableHeader,
11
+ TableRow,
12
+ TableCell,
13
+ DataTableSkeleton,
14
+ Button,
15
+ } from '@carbon/react';
16
+ import styles from './stock-operation-items-form-step.scc.scss';
17
+ import { ArrowLeft } from '@carbon/react/icons';
18
+
19
+ const formatDate = (date: Date | string | null) => {
20
+ if (!date) return ' ';
21
+ const d = new Date(date);
22
+ const day = String(d.getDate()).padStart(2, '0');
23
+ const month = String(d.getMonth() + 1).padStart(2, '0');
24
+ const year = d.getFullYear();
25
+ return `${month}/${day}/${year}`;
26
+ };
27
+
28
+ interface ReceivedItemsProps {
29
+ stockOperation?: StockOperationDTO;
30
+ onPrevious?: () => void;
31
+ }
32
+
33
+ const ReceivedItems: React.FC<ReceivedItemsProps> = ({ stockOperation, onPrevious }) => {
34
+ const { t } = useTranslation();
35
+
36
+ const headers = [
37
+ { key: 'item', header: t('item', 'Item') },
38
+ { key: 'requested', header: t('requested', 'Requested') },
39
+ { key: 'batch', header: t('batch', 'Batch No') },
40
+ { key: 'expiry', header: t('expiry', 'Expiry Date') },
41
+ { key: 'qtySent', header: t('quantitySent', 'Quantity Sent') },
42
+ { key: 'qtyReceived', header: t('quantityReceived', 'Quantity Received') },
43
+ {
44
+ key: 'qtyUoM',
45
+ header: t('quantityUoM', 'Quantity Unit of Measurement(UoM)'),
46
+ },
47
+ ];
48
+
49
+ const rows =
50
+ stockOperation?.stockOperationItems?.map((item) => ({
51
+ id: item.uuid,
52
+ item: item.stockItemName,
53
+ requested: item.quantityRequested || ' ',
54
+ batch: item.batchNo,
55
+ expiry: formatDate(item.expiration),
56
+ qtySent: item.quantity || ' ',
57
+ qtyReceived: item.quantityReceived || ' ',
58
+ qtyUoM: item.quantityReceivedPackagingUOMName,
59
+ })) || [];
60
+
61
+ if (!stockOperation) {
62
+ return <DataTableSkeleton role="progressbar" />;
63
+ }
64
+
65
+ const headerTitle = t('receivedItems', 'Received Items');
66
+
67
+ return (
68
+ <div style={{ margin: '10px' }}>
69
+ <div className={styles.tableContainer}>
70
+ <div className={styles.heading}>
71
+ <h4>{headerTitle}</h4>
72
+ </div>
73
+ <DataTable rows={rows} headers={headers}>
74
+ {({ rows, headers, getHeaderProps, getTableProps, getRowProps }) => (
75
+ <TableContainer>
76
+ <Table {...getTableProps()}>
77
+ <TableHead>
78
+ <TableRow>
79
+ {headers.map((header) => (
80
+ <TableHeader {...getHeaderProps({ header })} key={header.key}>
81
+ {header.header}
82
+ </TableHeader>
83
+ ))}
84
+ </TableRow>
85
+ </TableHead>
86
+ <TableBody>
87
+ {rows.map((row) => (
88
+ <TableRow {...getRowProps({ row })} key={row.id}>
89
+ {row.cells.map((cell) => (
90
+ <TableCell key={cell.id}>{cell.value}</TableCell>
91
+ ))}
92
+ </TableRow>
93
+ ))}
94
+ </TableBody>
95
+ </Table>
96
+ </TableContainer>
97
+ )}
98
+ </DataTable>
99
+ <div className={styles.btnSet}>
100
+ {typeof onPrevious === 'function' && (
101
+ <Button kind="secondary" onClick={onPrevious} renderIcon={ArrowLeft} hasIconOnly data-testid="previous-btn">
102
+ {/* {t('previous', 'Previous')} */}
103
+ </Button>
104
+ )}
105
+ </div>
106
+ </div>
107
+ </div>
108
+ );
109
+ };
110
+
111
+ export default ReceivedItems;
@@ -1,11 +1,10 @@
1
- import React, { useCallback, useEffect } from 'react';
2
- import { useStockItem } from '../../../stock-items/stock-items.resource';
3
- import { useTranslation } from 'react-i18next';
4
- import { showSnackbar } from '@openmrs/esm-framework';
5
1
  import { InlineLoading } from '@carbon/react';
6
- import { StockItemDTO } from '../../../core/api/types/stockItem/StockItem';
2
+ import { ConfigurableLink, showSnackbar, useConfig } from '@openmrs/esm-framework';
3
+ import React, { useEffect, useMemo } from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { ConfigObject } from '../../../config-schema';
7
6
  import { URL_STOCK_ITEM } from '../../../constants';
8
- import { Link } from 'react-router-dom';
7
+ import { useStockItem } from '../../../stock-items/stock-items.resource';
9
8
 
10
9
  type StockOperationItemCellProps = {
11
10
  stockItemUuid: string;
@@ -14,7 +13,19 @@ type StockOperationItemCellProps = {
14
13
  const StockOperationItemCell: React.FC<StockOperationItemCellProps> = ({ stockItemUuid }) => {
15
14
  const { isLoading, error, item } = useStockItem(stockItemUuid);
16
15
  const { t } = useTranslation();
16
+ const { useItemCommonNameAsDisplay } = useConfig<ConfigObject>();
17
+
18
+ const commonName = useMemo(() => {
19
+ if (!useItemCommonNameAsDisplay) return;
20
+ const drugName = item?.drugName ? `(Drug name: ${item.drugName})` : undefined;
21
+ return `${item?.commonName || t('noCommonNameAvailable', 'No common name available') + (drugName ?? '')}`;
22
+ }, [item, useItemCommonNameAsDisplay, t]);
17
23
 
24
+ const drugName = useMemo(() => {
25
+ if (useItemCommonNameAsDisplay) return;
26
+ const commonName = item?.commonName ? `(Common name: ${item.commonName})` : undefined;
27
+ return `${item?.drugName || t('noDrugNameAvailable', 'No drug name available') + (commonName ?? '')}`;
28
+ }, [item, useItemCommonNameAsDisplay, t]);
18
29
  useEffect(() => {
19
30
  if (error) {
20
31
  showSnackbar({
@@ -29,9 +40,9 @@ const StockOperationItemCell: React.FC<StockOperationItemCellProps> = ({ stockIt
29
40
  if (error) return <>--</>;
30
41
 
31
42
  return (
32
- <Link target={'_blank'} to={URL_STOCK_ITEM(stockItemUuid)}>
33
- {(item as StockItemDTO)?.commonName || 'No name available'}
34
- </Link>
43
+ <ConfigurableLink target={'_blank'} to={window.spaBase + URL_STOCK_ITEM(stockItemUuid)}>
44
+ {useItemCommonNameAsDisplay ? commonName : drugName}
45
+ </ConfigurableLink>
35
46
  );
36
47
  };
37
48
 
@@ -9,8 +9,7 @@ import {
9
9
  TableHeader,
10
10
  TableRow,
11
11
  } from '@carbon/react';
12
- import { Edit, TrashCan } from '@carbon/react/icons';
13
- import { isDesktop, launchWorkspace } from '@openmrs/esm-framework';
12
+ import { ArrowLeft, ArrowRight, Edit, TrashCan } from '@carbon/react/icons';
14
13
  import React, { useCallback, useMemo } from 'react';
15
14
  import { useFormContext } from 'react-hook-form';
16
15
  import { useTranslation } from 'react-i18next';
@@ -20,7 +19,6 @@ import { getStockOperationUniqueId } from '../../stock-operation.utils';
20
19
  import { BaseStockOperationItemFormData, StockOperationItemDtoSchema } from '../../validation-schema';
21
20
  import useOperationTypePermisions from '../hooks/useOperationTypePermisions';
22
21
  import StockItemSearch from '../input-components/stock-item-search.component';
23
- import { StockItemFormProps } from '../stock-item-form/stock-item-form.workspace';
24
22
  import QuantityUomCell from './quantity-uom-cell.component';
25
23
  import StockAvailability from './stock-availability-cell.component';
26
24
  import StockOperationItemBatchNoCell from './stock-operation-item-batch-no-cell.component';
@@ -33,12 +31,14 @@ type StockOperationItemsFormStepProps = {
33
31
  stockOperationType: StockOperationType;
34
32
  onNext?: () => void;
35
33
  onPrevious?: () => void;
34
+ onLaunchItemsForm?: (stockOperationItem?: BaseStockOperationItemFormData) => void;
36
35
  };
37
36
  const StockOperationItemsFormStep: React.FC<StockOperationItemsFormStepProps> = ({
38
37
  stockOperationType,
39
38
  stockOperation,
40
39
  onNext,
41
40
  onPrevious,
41
+ onLaunchItemsForm,
42
42
  }) => {
43
43
  const { t } = useTranslation();
44
44
  const operationTypePermision = useOperationTypePermisions(stockOperationType);
@@ -103,29 +103,6 @@ const StockOperationItemsFormStep: React.FC<StockOperationItemsFormStepProps> =
103
103
  ];
104
104
  }, [operationTypePermision, t]);
105
105
 
106
- const handleLaunchStockItem = useCallback(
107
- (stockOperationItem?: BaseStockOperationItemFormData) => {
108
- launchWorkspace('stock-operation-stock-items-form', {
109
- workspaceTitle: t('stockItem', 'StockItem'),
110
- ...({
111
- stockOperationType,
112
- stockOperationItem,
113
- onSave: (data) => {
114
- const items = (form.getValues('stockOperationItems') ?? []) as Array<BaseStockOperationItemFormData>;
115
- const index = items.findIndex((i) => i.uuid === data.uuid);
116
- if (index === -1) {
117
- items.push(data);
118
- } else {
119
- items[index] = data;
120
- }
121
- form.setValue('stockOperationItems', items as any);
122
- },
123
- } as StockItemFormProps),
124
- });
125
- },
126
- [stockOperationType, t, form],
127
- );
128
-
129
106
  const handleDeleteStockOperationItem = useCallback(
130
107
  (item: BaseStockOperationItemFormData) => {
131
108
  form.setValue('stockOperationItems', observableOperationItems.filter((i) => i.uuid !== item.uuid) as any);
@@ -183,7 +160,7 @@ const StockOperationItemsFormStep: React.FC<StockOperationItemsFormStepProps> =
183
160
  kind="ghost"
184
161
  renderIcon={Edit}
185
162
  onClick={() => {
186
- handleLaunchStockItem(item);
163
+ onLaunchItemsForm?.(item);
187
164
  }}
188
165
  />
189
166
  <Button
@@ -194,14 +171,14 @@ const StockOperationItemsFormStep: React.FC<StockOperationItemsFormStepProps> =
194
171
  kind="ghost"
195
172
  renderIcon={TrashCan}
196
173
  onClick={() => {
197
- handleDeleteStockOperationItem(item);
174
+ onLaunchItemsForm?.(item);
198
175
  }}
199
176
  />
200
177
  </>
201
178
  ),
202
179
  };
203
180
  });
204
- }, [observableOperationItems, handleLaunchStockItem, handleDeleteStockOperationItem, stockOperationType]);
181
+ }, [observableOperationItems, onLaunchItemsForm, stockOperationType]);
205
182
 
206
183
  const headerTitle = t('stockoperationItems', 'Stock operation items');
207
184
 
@@ -210,22 +187,10 @@ const StockOperationItemsFormStep: React.FC<StockOperationItemsFormStepProps> =
210
187
  <div className={styles.tableContainer}>
211
188
  <div className={styles.heading}>
212
189
  <h4>{headerTitle}</h4>
213
- <div className={styles.btnSet}>
214
- {typeof onPrevious === 'function' && (
215
- <Button kind="secondary" onClick={onPrevious}>
216
- {t('previous', 'Previous')}
217
- </Button>
218
- )}
219
- {typeof onNext === 'function' && (
220
- <Button kind="primary" onClick={onNext}>
221
- {t('next', 'Next')}
222
- </Button>
223
- )}
224
- </div>
225
190
  </div>
226
191
  <StockItemSearch
227
192
  onSelectedItem={(stockItem) =>
228
- handleLaunchStockItem({
193
+ onLaunchItemsForm({
229
194
  uuid: `new-item-${getStockOperationUniqueId()}`,
230
195
  stockItemUuid: stockItem.uuid,
231
196
  hasExpiration: stockItem.hasExpiration,
@@ -233,7 +198,6 @@ const StockOperationItemsFormStep: React.FC<StockOperationItemsFormStepProps> =
233
198
  })
234
199
  }
235
200
  />
236
-
237
201
  <DataTable
238
202
  rows={tableRows ?? []}
239
203
  headers={headers}
@@ -245,13 +209,12 @@ const StockOperationItemsFormStep: React.FC<StockOperationItemsFormStepProps> =
245
209
  <Table {...getTableProps()}>
246
210
  <TableHead>
247
211
  <TableRow>
248
- {headers.map((header: any) => (
212
+ {headers.map((header) => (
249
213
  <TableHeader
250
214
  {...getHeaderProps({
251
215
  header,
252
216
  isSortable: false,
253
217
  })}
254
- className={isDesktop ? styles.desktopHeader : styles.tabletHeader}
255
218
  style={header?.styles}
256
219
  key={`${header.key}`}
257
220
  >
@@ -272,7 +235,19 @@ const StockOperationItemsFormStep: React.FC<StockOperationItemsFormStepProps> =
272
235
  </Table>
273
236
  </TableContainer>
274
237
  )}
275
- ></DataTable>
238
+ />
239
+ <div className={styles.btnSet}>
240
+ {typeof onNext === 'function' && (
241
+ <Button kind="primary" onClick={onNext} renderIcon={ArrowRight}>
242
+ {t('next', 'Next')}
243
+ </Button>
244
+ )}
245
+ {typeof onPrevious === 'function' && (
246
+ <Button kind="secondary" onClick={onPrevious} renderIcon={ArrowLeft} hasIconOnly data-testid="previous-btn">
247
+ {/* {t('previous', 'Previous')} */}
248
+ </Button>
249
+ )}
250
+ </div>
276
251
  </div>
277
252
  </div>
278
253
  );
@@ -3,23 +3,6 @@
3
3
  @use '@carbon/type';
4
4
  @import '~@openmrs/esm-styleguide/src/vars';
5
5
 
6
- .tableContainer {
7
- :global(.cds--data-table-content) {
8
- height: calc(100vh - 150px);
9
- }
10
- }
11
-
12
- .tableHeader {
13
- width: 3% !important;
14
- }
15
-
16
- .tableBody {
17
- display: flex;
18
- flex-direction: row;
19
- width: 3% !important;
20
- gap: 8px;
21
- }
22
-
23
6
  .dataTable {
24
7
  width: 100%;
25
8
  }
@@ -57,8 +40,11 @@
57
40
  }
58
41
 
59
42
  .btnSet {
43
+ width: 100%;
44
+ flex: 1;
60
45
  display: flex;
61
- flex-direction: row;
46
+ flex-direction: row-reverse;
62
47
  gap: layout.$spacing-03;
63
48
  align-items: center;
49
+ margin-top: layout.$spacing-03;
64
50
  }
@@ -1,5 +1,5 @@
1
1
  import { Button, Column, InlineLoading, RadioButton, RadioButtonGroup, Stack } from '@carbon/react';
2
- import { Departure, ListChecked, Save, SendFilled } from '@carbon/react/icons';
2
+ import { ArrowLeft, ArrowRight, Departure, ListChecked, Save, SendFilled } from '@carbon/react/icons';
3
3
  import { restBaseUrl, showSnackbar } from '@openmrs/esm-framework';
4
4
  import React, { useCallback, useMemo, useState } from 'react';
5
5
  import { useFormContext } from 'react-hook-form';
@@ -20,11 +20,15 @@ type StockOperationSubmissionFormStepProps = {
20
20
  onPrevious?: () => void;
21
21
  stockOperation?: StockOperationDTO;
22
22
  stockOperationType: StockOperationType;
23
+ onNext?: () => void;
24
+ dismissWorkspace?: () => void;
23
25
  };
24
26
  const StockOperationSubmissionFormStep: React.FC<StockOperationSubmissionFormStepProps> = ({
25
27
  onPrevious,
26
28
  stockOperationType,
27
29
  stockOperation,
30
+ onNext,
31
+ dismissWorkspace,
28
32
  }) => {
29
33
  const { t } = useTranslation();
30
34
  const operationTypePermision = useOperationTypePermisions(stockOperationType);
@@ -93,6 +97,7 @@ const StockOperationSubmissionFormStep: React.FC<StockOperationSubmissionFormSte
93
97
  : createStockOperation(payload as any));
94
98
  result = resp.data; // Store the response data
95
99
  handleMutate(`${restBaseUrl}/stockmanagement/stockoperation`);
100
+ dismissWorkspace?.();
96
101
  showSnackbar({
97
102
  isLowContrast: true,
98
103
  title: stockOperation
@@ -115,7 +120,7 @@ const StockOperationSubmissionFormStep: React.FC<StockOperationSubmissionFormSte
115
120
  }
116
121
  })(); // Call handleSubmit to trigger validation and submission
117
122
  return result; // Return the result after handleSubmit completes
118
- }, [form, stockOperation, t, approvalRequired, isStockIssueOperation]);
123
+ }, [form, stockOperation, t, approvalRequired, isStockIssueOperation, dismissWorkspace]);
119
124
 
120
125
  const handleComplete = useCallback(() => {
121
126
  handleSave().then((operation) => {
@@ -141,13 +146,6 @@ const StockOperationSubmissionFormStep: React.FC<StockOperationSubmissionFormSte
141
146
  ? t('submitAndDispatch', 'Submit/Dispatch')
142
147
  : t('submitAndComplete', 'Submit/Complete')}
143
148
  </h4>
144
- <div className={styles.btnSet}>
145
- {typeof onPrevious === 'function' && (
146
- <Button kind="secondary" onClick={onPrevious}>
147
- Previous
148
- </Button>
149
- )}
150
- </div>
151
149
  </div>
152
150
 
153
151
  <Column>
@@ -156,7 +154,7 @@ const StockOperationSubmissionFormStep: React.FC<StockOperationSubmissionFormSte
156
154
  legendText={t('doesThisTransactionRequireApproval', 'Does the transaction require approval ?')}
157
155
  onChange={handleRadioButtonChange}
158
156
  readOnly={!editable}
159
- valueSelected={approvalRequired === true}
157
+ valueSelected={approvalRequired === true ? true : approvalRequired === false ? false : null}
160
158
  >
161
159
  <RadioButton value={true} id="rbgApprovelRequired-true" labelText={t('yes', 'Yes')} />
162
160
  <RadioButton value={false} id="rbgApprovelRequired-false" labelText={t('no', 'No')} />
@@ -169,6 +167,7 @@ const StockOperationSubmissionFormStep: React.FC<StockOperationSubmissionFormSte
169
167
  {!operationTypePermision.requiresDispatchAcknowledgement && !approvalRequired && (
170
168
  <Button
171
169
  name="complete"
170
+ data-testid="complete-button"
172
171
  type="button"
173
172
  style={{ margin: '4px' }}
174
173
  className="submitButton"
@@ -184,6 +183,7 @@ const StockOperationSubmissionFormStep: React.FC<StockOperationSubmissionFormSte
184
183
  name="dispatch"
185
184
  type="button"
186
185
  style={{ margin: '4px' }}
186
+ data-testid="dipatch-button"
187
187
  className="submitButton"
188
188
  kind="primary"
189
189
  onClick={handleDispatch}
@@ -229,6 +229,18 @@ const StockOperationSubmissionFormStep: React.FC<StockOperationSubmissionFormSte
229
229
  </Button>
230
230
  </Column>
231
231
  )}
232
+ <div className={styles.btnSet}>
233
+ {typeof onNext === 'function' && (
234
+ <Button kind="tertiary" onClick={onNext} renderIcon={ArrowRight}>
235
+ {t('next', 'Next')}
236
+ </Button>
237
+ )}
238
+ {typeof onPrevious === 'function' && (
239
+ <Button kind="tertiary" onClick={onPrevious} renderIcon={ArrowLeft} hasIconOnly data-testid="previous-btn">
240
+ {/* {t('previous', 'Previous')} */}
241
+ </Button>
242
+ )}
243
+ </div>
232
244
  </Stack>
233
245
  );
234
246
  };
@@ -1,10 +1,12 @@
1
- import { showSnackbar } from '@openmrs/esm-framework';
1
+ import { parseDate, showSnackbar } from '@openmrs/esm-framework';
2
2
  import React, { useEffect, useMemo } from 'react';
3
3
  import { useFormContext } from 'react-hook-form';
4
4
  import { useTranslation } from 'react-i18next';
5
5
  import { OperationType, StockOperationType } from '../../core/api/types/stockOperation/StockOperationType';
6
- import { useStockOperation } from '../stock-operations.resource';
6
+ import { useStockOperationAndItems } from '../stock-operations.resource';
7
7
  import { getStockOperationItemFormSchema, StockOperationItemDtoSchema } from '../validation-schema';
8
+ import { pick } from '../../core/utils/utils';
9
+ import { Loading } from '@carbon/react';
8
10
 
9
11
  type StockIssueFormInitializerWithRelatedRequisitionOperationProps = {
10
12
  stockRequisitionUuid: string;
@@ -16,11 +18,12 @@ const StockIssueFormInitializerWithRelatedRequisitionOperation: React.FC<
16
18
  > = ({ stockRequisitionUuid, stockOperationType }) => {
17
19
  const form = useFormContext<StockOperationItemDtoSchema>();
18
20
  const { t } = useTranslation();
19
- const { error, items: stockOperation, isLoading } = useStockOperation(stockRequisitionUuid);
21
+ const { error, items: stockOperation, isLoading } = useStockOperationAndItems(stockRequisitionUuid);
20
22
  const { setValue } = form;
21
23
  const stockOperationItemFormSchema = useMemo(() => {
22
24
  return getStockOperationItemFormSchema(OperationType.STOCK_ISSUE_OPERATION_TYPE);
23
25
  }, []);
26
+
24
27
  const items = form.watch('stockOperationItems');
25
28
  // initialize form values with requisition values for Stock issue operation type
26
29
  useEffect(() => {
@@ -30,6 +33,17 @@ const StockIssueFormInitializerWithRelatedRequisitionOperation: React.FC<
30
33
  setValue('destinationUuid', stockOperation.destinationUuid);
31
34
  setValue('requisitionStockOperationUuid', stockRequisitionUuid);
32
35
  setValue('operationTypeUuid', stockOperationType.uuid);
36
+ setValue('responsiblePersonUuid', stockOperation.responsiblePersonUuid);
37
+ setValue('responsiblePersonOther', stockOperation.responsiblePersonOther);
38
+ setValue(
39
+ 'stockOperationItems',
40
+ (stockOperation?.stockOperationItems?.map((item) =>
41
+ pick(
42
+ { ...item, expiration: item.expiration ? parseDate(item.expiration as any) : undefined },
43
+ stockOperationItemFormSchema.keyof().options,
44
+ ),
45
+ ) ?? []) as any,
46
+ );
33
47
  }
34
48
  }, [stockOperation, stockOperationItemFormSchema, setValue, items, stockOperationType, stockRequisitionUuid]);
35
49
 
@@ -49,6 +63,9 @@ const StockIssueFormInitializerWithRelatedRequisitionOperation: React.FC<
49
63
  });
50
64
  }
51
65
  }, [stockRequisitionUuid, error, t]);
66
+
67
+ if (isLoading) return <Loading active description="Loading" />;
68
+
52
69
  return <React.Fragment />;
53
70
  };
54
71
 
@@ -10,7 +10,7 @@ import {
10
10
  TextInput,
11
11
  } from '@carbon/react';
12
12
  import { zodResolver } from '@hookform/resolvers/zod';
13
- import { DefaultWorkspaceProps } from '@openmrs/esm-framework';
13
+ import { DefaultWorkspaceProps, useConfig } from '@openmrs/esm-framework';
14
14
  import React, { useMemo } from 'react';
15
15
  import { Controller, useForm } from 'react-hook-form';
16
16
  import { useTranslation } from 'react-i18next';
@@ -24,15 +24,16 @@ import BatchNoSelector from '../input-components/batch-no-selector.component';
24
24
  import QtyUomSelector from '../input-components/quantity-uom-selector.component';
25
25
  import styles from './stock-item-form.scss';
26
26
  import UniqueBatchNoEntryInput from '../input-components/unique-batch-no-entry-input.component';
27
+ import { ConfigObject } from '../../../config-schema';
27
28
 
28
29
  export interface StockItemFormProps {
29
30
  stockOperationType: StockOperationType;
30
31
  stockOperationItem: BaseStockOperationItemFormData;
31
32
  onSave?: (data: BaseStockOperationItemFormData) => void;
33
+ onBack?: () => void;
32
34
  }
33
35
 
34
- interface Props extends DefaultWorkspaceProps, StockItemFormProps {}
35
- const StockItemForm: React.FC<Props> = ({ closeWorkspace, stockOperationType, stockOperationItem, onSave }) => {
36
+ const StockItemForm: React.FC<StockItemFormProps> = ({ stockOperationType, stockOperationItem, onSave, onBack }) => {
36
37
  const operationType = useMemo(() => {
37
38
  return operationFromString(stockOperationType.operationType);
38
39
  }, [stockOperationType]);
@@ -40,6 +41,7 @@ const StockItemForm: React.FC<Props> = ({ closeWorkspace, stockOperationType, st
40
41
  return getStockOperationItemFormSchema(operationType);
41
42
  }, [operationType]);
42
43
  const operationTypePermision = useOperationTypePermisions(stockOperationType);
44
+ const { useItemCommonNameAsDisplay } = useConfig<ConfigObject>();
43
45
 
44
46
  const fields = formschema.keyof().options;
45
47
  const form = useForm<z.infer<typeof formschema>>({
@@ -49,15 +51,25 @@ const StockItemForm: React.FC<Props> = ({ closeWorkspace, stockOperationType, st
49
51
  });
50
52
  const { t } = useTranslation();
51
53
  const { item } = useStockItem(form.getValues('stockItemUuid'));
54
+ const commonName = useMemo(() => {
55
+ if (!useItemCommonNameAsDisplay) return;
56
+ const drugName = item?.drugName ? `(Drug name: ${item.drugName})` : undefined;
57
+ return `${item?.commonName || t('noCommonNameAvailable', 'No common name available') + (drugName ?? '')}`;
58
+ }, [item, useItemCommonNameAsDisplay, t]);
59
+
60
+ const drugName = useMemo(() => {
61
+ if (useItemCommonNameAsDisplay) return;
62
+ const commonName = item?.commonName ? `(Common name: ${item.commonName})` : undefined;
63
+ return `${item?.drugName || t('noDrugNameAvailable', 'No drug name available') + (commonName ?? '')}`;
64
+ }, [item, useItemCommonNameAsDisplay, t]);
65
+
52
66
  const onSubmit = (data: z.infer<typeof formschema>) => {
53
67
  onSave?.(data);
54
- closeWorkspace();
55
- // Implementation of adding or updating itsms in items table
56
68
  };
57
69
  return (
58
70
  <Form onSubmit={form.handleSubmit(onSubmit)} className={styles.form}>
59
71
  <Stack gap={4} className={styles.grid}>
60
- {item?.commonName && <p className={styles.title}>{item?.commonName}</p>}
72
+ <p className={styles.title}>{useItemCommonNameAsDisplay ? commonName : drugName}</p>
61
73
 
62
74
  {(operationTypePermision.requiresActualBatchInfo || operationTypePermision.requiresBatchUuid) &&
63
75
  fields.includes('batchNo' as any) && (
@@ -183,7 +195,7 @@ const StockItemForm: React.FC<Props> = ({ closeWorkspace, stockOperationType, st
183
195
  </Stack>
184
196
 
185
197
  <ButtonSet className={styles.buttonSet}>
186
- <Button className={styles.button} kind="secondary" onClick={closeWorkspace}>
198
+ <Button className={styles.button} kind="secondary" onClick={onBack}>
187
199
  {t('discard', 'Discard')}
188
200
  </Button>
189
201
  <Button className={styles.button} kind="primary" type="submit" disabled={form.formState.isSubmitting}>